# 第九阶段 · 模块九 · 第四节:SDK API 设计
Claude Code 的 SDK API 是如何设计的?核心类型和 Schema 是什么?SDK 的设计哲学是什么?
Claude Code 全局架构
┌─────────────────────────────────────────────────────────────────────┐
│ 高级主题 │
│ │
│ SDK API 设计 ← 本节 │
│ ├── coreSchemas ──> Zod Schema 定义 │
│ ├── coreTypes ──> TypeScript 类型生成 │
│ └── 设计模式 ──> Schema-first │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ SDK 消费者 │
│ - Web UI │
│ - CLI │
│ - 第三方集成 │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ SDK Core │
│ - coreSchemas.ts(Zod Schema) │
│ - coreTypes.ts(TypeScript 类型) │
│ - 控制平面 Schema │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 运行时 │
│ - Zod 验证 │
│ - 类型生成 │
└─────────────────────────────────────────────────────────────────────┘
源码位置:`src/entrypoints/sdk/coreSchemas.ts`
// Schema-first 设计
// 1. Zod Schema 是单一数据源
// 2. TypeScript 类型从 Schema 自动生成
// 3. 不允许手动修改生成的类型文件
// 工作流程:
// 1. 编辑 Zod schemas
// 2. 运行生成脚本
// 3. 提交生成的类型文件
问 1:为什么要用 Schema-first 设计?
// Schema-first 的优势:
// 1. 类型安全
// - Schema 验证运行时
// - TypeScript 验证编译时
// - 双重保障
// 2. 代码生成
// - 自动化减少手工错误
// - 保证类型和 Schema 一致
// 3. 文档化
// - Schema 本身就是文档
// - 包含描述信息
// 4. 可验证
// - 运行时检查输入
// - 清晰的错误信息
源码位置:`src/entrypoints/sdk/coreSchemas.ts`
export const ModelUsageSchema = lazySchema(() =>
z.object({
inputTokens: z.number(),
outputTokens: z.number(),
cacheReadInputTokens: z.number(),
cacheCreationInputTokens: z.number(),
webSearchRequests: z.number(),
costUSD: z.number(),
contextWindow: z.number(),
maxOutputTokens: z.number(),
}),
)
export const ThinkingConfigSchema = lazySchema(() =>
z.union([
ThinkingAdaptiveSchema(), // { type: 'adaptive' }
ThinkingEnabledSchema(), // { type: 'enabled', budgetTokens: number }
ThinkingDisabledSchema(), // { type: 'disabled' }
])
)
问 1:为什么使用 lazySchema?
// lazySchema = 延迟加载 Schema
// 原因:
// 1. 避免循环依赖
// 2. 改善构建性能
// 3. 支持 Schema 组合
// 例如:
// A 引用 B,B 引用 A
// 使用 lazySchema 避免无限递归
源码位置:`src/entrypoints/sdk/coreSchemas.ts`
// stdio 传输
export const McpStdioServerConfigSchema = lazySchema(() =>
z.object({
type: z.literal('stdio'),
command: z.string(),
args: z.array(z.string()).optional(),
env: z.record(z.string(), z.string()).optional(),
}),
)
// SSE 传输
export const McpSSEServerConfigSchema = lazySchema(() =>
z.object({
type: z.literal('sse'),
url: z.string(),
headers: z.record(z.string(), z.string()).optional(),
}),
)
// HTTP 传输
export const McpHttpServerConfigSchema = lazySchema(() =>
z.object({
type: z.literal('http'),
url: z.string(),
headers: z.record(z.string(), z.string()).optional(),
}),
)
// SDK 传输
export const McpSdkServerConfigSchema = lazySchema(() =>
z.object({
type: z.literal('sdk'),
name: z.string(),
}),
)
| 类型 | 使用场景 | 特点 |
| stdio | 本地进程 | 简单、安全 |
| SSE | 远程服务器 | 实时推送 |
| HTTP | REST API | 通用 |
| sdk | 进程内通信 | 最高性能 |
问 1:为什么需要多种 MCP 传输类型?
// 不同场景需要不同传输:
// 1. stdio
// - 本地 MCP 服务器
// - 安全隔离
// - 简单部署
// 2. SSE
// - 需要服务器推送
// - 实时更新
// - 网络通信
// 3. HTTP
// - 标准 REST API
// - 兼容性强
// - 无状态
源码位置:`src/constants/apiLimits.ts`
// 模型限制
MODEL_CONTEXT_WINDOW_DEFAULT = 200_000 // 200K tokens
// 图像限制
API_IMAGE_MAX_BASE64_SIZE = 5MB // base64 编码后
IMAGE_MAX_WIDTH = 1568
IMAGE_MAX_HEIGHT = 1568
IMAGE_TARGET_RAW_SIZE = 400KB
// Token 限制
CAPPED_DEFAULT_MAX_TOKENS = 8_000
ESCALATED_MAX_TOKENS = 64_000
// 限制层级:
// 1. API 限制(服务端)
// - Anthropic API 强制
// - 不可绕过
// 2. SDK 限制(客户端)
// - Claude Code 添加
// - 可配置
// 3. 本地限制(用户)
// - 用户可自定义
// - 环境变量
问 1:如何调整 API 限制?
// 调整限制的方式:
// 1. 环境变量
MAX_TOKENS=16000
// 2. 配置文件
// settings.json 中设置
// 3. 运行时参数
claude --print --max-tokens 20000
源码位置:`src/entrypoints/sdk/coreTypes.ts` 第 24 行
export const HOOK_EVENTS = [
'PreToolUse',
'PostToolUse',
'PostToolUseFailure',
'Notification',
'UserPromptSubmit',
'SessionStart',
'SessionEnd',
'Stop',
'StopFailure',
'SubagentStart',
'SubagentStop',
'PreCompact',
'PostCompact',
'PermissionRequest',
'PermissionDenied',
'Setup',
'TeammateIdle',
'TaskCreated',
'TaskCompleted',
'Elicitation',
'ElicitationResult',
'ConfigChange',
'WorktreeCreate',
'WorktreeRemove',
'InstructionsLoaded',
'CwdChanged',
'FileChanged',
] as const
// 生命周期事件
SessionStart, SessionEnd, Setup
// 工具事件
PreToolUse, PostToolUse, PostToolUseFailure
// 任务事件
TaskCreated, TaskCompleted, SubagentStart, SubagentStop
// 权限事件
PermissionRequest, PermissionDenied
// 界面事件
Notification, Elicitation, ElicitationResult
// 工作目录事件
CwdChanged, FileChanged, WorktreeCreate, WorktreeRemove
问 1:Hook 事件有什么用?
// Hook 事件的应用:
// 1. 监控
// - 记录所有工具调用
// - 统计使用情况
// 2. 拦截
// - 在工具执行前检查
// - 修改工具参数
// 3. 通知
// - 任务完成通知
// - 进度更新
源码位置:`src/entrypoints/sdk/coreTypes.ts` 第 45 行
export const EXIT_REASONS = [
'clear', // 用户清空会话
'resume', // 恢复会话
'logout', // 登出
'prompt_input_exit', // EOF 或 Ctrl+D
'other', // 其他原因
'bypass_permissions_disabled', // 权限绕过禁用
] as const
问 1:为什么需要退出原因?
// 退出原因的作用:
// 1. 调试
// - 了解会话如何结束
// - 排查异常退出
// 2. 统计
// - 分析用户行为
// - 优化产品
// 3. 恢复
// - 决定是否保存状态
// - 确定恢复策略
// 1. 使用 lazySchema 处理循环引用
const A = lazySchema(() => z.object({ b: B() }))
const B = lazySchema(() => z.object({ a: A() }))
// 2. 使用 describe 添加文档
z.string().describe('用户名,必须是邮箱格式')
// 3. 使用 refine 添加自定义验证
z.string().refine(val => val.includes('@'), '必须是邮箱')
// 4. 使用 transform 转换数据
z.string().transform(val => val.trim())
// 生成流程:
// 1. 编辑 Schema
// src/entrypoints/sdk/coreSchemas.ts
// 2. 运行生成脚本
// bun scripts/generate-sdk-types.ts
// 3. 提交生成的文件
// src/entrypoints/sdk/coreTypes.generated.ts
问 1:Schema-first 的缺点是什么?
// Schema-first 的缺点:
// 1. 复杂性
// - 需要额外的生成步骤
// - 调试困难
// 2. 延迟
// - Schema 变更需要重新生成
// - 迭代变慢
// 3. 学习曲线
// - 需要了解 Zod
// - 需要了解代码生成
答案:
// Zod 的优势:
// 1. 运行时验证
// - TypeScript 只在编译时检查
// - Zod 在运行时也检查
// - 网络输入必须有运行时验证
// 2. 验证逻辑复用
// - Schema 可用于前端、后端、CLI
// - 一处定义,多处使用
// 3. 更好的错误信息
// - Zod 提供清晰的验证失败原因
// - TypeScript 错误信息不够友好
答案:
// 扩展 SDK 的方式:
// 1. 添加新的 Schema
// - 在 coreSchemas.ts 中定义
// - 运行生成脚本
// 2. 添加新的 Hook
// - 在 HOOK_EVENTS 中添加
// - 实现钩子逻辑
// 3. 添加新的 MCP 服务器类型
// - 在 McpServerConfigSchema 中添加
// - 实现传输逻辑
答案:
// SDK 稳定性策略:
// 1. 版本化
// - 语义化版本
// - 变更日志
// 2. 向后兼容
// - 不删除字段
// - 不改变字段类型
// 3. 废弃警告
// - 添加 @deprecated 注释
// - 在变更日志中说明
// 4. 测试覆盖
// - Schema 验证测试
// - 类型生成测试
| 文件 | 核心内容 |
| `src/entrypoints/sdk/coreSchemas.ts` | Zod Schema 定义 |
| `src/entrypoints/sdk/coreTypes.ts` | TypeScript 类型 |
| `src/constants/apiLimits.ts` | API 限制常量 |
下一节我们将进入 第十章:实战案例:
- 项目初始化实战
- 代码重构实战
- Bug 修复实战
*- 第一轮:□ 事实准确性*
*- 第二轮:□ 深度与洞见*
*- 第三轮:□ 可读性与价值*