03 SDK 分层架构设计
学习目标
本章要解决什么问题:Cline SDK 为什么分四层?每层承担什么职责?依赖关系如何保证可替换性?
项目实践
四层依赖链
依赖方向:上层依赖下层,下层不依赖上层。这使得每层可以独立替换。
各层职责
| 层 | 职责 | 关键组件 |
|---|---|---|
@cline/shared | 底层类型、工具函数、Hook 契约 | 消息类型、错误定义、工具接口 |
@cline/llms | 提供商集成、模型目录、API 调用 | AnthropicHandler、OpenAiHandler、ModelInfo |
@cline/agents | 无状态 Agent Loop、Hook 系统 | AgentRuntime、Hook 生命周期 |
@cline/core | 有状态编排、Session 生命周期、存储 | 任务管理、上下文管理、持久化 |
AgentRuntime 无状态循环
AgentRuntime(sdk/packages/agents/src/agent-runtime.ts)是 SDK 的核心:
# 伪代码:AgentRuntime 循环class AgentRuntime { async run(input: AgentRunInput): Promise<AgentRunResult> { while (!abort) { // 1. 调用模型 const response = await this.llmProvider.complete(messages)
// 2. 解析工具调用 const toolCalls = parseToolCalls(response)
// 3. 执行工具 for (const call of toolCalls) { const result = await this.executeTool(call) messages.push({ role: "tool", result }) }
// 4. 检查完成条件 if (isComplete(response)) break } return { messages, status: "completed" } }}无状态的含义:AgentRuntime 本身不保存任何对话历史。每次 run() 调用传入完整的消息列表,返回完整的消息列表。Session 生命周期由 @cline/core 层管理。
Hook 系统
AgentRuntime 支持 Hook 系统,允许外部逻辑介入 Agent 循环:
| Hook | 触发时机 | 用途 |
|---|---|---|
beforeRun | 开始执行前 | 初始化资源、验证输入 |
beforeModel | 调用模型前 | 修改消息、切换模型 |
beforeTool | 执行工具前 | 审批检查、工具拦截 |
afterTool | 执行工具后 | 审计日志、结果修改 |
Hook 实现:Hook 是函数数组,按注册顺序依次调用。每个 Hook 可以返回修改后的数据或抛出异常中断流程。
从 SDK 到 CLI 的集成
CLI 应用(sdk/apps/cli/)基于上述四层 SDK 构建:
@cline/shared提供类型定义@cline/llms提供商集成@cline/agents提供 AgentRuntime@cline/core管理 Session 和存储
问题与规避
| 陷阱 | 场景 | 对策 |
|---|---|---|
| 循环依赖 | core 依赖 agents,agents 又依赖 core | 严格分层:agents 不依赖 core,core 依赖 agents |
| 版本不一致 | 四层包版本不同步 | npm workspace 统一管理版本 |
| Hook 异常中断 | Hook 抛出未捕获异常 | AgentRuntime 的 catch 块统一处理 Hook 异常 |
设计取舍
无状态 Agent Loop vs 有状态
| 方案 | 优势 | 代价 |
|---|---|---|
| 无状态 | 易于测试、可并行、可重入 | 需要外部管理状态 |
| 有状态 | 实现简单、状态内置 | 测试困难、状态管理复杂 |
Cline SDK 选择无状态 Agent Loop + 有状态编排:AgentRuntime 本身无状态,由 @cline/core 层负责状态管理。这样可以在不同场景下复用 Agent Loop(如 CLI、Webview、CI/CD),每种场景的状态管理策略可以不同。
分层 vs 一体化
| 方案 | 优势 | 代价 |
|---|---|---|
| 分层 | 每层可独立替换、测试、发布 | 依赖管理复杂、理解成本高 |
| 一体化 | 实现简单、无依赖问题 | 替换任何组件需要重构整体 |
Cline 选择分层,因为目标是在 VS Code 之外也支持 CLI、JetBrains 等多宿主。
参考来源
- Cline 源码:
sdk/ARCHITECTURE.md - Cline 源码:
sdk/packages/agents/src/agent-runtime.ts - Cline 源码:
sdk/packages/shared/src/