Roo Code

一句话定位

Roo Code 是一个以 VS Code 扩展形态运行的编码 Agent(Cline 的分支),核心是 src/core/task/Task.ts 驱动的栈式任务循环,采用原生 function-calling 工具协议、Mode 系统(Orchestrator/Boomerang 做多任务委派)、Claude-Code 风格 Skills,以及针对 Anthropic 模型的深度请求层适配(prompt caching、extended thinking、:thinking 虚拟模型 ID);项目已于 2026-05-15 正式关停归档,社区分叉为 ZooCode。

核心架构总览

Monorepo(pnpm + turbo),非独立 CLI(虽有 apps/cli 无头封装,见下):

  • src/ — 扩展本体:激活入口、核心 agent 逻辑(src/core/)、工具实现、API provider 适配、服务层(skills/mcp/checkpoints)
  • webview-ui/ — React 聊天面板前端,与 agent 逻辑无关
  • apps/cli/ — 独立无头 CLI(“Roo CLI”),通过 apps/cli/src/agent/extension-host.ts / extension-client.ts 的 IPC shim 复用同一套 src/core 引擎——反映关停前有把 harness 与 VS Code 解耦的尝试
  • apps/docs/ — Docusaurus 文档源(docs.roocode.com)
  • packages/types/ — 共享 Zod schema,含 RooCodeEventName 事件枚举与消息/工具 schema
  • packages/ipc/ — IPC client/server,供 CLI/extension-host 拆分使用
  • packages/corecustomToolRegistryformatNative,被 src/core/task/build-tools.ts 引用
  • 仓库根目录 .roo/commandsrulesrules-<mode>skillsguidance)——Roo Code 用自己的 Mode/Skill/Rule 体系构建自身(dogfooding)

引用 commit:b867ec9145750d0ae1ff7f02d35406e9bf2a0b16(2026-05-15,也是仓库最后一次提交——与官方关停公告日期完全吻合,docs.roocode.com 有 “Extension Shutdown” 横幅,指向社区分叉 ZooCode 与上游 Cline)。本 dossier 所有结论均来自这份最终态、可构建的完整源码,非文档摘要。

Agent Loop(主循环 / 何时继续何时停)

  • 入口 Task.initiateTaskLoop()Task.ts:2427):while (!this.abort) 循环,反复调用 recursivelyMakeClineRequests()Task.ts:2437)。若返回 didEndLoop = true 则外层 break;否则下一轮 user content 被合成为 formatResponse.noToolsUsed()——换言之”继续循环”的信号本质就是”模型没调工具,那就提醒它”。
  • 内层引擎 recursivelyMakeClineRequests()Task.ts:2461)尽管命名带 “recursively”,实际不是递归,而是显式栈机(const stack: StackItem[] = [...]while (stack.length > 0))——从递归重构为迭代栈式实现,代码里残留 “RooCode#recursivelyMakeRooRequests” 之类的错误字符串,暴露出从 “Cline” fork 而来的命名演化痕迹。
  • 循环体内发现的停止条件:
    • consecutiveMistakeCount >= consecutiveMistakeLimit(默认值 DEFAULT_CONSECUTIVE_MISTAKE_LIMIT,字段见 Task.ts:317,构造时可覆盖见 Task.ts:419/484)→ 通过 ask("mistake_limit_reached", ...) 询问用户。
    • consecutiveNoToolUseCount >= 2Task.ts:3487-3494)→ 连续两轮模型不调用任何工具,发出 "MODEL_NO_TOOLS_USED" 错误并计入 mistake 计数。
    • consecutiveNoAssistantMessagesCount >= 2Task.ts:3524-3613)→ 处理空 API 响应;若开启 autoApprovalEnabled 则带退避自动重试,否则询问用户。
    • 每次栈迭代顶部检查 this.abort,命中则抛出以展开栈。
    • Auto-approval 的请求数/费用上限(AutoApprovalHandler,见”安全与权限”)也可暂停/门控推进。
    • attempt_completion 工具(在 presentAssistantMessage.ts 的 switch 中)是模型发出的”我做完了”信号——但源码注释明确说明结构上并不硬性终止于此:“For now a task never ‘completes’. This will only happen if the user hits max requests and denies resetting the count.”,完成更多是靠 prompting(getObjectiveSection())约定俗成,而非代码强制状态机。
  • 子任务暂停/恢复:isPaused 标志——设置后栈循环仍会 push 一个空 item “so the loop continues to the pause check”(Task.ts:3506-3508),使 Orchestrator/Boomerang 委派流程(见”Router / 编排”)能在子任务运行期间挂起父任务。

记忆与上下文管理(压缩、长期记忆、会话持久化)

  • 压缩(“condense”)src/core/condense/index.tssummarizeConversation()(694 行文件的第 254 行)。使用专门的 SUMMARY_PROMPT,明确指示模型 “DO NOT call any tools or functions… Respond with text only”,并把这次总结请求当作独立于用户当前工作的 “SYSTEM OPERATION”。阈值:MIN_CONDENSE_THRESHOLD = 5MAX_CONDENSE_THRESHOLD = 100(占上下文窗口百分比)。
  • 压缩前工具/工具结果块会被转成纯文本(convertToolBlocksToTexttoolUseToTexttoolResultToText)——原因是部分 provider(注释提到 Bedrock)只要历史里出现 tool 块就强制要求同时传 tools 参数;转成文本后压缩阶段就不用重新声明工具 schema。
  • 非破坏性压缩ApiMessage 类型(src/core/task-persistence/apiMessages.ts)携带 condenseId/condenseParenttruncationId/truncationParent 字段——旧消息只是被”标记”为已被取代,只有在发送 API 时若存在有效的 summary/truncation 标记才会被过滤掉。也就是说磁盘上的完整原始历史在”压缩”之后依然完整保留。
  • Folded file contextsrc/core/condense/foldedFileContext.tsgenerateFoldedFileContext() 用 tree-sitter(parseSourceCodeDefinitionsForFile)为对话中读过的文件生成”仅签名、无函数体”的表示,包裹在独立的 <system-reminder> 块中,maxCharacters 默认上限 50000。这段内容在压缩阶段被注入,让模型保留”我见过这个文件的结构”而不必为完整文件体付出 token 成本。
  • 上下文窗口超限处理Task.handleContextWindowExceededError()Task.ts:3717)——读取按 API-profile 分组的 profileThresholds
  • 会话持久化:每个任务目录两个文件(src/shared/globalFileNames.ts):api_conversation_history.json(原始 Anthropic/OpenAI 格式消息数组,经 apiMessages.tsreadApiMessages/saveApiConversationHistory 读写)与 ui_messages.json(面向 UI 的 ClineMessage[] 时间线,say/ask 事件,经 taskMetadata.tscombineApiRequests/combineCommandSequences 组合用于重建 webview)。
  • 推理/思考持久化ApiMessage 还携带各 provider 特有的 reasoning 字段(summaryencrypted_contentreasoning_detailsreasoning_content),用于在多轮工具调用间往返回传 OpenAI o 系列的加密推理、OpenRouter/Gemini 3 的 reasoning_details、DeepSeek/Z.ai 的 reasoning_content——这部分与”模型协同设计”维度有重叠。
  • 未发现长期/跨会话记忆存储:没有向量数据库,没有持久化的 “memory bank” 文件——记忆仅限于单个任务的磁盘 JSON,加上仅在压缩阶段内部使用的 “folded file context”。RooIgnoreController/skills 发现机制会在文件变更时重新扫描,但那是配置而非对话记忆。

工具体系(定义/调用协议/注册/权限)

  • 协议system.ts:74-75 注释明确写道 // Tool calling is native-only.,紧接着 const toolsCatalog = ""——已在源码中直接核实(grep 命中 key-files/prompts-system.ts 第 74/83 行)。确认 Roo Code 已完全迁移出早期的 XML 标签式工具调用解析,改用 OpenAI 风格原生 function-calling(build-tools.ts 中大量使用 OpenAI.Chat.ChatCompletionTool 类型)。Anthropic 请求经 convertOpenAIToolsToAnthropic/convertOpenAIToolChoiceToAnthropicsrc/core/prompts/tools/native-tools/converters.ts,被 anthropic.ts 引用)转换——即工具只用 OpenAI 形态的 schema 定义一次,再按 provider 各自转换。
  • 注册buildNativeToolsArrayWithRestrictions()src/core/task/build-tools.ts:82)汇总三个来源:(a) getNativeTools()src/core/prompts/tools/native-tools/index.ts)提供的内置原生工具;(b) getMcpServerTools(mcpHub) 提供的 MCP 服务器工具;(c) customToolRegistry.loadFromDirectoriesIfStale(toolDirs) 提供的自定义工具,需 experiments?.customTools 开关,工具目录来自 getRooDirectoriesForCwd(cwd)/tools(项目级与全局级 .roo/tools/)。
  • 按 Mode 过滤filterNativeToolsForMode()/filterMcpToolsForMode()src/core/prompts/tools/filter-tools-for-mode.ts,456 行)按当前 Mode 声明的工具”组”(read/edit/command/mcp)过滤工具目录(例如 Architect 模式只拿到 read+mcp+受限于 markdown 的 edit;Orchestrator 不拿这些组,只有 new_task)。还做工具别名解析resolveToolAlias)——如 edit_file 依配置可能别名到 search_and_replace/edit,且对话历史中记录的是别名而非规范名,避免模型对话中途被改名搞混(Task.ts:3392-3396 注释)。
  • 调度src/core/assistant-message/presentAssistantMessage.ts 有一个大的 switch (block.type)"mcp_tool_use" | "text" | "tool_use"),在 "tool_use" 分支内再嵌套一个按 block.nameswitch(一处约 325 行构建审批 UI 用的工具”消息”,另一处约 651 行实际调用各工具的 .execute())。已确认的约 20 个一级工具:execute_commandread_filewrite_to_fileapply_diffapply_patchsearch_filesedit/search_and_replace/search_replace/edit_file(别名族)、list_filesuse_mcp_toolaccess_mcp_resourceask_followup_questionattempt_completionswitch_modecodebase_searchread_command_outputupdate_todo_listnew_taskrun_slash_commandskillgenerate_image
  • 工具类结构:每个工具是继承 BaseTool<"tool_name">src/core/tools/BaseTool.ts)的类,实现 execute(params, task, callbacks)callbacksaskApprovalhandleErrorpushToolResult——即审批门控是分散穿透到每个工具调用里,而非集中在一处。
  • 重复检测src/core/tools/ToolRepetitionDetector.ts,与 mistake 计数机制分离,专门跟踪连续相同的工具调用(用 Task.ts:513 处的 consecutiveMistakeLimit 构造)。

Prompt 设计(系统提示结构、动态组装)

  • 入口 SYSTEM_PROMPT()src/core/prompts/system.ts:112),调用 generatePrompt()(第 41 行)。提示词按固定顺序字符串拼接标注区块(system.ts:85-107):
    1. roleDefinition(Mode 特定人设,如 “A skilled software engineer…“)
    2. markdownFormattingSection()
    3. getSharedToolUseSection() + toolsCatalog显式设为空字符串,因为原生 function-calling 已通过 API 的 tools 参数带外传递工具 schema,不需要内联文本目录——已在源码核实)
    4. getToolUseGuidelinesSection()
    5. getCapabilitiesSection(cwd, mcpHub-若启用)
    6. getModesSection()(异步,与 skills 区块并行 await)
    7. getSkillsSection()(异步,仅非空时加入)
    8. getRulesSection(cwd, settings)
    9. getSystemInfoSection(cwd)
    10. getObjectiveSection()
    11. addCustomInstructions(baseInstructions, globalCustomInstructions, cwd, mode, {language, rooIgnoreInstructions, settings})——用户/项目级 .roorules*AGENTS.md、按 Mode 的自定义指令在此最后合并
  • Mode 感知:getModeSelection(mode, promptComponent, customModeConfigs) 解析 roleDefinition/baseInstructions,允许对内置或自定义 Mode 做完整覆盖(ModeConfigCustomModePrompts,来自 @roo-code/types)。
  • MCP 区块按条件构建:shouldIncludeMcp = hasMcpGroup && hasMcpServers——只有当前 Mode 的工具组包含 "mcp" 至少一个 MCP 服务器实际已连接时才生成,避免无服务器配置时的提示词膨胀。
  • settings: SystemPromptSettings 把若干 feature flag 传入提示词构建:todoListEnableduseAgentRules(VS Code 设置,默认 true)、enableSubfolderRulesnewTaskRequireTodosisStealthModel(针对 OpenRouter 类聚合平台上匿名/隐身模型的提示词变体渲染)。

Router / 编排(任务分解、多 agent、子 agent)

  • Roo Code 的多 agent 机制是 “Orchestrator Mode”(又称 Boomerang Mode/Tasks)——代码与官方文档(docs.roocode.com/features/boomerang-tasks,2026-07-07 抓取)双重确认。
  • 机制:new_task 工具(src/core/tools/NewTaskTool.ts),参数 {mode, message, todos?}。校验 mode+message 存在;若 VS Code 设置 newTaskRequireTodos 开启,还要求 markdown 复选框格式的 todos 参数(经 parseMarkdownChecklist 解析)。调用 task.startSubtask(message, initialTodos, mode)Task.ts:2335),暂停父任务(isPaused)并在目标 Mode 下派生一个拥有独立对话历史的子 Task 实例——不自动继承父任务上下文(官方文档确认:“Context Isolation… does not automatically inherit the parent’s context”;只有初始 message 下传,只有子任务通过 attempt_completion 产出的最终总结上传回父任务)。
  • Task.ts:2361resumeAfterDelegation() 在子任务完成后恢复父任务,推测是把子任务的完成总结作为下一轮 user-content 注入。
  • 委派隔离的强制执行:若模型在同一轮响应里把 new_task 和其他工具一起调用,Task.ts:3408-3437 会截断 new_task 之后列出的所有工具调用,并为它们注入合成的错误 tool_result(提示”因为本轮已调用 new_task 而未执行”)——因为委派会处置/暂停父任务,孤立的工具调用会破坏 API 历史的顺序完整性。
  • Orchestrator 本身是一个内置 Mode,工具组为空集(不含 read/edit/command/mcp)——依官方 FAQ:“Orchestrator mode is intentionally limited… Giving it the ability to read files by default causes the context to become filled with file reads.”。它只能调用 new_task 做委派,这是刻意设计,用于保持编排者自身上下文窗口小且专注于高层级任务排序。
  • 审批:子任务的创建与完成默认都走普通的 askApproval 门(依文档 “Subtasks” 一节,可通过 Auto-Approve 设置自动化)。
  • 未在已读文件中发现子任务嵌套子任务的显式最大深度限制——除了 pause/resume 栈机制外,任何拥有相应工具组的 Mode 理论上都可再调用 new_task 派生下一层子任务,但未找到显式深度守卫代码。

Skill / 插件体系

  • src/services/skills/SkillsManager.ts(719 行)——与 Claude Code 的 Skills 功能高度类似。Skill 从文件系统目录发现:getGlobalRooDirectory()getGlobalAgentsDirectory()getProjectAgentsDirectoryForCwd()(辅助函数来自 ../roo-config)——同时支持通用Skill 目录(skills/)和按 Mode 划分的目录(skills-{mode}/)。
  • 每个 Skill 是一个子目录,元数据经 gray-matter 解析(YAML frontmatter)——SkillMetadata/SkillContent 类型(src/shared/skills.ts)。名称经 validateSkillName/SkillNameValidationError/SKILL_NAME_MAX_LENGTH(来自 @roo-code/types)校验。
  • 显式支持符号链接:顶层 .roo/skills 目录本身与单个 Skill 子目录均可为符号链接;scanSkillsDirectory()fs.realpath() 解析真实路径,但保留符号链接自身的名字作为 Skill 名(使一个被符号链接的共享 Skill 仓库可以在本地”重命名”)。
  • 基于文件监视的实时重载:setupFileWatchers()——Skill 在文件系统变更时重新扫描,无需重启扩展。
  • 调用:src/services/skills/skillInvocation.ts(54 行,较短)+ skill 原生工具(src/core/tools/SkillTool.ts),在 presentAssistantMessage.ts 的工具 switch 中经 case "skill" 调度。
  • 还存在一个独立、更轻量的机制:run_slash_command 工具 + 仓库根目录可见的 .roo/commands/ 目录——slash command 是与 Skills 相区分的更轻概念(一个命令也可以在 frontmatter 中请求切换 Mode,见 Task.ts:2554-2564 注释 “Switch mode if specified in a slash command’s frontmatter”)。
  • 该仓库自身践行 dogfooding:根目录同时存在 .roo/skills.roo/commands.roo/rules.roo/rules-<mode>(code/debug/docs-extractor/issue-fixer/issue-investigator/issue-writer/merge-resolver/pr-fixer/translate)、.roo/guidance——即 Roo Code 团队用 Roo Code 自身的 Skill+Mode+Rule 体系来构建 Roo Code。
  • 文档导航中另有 Marketplace 功能引用,用于分享 Mode/MCP 配置——未深挖代码,仅作为后续阶段的线索标记(未在代码层验证)。

自进化能力(自我改进 / 学习型记忆 / eval 驱动纠错)

未发现自进化、自我改进或 eval 驱动的自纠错机制。src/**/*.ts(排除测试)中搜索 fine-tuning/training-data/RLHF/self-improvement 相关关键词,零命中。

最接近的相邻概念是”Agent Loop”一节提到的连续 mistake 计数机制,但那纯粹是同一会话内的护栏(询问用户/停止循环),不构成跨会话的学习信号。

结论:该维度未实现 / 不适用于此 harness(与其作为人机协同编码助手产品、而非自主/自我改进型 agent 框架的定位一致)。

可观测性(日志 / trace 格式)

  • 事件总线packages/types/src/events.ts 定义 enum RooCodeEventName,约 25 种事件类型,分几类:任务提供者生命周期(TaskCreated)、任务生命周期(TaskStartedTaskCompletedTaskAbortedTaskFocused/UnfocusedTaskActiveTaskInteractiveTaskResumableTaskIdle)、子任务生命周期(TaskPausedTaskUnpausedTaskSpawnedTaskDelegatedTaskDelegationCompletedTaskDelegationResumed)、任务执行(MessageTaskModeSwitchedTaskAskRespondedTaskUserMessageQueuedMessagesUpdated)、任务分析(TaskTokenUsageUpdatedTaskToolFailed)、配置变更(ModeChangedProviderProfileChanged)、查询响应(CommandsResponseModesResponseModelsResponse)。每个事件配有 Zod 元组 schema(rooCodeEventsSchema)——这是 IPC 层(packages/ipc)用来让外部进程(如无头 apps/cli)订阅任务事件的强类型契约。
  • Task 继承 EventEmitter,直接调用 this.emit(RooCodeEventName.TaskStarted) 等(见 Task.ts:2434)。
  • 本次 depth-1 克隆中未发现专门的遥测/分析客户端(如 PostHog)——在 srcpackages 中搜索 posthog/PostHog/TelemetryClient,零命中。(据公开信息 Roo Code 历史上其 monorepo 中曾有云端遥测 package,但本 commit/深度下不存在——可能是关停时被移除,也可能拆分到了未公开的私有 package。此处标注为”本快照中未找到”而非断言”从未存在”。)
  • 磁盘上的 trace 格式:没有独立于”记忆与上下文管理”一节所述两个持久化文件之外的结构化 “trace” 文件——ui_messages.json(顺序排列的 ClineMessage[],含 say/ask 类型,每条带时间戳 ts)是最接近人类/机器可读执行轨迹的东西;api_req_started 消息把协议/费用/token 的 JSON 内联嵌入其 text 字段(见 Task.ts:2660-2669ClineApiReqInfo 结构:tokensIntokensOutcacheWritescacheReadscostcancelReasonstreamingFailedMessage)。
  • 日志:代码中散布 console.log/console.error,加上一个 provider?.log(message) 透传到 VS Code 输出面板(见 checkpoints/index.tslog() 辅助函数)——未发现结构化/分级的日志抽象。

安全与权限(审批门、密钥管理)

  • 审批门(“ask”):每个工具的 execute() 都接收一个 askApproval 回调(从 presentAssistantMessage.ts 穿透传入);这是逐工具调用的人机在环确认提示,在 VS Code webview 中展示——代码与官方文档(auto-approving-actions 页面)双重确认,文档含明确的”安全警告”横幅:“Auto-approve settings bypass confirmation prompts, giving Roo direct access to your system. This can result in data loss, file corruption, or worse.”
  • 自动审批上限AutoApprovalHandlersrc/core/auto-approval/AutoApprovalHandler.ts)即使开启自动审批,也强制两个独立上限:allowedMaxRequests(自上次重置以来的 api_req_started 消息计数)与 allowedMaxCost(经 getApiMetrics)。超出任一上限都会重新询问用户("auto_approval_max_req_reached" ask 类型),即便处于自动审批会话中途。
  • 命令白/黑名单src/core/auto-approval/commands.tsfindLongestPrefixMatch() 实现最长前缀匹配(支持 "*" 通配符),用于判断 execute_command 调用能否跳过审批提示。另有 containsDangerousSubstitution():一个硬编码的正则黑名单,检测 shell 元字符技巧(无论白名单是否匹配都始终需要审批)——包括参数展开操作符 ${var@P}/${var@Q}/${var@E}/${var@A}/${var@a}、间接变量引用 ${!var}、带命令替换的 here-string(<<<$(...))、zsh 进程替换 =(...)、zsh glob 限定符代码执行 *(e:cmd:)
  • 文件写保护src/core/protect/RooProtectedController.ts——静态 glob 模式列表(.rooignore.roomodes.roorules*.clinerules*.roo/**.vscode/***.code-workspaceAGENTS.mdAGENT.md),使用 ignore npm 包(gitignore 语法)对自动审批的编辑始终加以写保护,UI 上以盾牌 emoji(SHIELD_SYMBOL = "🛡")展示。
  • 文件读取/访问门控src/core/ignore/RooIgnoreController.ts——.rooignore 文件(经 ignore 包实现 gitignore 语法)限制 LLM 可读取/访问/引用的文件;文件监视实时更新;还有一个 validateCommand() 方法,在任何 shell 命令执行前由 ExecuteCommandTool 调用(命令文本会被扫描是否引用了被忽略的文件,命中则以 rooignore_error say-event 阻断)。
  • MCP 工具权限McpHub.ts 为每个服务器存储逐工具的 alwaysAllow: string[] 列表(支持 "*" 通配符),从服务器 JSON 配置读取;新工具默认 alwaysAllow: false 除非命中匹配。
  • 密钥管理:本轮未深入(需要读 src/core/config 及 provider-settings 存储层),标记为阶段二待补的空白;已注意到 anthropic.tsapiKeyFieldName 的逻辑(在 apiKeyauthToken 字段间选择),但未追踪底层密钥实际存于何处(推测是 VS Code 标准 SecretStorage API,但本轮未通过读实际存储代码确认)。

沙箱与执行隔离

  • 未发现容器/虚拟机/沙箱层。 execute_commandsrc/core/tools/ExecuteCommandTool.ts)通过 VS Code 集成终端/shell-integration API(src/integrations/terminal/Terminal.tsTerminalProcess.tsTerminalRegistry.ts)直接在宿主机上运行 shell 命令,或以 execa 作为后备路径(ExecaTerminal.tsExecaTerminalProcess.ts——仅目录列表确认,未深读)。
  • 隔离完全依赖”安全与权限”一节所述的审批门 + 白/黑名单 + 受保护文件模式三层,而非操作系统级沙箱(未在已读文件或目录名中发现 seccomp、Docker、VM、chroot 相关引用)。
  • resolveAgentTimeoutMs()ExecuteCommandTool.ts)显示一个 CLI 专用覆盖:当 process.env.ROO_CLI_RUNTIME === "1" 时,忽略模型提供的后台命令超时,改用单一用户配置的 commandExecutionTimeout(注释:“In CLI runtime, stdin harnesses expect command lifetime to be governed solely by commandExecutionTimeout.“)。
  • 检查点作为安全网(非沙箱)src/services/checkpoints/ShadowCheckpointService.ts 使用 simple-git 为每个任务维护一个影子 git 仓库RepoPerTaskCheckpointService extends ShadowCheckpointService),自动提交工作区状态,使用户能回滚 agent 所做的更改——这是可逆性机制,不是预防机制。利用 core.worktree git 配置技巧(shadowGitConfigWorktree)让独立的 .git 指向真实工作树,同时不干扰用户自己的 git 仓库。

与模型的协同设计

  • 仅原生 function-calling——系统提示词显式排除文本工具目录(toolsCatalog = ""system.ts:82-83,已在源码核实),因为工具 schema 经各 provider 的原生 function-calling API 字段传递,不再内联为 XML/文本——这是硬性架构承诺,非逐请求判断。
  • 按 provider 定制请求体src/api/providers/anthropic.ts 展示了深度 Anthropic 特化处理:
    • Prompt caching:对系统提示词和倒数第二条 user 消息应用 cache_control: { type: "ephemeral" }(标准 Anthropic 多轮缓存模式),门控条件是检查模型是否 “supports prompt caching”,并推送 "prompt-caching-2024-07-31" beta header。
    • Extended thinking:透传 reasoning/thinking 参数,把 reasoning_delta/thinking_delta 流事件映射为 "reasoning" 类型的 ApiStream chunk。
    • 模型 ID 处理:claude-3-7-sonnet-20250219:thinking 后缀在发送前被剥离(映射回 claude-3-7-sonnet-20250219),但会触发 betas: ["output-128k-2025-02-19"]——即 Roo 自己模型列表里的一个虚拟/伪模型 ID,映射到真实模型 ID + 一个 beta 功能开关。
    • Beta header fine-grained-tool-streaming-2025-05-14 是默认始终请求的 beta。
    • 代码注释引用了一个公开来源解释该缓存模式:https://x.com/alexalbert__/status/1823751995901272068
  • 跨 provider 推理内容往返ApiMessage(见”记忆与上下文管理”)持久化各 provider 特有的推理产物(OpenAI 加密的 summary/encrypted_content、OpenRouter/Gemini-3 的 reasoning_details 数组、DeepSeek/Z.ai 的 reasoning_content 字符串),使交错思考(interleaved thinking)模型在多轮工具调用序列中保持思维链有效,即便 Roo 内部的对话格式本身是 provider 无关的。
  • isStealthModel 标志被传入系统提示词设置——意味着至少有一条代码路径会为匿名化/隐身模型(例如经 OpenRouter stealth-model 项目提供的模型)渲染不同/精简版提示词,但本轮未追踪具体差异内容。
  • 按 Mode 记忆上次用模型:依文档确认(本轮未在代码层验证)——“Each mode remembers your last-used model… Roo automatically selects that model”,切换 Mode 时自动选用。

轨迹利用(session/trajectory 是否反哺训练/评测)

  • 轨迹(每任务两个 JSON 文件,见”记忆与上下文管理”/“可观测性”)仅用于:(a) IDE 重载后恢复/重建任务(resumeTaskFromHistory()Task.ts:1956);(b) 渲染 webview 历史列表(taskMetadata() 计算大小/费用/时间戳);(c) 检查点/回滚功能(影子 git 仓库,与这两个 JSON 文件是分开的机制)。
  • 未发现任何轨迹被反馈进模型训练、微调或离线 eval harness 的证据。 在遍历过的目录(src/apps/packages/)中未发现 evals/benchmarks/ 目录或数据集导出工具。这与 Roo Code 作为面向产品的 IDE 扩展、而非研究/训练 harness 的定位一致。
  • 鉴于”可观测性”一节中”未发现遥测客户端”的观察以及项目已关停的事实,若曾经存在轨迹反哺训练的管线,很可能存在于一个私有/已移除的 package 中,在这份最终公开快照里缺席——按任务的诚实性要求,此处标注为**“未找到”,而非”确认不存在”**。

与同类 harness 的关键差异(1-3 条)

概述性判断,留待后续 synthesis 阶段做跨 harness 系统对比:

  1. Orchestrator/Boomerang 模式的子任务隔离是严格单向、无自动上下文继承的(仅初始消息下传、仅完成总结上传),比一些同类 harness 更彻底地把”编排者”限制为空工具组的纯调度角色,刻意避免编排者上下文被文件读取污染。
  2. 压缩机制是非破坏性标记式condenseId/truncationId 标记而非删除),原始历史始终完整落盘,这与直接截断/丢弃历史的实现思路不同。
  3. 安全模型完全基于应用层审批门 + 命令黑白名单 + 受保护文件模式,没有任何操作系统级沙箱/容器隔离,回滚安全网依赖 git 影子仓库而非执行前阻断——这使其安全边界弱于有沙箱/容器隔离的 harness。

原始源码定位

  • repo: https://github.com/RooCodeInc/Roo-Code
  • commit/version analyzed: b867ec9145750d0ae1ff7f02d35406e9bf2a0b16(2026-05-15,仓库最后一次提交,与官方关停日期吻合)
  • 关键文件列表(相对路径):
    • src/core/task/Task.ts(4619 行,任务生命周期核心:对话历史、ask/say、流式处理、重试、工具结果、检查点钩子、系统提示词组装、上下文窗口超限处理、限流)
    • src/core/assistant-message/presentAssistantMessage.ts(967 行,逐工具调用的分发器/switch 与 askApproval 接线)
    • src/core/task/build-tools.ts(原生工具数组构建:Mode 过滤、MCP 工具、自定义工具)
    • src/core/prompts/system.ts(系统提示词组装入口 SYSTEM_PROMPT
    • src/core/prompts/tools/filter-tools-for-mode.ts(456 行,按 Mode 的工具允许/拒绝 + 别名解析)
    • src/core/tools/ExecuteCommandTool.ts(shell 执行工具实现)
    • src/core/tools/NewTaskTool.ts(子任务/委派工具实现)
    • src/core/auto-approval/AutoApprovalHandler.ts(请求数/费用上限自动审批门)
    • src/core/auto-approval/commands.ts(命令字符串允许/拒绝列表匹配、危险替换检测)
    • src/core/protect/RooProtectedController.ts(Roo 自身配置文件写保护)
    • src/core/ignore/RooIgnoreController.ts.rooignore 读取/访问门控)
    • src/core/condense/index.ts(694 行,LLM 驱动的上下文摘要/“condense”)
    • src/core/condense/foldedFileContext.ts(tree-sitter 签名折叠文件上下文)
    • src/core/checkpoints/index.tssrc/services/checkpoints/ShadowCheckpointService.tsRepoPerTaskCheckpointService.ts(git 影子仓库检查点/回滚系统)
    • src/core/task-persistence/apiMessages.tstaskMetadata.ts(磁盘会话/轨迹 JSON 持久化)
    • src/shared/globalFileNames.tsapi_conversation_history.jsonui_messages.json 两个规范文件名)
    • src/services/skills/SkillsManager.ts(719 行)、skillInvocation.ts(Claude-Code 风格 Skills 系统)
    • src/services/mcp/McpHub.ts(约 67KB,MCP 服务器注册/连接/工具列表,逐工具 alwaysAllow 配置)
    • packages/types/src/events.tsRooCodeEventName 枚举 + Zod schema,事件/可观测性契约)
    • src/api/providers/anthropic.ts(Anthropic 专用请求构建:prompt caching、extended thinking、beta header、:thinking 模型 ID 处理)
    • 仅目录列表未深读:src/integrations/terminal/*(Terminal.ts、TerminalProcess.ts、ExecaTerminal.ts、ExecaTerminalProcess.ts、TerminalRegistry.ts)、apps/cli/src/agent/*(无头 CLI agent 循环 shim)

一手源存档(sources/)

/Users/zhao/projects/self-wiki/ai-research/sources/harness/roo-code/ 下:

  • NOTES.md(阶段一调研笔记,含 provenance、逐维度发现原文)
  • key-files/(21 个源文件,约 480KB,从上述关键文件裁剪保存,已核实与仓库实际路径的对应关系): Task.tspresentAssistantMessage.tsbuild-tools.ts(存为 build-tools.ts)、filter-tools-for-mode.tsExecuteCommandTool.tsNewTaskTool.tsAutoApprovalHandler.tsauto-approval-commands.ts(= commands.ts)、RooProtectedController.tsRooIgnoreController.tscondense-index.ts(= condense/index.ts)、foldedFileContext.tscheckpoints-index.ts(= checkpoints/index.ts)、ShadowCheckpointService.tsapiMessages.tstaskMetadata.tsglobalFileNames.tsSkillsManager.tsskillInvocation.tsMcpHub.tsevents.tsprompts-system.ts(= src/core/prompts/system.ts)。