stitch-sdk-development

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Stitch SDK Development

Stitch SDK 开发

This skill encodes the expertise needed to develop
@google/stitch-sdk
— the core systems, patterns, and philosophies. It does not enumerate every method (the codebase is the source of truth for that). It teaches you how to think about the system.

本指南涵盖了开发
@google/stitch-sdk
所需的核心系统、模式与理念相关知识。它不会罗列每一个方法(代码库才是这方面的权威来源),而是教你如何理解整个系统的设计思路。

The Generation Pipeline

生成流水线

The domain layer is fully generated. No handwritten domain classes. The pipeline has 3 stages:
Stage 1: Capture            Stage 2: Domain Design       Stage 3: Generate
┌──────────────────┐       ┌──────────────────┐        ┌──────────────────┐
│ capture-tools.ts │──────▶│  domain-map.json │───────▶│ generate-sdk.ts  │
│                  │       │  (the IR)        │        │                  │
│ Connects to MCP  │       │ Classes, bindings│        │ Deterministic    │
│ server, calls    │       │ arg routing,     │        │ codegen into     │
│ tools/list       │       │ cache, extraction│        │ packages/sdk/generated/  │
└──────────────────┘       └──────────────────┘        └──────────────────┘
        │                          │                           │
        ▼                          ▼                           ▼
 tools-manifest.json        domain-map.json          packages/sdk/generated/src/*.ts
 (raw MCP tool schemas)     (tool→class mapping)     (Stitch, Project, Screen)
Stage 1 (
bun scripts/capture-tools.ts
): Connects to the live Stitch MCP server, calls
tools/list
, writes
tools-manifest.json
. Source of truth for what tools exist.
Stage 2 (agent/human): Reads the manifest and produces
domain-map.json
— the intermediate representation. This is where judgment lives: which tool maps to which class, what args come from
self
vs
param
vs
computed
, how to extract the return value, and what data to cache.
Stage 3 (
bun scripts/generate-sdk.ts
): Deterministic codegen. Reads manifest + domain-map, emits TypeScript classes in
packages/sdk/generated/src/
. No LLM involved — pure template expansion.
Integrity:
stitch-sdk.lock
records SHA-256 hashes of all inputs and outputs.
bun scripts/validate-generated.ts
verifies consistency. Run in CI to prevent publishing stale code.
领域层是完全自动生成的,无需手动编写领域类。该流水线包含3个阶段:
Stage 1: Capture            Stage 2: Domain Design       Stage 3: Generate
┌──────────────────┐       ┌──────────────────┐        ┌──────────────────┐
│ capture-tools.ts │──────▶│  domain-map.json │───────▶│ generate-sdk.ts  │
│                  │       │  (the IR)        │        │                  │
│ Connects to MCP  │       │ Classes, bindings│        │ Deterministic    │
│ server, calls    │       │ arg routing,     │        │ codegen into     │
│ tools/list       │       │ cache, extraction│        │ packages/sdk/generated/  │
└──────────────────┘       └──────────────────┘        └──────────────────┘
        │                          │                           │
        ▼                          ▼                           ▼
 tools-manifest.json        domain-map.json          packages/sdk/generated/src/*.ts
 (raw MCP tool schemas)     (tool→class mapping)     (Stitch, Project, Screen)
阶段1
bun scripts/capture-tools.ts
):连接到Stitch MCP实时服务器,调用
tools/list
接口,生成
tools-manifest.json
文件。这是确认现有工具的权威来源。
阶段2(Agent/人工操作):读取清单文件并生成
domain-map.json
——即中间表示(IR)。这一步需要人工判断:将哪个工具映射到哪个类,参数来自
self
param
还是
computed
,如何提取返回值,以及需要缓存哪些数据。
阶段3
bun scripts/generate-sdk.ts
):确定性代码生成。读取清单文件和domain-map,在
packages/sdk/generated/src/
目录下生成TypeScript类。此过程不涉及LLM,仅为纯模板展开。
完整性校验
stitch-sdk.lock
记录了所有输入和输出的SHA-256哈希值。
bun scripts/validate-generated.ts
用于验证一致性。需在CI流程中运行该命令,防止发布过期代码。

Supporting a New Tool

支持新工具

When the Stitch MCP server adds a new tool:
  1. Run Stage 1 to capture the updated manifest
  2. Run Stage 2: add a binding in
    domain-map.json
    for the new tool
  3. Run Stage 3 to regenerate the SDK classes
  4. Run
    validate-generated.ts
    to confirm consistency
  5. Update tests as needed
当Stitch MCP服务器新增工具时,执行以下步骤:
  1. 运行阶段1,捕获更新后的清单文件
  2. 运行阶段2:在
    domain-map.json
    中为新工具添加绑定配置
  3. 运行阶段3,重新生成SDK类
  4. 运行
    validate-generated.ts
    确认一致性
  5. 根据需要更新测试用例

The Domain Map IR

领域映射中间表示(IR)

domain-map.json
expresses two things:
Classes: What domain objects exist and how they're constructed.
json
{
  "Screen": {
    "constructorParams": ["projectId", "screenId"],
    "fieldMapping": {
      "projectId": { "from": "projectId" },
      "screenId": { "from": "id", "fallback": { "field": "name", "splitOn": "/screens/" } }
    },
    "parentField": "projectId",
    "idField": "screenId"
  }
}
Bindings: How MCP tools map to class methods.
json
{
  "tool": "generate_screen_from_text",
  "class": "Project",
  "method": "generate",
  "args": {
    "projectId": { "from": "self" },
    "prompt": { "from": "param" },
    "name": { "from": "computed", "template": "projects/{projectId}/screens/{screenId}" }
  },
  "returns": {
    "class": "Screen",
    "projection": [
      { "prop": "outputComponents", "index": 0 },
      { "prop": "design" },
      { "prop": "screens", "index": 0 }
    ]
  }
}
Arg routing:
self
= injected from
this
,
param
= passed by the caller,
computed
= built from a template at call time,
selfArray
=
[this.field]
wrapped as array.
Response projections: Structured
ProjectionStep[]
arrays validated against
outputSchema
. Use
index
for single items,
each
for arrays. Empty
[]
= direct return.
Cache: Methods can specify a
cache
with a structured
projection
to check
this.data
before calling the API:
json
{
  "cache": { "projection": [{ "prop": "htmlCode" }, { "prop": "downloadUrl" }], "description": "Use cached download URL from generation response" }
}

domain-map.json
主要包含两部分内容:
类定义:定义存在哪些领域对象及其构造方式。
json
{
  "Screen": {
    "constructorParams": ["projectId", "screenId"],
    "fieldMapping": {
      "projectId": { "from": "projectId" },
      "screenId": { "from": "id", "fallback": { "field": "name", "splitOn": "/screens/" } }
    },
    "parentField": "projectId",
    "idField": "screenId"
  }
}
绑定配置:定义MCP工具如何映射到类方法。
json
{
  "tool": "generate_screen_from_text",
  "class": "Project",
  "method": "generate",
  "args": {
    "projectId": { "from": "self" },
    "prompt": { "from": "param" },
    "name": { "from": "computed", "template": "projects/{projectId}/screens/{screenId}" }
  },
  "returns": {
    "class": "Screen",
    "projection": [
      { "prop": "outputComponents", "index": 0 },
      { "prop": "design" },
      { "prop": "screens", "index": 0 }
    ]
  }
}
参数路由
self
表示从
this
注入,
param
表示由调用者传入,
computed
表示调用时通过模板生成,
selfArray
表示将
[this.field]
包装为数组。
响应投影:结构化的
ProjectionStep[]
数组,会根据
outputSchema
进行校验。使用
index
获取单个元素,
each
处理数组。空数组
[]
表示直接返回结果。
缓存配置:方法可指定带有结构化
projection
cache
配置,调用API前会先检查
this.data
json
{
  "cache": { "projection": [{ "prop": "htmlCode" }, { "prop": "downloadUrl" }], "description": "Use cached download URL from generation response" }
}

Dual Modality

双模式架构

The SDK serves two distinct consumers with different needs:
SDK服务于两类需求截然不同的使用者:

Agent Modality —
StitchToolClient

Agent模式 ——
StitchToolClient

For AI agents and orchestration scripts. Raw tool pipe. The agent receives tool schemas, constructs JSON, sends it, gets JSON back. No domain knowledge required.
typescript
const client = new StitchToolClient();
const tools = await client.listTools();
const result = await client.callTool("generate_screen_from_text", {
  projectId: "123", prompt: "A login page"
});
适用于AI Agent和编排脚本。为原生工具管道,Agent接收工具 schema,构造JSON请求,发送后获取JSON响应。无需具备领域知识。
typescript
const client = new StitchToolClient();
const tools = await client.listTools();
const result = await client.callTool("generate_screen_from_text", {
  projectId: "123", prompt: "A login page"
});

SDK Modality — Generated Domain Classes

SDK模式 —— 生成的领域类

For humans writing precise, programmatic scripts. Generated domain facade over
callTool
. Typed parameters, domain objects returned,
StitchError
thrown on failure.
typescript
const project = await stitch.createProject("My App");
const screen = await project.generate("A login page");
const html = await screen.getHtml();
Both modalities share
StitchToolClient
underneath. The domain classes are a typed layer over
callTool
.
适用于编写精确、程序化脚本的开发人员。在
callTool
之上封装了生成的领域外观层,提供类型化参数,返回领域对象,失败时抛出
StitchError
typescript
const project = await stitch.createProject("My App");
const screen = await project.generate("A login page");
const html = await screen.getHtml();
两种模式底层均基于
StitchToolClient
。领域类是
callTool
之上的类型化封装层。

Error Handling — Throws at the Boundary

错误处理 —— 在边界处抛出异常

All generated methods use
throw StitchError
for error handling. No
Result<T>
pattern.
typescript
// Generated method pattern (inside each method):
try {
  const raw = await this.client.callTool<any>("tool_name", args);
  return /* extracted result */;
} catch (error) {
  throw StitchError.fromUnknown(error);
}
StitchError.fromUnknown()
ensures all errors are normalized to
StitchError
with a code, message, and recoverability hint.
所有生成的方法均使用
throw StitchError
进行错误处理,不采用
Result<T>
模式。
typescript
// Generated method pattern (inside each method):
try {
  const raw = await this.client.callTool<any>("tool_name", args);
  return /* extracted result */;
} catch (error) {
  throw StitchError.fromUnknown(error);
}
StitchError.fromUnknown()
确保所有错误都被规范化为
StitchError
,包含错误码、错误信息和恢复提示。

Infrastructure (Handwritten)

基础设施代码(手动编写)

These components remain handwritten as they provide foundational plumbing:
  • StitchToolClient
    — MCP transport, auth, tool invocation
  • StitchError
    — typed error class with codes, messages, recovery hints
  • StitchProxy
    — MCP proxy server for re-exposing Stitch to other agents
  • singleton.ts
    — lazy proxy for
    stitch
    export with env var config

以下组件需手动编写,因为它们提供基础的底层能力:
  • StitchToolClient
    —— MCP传输、认证、工具调用
  • StitchError
    —— 带错误码、错误信息和恢复提示的类型化错误类
  • StitchProxy
    —— MCP代理服务器,用于向其他Agent暴露Stitch服务
  • singleton.ts
    ——
    stitch
    导出的懒加载代理,支持环境变量配置

Traffic Light Implementation (Red → Green → Yellow)

红绿灯实现流程(红→绿→黄)

When implementing a new feature or fixing a bug, follow the Traffic Light pattern:
新增功能或修复Bug时,请遵循红绿灯模式:

🔴 Red — Write Breaking Tests

🔴 红色阶段 —— 编写失败的测试用例

Write the test first. It must fail. This defines the contract before any implementation exists.
bash
undefined
先编写测试用例,确保测试失败。这会在实现前先定义好契约。
bash
undefined

Unit tests for generated classes

生成类的单元测试

npx vitest run test/unit/sdk.test.ts
npx vitest run test/unit/sdk.test.ts

→ FAIL (new method doesn't exist yet)

→ 失败(新方法尚未实现)

E2E test for the public API

公开API的端到端测试

bun scripts/e2e-test.ts
bun scripts/e2e-test.ts

→ FAIL (method doesn't exist yet)

→ 失败(方法尚未实现)

undefined
undefined

🟢 Green — Implement

🟢 绿色阶段 —— 实现功能

  1. Add a binding to
    domain-map.json
    (Stage 2)
  2. Run
    bun scripts/generate-sdk.ts
    (Stage 3)
  3. Update tests to verify correct behavior
bash
npx vitest run  # All tests pass
bun scripts/e2e-test.ts  # E2E passes
  1. domain-map.json
    中添加绑定配置(阶段2)
  2. 运行
    bun scripts/generate-sdk.ts
    (阶段3)
  3. 更新测试用例以验证功能正确性
bash
npx vitest run  # 所有测试通过
bun scripts/e2e-test.ts  # 端到端测试通过

🟡 Yellow — Refactor / Refine / Revisit

🟡 黄色阶段 —— 重构/优化/复查

With passing tests as your safety net:
  • Refactor for clarity (extract helpers, simplify args)
  • Add edge case tests
  • Run
    npx tsc
    to verify type safety
  • Run
    bun scripts/validate-generated.ts
    to verify pipeline integrity

在测试通过的安全前提下:
  • 重构代码以提升可读性(提取辅助函数、简化参数)
  • 添加边缘场景测试用例
  • 运行
    npx tsc
    验证类型安全性
  • 运行
    bun scripts/validate-generated.ts
    验证流水线完整性

Orienting in the Codebase

代码库导航

Discover the current state by reading the codebase directly. The key entry points:
  • Public surface: Start at
    packages/sdk/src/index.ts
    — every public export is listed here
  • Generated classes:
    packages/sdk/generated/src/
    — Stitch, Project, Screen
  • Pipeline artifacts:
    packages/sdk/generated/domain-map.json
    ,
    packages/sdk/generated/tools-manifest.json
  • Infrastructure:
    packages/sdk/src/client.ts
    ,
    packages/sdk/src/spec/errors.ts
    ,
    packages/sdk/src/singleton.ts
  • Test structure:
    packages/sdk/test/unit/
    for unit tests,
    packages/sdk/test/integration/
    for live tests
  • Available commands: Read the
    scripts
    field in
    package.json
Do not rely on cached descriptions of files or directory trees. Read the source.
直接阅读代码库以了解当前状态,关键入口点如下:
  • 公开接口:从
    packages/sdk/src/index.ts
    开始——所有公开导出均在此列出
  • 生成的类
    packages/sdk/generated/src/
    —— Stitch、Project、Screen等类
  • 流水线产物
    packages/sdk/generated/domain-map.json
    packages/sdk/generated/tools-manifest.json
  • 基础设施代码
    packages/sdk/src/client.ts
    packages/sdk/src/spec/errors.ts
    packages/sdk/src/singleton.ts
  • 测试结构
    packages/sdk/test/unit/
    存放单元测试,
    packages/sdk/test/integration/
    存放集成测试
  • 可用命令:查看
    package.json
    中的
    scripts
    字段
请勿依赖缓存的文件描述或目录结构,直接阅读源代码。

Import Convention

导入约定

Use
.js
extensions for ESM compatibility:
typescript
import { StitchError } from '../../src/spec/errors.js';  // ✓
import { StitchError } from '../../src/spec/errors';     // ✗
为了兼容ESM,请使用
.js
扩展名:
typescript
import { StitchError } from '../../src/spec/errors.js';  // ✓
import { StitchError } from '../../src/spec/errors';     // ✗