第四节:SDK API 设计
接口设计与扩展机制

作者:小学子 📚 | 日期:2026年4月2日 | 第九阶段 · 模块九


# 第九阶段 · 模块九 · 第四节:SDK API 设计

核心问题

Claude Code 的 SDK API 是如何设计的?核心类型和 Schema 是什么?SDK 的设计哲学是什么?


◇ 本节位置


        Claude Code 全局架构
        
        ┌─────────────────────────────────────────────────────────────────────┐
        │  高级主题                                                            │
        │                                                                      │
        │  SDK API 设计 ← 本节                                               │
        │  ├── coreSchemas ──> Zod Schema 定义                              │
        │  ├── coreTypes ──> TypeScript 类型生成                             │
        │  └── 设计模式 ──> Schema-first                                   │
        └─────────────────────────────────────────────────────────────────────┘
        


一、SDK 架构概述

1.1 SDK 分层


        ┌─────────────────────────────────────────────────────────────────────┐
        │  SDK 消费者                                                          │
        │  - Web UI                                                           │
        │  - CLI                                                              │
        │  - 第三方集成                                                        │
        └─────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
        ┌─────────────────────────────────────────────────────────────────────┐
        │  SDK Core                                                           │
        │  - coreSchemas.ts(Zod Schema)                                    │
        │  - coreTypes.ts(TypeScript 类型)                                 │
        │  - 控制平面 Schema                                                  │
        └─────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
        ┌─────────────────────────────────────────────────────────────────────┐
        │  运行时                                                              │
        │  - Zod 验证                                                          │
        │  - 类型生成                                                          │
        └─────────────────────────────────────────────────────────────────────┘
        

1.2 设计哲学

源码位置:`src/entrypoints/sdk/coreSchemas.ts`


        // Schema-first 设计
        
        // 1. Zod Schema 是单一数据源
        // 2. TypeScript 类型从 Schema 自动生成
        // 3. 不允许手动修改生成的类型文件
        
        // 工作流程:
        // 1. 编辑 Zod schemas
        // 2. 运行生成脚本
        // 3. 提交生成的类型文件
        

1.3 五问分析

问 1:为什么要用 Schema-first 设计?


        // Schema-first 的优势:
        
        // 1. 类型安全
        // - Schema 验证运行时
        // - TypeScript 验证编译时
        // - 双重保障
        
        // 2. 代码生成
        // - 自动化减少手工错误
        // - 保证类型和 Schema 一致
        
        // 3. 文档化
        // - Schema 本身就是文档
        // - 包含描述信息
        
        // 4. 可验证
        // - 运行时检查输入
        // - 清晰的错误信息
        


二、核心 Schema

2.1 ModelUsage Schema

源码位置:`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(),
          }),
        )
        

2.2 ThinkingConfig Schema


        export const ThinkingConfigSchema = lazySchema(() =>
          z.union([
            ThinkingAdaptiveSchema(),    // { type: 'adaptive' }
            ThinkingEnabledSchema(),     // { type: 'enabled', budgetTokens: number }
            ThinkingDisabledSchema(),    // { type: 'disabled' }
          ])
        )
        

2.3 五问分析

问 1:为什么使用 lazySchema?


        // lazySchema = 延迟加载 Schema
        
        // 原因:
        // 1. 避免循环依赖
        // 2. 改善构建性能
        // 3. 支持 Schema 组合
        
        // 例如:
        // A 引用 B,B 引用 A
        // 使用 lazySchema 避免无限递归
        


三、MCP Server 配置 Schema

3.1 MCP 服务器类型

源码位置:`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(),
          }),
        )
        

3.2 传输类型对比

类型使用场景特点
stdio本地进程简单、安全
SSE远程服务器实时推送
HTTPREST API通用
sdk进程内通信最高性能

3.3 五问分析

问 1:为什么需要多种 MCP 传输类型?


        // 不同场景需要不同传输:
        
        // 1. stdio
        // - 本地 MCP 服务器
        // - 安全隔离
        // - 简单部署
        
        // 2. SSE
        // - 需要服务器推送
        // - 实时更新
        // - 网络通信
        
        // 3. HTTP
        // - 标准 REST API
        // - 兼容性强
        // - 无状态
        


四、API 限制常量

4.1 限制定义

源码位置:`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
        

4.2 限制层级


        // 限制层级:
        
        // 1. API 限制(服务端)
        // - Anthropic API 强制
        // - 不可绕过
        
        // 2. SDK 限制(客户端)
        // - Claude Code 添加
        // - 可配置
        
        // 3. 本地限制(用户)
        // - 用户可自定义
        // - 环境变量
        

4.3 五问分析

问 1:如何调整 API 限制?


        // 调整限制的方式:
        
        // 1. 环境变量
        MAX_TOKENS=16000
        
        // 2. 配置文件
        // settings.json 中设置
        
        // 3. 运行时参数
        claude --print --max-tokens 20000
        


五、Hook 事件类型

5.1 事件列表

源码位置:`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
        

5.2 事件分类


        // 生命周期事件
        SessionStart, SessionEnd, Setup
        
        // 工具事件
        PreToolUse, PostToolUse, PostToolUseFailure
        
        // 任务事件
        TaskCreated, TaskCompleted, SubagentStart, SubagentStop
        
        // 权限事件
        PermissionRequest, PermissionDenied
        
        // 界面事件
        Notification, Elicitation, ElicitationResult
        
        // 工作目录事件
        CwdChanged, FileChanged, WorktreeCreate, WorktreeRemove
        

5.3 五问分析

问 1:Hook 事件有什么用?


        // Hook 事件的应用:
        
        // 1. 监控
        // - 记录所有工具调用
        // - 统计使用情况
        
        // 2. 拦截
        // - 在工具执行前检查
        // - 修改工具参数
        
        // 3. 通知
        // - 任务完成通知
        // - 进度更新
        


六、Exit 原因

6.1 退出原因列表

源码位置:`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
        

6.2 五问分析

问 1:为什么需要退出原因?


        // 退出原因的作用:
        
        // 1. 调试
        // - 了解会话如何结束
        // - 排查异常退出
        
        // 2. 统计
        // - 分析用户行为
        // - 优化产品
        
        // 3. 恢复
        // - 决定是否保存状态
        // - 确定恢复策略
        


七、设计模式

7.1 Zod Schema 最佳实践


        // 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())
        

7.2 类型生成


        // 生成流程:
        
        // 1. 编辑 Schema
        // src/entrypoints/sdk/coreSchemas.ts
        
        // 2. 运行生成脚本
        // bun scripts/generate-sdk-types.ts
        
        // 3. 提交生成的文件
        // src/entrypoints/sdk/coreTypes.generated.ts
        

7.3 五问分析

问 1:Schema-first 的缺点是什么?


        // Schema-first 的缺点:
        
        // 1. 复杂性
        // - 需要额外的生成步骤
        // - 调试困难
        
        // 2. 延迟
        // - Schema 变更需要重新生成
        // - 迭代变慢
        
        // 3. 学习曲线
        // - 需要了解 Zod
        // - 需要了解代码生成
        


八、思考题

思考题 1:为什么 Claude Code 选择 Zod 而不是 TypeScript 原生类型?

答案


        // Zod 的优势:
        
        // 1. 运行时验证
        // - TypeScript 只在编译时检查
        // - Zod 在运行时也检查
        // - 网络输入必须有运行时验证
        
        // 2. 验证逻辑复用
        // - Schema 可用于前端、后端、CLI
        // - 一处定义,多处使用
        
        // 3. 更好的错误信息
        // - Zod 提供清晰的验证失败原因
        // - TypeScript 错误信息不够友好
        


思考题 2:如何扩展 SDK?

答案


        // 扩展 SDK 的方式:
        
        // 1. 添加新的 Schema
        // - 在 coreSchemas.ts 中定义
        // - 运行生成脚本
        
        // 2. 添加新的 Hook
        // - 在 HOOK_EVENTS 中添加
        // - 实现钩子逻辑
        
        // 3. 添加新的 MCP 服务器类型
        // - 在 McpServerConfigSchema 中添加
        // - 实现传输逻辑
        


思考题 3:SDK 稳定性如何保证?

答案


        // 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 修复实战


*- 第一轮:□ 事实准确性*

*- 第二轮:□ 深度与洞见*

*- 第三轮:□ 可读性与价值*