本文档详细解析 OpenCode AI 编码助手的主工作流实现。
| 文档 | 内容 |
|---|
| 待思考项记录 | BatchTool 实现、Tools/Skills/MCPs 提示词规划策略 |
┌─────────────────────────────────────────────────────────────────────────────────┐
│ OpenCode 主工作流 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 用户输入 │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Step 1: 用户输入处理 │ │
│ │ - 解析 message-v2 格式 │ │
│ │ - 处理 text/file/agent/mcp_resource parts │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Step 2: Agent 选择 │ │
│ │ - 解析 @agent_name 或 message.agent 字段 │ │
│ │ - 匹配 Agent 配置(name/description/model) │ │
│ │ - 应用 3 层权限合并(defaults/agent/user config) │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Step 3: 加载 Agent 配置 │ │
│ │ - 合并 defaults/agent/session 三层配置 │ │
│ │ - 绑定到消息:agent、model、tools、permission │ │
│ │ - 处理 noReply 模式(hidden agent) │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Step 4: 会话状态检查 │ │
│ │ - 加载 Compaction/Prune 配置 │ │
│ │ - 检查 isOverflow(context - output - buffer) │ │
│ │ - 触发自动 Compaction │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Step 5: System Prompt 组装 │ │
│ │ - environment: 系统上下文(时间、目录、Project Rules、Git Status) │ │
│ │ - skills: Agent 可用 Skill 列表 │ │
│ │ - instructions: Agent 专用指令 │ │
│ │ - reminders: 待办提醒(可选) │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Step 6: Tool List 组装 │ │
│ │ - ToolRegistry.all(): 获取所有工具 │ │
│ │ - resolveTools(): 过滤禁用工具 + MCP 合并 │ │
│ │ - 模型特定过滤(apply_patch vs edit) │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Step 7: 第一次 LLM 调用 │ │
│ │ - streamText(): 流式调用 │ │
│ │ - SessionProcessor: 事件处理(step-finish/tool-call) │ │
│ │ - Doom Loop 检测:3 次重复调用触发确认 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Step 8: Tool 执行 │ │
│ │ - 创建 Tool Part(status=pending) │ │
│ │ - 更新为 running,执行 tool.execute() │ │
│ │ - 2 层权限检查:external_directory + bash │ │
│ │ - 超时/取消处理(AbortSignal) │ │
│ │ - 更新为 completed/error │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Step 9: User Content 组装和第二次 LLM 调用 │ │
│ │ - MessageV2.toModelMessages(): 格式转换 │ │
│ │ - 特殊处理:媒体文件提取、Compaction 占位符 │ │
│ │ - 第二次 LLM 调用,AI 基于 Tool Results 生成回复 │ │
│ │ - 循环控制:结束或继续 │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 返回结果给用户 / 继续循环 │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
| 类型 | 用途 | 可见性 |
|---|
primary | 用户对话 | 用户可见 |
subagent | 子任务处理 | 用户可见(子会话) |
hidden | 系统任务 | 用户不可见 |
用户配置(opencode.yml)
↓ 覆盖
Agent 配置(Agent 定义)
↓ 覆盖
系统默认(src/agent/defaults.ts)
| 机制 | 触发条件 | 作用 |
|---|
| Prune | 每次 step 后 | 删除 40K tokens 前的旧 tool outputs |
| Compaction | 上下文溢出时 | AI 生成对话摘要,替换历史消息 |
Internal (MessageV2.WithParts) ↓
UI (UIMessage)
↓
Model (ModelMessage)