第三部分:能力接缝模块群
以下为 dsh 能力接缝模块群的深度分析,涵盖 llm、shell、subprocess、fs、web、lsp、terminal、code-runtime、sandbox、skill、subagent、workflow、compaction、e2b、mcp 十五个模块。
1. LLM 适配层(llm)
路径 :packages/llm/llm/src/
核心作用 :定义提供商中立的 LLM 运行时抽象------流式调用、块组装、品牌 ID、重试策略、不变式验证。所有 LLM 提供商(如 deepseek、openai)通过实现 LlmAdapter 接口接入。
内部架构
#mermaid-svg-bu7y7WsO9unvmVs1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bu7y7WsO9unvmVs1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bu7y7WsO9unvmVs1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bu7y7WsO9unvmVs1 .error-icon{fill:#552222;}#mermaid-svg-bu7y7WsO9unvmVs1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bu7y7WsO9unvmVs1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bu7y7WsO9unvmVs1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bu7y7WsO9unvmVs1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bu7y7WsO9unvmVs1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bu7y7WsO9unvmVs1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bu7y7WsO9unvmVs1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bu7y7WsO9unvmVs1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bu7y7WsO9unvmVs1 .marker.cross{stroke:#333333;}#mermaid-svg-bu7y7WsO9unvmVs1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bu7y7WsO9unvmVs1 p{margin:0;}#mermaid-svg-bu7y7WsO9unvmVs1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bu7y7WsO9unvmVs1 .cluster-label text{fill:#333;}#mermaid-svg-bu7y7WsO9unvmVs1 .cluster-label span{color:#333;}#mermaid-svg-bu7y7WsO9unvmVs1 .cluster-label span p{background-color:transparent;}#mermaid-svg-bu7y7WsO9unvmVs1 .label text,#mermaid-svg-bu7y7WsO9unvmVs1 span{fill:#333;color:#333;}#mermaid-svg-bu7y7WsO9unvmVs1 .node rect,#mermaid-svg-bu7y7WsO9unvmVs1 .node circle,#mermaid-svg-bu7y7WsO9unvmVs1 .node ellipse,#mermaid-svg-bu7y7WsO9unvmVs1 .node polygon,#mermaid-svg-bu7y7WsO9unvmVs1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bu7y7WsO9unvmVs1 .rough-node .label text,#mermaid-svg-bu7y7WsO9unvmVs1 .node .label text,#mermaid-svg-bu7y7WsO9unvmVs1 .image-shape .label,#mermaid-svg-bu7y7WsO9unvmVs1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-bu7y7WsO9unvmVs1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-bu7y7WsO9unvmVs1 .rough-node .label,#mermaid-svg-bu7y7WsO9unvmVs1 .node .label,#mermaid-svg-bu7y7WsO9unvmVs1 .image-shape .label,#mermaid-svg-bu7y7WsO9unvmVs1 .icon-shape .label{text-align:center;}#mermaid-svg-bu7y7WsO9unvmVs1 .node.clickable{cursor:pointer;}#mermaid-svg-bu7y7WsO9unvmVs1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-bu7y7WsO9unvmVs1 .arrowheadPath{fill:#333333;}#mermaid-svg-bu7y7WsO9unvmVs1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bu7y7WsO9unvmVs1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bu7y7WsO9unvmVs1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bu7y7WsO9unvmVs1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bu7y7WsO9unvmVs1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bu7y7WsO9unvmVs1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-bu7y7WsO9unvmVs1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bu7y7WsO9unvmVs1 .cluster text{fill:#333;}#mermaid-svg-bu7y7WsO9unvmVs1 .cluster span{color:#333;}#mermaid-svg-bu7y7WsO9unvmVs1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-bu7y7WsO9unvmVs1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bu7y7WsO9unvmVs1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-bu7y7WsO9unvmVs1 .icon-shape,#mermaid-svg-bu7y7WsO9unvmVs1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bu7y7WsO9unvmVs1 .icon-shape p,#mermaid-svg-bu7y7WsO9unvmVs1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-bu7y7WsO9unvmVs1 .icon-shape .label rect,#mermaid-svg-bu7y7WsO9unvmVs1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bu7y7WsO9unvmVs1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bu7y7WsO9unvmVs1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bu7y7WsO9unvmVs1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-bu7y7WsO9unvmVs1 .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-bu7y7WsO9unvmVs1 .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-bu7y7WsO9unvmVs1 .def tspan{fill:#fff!important;}#mermaid-svg-bu7y7WsO9unvmVs1 .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-bu7y7WsO9unvmVs1 .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-bu7y7WsO9unvmVs1 .prov tspan{fill:#fff!important;}#mermaid-svg-bu7y7WsO9unvmVs1 .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-bu7y7WsO9unvmVs1 .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-bu7y7WsO9unvmVs1 .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
registerAdapter
stream/call
ctx.llm.stream
间接通过 Agent
LlmRuntime (Service)
LlmAdapter (abstract)
BlockAssembler
types.ts / brand.ts / content.ts
LlmAdapter 实现
(deepseek, openai 等)
Agent 主循环
模型工具层
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
LlmRuntime |
Service (class) | 注册 LLM 适配器,提供 stream() / call() 入口,管理适配器注册表 |
LlmAdapter |
abstract class | LLM 提供商实现的抽象接口:流式请求、非流式请求、模型信息解析 |
BlockAssembler |
class | 将流式增量块组装为完整 ContentBlock,处理部分 JSON 和工具调用拼接 |
MessageId / CallId / StreamId |
Brand types | 品牌化 ID 类型,确保消息/调用/流的全链路追踪 |
RetryPolicy |
class | LLM 调用重试策略:指数退避、最大重试次数、可重试错误判定 |
LlmCallConfig |
interface | 一次 LLM 调用的配置:provider、model、temperature、maxTokens 等 |
ContentBlock |
type union | 统一的内容块类型:text、tool_use、tool_result、thinking 等 |
HarnessError |
class | 分类错误基类,携带 machine-routable code |
assertNever() |
function | 闭联集穷尽性守卫 |
LlmAdapterFailure |
class | 适配器失败包装类 |
与其他模块的关系
- agent :Agent 主循环通过
ctx.llm.stream()发起 LLM 请求。 - session:消息和调用 ID 品牌类型用于会话事件追踪。
- compaction :压缩后端通过
ctx.llm.stream()生成摘要。 - subagent:子代理通过 Agent 间接使用 LLM 运行时。
- skill :技能内容通过
createUserMessage()进入 LLM 消息流。 - tools (dsh-tools):工具定义的
output.render()产出ContentBlock。
2. Shell 执行能力(shell)
路径 :packages/shell/
核心作用:定义 Shell 执行的抽象服务,支持多后端(bash-local、bash-sandbox、pwsh-local、pwsh-sandbox),为模型工具(tool-bash、tool-bash-persistent、tool-pwsh)提供命令执行入口。
内部架构
#mermaid-svg-mdD5f33ZsiwP9WXw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mdD5f33ZsiwP9WXw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mdD5f33ZsiwP9WXw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mdD5f33ZsiwP9WXw .error-icon{fill:#552222;}#mermaid-svg-mdD5f33ZsiwP9WXw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mdD5f33ZsiwP9WXw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mdD5f33ZsiwP9WXw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mdD5f33ZsiwP9WXw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mdD5f33ZsiwP9WXw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mdD5f33ZsiwP9WXw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mdD5f33ZsiwP9WXw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mdD5f33ZsiwP9WXw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mdD5f33ZsiwP9WXw .marker.cross{stroke:#333333;}#mermaid-svg-mdD5f33ZsiwP9WXw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mdD5f33ZsiwP9WXw p{margin:0;}#mermaid-svg-mdD5f33ZsiwP9WXw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mdD5f33ZsiwP9WXw .cluster-label text{fill:#333;}#mermaid-svg-mdD5f33ZsiwP9WXw .cluster-label span{color:#333;}#mermaid-svg-mdD5f33ZsiwP9WXw .cluster-label span p{background-color:transparent;}#mermaid-svg-mdD5f33ZsiwP9WXw .label text,#mermaid-svg-mdD5f33ZsiwP9WXw span{fill:#333;color:#333;}#mermaid-svg-mdD5f33ZsiwP9WXw .node rect,#mermaid-svg-mdD5f33ZsiwP9WXw .node circle,#mermaid-svg-mdD5f33ZsiwP9WXw .node ellipse,#mermaid-svg-mdD5f33ZsiwP9WXw .node polygon,#mermaid-svg-mdD5f33ZsiwP9WXw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mdD5f33ZsiwP9WXw .rough-node .label text,#mermaid-svg-mdD5f33ZsiwP9WXw .node .label text,#mermaid-svg-mdD5f33ZsiwP9WXw .image-shape .label,#mermaid-svg-mdD5f33ZsiwP9WXw .icon-shape .label{text-anchor:middle;}#mermaid-svg-mdD5f33ZsiwP9WXw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mdD5f33ZsiwP9WXw .rough-node .label,#mermaid-svg-mdD5f33ZsiwP9WXw .node .label,#mermaid-svg-mdD5f33ZsiwP9WXw .image-shape .label,#mermaid-svg-mdD5f33ZsiwP9WXw .icon-shape .label{text-align:center;}#mermaid-svg-mdD5f33ZsiwP9WXw .node.clickable{cursor:pointer;}#mermaid-svg-mdD5f33ZsiwP9WXw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mdD5f33ZsiwP9WXw .arrowheadPath{fill:#333333;}#mermaid-svg-mdD5f33ZsiwP9WXw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mdD5f33ZsiwP9WXw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mdD5f33ZsiwP9WXw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mdD5f33ZsiwP9WXw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mdD5f33ZsiwP9WXw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mdD5f33ZsiwP9WXw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mdD5f33ZsiwP9WXw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mdD5f33ZsiwP9WXw .cluster text{fill:#333;}#mermaid-svg-mdD5f33ZsiwP9WXw .cluster span{color:#333;}#mermaid-svg-mdD5f33ZsiwP9WXw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mdD5f33ZsiwP9WXw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mdD5f33ZsiwP9WXw rect.text{fill:none;stroke-width:0;}#mermaid-svg-mdD5f33ZsiwP9WXw .icon-shape,#mermaid-svg-mdD5f33ZsiwP9WXw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mdD5f33ZsiwP9WXw .icon-shape p,#mermaid-svg-mdD5f33ZsiwP9WXw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mdD5f33ZsiwP9WXw .icon-shape .label rect,#mermaid-svg-mdD5f33ZsiwP9WXw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mdD5f33ZsiwP9WXw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mdD5f33ZsiwP9WXw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mdD5f33ZsiwP9WXw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-mdD5f33ZsiwP9WXw .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-mdD5f33ZsiwP9WXw .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-mdD5f33ZsiwP9WXw .def tspan{fill:#fff!important;}#mermaid-svg-mdD5f33ZsiwP9WXw .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-mdD5f33ZsiwP9WXw .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-mdD5f33ZsiwP9WXw .prov tspan{fill:#fff!important;}#mermaid-svg-mdD5f33ZsiwP9WXw .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-mdD5f33ZsiwP9WXw .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-mdD5f33ZsiwP9WXw .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
注册
注册
注册
注册
ctx.shell.exec
ctx.shell.exec
ctx.shell.exec
ShellExecutor (Service)
types.ts / render.ts / invariant.ts
bash-local
(本地 Bash)
bash-sandbox
(沙箱 Bash)
pwsh-local
(本地 PowerShell)
pwsh-sandbox
(沙箱 PowerShell)
shell-env
(环境注册表)
tool-bash
(一次性 Bash 工具)
tool-bash-persistent
(持久 Bash 工具)
tool-pwsh
(PowerShell 工具)
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
ShellExecutor |
Service (class) | Shell 执行服务定义,声明 exec() 抽象方法,管理生命周期 |
BashLocalProvider |
provider class | 本地 Bash 执行后端,直接调用 /bin/bash |
BashSandboxProvider |
provider class | 沙箱 Bash 后端,通过沙箱隔离执行 |
PwshLocalProvider |
provider class | 本地 PowerShell 后端 |
PwshSandboxProvider |
provider class | 沙箱 PowerShell 后端 |
ShellEnvRegistry |
class | Shell 环境变量注册表,合并系统与用户配置 |
ShellRender |
function | 将 stdout/stderr 渲染为模型可读文本 |
background.ts (tool-bash) |
module | 后台 Shell 进程管理:启动、轮询、终止 |
ShellInvariant |
function | Shell 执行前置/后置不变式校验 |
与其他模块的关系
- sandbox :
bash-sandbox/pwsh-sandbox依赖SandboxProvider进行隔离执行。 - terminal :
terminal-bash后端复用 Shell 执行能力。 - fs :Shell 命令的文件操作通过
ctx.fs统一审计。 - subprocess:Shell 执行底层依赖子进程能力。
3. 子进程能力(subprocess)
路径 :packages/subprocess/
核心作用:定义子进程生命周期的抽象运行时------spawn、等待退出、终止、终端会话。支持本地和远程(E2B)后端。
内部架构
#mermaid-svg-n4r3dHx06ekoRzkn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-n4r3dHx06ekoRzkn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-n4r3dHx06ekoRzkn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-n4r3dHx06ekoRzkn .error-icon{fill:#552222;}#mermaid-svg-n4r3dHx06ekoRzkn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-n4r3dHx06ekoRzkn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-n4r3dHx06ekoRzkn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-n4r3dHx06ekoRzkn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-n4r3dHx06ekoRzkn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-n4r3dHx06ekoRzkn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-n4r3dHx06ekoRzkn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-n4r3dHx06ekoRzkn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-n4r3dHx06ekoRzkn .marker.cross{stroke:#333333;}#mermaid-svg-n4r3dHx06ekoRzkn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-n4r3dHx06ekoRzkn p{margin:0;}#mermaid-svg-n4r3dHx06ekoRzkn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-n4r3dHx06ekoRzkn .cluster-label text{fill:#333;}#mermaid-svg-n4r3dHx06ekoRzkn .cluster-label span{color:#333;}#mermaid-svg-n4r3dHx06ekoRzkn .cluster-label span p{background-color:transparent;}#mermaid-svg-n4r3dHx06ekoRzkn .label text,#mermaid-svg-n4r3dHx06ekoRzkn span{fill:#333;color:#333;}#mermaid-svg-n4r3dHx06ekoRzkn .node rect,#mermaid-svg-n4r3dHx06ekoRzkn .node circle,#mermaid-svg-n4r3dHx06ekoRzkn .node ellipse,#mermaid-svg-n4r3dHx06ekoRzkn .node polygon,#mermaid-svg-n4r3dHx06ekoRzkn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-n4r3dHx06ekoRzkn .rough-node .label text,#mermaid-svg-n4r3dHx06ekoRzkn .node .label text,#mermaid-svg-n4r3dHx06ekoRzkn .image-shape .label,#mermaid-svg-n4r3dHx06ekoRzkn .icon-shape .label{text-anchor:middle;}#mermaid-svg-n4r3dHx06ekoRzkn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-n4r3dHx06ekoRzkn .rough-node .label,#mermaid-svg-n4r3dHx06ekoRzkn .node .label,#mermaid-svg-n4r3dHx06ekoRzkn .image-shape .label,#mermaid-svg-n4r3dHx06ekoRzkn .icon-shape .label{text-align:center;}#mermaid-svg-n4r3dHx06ekoRzkn .node.clickable{cursor:pointer;}#mermaid-svg-n4r3dHx06ekoRzkn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-n4r3dHx06ekoRzkn .arrowheadPath{fill:#333333;}#mermaid-svg-n4r3dHx06ekoRzkn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-n4r3dHx06ekoRzkn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-n4r3dHx06ekoRzkn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-n4r3dHx06ekoRzkn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-n4r3dHx06ekoRzkn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-n4r3dHx06ekoRzkn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-n4r3dHx06ekoRzkn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-n4r3dHx06ekoRzkn .cluster text{fill:#333;}#mermaid-svg-n4r3dHx06ekoRzkn .cluster span{color:#333;}#mermaid-svg-n4r3dHx06ekoRzkn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-n4r3dHx06ekoRzkn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-n4r3dHx06ekoRzkn rect.text{fill:none;stroke-width:0;}#mermaid-svg-n4r3dHx06ekoRzkn .icon-shape,#mermaid-svg-n4r3dHx06ekoRzkn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-n4r3dHx06ekoRzkn .icon-shape p,#mermaid-svg-n4r3dHx06ekoRzkn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-n4r3dHx06ekoRzkn .icon-shape .label rect,#mermaid-svg-n4r3dHx06ekoRzkn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-n4r3dHx06ekoRzkn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-n4r3dHx06ekoRzkn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-n4r3dHx06ekoRzkn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-n4r3dHx06ekoRzkn .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-n4r3dHx06ekoRzkn .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-n4r3dHx06ekoRzkn .def tspan{fill:#fff!important;}#mermaid-svg-n4r3dHx06ekoRzkn .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-n4r3dHx06ekoRzkn .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-n4r3dHx06ekoRzkn .prov tspan{fill:#fff!important;}#mermaid-svg-n4r3dHx06ekoRzkn .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-n4r3dHx06ekoRzkn .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-n4r3dHx06ekoRzkn .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
注册
注册
ctx.subprocess.spawn
ctx.subprocess.spawnTerminal
ctx.subprocess
SubprocessRuntime (Service)
types.ts
spawn.ts (本地 spawn 实现)
subprocess-local
(本地子进程)
subprocess-e2b
(E2B 远程子进程)
shell Providers
terminal-bash 后端
code-runtime worker
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
SubprocessRuntime |
Service (abstract) | 子进程运行时服务定义:spawn()、spawnTerminal()、resolveExecutable() |
SubprocessHandle |
interface | 子进程句柄:wait()、terminate()、kill()、stdin/stdout/stderr 流 |
SubprocessSpawnSpec |
interface | spawn 参数:argv、env、cwd、graceMs、signal |
SubprocessTerminalHandle |
interface | 终端会话句柄:resize()、write()、输出流 |
LocalSubprocessRuntime |
class | 本地子进程实现,基于 Node.js child_process |
E2BSubprocessRuntime |
class | E2B 远程子进程实现,通过共享沙箱执行 |
spawn() (local) |
function | 本地 spawn 核心逻辑:进程创建、信号处理、优雅终止 |
与其他模块的关系
- shell:Shell Provider 是 subprocess 的主要消费者。
- terminal :终端后端通过
spawnTerminal()创建 PTY 会话。 - e2b :
subprocess-e2b将子进程操作映射到远程 E2B 沙箱。 - code-runtime:代码运行时的 worker-thread 通过子进程能力管理。
4. 文件系统能力(fs)
路径 :packages/fs/
核心作用:定义文件系统抽象接口------路径解析、读写、编辑、目录列举、流式读取。支持本地文件系统和 E2B 远程文件系统,沙箱环境下提供路径隔离。
内部架构
#mermaid-svg-fsi63mY76LUMWRw7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fsi63mY76LUMWRw7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fsi63mY76LUMWRw7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fsi63mY76LUMWRw7 .error-icon{fill:#552222;}#mermaid-svg-fsi63mY76LUMWRw7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fsi63mY76LUMWRw7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fsi63mY76LUMWRw7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fsi63mY76LUMWRw7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fsi63mY76LUMWRw7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fsi63mY76LUMWRw7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fsi63mY76LUMWRw7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fsi63mY76LUMWRw7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fsi63mY76LUMWRw7 .marker.cross{stroke:#333333;}#mermaid-svg-fsi63mY76LUMWRw7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fsi63mY76LUMWRw7 p{margin:0;}#mermaid-svg-fsi63mY76LUMWRw7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-fsi63mY76LUMWRw7 .cluster-label text{fill:#333;}#mermaid-svg-fsi63mY76LUMWRw7 .cluster-label span{color:#333;}#mermaid-svg-fsi63mY76LUMWRw7 .cluster-label span p{background-color:transparent;}#mermaid-svg-fsi63mY76LUMWRw7 .label text,#mermaid-svg-fsi63mY76LUMWRw7 span{fill:#333;color:#333;}#mermaid-svg-fsi63mY76LUMWRw7 .node rect,#mermaid-svg-fsi63mY76LUMWRw7 .node circle,#mermaid-svg-fsi63mY76LUMWRw7 .node ellipse,#mermaid-svg-fsi63mY76LUMWRw7 .node polygon,#mermaid-svg-fsi63mY76LUMWRw7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fsi63mY76LUMWRw7 .rough-node .label text,#mermaid-svg-fsi63mY76LUMWRw7 .node .label text,#mermaid-svg-fsi63mY76LUMWRw7 .image-shape .label,#mermaid-svg-fsi63mY76LUMWRw7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-fsi63mY76LUMWRw7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fsi63mY76LUMWRw7 .rough-node .label,#mermaid-svg-fsi63mY76LUMWRw7 .node .label,#mermaid-svg-fsi63mY76LUMWRw7 .image-shape .label,#mermaid-svg-fsi63mY76LUMWRw7 .icon-shape .label{text-align:center;}#mermaid-svg-fsi63mY76LUMWRw7 .node.clickable{cursor:pointer;}#mermaid-svg-fsi63mY76LUMWRw7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fsi63mY76LUMWRw7 .arrowheadPath{fill:#333333;}#mermaid-svg-fsi63mY76LUMWRw7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fsi63mY76LUMWRw7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fsi63mY76LUMWRw7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fsi63mY76LUMWRw7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fsi63mY76LUMWRw7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fsi63mY76LUMWRw7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fsi63mY76LUMWRw7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fsi63mY76LUMWRw7 .cluster text{fill:#333;}#mermaid-svg-fsi63mY76LUMWRw7 .cluster span{color:#333;}#mermaid-svg-fsi63mY76LUMWRw7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fsi63mY76LUMWRw7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fsi63mY76LUMWRw7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-fsi63mY76LUMWRw7 .icon-shape,#mermaid-svg-fsi63mY76LUMWRw7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fsi63mY76LUMWRw7 .icon-shape p,#mermaid-svg-fsi63mY76LUMWRw7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fsi63mY76LUMWRw7 .icon-shape .label rect,#mermaid-svg-fsi63mY76LUMWRw7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fsi63mY76LUMWRw7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fsi63mY76LUMWRw7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fsi63mY76LUMWRw7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-fsi63mY76LUMWRw7 .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-fsi63mY76LUMWRw7 .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-fsi63mY76LUMWRw7 .def tspan{fill:#fff!important;}#mermaid-svg-fsi63mY76LUMWRw7 .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-fsi63mY76LUMWRw7 .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-fsi63mY76LUMWRw7 .prov tspan{fill:#fff!important;}#mermaid-svg-fsi63mY76LUMWRw7 .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-fsi63mY76LUMWRw7 .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-fsi63mY76LUMWRw7 .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
注册
注册
注册
ctx.fs.*
ctx.fs.*
FileSystem (abstract)
types.ts (FsTarget, FsInfo, FsError)
fs-local
(本地文件系统)
fs-sandbox
(沙箱文件系统)
fs-e2b
(E2B 远程文件系统)
tool-fs
(模型文件工具)
skill-filesystem
(技能文件发现)
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
FileSystem |
abstract class | 文件系统服务定义:resolve()、stat()、readText()、readBytes()、writeText()、editText()、listDir()、streamText() |
FsTarget |
interface | 路径解析结果:targetKey + displayPath,解耦显示路径与后端路径 |
FsInfo |
interface | 文件/目录信息:类型、大小、版本 |
FsVersion |
brand type | 文件版本标识,用于乐观并发控制 |
FsError |
class | 文件系统错误类,携带稳定错误码(FS_NOT_FOUND、FS_PERMISSION_DENIED 等) |
FsWriteIntent |
type | 写入意图:createIfAbsent 或 replaceIfVersion |
FsEditRequest |
interface | 编辑请求:oldString、newString、replaceAll |
LocalFileSystem |
class | 本地 FS 实现,直接使用 Node.js fs 模块 |
SandboxedFileSystem |
class | 沙箱 FS 实现,路径隔离与权限检查 |
E2BFileSystem |
class | E2B 远程 FS 实现,通过共享沙箱的文件 API 操作 |
tool-fs |
tool | 模型工具:read_file、write_file、edit_file、list_directory |
与其他模块的关系
- sandbox :
fs-sandbox依赖SandboxProvider进行路径隔离。 - e2b :
fs-e2b依赖ctx.e2b.getSandbox()获取远程沙箱句柄。 - skill :
skill-filesystem通过ctx.fs读取技能文件(当 FS 服务存在时)。 - shell :Shell 命令的文件操作通过
ctx.fs统一审计。 - compaction:压缩后端读取会话事件中的文件操作记录。
5. Web 搜索/抓取能力(web)
路径 :packages/web/
核心作用 :定义 Web 搜索和页面抓取的抽象运行时。支持多搜索提供商(deepseek、exa、perplexity)和 HTTP 抓取,为 tool-web 模型工具提供统一接口。
内部架构
#mermaid-svg-1keRfnQhu4LYsEA9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1keRfnQhu4LYsEA9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1keRfnQhu4LYsEA9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1keRfnQhu4LYsEA9 .error-icon{fill:#552222;}#mermaid-svg-1keRfnQhu4LYsEA9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1keRfnQhu4LYsEA9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1keRfnQhu4LYsEA9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1keRfnQhu4LYsEA9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1keRfnQhu4LYsEA9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1keRfnQhu4LYsEA9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1keRfnQhu4LYsEA9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1keRfnQhu4LYsEA9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1keRfnQhu4LYsEA9 .marker.cross{stroke:#333333;}#mermaid-svg-1keRfnQhu4LYsEA9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1keRfnQhu4LYsEA9 p{margin:0;}#mermaid-svg-1keRfnQhu4LYsEA9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1keRfnQhu4LYsEA9 .cluster-label text{fill:#333;}#mermaid-svg-1keRfnQhu4LYsEA9 .cluster-label span{color:#333;}#mermaid-svg-1keRfnQhu4LYsEA9 .cluster-label span p{background-color:transparent;}#mermaid-svg-1keRfnQhu4LYsEA9 .label text,#mermaid-svg-1keRfnQhu4LYsEA9 span{fill:#333;color:#333;}#mermaid-svg-1keRfnQhu4LYsEA9 .node rect,#mermaid-svg-1keRfnQhu4LYsEA9 .node circle,#mermaid-svg-1keRfnQhu4LYsEA9 .node ellipse,#mermaid-svg-1keRfnQhu4LYsEA9 .node polygon,#mermaid-svg-1keRfnQhu4LYsEA9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1keRfnQhu4LYsEA9 .rough-node .label text,#mermaid-svg-1keRfnQhu4LYsEA9 .node .label text,#mermaid-svg-1keRfnQhu4LYsEA9 .image-shape .label,#mermaid-svg-1keRfnQhu4LYsEA9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-1keRfnQhu4LYsEA9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1keRfnQhu4LYsEA9 .rough-node .label,#mermaid-svg-1keRfnQhu4LYsEA9 .node .label,#mermaid-svg-1keRfnQhu4LYsEA9 .image-shape .label,#mermaid-svg-1keRfnQhu4LYsEA9 .icon-shape .label{text-align:center;}#mermaid-svg-1keRfnQhu4LYsEA9 .node.clickable{cursor:pointer;}#mermaid-svg-1keRfnQhu4LYsEA9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1keRfnQhu4LYsEA9 .arrowheadPath{fill:#333333;}#mermaid-svg-1keRfnQhu4LYsEA9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1keRfnQhu4LYsEA9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1keRfnQhu4LYsEA9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1keRfnQhu4LYsEA9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1keRfnQhu4LYsEA9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1keRfnQhu4LYsEA9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1keRfnQhu4LYsEA9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1keRfnQhu4LYsEA9 .cluster text{fill:#333;}#mermaid-svg-1keRfnQhu4LYsEA9 .cluster span{color:#333;}#mermaid-svg-1keRfnQhu4LYsEA9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1keRfnQhu4LYsEA9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1keRfnQhu4LYsEA9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-1keRfnQhu4LYsEA9 .icon-shape,#mermaid-svg-1keRfnQhu4LYsEA9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1keRfnQhu4LYsEA9 .icon-shape p,#mermaid-svg-1keRfnQhu4LYsEA9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1keRfnQhu4LYsEA9 .icon-shape .label rect,#mermaid-svg-1keRfnQhu4LYsEA9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1keRfnQhu4LYsEA9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1keRfnQhu4LYsEA9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1keRfnQhu4LYsEA9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-1keRfnQhu4LYsEA9 .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-1keRfnQhu4LYsEA9 .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-1keRfnQhu4LYsEA9 .def tspan{fill:#fff!important;}#mermaid-svg-1keRfnQhu4LYsEA9 .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-1keRfnQhu4LYsEA9 .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-1keRfnQhu4LYsEA9 .prov tspan{fill:#fff!important;}#mermaid-svg-1keRfnQhu4LYsEA9 .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-1keRfnQhu4LYsEA9 .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-1keRfnQhu4LYsEA9 .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
注册
注册
ctx.web.search/fetch
WebRuntime (Service)
types.ts
web-search-deepseek
(DeepSeek 搜索)
web-fetch-http
(HTTP 抓取)
tool-web
(模型 Web 工具)
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
WebRuntime |
Service (class) | Web 能力服务定义:search()、fetch() 抽象方法 |
WebSearchResult |
interface | 搜索结果:标题、URL、摘要 |
WebFetchResult |
interface | 抓取结果:URL、内容、MIME 类型 |
DeepseekSearchProvider |
class | DeepSeek 搜索后端实现 |
HttpFetchProvider |
class | HTTP 抓取后端实现 |
tool-web |
tool | 模型工具:web_search、web_fetch |
与其他模块的关系
- llm :搜索/抓取结果作为
ContentBlock注入 LLM 消息流。 - agent :Agent 主循环调用
tool-web执行 Web 操作。
6. 语言服务器能力(lsp)
路径 :packages/lsp/
核心作用 :定义 LSP(语言服务器协议)服务抽象------启动/停止语言服务器、诊断查询、符号定义/引用查找。为 tool-lsp 模型工具提供代码智能能力。
内部架构
#mermaid-svg-S3Flgy19UKPocAV9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-S3Flgy19UKPocAV9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-S3Flgy19UKPocAV9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-S3Flgy19UKPocAV9 .error-icon{fill:#552222;}#mermaid-svg-S3Flgy19UKPocAV9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-S3Flgy19UKPocAV9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-S3Flgy19UKPocAV9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-S3Flgy19UKPocAV9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-S3Flgy19UKPocAV9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-S3Flgy19UKPocAV9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-S3Flgy19UKPocAV9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-S3Flgy19UKPocAV9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-S3Flgy19UKPocAV9 .marker.cross{stroke:#333333;}#mermaid-svg-S3Flgy19UKPocAV9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-S3Flgy19UKPocAV9 p{margin:0;}#mermaid-svg-S3Flgy19UKPocAV9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-S3Flgy19UKPocAV9 .cluster-label text{fill:#333;}#mermaid-svg-S3Flgy19UKPocAV9 .cluster-label span{color:#333;}#mermaid-svg-S3Flgy19UKPocAV9 .cluster-label span p{background-color:transparent;}#mermaid-svg-S3Flgy19UKPocAV9 .label text,#mermaid-svg-S3Flgy19UKPocAV9 span{fill:#333;color:#333;}#mermaid-svg-S3Flgy19UKPocAV9 .node rect,#mermaid-svg-S3Flgy19UKPocAV9 .node circle,#mermaid-svg-S3Flgy19UKPocAV9 .node ellipse,#mermaid-svg-S3Flgy19UKPocAV9 .node polygon,#mermaid-svg-S3Flgy19UKPocAV9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-S3Flgy19UKPocAV9 .rough-node .label text,#mermaid-svg-S3Flgy19UKPocAV9 .node .label text,#mermaid-svg-S3Flgy19UKPocAV9 .image-shape .label,#mermaid-svg-S3Flgy19UKPocAV9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-S3Flgy19UKPocAV9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-S3Flgy19UKPocAV9 .rough-node .label,#mermaid-svg-S3Flgy19UKPocAV9 .node .label,#mermaid-svg-S3Flgy19UKPocAV9 .image-shape .label,#mermaid-svg-S3Flgy19UKPocAV9 .icon-shape .label{text-align:center;}#mermaid-svg-S3Flgy19UKPocAV9 .node.clickable{cursor:pointer;}#mermaid-svg-S3Flgy19UKPocAV9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-S3Flgy19UKPocAV9 .arrowheadPath{fill:#333333;}#mermaid-svg-S3Flgy19UKPocAV9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-S3Flgy19UKPocAV9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-S3Flgy19UKPocAV9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-S3Flgy19UKPocAV9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-S3Flgy19UKPocAV9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-S3Flgy19UKPocAV9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-S3Flgy19UKPocAV9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-S3Flgy19UKPocAV9 .cluster text{fill:#333;}#mermaid-svg-S3Flgy19UKPocAV9 .cluster span{color:#333;}#mermaid-svg-S3Flgy19UKPocAV9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-S3Flgy19UKPocAV9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-S3Flgy19UKPocAV9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-S3Flgy19UKPocAV9 .icon-shape,#mermaid-svg-S3Flgy19UKPocAV9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-S3Flgy19UKPocAV9 .icon-shape p,#mermaid-svg-S3Flgy19UKPocAV9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-S3Flgy19UKPocAV9 .icon-shape .label rect,#mermaid-svg-S3Flgy19UKPocAV9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-S3Flgy19UKPocAV9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-S3Flgy19UKPocAV9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-S3Flgy19UKPocAV9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-S3Flgy19UKPocAV9 .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-S3Flgy19UKPocAV9 .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-S3Flgy19UKPocAV9 .def tspan{fill:#fff!important;}#mermaid-svg-S3Flgy19UKPocAV9 .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-S3Flgy19UKPocAV9 .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-S3Flgy19UKPocAV9 .prov tspan{fill:#fff!important;}#mermaid-svg-S3Flgy19UKPocAV9 .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-S3Flgy19UKPocAV9 .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-S3Flgy19UKPocAV9 .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
注册
ctx.lsp.*
LspService (Service)
types.ts
lsp-stdio
(stdio 传输 LSP)
tool-lsp
(模型 LSP 工具)
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
LspService |
Service (abstract) | LSP 服务定义:start()、stop()、diagnostics()、definitions()、references() |
LspStdioProvider |
class | stdio 传输的 LSP 后端,通过子进程启动语言服务器 |
tool-lsp |
tool | 模型工具:lsp_diagnostics、lsp_definitions、lsp_references |
与其他模块的关系
- subprocess :
lsp-stdio通过ctx.subprocess.spawn()启动语言服务器进程。 - fs :LSP 操作涉及文件路径通过
ctx.fs解析。 - agent :Agent 调用
tool-lsp获取代码智能信息。
7. 持久终端能力(terminal)
路径 :packages/terminal/
核心作用:定义持久交互式终端会话抽象------创建、写入、调整大小、读取输出。与一次性 Shell 执行不同,终端会话保持状态(工作目录、环境变量、历史),适合交互式开发场景。
内部架构
#mermaid-svg-n9ZVs3okOsAJFqOj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-n9ZVs3okOsAJFqOj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-n9ZVs3okOsAJFqOj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-n9ZVs3okOsAJFqOj .error-icon{fill:#552222;}#mermaid-svg-n9ZVs3okOsAJFqOj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-n9ZVs3okOsAJFqOj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-n9ZVs3okOsAJFqOj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-n9ZVs3okOsAJFqOj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-n9ZVs3okOsAJFqOj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-n9ZVs3okOsAJFqOj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-n9ZVs3okOsAJFqOj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-n9ZVs3okOsAJFqOj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-n9ZVs3okOsAJFqOj .marker.cross{stroke:#333333;}#mermaid-svg-n9ZVs3okOsAJFqOj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-n9ZVs3okOsAJFqOj p{margin:0;}#mermaid-svg-n9ZVs3okOsAJFqOj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-n9ZVs3okOsAJFqOj .cluster-label text{fill:#333;}#mermaid-svg-n9ZVs3okOsAJFqOj .cluster-label span{color:#333;}#mermaid-svg-n9ZVs3okOsAJFqOj .cluster-label span p{background-color:transparent;}#mermaid-svg-n9ZVs3okOsAJFqOj .label text,#mermaid-svg-n9ZVs3okOsAJFqOj span{fill:#333;color:#333;}#mermaid-svg-n9ZVs3okOsAJFqOj .node rect,#mermaid-svg-n9ZVs3okOsAJFqOj .node circle,#mermaid-svg-n9ZVs3okOsAJFqOj .node ellipse,#mermaid-svg-n9ZVs3okOsAJFqOj .node polygon,#mermaid-svg-n9ZVs3okOsAJFqOj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-n9ZVs3okOsAJFqOj .rough-node .label text,#mermaid-svg-n9ZVs3okOsAJFqOj .node .label text,#mermaid-svg-n9ZVs3okOsAJFqOj .image-shape .label,#mermaid-svg-n9ZVs3okOsAJFqOj .icon-shape .label{text-anchor:middle;}#mermaid-svg-n9ZVs3okOsAJFqOj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-n9ZVs3okOsAJFqOj .rough-node .label,#mermaid-svg-n9ZVs3okOsAJFqOj .node .label,#mermaid-svg-n9ZVs3okOsAJFqOj .image-shape .label,#mermaid-svg-n9ZVs3okOsAJFqOj .icon-shape .label{text-align:center;}#mermaid-svg-n9ZVs3okOsAJFqOj .node.clickable{cursor:pointer;}#mermaid-svg-n9ZVs3okOsAJFqOj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-n9ZVs3okOsAJFqOj .arrowheadPath{fill:#333333;}#mermaid-svg-n9ZVs3okOsAJFqOj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-n9ZVs3okOsAJFqOj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-n9ZVs3okOsAJFqOj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-n9ZVs3okOsAJFqOj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-n9ZVs3okOsAJFqOj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-n9ZVs3okOsAJFqOj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-n9ZVs3okOsAJFqOj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-n9ZVs3okOsAJFqOj .cluster text{fill:#333;}#mermaid-svg-n9ZVs3okOsAJFqOj .cluster span{color:#333;}#mermaid-svg-n9ZVs3okOsAJFqOj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-n9ZVs3okOsAJFqOj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-n9ZVs3okOsAJFqOj rect.text{fill:none;stroke-width:0;}#mermaid-svg-n9ZVs3okOsAJFqOj .icon-shape,#mermaid-svg-n9ZVs3okOsAJFqOj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-n9ZVs3okOsAJFqOj .icon-shape p,#mermaid-svg-n9ZVs3okOsAJFqOj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-n9ZVs3okOsAJFqOj .icon-shape .label rect,#mermaid-svg-n9ZVs3okOsAJFqOj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-n9ZVs3okOsAJFqOj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-n9ZVs3okOsAJFqOj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-n9ZVs3okOsAJFqOj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-n9ZVs3okOsAJFqOj .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-n9ZVs3okOsAJFqOj .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-n9ZVs3okOsAJFqOj .def tspan{fill:#fff!important;}#mermaid-svg-n9ZVs3okOsAJFqOj .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-n9ZVs3okOsAJFqOj .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-n9ZVs3okOsAJFqOj .prov tspan{fill:#fff!important;}#mermaid-svg-n9ZVs3okOsAJFqOj .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-n9ZVs3okOsAJFqOj .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-n9ZVs3okOsAJFqOj .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
注册
ctx.terminals.*
TerminalSessionService (Service)
types.ts
terminal-bash
(Bash 终端后端)
tool-terminal
(模型终端工具)
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
TerminalSessionService |
Service (abstract) | 终端服务定义:create()、write()、resize()、kill()、输出流 |
TerminalSession |
interface | 终端会话句柄:输入/输出流、尺寸、退出码 |
TerminalBashBackend |
class | Bash 终端后端,通过 PTY 创建交互式会话 |
tool-terminal |
tool | 模型工具:terminal_create、terminal_write、terminal_resize、terminal_kill |
与其他模块的关系
- subprocess :
terminal-bash通过ctx.subprocess.spawnTerminal()创建 PTY。 - shell :终端后端复用 Shell 环境配置(
shell-env)。 - fs :终端会话的 cwd 通过
ctx.fs验证。
8. 代码运行时能力(code-runtime)
路径 :packages/code-runtime/
核心作用:定义代码执行运行时抽象------在隔离的 Worker Thread 中执行 JavaScript 代码,支持超时和取消。为模型提供安全的代码执行能力。
内部架构
#mermaid-svg-2OJuCQJlzSnO3P83{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2OJuCQJlzSnO3P83 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2OJuCQJlzSnO3P83 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2OJuCQJlzSnO3P83 .error-icon{fill:#552222;}#mermaid-svg-2OJuCQJlzSnO3P83 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2OJuCQJlzSnO3P83 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2OJuCQJlzSnO3P83 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2OJuCQJlzSnO3P83 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2OJuCQJlzSnO3P83 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2OJuCQJlzSnO3P83 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2OJuCQJlzSnO3P83 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2OJuCQJlzSnO3P83 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2OJuCQJlzSnO3P83 .marker.cross{stroke:#333333;}#mermaid-svg-2OJuCQJlzSnO3P83 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2OJuCQJlzSnO3P83 p{margin:0;}#mermaid-svg-2OJuCQJlzSnO3P83 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2OJuCQJlzSnO3P83 .cluster-label text{fill:#333;}#mermaid-svg-2OJuCQJlzSnO3P83 .cluster-label span{color:#333;}#mermaid-svg-2OJuCQJlzSnO3P83 .cluster-label span p{background-color:transparent;}#mermaid-svg-2OJuCQJlzSnO3P83 .label text,#mermaid-svg-2OJuCQJlzSnO3P83 span{fill:#333;color:#333;}#mermaid-svg-2OJuCQJlzSnO3P83 .node rect,#mermaid-svg-2OJuCQJlzSnO3P83 .node circle,#mermaid-svg-2OJuCQJlzSnO3P83 .node ellipse,#mermaid-svg-2OJuCQJlzSnO3P83 .node polygon,#mermaid-svg-2OJuCQJlzSnO3P83 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2OJuCQJlzSnO3P83 .rough-node .label text,#mermaid-svg-2OJuCQJlzSnO3P83 .node .label text,#mermaid-svg-2OJuCQJlzSnO3P83 .image-shape .label,#mermaid-svg-2OJuCQJlzSnO3P83 .icon-shape .label{text-anchor:middle;}#mermaid-svg-2OJuCQJlzSnO3P83 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2OJuCQJlzSnO3P83 .rough-node .label,#mermaid-svg-2OJuCQJlzSnO3P83 .node .label,#mermaid-svg-2OJuCQJlzSnO3P83 .image-shape .label,#mermaid-svg-2OJuCQJlzSnO3P83 .icon-shape .label{text-align:center;}#mermaid-svg-2OJuCQJlzSnO3P83 .node.clickable{cursor:pointer;}#mermaid-svg-2OJuCQJlzSnO3P83 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2OJuCQJlzSnO3P83 .arrowheadPath{fill:#333333;}#mermaid-svg-2OJuCQJlzSnO3P83 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2OJuCQJlzSnO3P83 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2OJuCQJlzSnO3P83 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2OJuCQJlzSnO3P83 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2OJuCQJlzSnO3P83 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2OJuCQJlzSnO3P83 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2OJuCQJlzSnO3P83 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2OJuCQJlzSnO3P83 .cluster text{fill:#333;}#mermaid-svg-2OJuCQJlzSnO3P83 .cluster span{color:#333;}#mermaid-svg-2OJuCQJlzSnO3P83 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2OJuCQJlzSnO3P83 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2OJuCQJlzSnO3P83 rect.text{fill:none;stroke-width:0;}#mermaid-svg-2OJuCQJlzSnO3P83 .icon-shape,#mermaid-svg-2OJuCQJlzSnO3P83 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2OJuCQJlzSnO3P83 .icon-shape p,#mermaid-svg-2OJuCQJlzSnO3P83 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2OJuCQJlzSnO3P83 .icon-shape .label rect,#mermaid-svg-2OJuCQJlzSnO3P83 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2OJuCQJlzSnO3P83 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2OJuCQJlzSnO3P83 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2OJuCQJlzSnO3P83 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-2OJuCQJlzSnO3P83 .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-2OJuCQJlzSnO3P83 .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-2OJuCQJlzSnO3P83 .def tspan{fill:#fff!important;}#mermaid-svg-2OJuCQJlzSnO3P83 .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-2OJuCQJlzSnO3P83 .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-2OJuCQJlzSnO3P83 .prov tspan{fill:#fff!important;}#mermaid-svg-2OJuCQJlzSnO3P83 .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-2OJuCQJlzSnO3P83 .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-2OJuCQJlzSnO3P83 .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
注册
ctx.codeRuntime.*
CodeRuntime (Service)
types.ts
code-runtime-worker-thread
(Worker Thread 执行器)
tool-code (隐含)
(模型代码执行工具)
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
CodeRuntime |
Service (abstract) | 代码运行时服务定义:execute() 抽象方法 |
CodeExecutionContext |
interface | 执行上下文:代码字符串、超时、信号 |
CodeExecutionResult |
interface | 执行结果:输出值、stdout、stderr、异常 |
WorkerThreadCodeRuntime |
class | Worker Thread 实现,在隔离线程中执行 JS 代码 |
index.ts (worker-thread) |
module | Worker 端入口:vm 沙箱、超时控制、结果序列化 |
与其他模块的关系
- subprocess:Worker Thread 的生命周期管理通过子进程能力。
- llm :代码执行结果作为
ContentBlock注入 LLM 上下文。 - workflow:工作流引擎的脚本执行机制与代码运行时共享 vm 沙箱理念。
9. 沙箱能力(sandbox)
路径 :packages/sandbox/
核心作用 :定义沙箱提供商抽象------为 Shell、FS、子进程等能力提供隔离执行环境。sandbox-local 提供本地命名空间隔离,sandbox-policy 定义安全策略。
内部架构
#mermaid-svg-C6eHR8EJmzY3U0Eg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-C6eHR8EJmzY3U0Eg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-C6eHR8EJmzY3U0Eg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-C6eHR8EJmzY3U0Eg .error-icon{fill:#552222;}#mermaid-svg-C6eHR8EJmzY3U0Eg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-C6eHR8EJmzY3U0Eg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-C6eHR8EJmzY3U0Eg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-C6eHR8EJmzY3U0Eg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-C6eHR8EJmzY3U0Eg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-C6eHR8EJmzY3U0Eg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-C6eHR8EJmzY3U0Eg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-C6eHR8EJmzY3U0Eg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-C6eHR8EJmzY3U0Eg .marker.cross{stroke:#333333;}#mermaid-svg-C6eHR8EJmzY3U0Eg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-C6eHR8EJmzY3U0Eg p{margin:0;}#mermaid-svg-C6eHR8EJmzY3U0Eg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-C6eHR8EJmzY3U0Eg .cluster-label text{fill:#333;}#mermaid-svg-C6eHR8EJmzY3U0Eg .cluster-label span{color:#333;}#mermaid-svg-C6eHR8EJmzY3U0Eg .cluster-label span p{background-color:transparent;}#mermaid-svg-C6eHR8EJmzY3U0Eg .label text,#mermaid-svg-C6eHR8EJmzY3U0Eg span{fill:#333;color:#333;}#mermaid-svg-C6eHR8EJmzY3U0Eg .node rect,#mermaid-svg-C6eHR8EJmzY3U0Eg .node circle,#mermaid-svg-C6eHR8EJmzY3U0Eg .node ellipse,#mermaid-svg-C6eHR8EJmzY3U0Eg .node polygon,#mermaid-svg-C6eHR8EJmzY3U0Eg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-C6eHR8EJmzY3U0Eg .rough-node .label text,#mermaid-svg-C6eHR8EJmzY3U0Eg .node .label text,#mermaid-svg-C6eHR8EJmzY3U0Eg .image-shape .label,#mermaid-svg-C6eHR8EJmzY3U0Eg .icon-shape .label{text-anchor:middle;}#mermaid-svg-C6eHR8EJmzY3U0Eg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-C6eHR8EJmzY3U0Eg .rough-node .label,#mermaid-svg-C6eHR8EJmzY3U0Eg .node .label,#mermaid-svg-C6eHR8EJmzY3U0Eg .image-shape .label,#mermaid-svg-C6eHR8EJmzY3U0Eg .icon-shape .label{text-align:center;}#mermaid-svg-C6eHR8EJmzY3U0Eg .node.clickable{cursor:pointer;}#mermaid-svg-C6eHR8EJmzY3U0Eg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-C6eHR8EJmzY3U0Eg .arrowheadPath{fill:#333333;}#mermaid-svg-C6eHR8EJmzY3U0Eg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-C6eHR8EJmzY3U0Eg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-C6eHR8EJmzY3U0Eg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-C6eHR8EJmzY3U0Eg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-C6eHR8EJmzY3U0Eg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-C6eHR8EJmzY3U0Eg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-C6eHR8EJmzY3U0Eg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-C6eHR8EJmzY3U0Eg .cluster text{fill:#333;}#mermaid-svg-C6eHR8EJmzY3U0Eg .cluster span{color:#333;}#mermaid-svg-C6eHR8EJmzY3U0Eg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-C6eHR8EJmzY3U0Eg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-C6eHR8EJmzY3U0Eg rect.text{fill:none;stroke-width:0;}#mermaid-svg-C6eHR8EJmzY3U0Eg .icon-shape,#mermaid-svg-C6eHR8EJmzY3U0Eg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-C6eHR8EJmzY3U0Eg .icon-shape p,#mermaid-svg-C6eHR8EJmzY3U0Eg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-C6eHR8EJmzY3U0Eg .icon-shape .label rect,#mermaid-svg-C6eHR8EJmzY3U0Eg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-C6eHR8EJmzY3U0Eg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-C6eHR8EJmzY3U0Eg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-C6eHR8EJmzY3U0Eg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-C6eHR8EJmzY3U0Eg .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-C6eHR8EJmzY3U0Eg .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-C6eHR8EJmzY3U0Eg .def tspan{fill:#fff!important;}#mermaid-svg-C6eHR8EJmzY3U0Eg .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-C6eHR8EJmzY3U0Eg .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-C6eHR8EJmzY3U0Eg .prov tspan{fill:#fff!important;}#mermaid-svg-C6eHR8EJmzY3U0Eg .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-C6eHR8EJmzY3U0Eg .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-C6eHR8EJmzY3U0Eg .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
注册
策略注入
ctx.sandbox.*
ctx.sandbox.*
SandboxProvider (abstract)
sandbox/src/index.ts
sandbox-local
(本地沙箱)
sandbox-policy
(安全策略)
bash-sandbox Provider
fs-sandbox Provider
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
SandboxProvider |
abstract class | 沙箱服务定义:创建隔离环境、路径映射、资源限制 |
SandboxLocalProvider |
class | 本地沙箱实现:命名空间隔离、路径重映射 |
SandboxPolicy |
module | 安全策略定义:允许/拒绝的路径、命令、网络访问 |
SandboxConfig |
interface | 沙箱配置:根目录、挂载点、权限 |
与其他模块的关系
- shell :
bash-sandbox/pwsh-sandbox依赖沙箱进行隔离执行。 - fs :
fs-sandbox依赖沙箱进行路径隔离。 - subprocess:沙箱内的子进程操作受限。
10. 技能注册能力(skill)
路径 :packages/skill/
核心作用 :定义技能提供商注册表和技能发现/加载机制。技能是可复用的指令模板,从项目、用户、自定义和内置目录发现,按 rank 优先级合并。tool-skill 将技能目录暴露给模型,模型可按名称加载技能内容。
内部架构
#mermaid-svg-BUpIHWz0U3AT1NzV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BUpIHWz0U3AT1NzV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BUpIHWz0U3AT1NzV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BUpIHWz0U3AT1NzV .error-icon{fill:#552222;}#mermaid-svg-BUpIHWz0U3AT1NzV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BUpIHWz0U3AT1NzV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BUpIHWz0U3AT1NzV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BUpIHWz0U3AT1NzV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BUpIHWz0U3AT1NzV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BUpIHWz0U3AT1NzV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BUpIHWz0U3AT1NzV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BUpIHWz0U3AT1NzV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BUpIHWz0U3AT1NzV .marker.cross{stroke:#333333;}#mermaid-svg-BUpIHWz0U3AT1NzV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BUpIHWz0U3AT1NzV p{margin:0;}#mermaid-svg-BUpIHWz0U3AT1NzV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BUpIHWz0U3AT1NzV .cluster-label text{fill:#333;}#mermaid-svg-BUpIHWz0U3AT1NzV .cluster-label span{color:#333;}#mermaid-svg-BUpIHWz0U3AT1NzV .cluster-label span p{background-color:transparent;}#mermaid-svg-BUpIHWz0U3AT1NzV .label text,#mermaid-svg-BUpIHWz0U3AT1NzV span{fill:#333;color:#333;}#mermaid-svg-BUpIHWz0U3AT1NzV .node rect,#mermaid-svg-BUpIHWz0U3AT1NzV .node circle,#mermaid-svg-BUpIHWz0U3AT1NzV .node ellipse,#mermaid-svg-BUpIHWz0U3AT1NzV .node polygon,#mermaid-svg-BUpIHWz0U3AT1NzV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BUpIHWz0U3AT1NzV .rough-node .label text,#mermaid-svg-BUpIHWz0U3AT1NzV .node .label text,#mermaid-svg-BUpIHWz0U3AT1NzV .image-shape .label,#mermaid-svg-BUpIHWz0U3AT1NzV .icon-shape .label{text-anchor:middle;}#mermaid-svg-BUpIHWz0U3AT1NzV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BUpIHWz0U3AT1NzV .rough-node .label,#mermaid-svg-BUpIHWz0U3AT1NzV .node .label,#mermaid-svg-BUpIHWz0U3AT1NzV .image-shape .label,#mermaid-svg-BUpIHWz0U3AT1NzV .icon-shape .label{text-align:center;}#mermaid-svg-BUpIHWz0U3AT1NzV .node.clickable{cursor:pointer;}#mermaid-svg-BUpIHWz0U3AT1NzV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BUpIHWz0U3AT1NzV .arrowheadPath{fill:#333333;}#mermaid-svg-BUpIHWz0U3AT1NzV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BUpIHWz0U3AT1NzV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BUpIHWz0U3AT1NzV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BUpIHWz0U3AT1NzV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BUpIHWz0U3AT1NzV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BUpIHWz0U3AT1NzV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BUpIHWz0U3AT1NzV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BUpIHWz0U3AT1NzV .cluster text{fill:#333;}#mermaid-svg-BUpIHWz0U3AT1NzV .cluster span{color:#333;}#mermaid-svg-BUpIHWz0U3AT1NzV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BUpIHWz0U3AT1NzV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BUpIHWz0U3AT1NzV rect.text{fill:none;stroke-width:0;}#mermaid-svg-BUpIHWz0U3AT1NzV .icon-shape,#mermaid-svg-BUpIHWz0U3AT1NzV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BUpIHWz0U3AT1NzV .icon-shape p,#mermaid-svg-BUpIHWz0U3AT1NzV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BUpIHWz0U3AT1NzV .icon-shape .label rect,#mermaid-svg-BUpIHWz0U3AT1NzV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BUpIHWz0U3AT1NzV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BUpIHWz0U3AT1NzV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BUpIHWz0U3AT1NzV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-BUpIHWz0U3AT1NzV .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-BUpIHWz0U3AT1NzV .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-BUpIHWz0U3AT1NzV .def tspan{fill:#fff!important;}#mermaid-svg-BUpIHWz0U3AT1NzV .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-BUpIHWz0U3AT1NzV .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-BUpIHWz0U3AT1NzV .prov tspan{fill:#fff!important;}#mermaid-svg-BUpIHWz0U3AT1NzV .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-BUpIHWz0U3AT1NzV .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-BUpIHWz0U3AT1NzV .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
registerProvider
registerProvider
ctx.skills.list/get
ctx.skills (Service)
SkillSummary / SkillDefinition
invariant.ts
skill-filesystem
(文件系统技能发现)
skill-badge
(内置 dsh-badge 技能)
tool-skill
(模型技能加载工具)
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
SkillService |
Service (class) | 技能注册表:registerProvider()、list()、get(),按 rank 合并多提供商目录 |
SkillSummary |
interface | 技能摘要:name、description、whenToUse、invocation 策略、source、provider |
SkillDefinition |
interface | 完整技能定义:包含 content(Markdown 指令体)和 metadata |
SkillCandidate |
interface | 提供商目录条目:SkillSummary + rank + locator |
SkillProvider |
interface | 提供商接口:list() 返回候选列表,get() 加载完整技能 |
SkillInvocationPolicy |
interface | 调用策略:modelInvocable(模型可见)、userInvocable(用户命令可见) |
isSkillName() |
function | kebab-case 技能名验证 |
isModelInvocable() / isUserInvocable() |
function | 调用策略判定 |
FileSystemSkillProvider |
class | 文件系统技能发现:扫描 project/user/custom/bundled 根目录,解析 YAML frontmatter |
SkillWatchManager |
class | 技能文件监听管理器:Chokidar 监听 + 稳定性检查 + 失效通知 |
skill-badge |
provider | 内置 dsh-badge 技能提供商 |
tool-skill |
tool | 模型工具:发布技能目录 <available_skills>,按名称加载技能内容 |
SkillCatalogSource |
interface | 持久化技能目录源,记录会话中发布的技能条目 |
renderSkillContent() |
function | 渲染技能内容供模型消费 |
BUNDLED_SKILL_RANK |
constant | 内置技能优先级常量 (600) |
与其他模块的关系
- fs :
skill-filesystem通过ctx.fs读取技能文件(当 FS 服务存在时),否则直接使用 Node.jsfs。 - llm :技能内容通过
createUserMessage()注入 LLM 消息流;assertNever从 llm 模块导入。 - scope:技能支持作用域分层(project-dsh、project-agents、user-dsh、user-agents、custom、bundled)。
- agent :Agent 启动时
tool-skill发布技能目录,模型按需加载。 - home-paths :技能根目录解析依赖
resolveDshHome()和DSH_AGENTS_HOME。
11. 子代理能力(subagent)
路径 :packages/subagent/
核心作用 :定义子代理委派抽象------命名提供商注册表 + 能力验证的异步启动 API。支持多种后端:spawn(新鲜子进程)、fork(继承父上下文)、acp(外部代理通信协议)、claude-code、codex、dsh-sdk。模型通过 tool-subagent 委派任务给子代理。
内部架构
#mermaid-svg-RrPhNzjt7Hh3XP7Q{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .error-icon{fill:#552222;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .marker.cross{stroke:#333333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RrPhNzjt7Hh3XP7Q p{margin:0;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .cluster-label text{fill:#333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .cluster-label span{color:#333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .cluster-label span p{background-color:transparent;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .label text,#mermaid-svg-RrPhNzjt7Hh3XP7Q span{fill:#333;color:#333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .node rect,#mermaid-svg-RrPhNzjt7Hh3XP7Q .node circle,#mermaid-svg-RrPhNzjt7Hh3XP7Q .node ellipse,#mermaid-svg-RrPhNzjt7Hh3XP7Q .node polygon,#mermaid-svg-RrPhNzjt7Hh3XP7Q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .rough-node .label text,#mermaid-svg-RrPhNzjt7Hh3XP7Q .node .label text,#mermaid-svg-RrPhNzjt7Hh3XP7Q .image-shape .label,#mermaid-svg-RrPhNzjt7Hh3XP7Q .icon-shape .label{text-anchor:middle;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .rough-node .label,#mermaid-svg-RrPhNzjt7Hh3XP7Q .node .label,#mermaid-svg-RrPhNzjt7Hh3XP7Q .image-shape .label,#mermaid-svg-RrPhNzjt7Hh3XP7Q .icon-shape .label{text-align:center;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .node.clickable{cursor:pointer;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .arrowheadPath{fill:#333333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RrPhNzjt7Hh3XP7Q .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RrPhNzjt7Hh3XP7Q .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RrPhNzjt7Hh3XP7Q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .cluster text{fill:#333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .cluster span{color:#333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RrPhNzjt7Hh3XP7Q rect.text{fill:none;stroke-width:0;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .icon-shape,#mermaid-svg-RrPhNzjt7Hh3XP7Q .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .icon-shape p,#mermaid-svg-RrPhNzjt7Hh3XP7Q .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .icon-shape .label rect,#mermaid-svg-RrPhNzjt7Hh3XP7Q .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RrPhNzjt7Hh3XP7Q .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RrPhNzjt7Hh3XP7Q :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .def tspan{fill:#fff!important;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .prov tspan{fill:#fff!important;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-RrPhNzjt7Hh3XP7Q .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
registerProvider
registerProvider
registerProvider
registerProvider
registerProvider
registerProvider
ctx.subagents.start
ctx.subagents
ctx.subagents
SubagentRuntime (Service)
types.ts
continuation.ts
lifecycle.ts
depth.ts
descriptor.ts
subagent-spawn-in-process
(新鲜子进程)
subagent-fork-in-process
(继承上下文子进程)
subagent-acp
(ACP 协议)
subagent-claude-code
subagent-codex
subagent-dsh-sdk
tool-subagent
(模型委派工具)
tool-subagent-control
(子代理控制)
tool-subagent-report
(子代理报告)
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
SubagentRuntime |
Service (class) | 子代理运行时:registerProvider()、start()、startContinuable()、followup(),命名提供商注册表 |
SubagentProvider |
interface | 提供商接口:name、capabilities、inheritsParentContext、start()、prepareContinuable?() |
SubagentCapabilities |
interface | 能力声明:outputSchema、depthLimit、toolFilter、persona |
SubagentStartRequest |
interface | 启动请求:prompt、parent、signal、agentOptions、outputSchema、maxDepth、toolFilter、persona |
SubagentRun |
interface | 一次性运行句柄:id、localAgent、result、dispose() |
SubagentResult |
interface | 运行结果:output(ContentBlock\[\])、structured?、stopReason |
SubagentStopReason |
type | 停止原因:completed、aborted、error、max-tokens、refusal |
SubagentContinuationManager |
class | 可继续子代理管理器:身份预留、组合、提示投递、冷恢复 |
assertSubagentMaxDepth() |
function | 递归深度断言 |
settleRun() |
function | 运行结算:将 SubagentRun.result 映射到 SubagentResult |
snapshotSubagentDescriptor() |
function | 子代理描述符快照 |
SpawnInProcessProvider |
class | spawn 后端:新鲜子 Agent,不继承父上下文 |
ForkInProcessProvider |
class | fork 后端:子 Agent 继承父已完成轮次的前缀 |
tool-subagent |
tool | 模型委派工具:provider 配置选择后端,backgroundMode 选择 one-shot/continuable |
与其他模块的关系
- agent:子代理是子 Agent 实例,复用 Agent 工厂和主循环。
- llm:子代理通过 Agent 间接使用 LLM 运行时。
- session :子代理有自己的 Session,记录
parentSession关系。 - workflow :工作流的
agent()调用通过ctx.subagents.start()委派。 - tools (dsh-tools):子代理的工具过滤通过
tools.restrict()实现。 - system-prompt :子代理的 persona 通过
systemPrompt覆盖部署默认值。 - scope:子代理的作用域链继承父代理。
12. 工作流能力(workflow)
路径 :packages/workflow/
核心作用 :定义工作流引擎抽象------执行模型编写的 JavaScript 编排脚本,脚本中可调用 agent() 扇出子代理、使用 parallel()/pipeline() 组合器。Worker Thread 引擎在隔离线程中执行脚本,防止同步脚本阻塞宿主。
内部架构
#mermaid-svg-fZuteJYNlV4GJfXm{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fZuteJYNlV4GJfXm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fZuteJYNlV4GJfXm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fZuteJYNlV4GJfXm .error-icon{fill:#552222;}#mermaid-svg-fZuteJYNlV4GJfXm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fZuteJYNlV4GJfXm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fZuteJYNlV4GJfXm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fZuteJYNlV4GJfXm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fZuteJYNlV4GJfXm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fZuteJYNlV4GJfXm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fZuteJYNlV4GJfXm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fZuteJYNlV4GJfXm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fZuteJYNlV4GJfXm .marker.cross{stroke:#333333;}#mermaid-svg-fZuteJYNlV4GJfXm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fZuteJYNlV4GJfXm p{margin:0;}#mermaid-svg-fZuteJYNlV4GJfXm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-fZuteJYNlV4GJfXm .cluster-label text{fill:#333;}#mermaid-svg-fZuteJYNlV4GJfXm .cluster-label span{color:#333;}#mermaid-svg-fZuteJYNlV4GJfXm .cluster-label span p{background-color:transparent;}#mermaid-svg-fZuteJYNlV4GJfXm .label text,#mermaid-svg-fZuteJYNlV4GJfXm span{fill:#333;color:#333;}#mermaid-svg-fZuteJYNlV4GJfXm .node rect,#mermaid-svg-fZuteJYNlV4GJfXm .node circle,#mermaid-svg-fZuteJYNlV4GJfXm .node ellipse,#mermaid-svg-fZuteJYNlV4GJfXm .node polygon,#mermaid-svg-fZuteJYNlV4GJfXm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fZuteJYNlV4GJfXm .rough-node .label text,#mermaid-svg-fZuteJYNlV4GJfXm .node .label text,#mermaid-svg-fZuteJYNlV4GJfXm .image-shape .label,#mermaid-svg-fZuteJYNlV4GJfXm .icon-shape .label{text-anchor:middle;}#mermaid-svg-fZuteJYNlV4GJfXm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fZuteJYNlV4GJfXm .rough-node .label,#mermaid-svg-fZuteJYNlV4GJfXm .node .label,#mermaid-svg-fZuteJYNlV4GJfXm .image-shape .label,#mermaid-svg-fZuteJYNlV4GJfXm .icon-shape .label{text-align:center;}#mermaid-svg-fZuteJYNlV4GJfXm .node.clickable{cursor:pointer;}#mermaid-svg-fZuteJYNlV4GJfXm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fZuteJYNlV4GJfXm .arrowheadPath{fill:#333333;}#mermaid-svg-fZuteJYNlV4GJfXm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fZuteJYNlV4GJfXm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fZuteJYNlV4GJfXm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fZuteJYNlV4GJfXm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fZuteJYNlV4GJfXm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fZuteJYNlV4GJfXm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fZuteJYNlV4GJfXm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fZuteJYNlV4GJfXm .cluster text{fill:#333;}#mermaid-svg-fZuteJYNlV4GJfXm .cluster span{color:#333;}#mermaid-svg-fZuteJYNlV4GJfXm div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fZuteJYNlV4GJfXm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fZuteJYNlV4GJfXm rect.text{fill:none;stroke-width:0;}#mermaid-svg-fZuteJYNlV4GJfXm .icon-shape,#mermaid-svg-fZuteJYNlV4GJfXm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fZuteJYNlV4GJfXm .icon-shape p,#mermaid-svg-fZuteJYNlV4GJfXm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fZuteJYNlV4GJfXm .icon-shape .label rect,#mermaid-svg-fZuteJYNlV4GJfXm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fZuteJYNlV4GJfXm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fZuteJYNlV4GJfXm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fZuteJYNlV4GJfXm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-fZuteJYNlV4GJfXm .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-fZuteJYNlV4GJfXm .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-fZuteJYNlV4GJfXm .def tspan{fill:#fff!important;}#mermaid-svg-fZuteJYNlV4GJfXm .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-fZuteJYNlV4GJfXm .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-fZuteJYNlV4GJfXm .prov tspan{fill:#fff!important;}#mermaid-svg-fZuteJYNlV4GJfXm .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-fZuteJYNlV4GJfXm .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-fZuteJYNlV4GJfXm .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
注册
ctx.workflowEngine.start
ctx.workflowEngine.start
WorkflowEngine (Service)
types.ts / runtime-types.ts
invariant.ts
workflow-worker-thread
(Worker Thread 引擎)
tool-workflow
(模型工作流工具)
tool-ralph
(Ralph 工作流工具)
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
WorkflowEngine |
Service (abstract) | 工作流引擎服务定义:start() 抽象方法,emitWorkflowEvent() 事件分发 |
WorkflowStartRequest |
interface | 启动请求:script、meta、args、subagentProvider、maxTotalAgents、parent、signal |
WorkflowRun |
interface | 运行句柄:id、meta、result、cancel()、dispose() |
WorkflowResult |
interface | 运行结果:value、stopReason、error?、agentsStarted |
WorkflowMeta |
interface | 脚本身份块:name、description、whenToUse、phases |
WorkflowStopReason |
type | 停止原因:completed、cancelled、error |
WorkflowError |
class | 工作流错误:携带 code(SCRIPT_PARSE、META_INVALID 等)和 fatal 标志 |
WorkflowErrorCode |
type | 错误码闭联集 |
WorkflowEventName |
type | 事件名:workflow/start、phase、log、agent-start、agent-end、end |
WorkerThreadWorkflowEngine |
class | Worker Thread 引擎实现:vm 沙箱、子代理桥接、超时控制 |
WorkerRun (host.ts) |
class | Worker 运行管理:消息协议、子代理调度、取消与处置 |
validateMeta() |
function | meta 块验证 |
assertBodyParses() |
function | 脚本体解析检查(同步抛出 SCRIPT_PARSE) |
tool-workflow |
tool | 模型工具:执行编排脚本,返回脚本最终值 |
tool-ralph |
tool | Ralph 工作流工具变体 |
与其他模块的关系
- subagent :工作流的
agent()调用通过ctx.subagents.start()委派给子代理提供商。 - llm :
WorkflowError继承HarnessError(来自 llm 模块)。 - session:工作流事件投影到父会话。
- agent :
WorkflowStartRequest.parent是发起工作流的 Agent。 - code-runtime:Worker Thread 执行机制与代码运行时共享隔离理念。
13. 上下文压缩能力(compaction)
路径 :packages/compaction/
核心作用 :定义上下文压缩服务抽象------当对话历史超过阈值时,将一段历史替换为 LLM 生成的摘要节点。支持自动压力触发和手动触发,compaction-basic 是默认后端,compaction-tool-result-pruner 提供工具结果裁剪。
内部架构
#mermaid-svg-LJtStXW3gttoyfcz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LJtStXW3gttoyfcz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LJtStXW3gttoyfcz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LJtStXW3gttoyfcz .error-icon{fill:#552222;}#mermaid-svg-LJtStXW3gttoyfcz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LJtStXW3gttoyfcz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LJtStXW3gttoyfcz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LJtStXW3gttoyfcz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LJtStXW3gttoyfcz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LJtStXW3gttoyfcz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LJtStXW3gttoyfcz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LJtStXW3gttoyfcz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LJtStXW3gttoyfcz .marker.cross{stroke:#333333;}#mermaid-svg-LJtStXW3gttoyfcz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LJtStXW3gttoyfcz p{margin:0;}#mermaid-svg-LJtStXW3gttoyfcz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LJtStXW3gttoyfcz .cluster-label text{fill:#333;}#mermaid-svg-LJtStXW3gttoyfcz .cluster-label span{color:#333;}#mermaid-svg-LJtStXW3gttoyfcz .cluster-label span p{background-color:transparent;}#mermaid-svg-LJtStXW3gttoyfcz .label text,#mermaid-svg-LJtStXW3gttoyfcz span{fill:#333;color:#333;}#mermaid-svg-LJtStXW3gttoyfcz .node rect,#mermaid-svg-LJtStXW3gttoyfcz .node circle,#mermaid-svg-LJtStXW3gttoyfcz .node ellipse,#mermaid-svg-LJtStXW3gttoyfcz .node polygon,#mermaid-svg-LJtStXW3gttoyfcz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LJtStXW3gttoyfcz .rough-node .label text,#mermaid-svg-LJtStXW3gttoyfcz .node .label text,#mermaid-svg-LJtStXW3gttoyfcz .image-shape .label,#mermaid-svg-LJtStXW3gttoyfcz .icon-shape .label{text-anchor:middle;}#mermaid-svg-LJtStXW3gttoyfcz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LJtStXW3gttoyfcz .rough-node .label,#mermaid-svg-LJtStXW3gttoyfcz .node .label,#mermaid-svg-LJtStXW3gttoyfcz .image-shape .label,#mermaid-svg-LJtStXW3gttoyfcz .icon-shape .label{text-align:center;}#mermaid-svg-LJtStXW3gttoyfcz .node.clickable{cursor:pointer;}#mermaid-svg-LJtStXW3gttoyfcz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LJtStXW3gttoyfcz .arrowheadPath{fill:#333333;}#mermaid-svg-LJtStXW3gttoyfcz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LJtStXW3gttoyfcz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LJtStXW3gttoyfcz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LJtStXW3gttoyfcz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LJtStXW3gttoyfcz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LJtStXW3gttoyfcz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LJtStXW3gttoyfcz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LJtStXW3gttoyfcz .cluster text{fill:#333;}#mermaid-svg-LJtStXW3gttoyfcz .cluster span{color:#333;}#mermaid-svg-LJtStXW3gttoyfcz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LJtStXW3gttoyfcz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LJtStXW3gttoyfcz rect.text{fill:none;stroke-width:0;}#mermaid-svg-LJtStXW3gttoyfcz .icon-shape,#mermaid-svg-LJtStXW3gttoyfcz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LJtStXW3gttoyfcz .icon-shape p,#mermaid-svg-LJtStXW3gttoyfcz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LJtStXW3gttoyfcz .icon-shape .label rect,#mermaid-svg-LJtStXW3gttoyfcz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LJtStXW3gttoyfcz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LJtStXW3gttoyfcz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LJtStXW3gttoyfcz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-LJtStXW3gttoyfcz .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-LJtStXW3gttoyfcz .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-LJtStXW3gttoyfcz .def tspan{fill:#fff!important;}#mermaid-svg-LJtStXW3gttoyfcz .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-LJtStXW3gttoyfcz .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-LJtStXW3gttoyfcz .prov tspan{fill:#fff!important;}#mermaid-svg-LJtStXW3gttoyfcz .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-LJtStXW3gttoyfcz .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-LJtStXW3gttoyfcz .cons tspan{fill:#fff!important;} Consumer
Service Provider
Service Definition
注册
可选注册
ctx.compaction.compactNow
ctx.compaction.compactIfNeeded
CompactionEngine (abstract Service)
types.ts
brand.ts (CompactionId)
checkpoint.ts
tool-pairing.ts
compaction-basic
(基础压缩后端)
compaction-tool-result-pruner
(工具结果裁剪)
command-compact
(手动压缩命令)
Agent 主循环
(自动压力触发)
ctx
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
CompactionEngine |
abstract Service | 压缩服务定义:compactIfNeeded()、compactNow()、compactRegion() 抽象方法 |
CompactionResult |
interface | 压缩结果:compactionId、startSeq/summarySeq/endSeq、summary、shadowedRange、shadowedSeqs、shadowedTokenCount |
CompactionTrigger |
type | 触发原因:pressure(压力)、context-overflow(上下文溢出) |
ManualCompactionError |
class | 手动压缩错误:busy、cancelled、changed、summary、commit、persistence |
CompactionId |
brand type | 压缩事务唯一标识 |
compactCheckpointSource() |
function | 压缩检查点源构造器 |
toolPairingBalancedBefore/After() |
function | 工具配对平衡检查(压缩前后) |
BasicCompactionEngine |
class | 基础压缩后端:token 计量、区域选择、LLM 摘要、重试 |
compaction-basic/summarizer.ts |
module | LLM 摘要器:复用会话前缀(系统提示+工具+消息)保持 KV 缓存 |
compaction-basic/region.ts |
module | 区域选择:选择可压缩的历史范围 |
compaction-basic/config.ts |
module | 配置解析:thresholdRatio、retainRatio、retainTokens、modelPolicies |
compaction-tool-result-pruner |
provider | 工具结果裁剪后端:在摘要前先裁剪过大的工具结果 |
command-compact |
command | 手动压缩命令 |
与其他模块的关系
- llm :
compaction-basic通过ctx.llm.stream()生成摘要;HarnessError、assertNever、CONTEXT_WINDOW_EXCEEDED_CODE来自 llm 模块。 - session :压缩操作修改会话 surface(替换历史范围),发出
compaction/start、compaction/summary、compaction/end、compaction/prune事件。 - token-meter :
compaction-basic依赖ctx.tokenMeter进行 token 计量。 - agent :自动压缩在
agent/pre-step事件中触发;上下文溢出在agent/request-error中恢复。 - commands :手动压缩命令通过
CommandId关联。 - sessions :手动压缩后通过
ctx.sessions.flush()持久化。
14. E2B 沙箱能力(e2b)
路径 :packages/e2b/
核心作用 :共享 E2B 沙箱拥有者------创建一个 E2B SDK 句柄,文件系统和子进程操作共享同一个远程 Linux 世界。e2b 是服务定义+提供者合一的运行时,fs-e2b 和 subprocess-e2b 是适配器。
内部架构
#mermaid-svg-KvXDlCjJqsr9yP5q{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KvXDlCjJqsr9yP5q .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KvXDlCjJqsr9yP5q .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KvXDlCjJqsr9yP5q .error-icon{fill:#552222;}#mermaid-svg-KvXDlCjJqsr9yP5q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KvXDlCjJqsr9yP5q .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KvXDlCjJqsr9yP5q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KvXDlCjJqsr9yP5q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KvXDlCjJqsr9yP5q .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KvXDlCjJqsr9yP5q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KvXDlCjJqsr9yP5q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KvXDlCjJqsr9yP5q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KvXDlCjJqsr9yP5q .marker.cross{stroke:#333333;}#mermaid-svg-KvXDlCjJqsr9yP5q svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KvXDlCjJqsr9yP5q p{margin:0;}#mermaid-svg-KvXDlCjJqsr9yP5q .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KvXDlCjJqsr9yP5q .cluster-label text{fill:#333;}#mermaid-svg-KvXDlCjJqsr9yP5q .cluster-label span{color:#333;}#mermaid-svg-KvXDlCjJqsr9yP5q .cluster-label span p{background-color:transparent;}#mermaid-svg-KvXDlCjJqsr9yP5q .label text,#mermaid-svg-KvXDlCjJqsr9yP5q span{fill:#333;color:#333;}#mermaid-svg-KvXDlCjJqsr9yP5q .node rect,#mermaid-svg-KvXDlCjJqsr9yP5q .node circle,#mermaid-svg-KvXDlCjJqsr9yP5q .node ellipse,#mermaid-svg-KvXDlCjJqsr9yP5q .node polygon,#mermaid-svg-KvXDlCjJqsr9yP5q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KvXDlCjJqsr9yP5q .rough-node .label text,#mermaid-svg-KvXDlCjJqsr9yP5q .node .label text,#mermaid-svg-KvXDlCjJqsr9yP5q .image-shape .label,#mermaid-svg-KvXDlCjJqsr9yP5q .icon-shape .label{text-anchor:middle;}#mermaid-svg-KvXDlCjJqsr9yP5q .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KvXDlCjJqsr9yP5q .rough-node .label,#mermaid-svg-KvXDlCjJqsr9yP5q .node .label,#mermaid-svg-KvXDlCjJqsr9yP5q .image-shape .label,#mermaid-svg-KvXDlCjJqsr9yP5q .icon-shape .label{text-align:center;}#mermaid-svg-KvXDlCjJqsr9yP5q .node.clickable{cursor:pointer;}#mermaid-svg-KvXDlCjJqsr9yP5q .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KvXDlCjJqsr9yP5q .arrowheadPath{fill:#333333;}#mermaid-svg-KvXDlCjJqsr9yP5q .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KvXDlCjJqsr9yP5q .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KvXDlCjJqsr9yP5q .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KvXDlCjJqsr9yP5q .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KvXDlCjJqsr9yP5q .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KvXDlCjJqsr9yP5q .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KvXDlCjJqsr9yP5q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KvXDlCjJqsr9yP5q .cluster text{fill:#333;}#mermaid-svg-KvXDlCjJqsr9yP5q .cluster span{color:#333;}#mermaid-svg-KvXDlCjJqsr9yP5q div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KvXDlCjJqsr9yP5q .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KvXDlCjJqsr9yP5q rect.text{fill:none;stroke-width:0;}#mermaid-svg-KvXDlCjJqsr9yP5q .icon-shape,#mermaid-svg-KvXDlCjJqsr9yP5q .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KvXDlCjJqsr9yP5q .icon-shape p,#mermaid-svg-KvXDlCjJqsr9yP5q .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KvXDlCjJqsr9yP5q .icon-shape .label rect,#mermaid-svg-KvXDlCjJqsr9yP5q .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KvXDlCjJqsr9yP5q .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KvXDlCjJqsr9yP5q .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KvXDlCjJqsr9yP5q :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-KvXDlCjJqsr9yP5q .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .def tspan{fill:#fff!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .prov tspan{fill:#fff!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .cons tspan{fill:#fff!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .ifc>*{fill:#f8f9fa!important;stroke:#6c757d!important;color:#212529!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .ifc span{fill:#f8f9fa!important;stroke:#6c757d!important;color:#212529!important;}#mermaid-svg-KvXDlCjJqsr9yP5q .ifc tspan{fill:#212529!important;} Consumer
Adapters (Provider for other seams)
Service Definition + Provider
getSandbox()
getSandbox()
注册到 ctx.fs
注册到 ctx.subprocess
ctx.fs / ctx.subprocess
ctx.fs / ctx.subprocess
E2BRuntime (Service)
Config (apiKey, cwd, timeoutMs)
fs-e2b
(E2B 文件系统适配器)
subprocess-e2b
(E2B 子进程适配器)
模型工具
(通过 ctx.fs / ctx.subprocess)
文件系统接口
子进程运行时接口
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
E2BRuntime |
Service (class) | E2B 沙箱运行时:懒创建 SDK 句柄、超时自动删除、共享 cwd 和 runtimeRoot |
Config |
interface | E2B 配置:apiKey(或 E2B_API_KEY)、cwd、timeoutMs |
getSandbox() |
method | 获取共享 SDK 句柄 |
quoteE2BShellArg() |
function | E2B shell 参数引用(SDK 强制 /bin/bash -l -c) |
e2bControlEnvs() |
function | 隔离 E2B 登录 shell 的随机 HOME 路径 |
E2BFileSystem |
class | E2B FS 适配器:路径解析(realpath)、原子写入(staging 目录+rename)、版本追踪 |
E2BSubprocessRuntime |
class | E2B 子进程适配器:远程命令执行、终端会话、轮询状态 |
E2BSubprocessHandle |
class | 远程子进程句柄 |
与其他模块的关系
- fs :
fs-e2b实现FileSystem抽象,注册到ctx.fs。 - subprocess :
subprocess-e2b实现SubprocessRuntime,注册到ctx.subprocess。 - shell:E2B 沙箱可为 Shell 执行提供远程隔离环境。
- terminal :
subprocess-e2b支持spawnTerminal()创建远程终端。
15. MCP 协议能力(mcp)
路径 :packages/mcp/mcp-client/
核心作用 :MCP 客户端桥接插件------连接外部 MCP 服务器,将其工具注册到 ctx.tools 上,使用服务器限定的公开名称 mcp__<serverName>__<rawName>。支持 stdio 和 Streamable HTTP 两种传输方式,自动重连。
内部架构
#mermaid-svg-ozyTlX1xrg4V2uZI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ozyTlX1xrg4V2uZI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ozyTlX1xrg4V2uZI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ozyTlX1xrg4V2uZI .error-icon{fill:#552222;}#mermaid-svg-ozyTlX1xrg4V2uZI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ozyTlX1xrg4V2uZI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ozyTlX1xrg4V2uZI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ozyTlX1xrg4V2uZI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ozyTlX1xrg4V2uZI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ozyTlX1xrg4V2uZI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ozyTlX1xrg4V2uZI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ozyTlX1xrg4V2uZI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ozyTlX1xrg4V2uZI .marker.cross{stroke:#333333;}#mermaid-svg-ozyTlX1xrg4V2uZI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ozyTlX1xrg4V2uZI p{margin:0;}#mermaid-svg-ozyTlX1xrg4V2uZI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ozyTlX1xrg4V2uZI .cluster-label text{fill:#333;}#mermaid-svg-ozyTlX1xrg4V2uZI .cluster-label span{color:#333;}#mermaid-svg-ozyTlX1xrg4V2uZI .cluster-label span p{background-color:transparent;}#mermaid-svg-ozyTlX1xrg4V2uZI .label text,#mermaid-svg-ozyTlX1xrg4V2uZI span{fill:#333;color:#333;}#mermaid-svg-ozyTlX1xrg4V2uZI .node rect,#mermaid-svg-ozyTlX1xrg4V2uZI .node circle,#mermaid-svg-ozyTlX1xrg4V2uZI .node ellipse,#mermaid-svg-ozyTlX1xrg4V2uZI .node polygon,#mermaid-svg-ozyTlX1xrg4V2uZI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ozyTlX1xrg4V2uZI .rough-node .label text,#mermaid-svg-ozyTlX1xrg4V2uZI .node .label text,#mermaid-svg-ozyTlX1xrg4V2uZI .image-shape .label,#mermaid-svg-ozyTlX1xrg4V2uZI .icon-shape .label{text-anchor:middle;}#mermaid-svg-ozyTlX1xrg4V2uZI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ozyTlX1xrg4V2uZI .rough-node .label,#mermaid-svg-ozyTlX1xrg4V2uZI .node .label,#mermaid-svg-ozyTlX1xrg4V2uZI .image-shape .label,#mermaid-svg-ozyTlX1xrg4V2uZI .icon-shape .label{text-align:center;}#mermaid-svg-ozyTlX1xrg4V2uZI .node.clickable{cursor:pointer;}#mermaid-svg-ozyTlX1xrg4V2uZI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ozyTlX1xrg4V2uZI .arrowheadPath{fill:#333333;}#mermaid-svg-ozyTlX1xrg4V2uZI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ozyTlX1xrg4V2uZI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ozyTlX1xrg4V2uZI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ozyTlX1xrg4V2uZI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ozyTlX1xrg4V2uZI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ozyTlX1xrg4V2uZI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ozyTlX1xrg4V2uZI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ozyTlX1xrg4V2uZI .cluster text{fill:#333;}#mermaid-svg-ozyTlX1xrg4V2uZI .cluster span{color:#333;}#mermaid-svg-ozyTlX1xrg4V2uZI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ozyTlX1xrg4V2uZI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ozyTlX1xrg4V2uZI rect.text{fill:none;stroke-width:0;}#mermaid-svg-ozyTlX1xrg4V2uZI .icon-shape,#mermaid-svg-ozyTlX1xrg4V2uZI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ozyTlX1xrg4V2uZI .icon-shape p,#mermaid-svg-ozyTlX1xrg4V2uZI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ozyTlX1xrg4V2uZI .icon-shape .label rect,#mermaid-svg-ozyTlX1xrg4V2uZI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ozyTlX1xrg4V2uZI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ozyTlX1xrg4V2uZI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ozyTlX1xrg4V2uZI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-ozyTlX1xrg4V2uZI .def>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-ozyTlX1xrg4V2uZI .def span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-ozyTlX1xrg4V2uZI .def tspan{fill:#fff!important;}#mermaid-svg-ozyTlX1xrg4V2uZI .prov>*{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-ozyTlX1xrg4V2uZI .prov span{fill:#F5A623!important;stroke:#D4860B!important;color:#fff!important;}#mermaid-svg-ozyTlX1xrg4V2uZI .prov tspan{fill:#fff!important;}#mermaid-svg-ozyTlX1xrg4V2uZI .cons>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-ozyTlX1xrg4V2uZI .cons span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-ozyTlX1xrg4V2uZI .cons tspan{fill:#fff!important;} Consumer
Tool Bridge
Connection Layer
Service Definition
syncTools
ctx.tools.register
调用 mcp__ 工具
mcp-client (plugin)
Config (stdio / streamable-http)
connection.ts
(连接监督器)
transport.ts
(stdio / HTTP 传输)
tools.ts
(工具同步桥)
ctx.tools
(Harness 工具注册表)
Agent 主循环
关键类/函数
| 名称 | 类型 | 职责 |
|---|---|---|
apply() |
function | 插件入口:连接 MCP 服务器、初始工具发现、注册到 ctx.tools |
Config |
type union | 传输配置:stdio(command/args/env/cwd)或 streamable-http(url/headers) |
startConnection() |
function | 连接监督器:世代管理、自动重连(指数退避)、工具同步 |
resolveReconnectPolicy() |
function | 重连策略解析:enabled、initialDelayMs、maxDelayMs、maxAttempts |
syncTools() |
function | 工具同步桥:分页 tools/list、构建 ToolDefinition、交换世代、注册到 ctx.tools |
publicToolName() |
function | 公开名称生成:mcp__<serverName>__<rawName>,规范化+哈希防碰撞 |
createExecutor() |
function | 工具执行器:发送 tools/call(使用 rawName)、信号/超时、结果映射 |
createOutput() |
function | 输出 schema 构建:content + structuredContent |
RECONNECT_DEFAULTS |
const | 默认重连参数:initialDelay=500ms、maxDelay=30s、maxAttempts=10 |
activeServerNames |
WeakMap | 活跃服务器名注册表,防止命名空间冲突 |
与其他模块的关系
- tools (dsh-tools):MCP 工具注册到
ctx.tools,使用ToolDefinition和ToolExecution接口。 - timeout :重连策略使用
MAX_TIMER_DELAY_MS边界。 - agent :Agent 主循环通过 ToolRuntime 调用
mcp__*工具。 - llm :MCP 工具的输出通过
ContentBlock注入 LLM 上下文。
能力接缝整体协作
中心枢纽架构
所有能力接缝通过 Cordis 的 Context(ctx)对象作为中心枢纽连接。每个接缝通过 declare module '@deepseek-ai/cordis' 的接口合并(declaration merging)将自己的服务声明添加到 Context 上:
ctx.llm--- LLM 运行时ctx.shell--- Shell 执行器ctx.subprocess--- 子进程运行时ctx.fs--- 文件系统ctx.web--- Web 搜索/抓取ctx.lsp--- 语言服务器ctx.terminals--- 终端会话ctx.codeRuntime--- 代码运行时ctx.sandbox--- 沙箱提供商ctx.skills--- 技能注册表ctx.subagents--- 子代理运行时ctx.workflowEngine--- 工作流引擎ctx.compaction--- 上下文压缩ctx.e2b--- E2B 沙箱ctx.tools--- 工具注册表(dsh-tools,非本分析范围但 MCP 依赖)
整体协作图
#mermaid-svg-gtQlE6VzdsBwlhlz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gtQlE6VzdsBwlhlz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gtQlE6VzdsBwlhlz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gtQlE6VzdsBwlhlz .error-icon{fill:#552222;}#mermaid-svg-gtQlE6VzdsBwlhlz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gtQlE6VzdsBwlhlz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gtQlE6VzdsBwlhlz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gtQlE6VzdsBwlhlz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gtQlE6VzdsBwlhlz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gtQlE6VzdsBwlhlz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gtQlE6VzdsBwlhlz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gtQlE6VzdsBwlhlz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gtQlE6VzdsBwlhlz .marker.cross{stroke:#333333;}#mermaid-svg-gtQlE6VzdsBwlhlz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gtQlE6VzdsBwlhlz p{margin:0;}#mermaid-svg-gtQlE6VzdsBwlhlz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gtQlE6VzdsBwlhlz .cluster-label text{fill:#333;}#mermaid-svg-gtQlE6VzdsBwlhlz .cluster-label span{color:#333;}#mermaid-svg-gtQlE6VzdsBwlhlz .cluster-label span p{background-color:transparent;}#mermaid-svg-gtQlE6VzdsBwlhlz .label text,#mermaid-svg-gtQlE6VzdsBwlhlz span{fill:#333;color:#333;}#mermaid-svg-gtQlE6VzdsBwlhlz .node rect,#mermaid-svg-gtQlE6VzdsBwlhlz .node circle,#mermaid-svg-gtQlE6VzdsBwlhlz .node ellipse,#mermaid-svg-gtQlE6VzdsBwlhlz .node polygon,#mermaid-svg-gtQlE6VzdsBwlhlz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gtQlE6VzdsBwlhlz .rough-node .label text,#mermaid-svg-gtQlE6VzdsBwlhlz .node .label text,#mermaid-svg-gtQlE6VzdsBwlhlz .image-shape .label,#mermaid-svg-gtQlE6VzdsBwlhlz .icon-shape .label{text-anchor:middle;}#mermaid-svg-gtQlE6VzdsBwlhlz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gtQlE6VzdsBwlhlz .rough-node .label,#mermaid-svg-gtQlE6VzdsBwlhlz .node .label,#mermaid-svg-gtQlE6VzdsBwlhlz .image-shape .label,#mermaid-svg-gtQlE6VzdsBwlhlz .icon-shape .label{text-align:center;}#mermaid-svg-gtQlE6VzdsBwlhlz .node.clickable{cursor:pointer;}#mermaid-svg-gtQlE6VzdsBwlhlz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gtQlE6VzdsBwlhlz .arrowheadPath{fill:#333333;}#mermaid-svg-gtQlE6VzdsBwlhlz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gtQlE6VzdsBwlhlz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gtQlE6VzdsBwlhlz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gtQlE6VzdsBwlhlz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gtQlE6VzdsBwlhlz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gtQlE6VzdsBwlhlz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gtQlE6VzdsBwlhlz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gtQlE6VzdsBwlhlz .cluster text{fill:#333;}#mermaid-svg-gtQlE6VzdsBwlhlz .cluster span{color:#333;}#mermaid-svg-gtQlE6VzdsBwlhlz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gtQlE6VzdsBwlhlz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gtQlE6VzdsBwlhlz rect.text{fill:none;stroke-width:0;}#mermaid-svg-gtQlE6VzdsBwlhlz .icon-shape,#mermaid-svg-gtQlE6VzdsBwlhlz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gtQlE6VzdsBwlhlz .icon-shape p,#mermaid-svg-gtQlE6VzdsBwlhlz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gtQlE6VzdsBwlhlz .icon-shape .label rect,#mermaid-svg-gtQlE6VzdsBwlhlz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gtQlE6VzdsBwlhlz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gtQlE6VzdsBwlhlz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gtQlE6VzdsBwlhlz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-gtQlE6VzdsBwlhlz .hub>*{fill:#9B59B6!important;stroke:#7D3C98!important;color:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .hub span{fill:#9B59B6!important;stroke:#7D3C98!important;color:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .hub tspan{fill:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .seam>*{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .seam span{fill:#4A90D9!important;stroke:#2C5F8A!important;color:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .seam tspan{fill:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .agent>*{fill:#E74C3C!important;stroke:#C0392B!important;color:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .agent span{fill:#E74C3C!important;stroke:#C0392B!important;color:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .agent tspan{fill:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .tool>*{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .tool span{fill:#7ED321!important;stroke:#5DA016!important;color:#fff!important;}#mermaid-svg-gtQlE6VzdsBwlhlz .tool tspan{fill:#fff!important;} Model Tools (Consumers)
Agent 主循环
Capability Seams
Cordis Context (ctx) --- 中心枢纽
ctx.llm.stream
ctx.compaction
ctx.subagents
ctx.tools
ctx.tools.register
Context
ctx.llm
ctx.shell
ctx.subprocess
ctx.fs
ctx.web
ctx.lsp
ctx.terminals
ctx.codeRuntime
ctx.sandbox
ctx.skills
ctx.subagents
ctx.workflowEngine
ctx.compaction
ctx.e2b
mcp-client → ctx.tools
Agent Loop
systemPrompt
tool-bash
tool-fs
tool-web
tool-lsp
tool-terminal
tool-skill
tool-subagent
tool-workflow
mcp__* tools
典型调用链路
链路 1:模型执行 Shell 命令
Agent → tool-bash → ctx.shell.exec(command)
→ ShellExecutor (bash-local 或 bash-sandbox)
→ ctx.subprocess.spawn(argv) [如果需要子进程]
→ LocalSubprocessRuntime / E2BSubprocessRuntime
→ 返回 stdout/stderr/exitCode
→ 渲染为 ContentBlock
→ 注入会话历史
→ 下一轮 LLM 调用 (ctx.llm.stream)
链路 2:模型委派子代理
Agent → tool-subagent → ctx.subagents.start(request)
→ SubagentRuntime 选择命名 Provider (spawn/fork/acp)
→ SpawnInProcessProvider.start()
→ 创建子 Agent (复用 Agent 工厂)
→ 子 Agent 主循环
→ ctx.llm.stream() [子代理的 LLM 调用]
→ 可递归调用工具 (ctx.shell, ctx.fs, ...)
→ 子 Agent 完成
→ SubagentRun.result 解析
→ 返回 SubagentResult.output
→ 注入父会话历史
链路 3:模型执行工作流脚本
Agent → tool-workflow → ctx.workflowEngine.start(request)
→ WorkerThreadWorkflowEngine.start()
→ 验证 meta + 解析脚本体
→ 创建 Worker Thread
→ Worker 执行脚本 (vm 沙箱)
→ agent() 调用 → ctx.subagents.start() [桥接到宿主]
→ 子代理执行并返回结果
→ parallel() / pipeline() 组合器
→ phase() / log() 进度事件
→ 脚本 return 值
→ WorkflowRun.result 解析
→ 返回 value
→ 注入会话历史
链路 4:自动上下文压缩
Agent 主循环 → agent/pre-step 事件
→ BasicCompactionEngine.compactIfNeeded(agent, 'pressure')
→ ctx.tokenMeter.measure(session) [token 计量]
→ 超过阈值?
→ compaction-tool-result-pruner.pruneSession() [可选裁剪]
→ 重新计量
→ selectCompactableRange() [选择压缩范围]
→ summarizeWithLlm() [通过 ctx.llm.stream() 生成摘要]
→ 复用会话前缀 (系统提示 + 工具 + 消息) 保持 KV 缓存
→ compactSurfaceRegion() [替换历史范围为摘要节点]
→ 发出 compaction/start, compaction/summary, compaction/end 事件
→ 返回 CompactionResult
链路 5:MCP 工具调用
Agent → 模型选择 mcp__<server>__<tool> 工具
→ ctx.tools 执行注册的 execute 函数
→ mcp-client createExecutor()
→ client.request('tools/call', { name: rawName, arguments })
→ MCP 服务器进程 (stdio 或 HTTP)
→ 返回 content + structuredContent
→ 映射为 ContentBlock
→ 注入会话历史
链路 6:E2B 远程隔离执行
Agent → tool-bash → ctx.shell.exec(command)
→ bash-sandbox Provider
→ ctx.sandbox (或直接) → E2BSubprocessRuntime
→ ctx.e2b.getSandbox() [获取共享 E2B 沙箱]
→ sandbox.commands.run(command)
→ 远程 Linux 沙箱执行
→ 返回 stdout/stderr/exitCode
模型读取远程文件:
Agent → tool-fs → ctx.fs.readText(target)
→ E2BFileSystem
→ ctx.e2b.getSandbox()
→ sandbox.files.read(path)
→ 返回文件内容
设计模式总结
-
定义→提供者→消费者三方分离 :每个能力接缝严格遵循三层分离,Service Definition 只声明接口和类型,Service Provider 实现接口并注册,Consumer(通常是 tool)通过
ctx.<capability>调用。这使得同一接口可以有多种后端实现(本地、沙箱、远程)而不影响消费者代码。 -
命名提供商注册表 vs 单一服务:某些接缝(shell、fs、subprocess)是单一服务模式------一个上下文只加载一个 Provider,第二次加载抛异常。另一些(subagent、llm)是命名注册表模式------多 Provider 共存,调用方按名称选择。后者镜像了 LLM 适配器注册表的设计。
-
能力验证(Fail Loud) :
SubagentProvider.capabilities声明支持的功能(outputSchema、depthLimit、toolFilter、persona),服务在委派前验证请求的能力是否被支持------不支持则抛出类型化错误,而非静默降级。 -
品牌 ID 与不变式 :LLM 模块定义了
MessageId、CallId、StreamId等品牌 ID,compaction 定义CompactionId,subagent 定义SubagentRunId、workflow 定义WorkflowRunId------品牌类型防止跨模块的 ID 混用,不变式函数在关键边界断言合法性。 -
事件驱动的生命周期 :每个接缝通过 Cordis 的
declare module机制向Events接口合并自己的事件(如workflow/start、subagent/start、compaction/start),观察者可以订阅这些事件而不持有运行句柄。 -
E2B 作为跨接缝共享层 :E2B 沙箱是一个特殊的"元接缝"------它不直接暴露给模型工具,而是作为
fs和subprocess接缝的远程后端,通过共享 SDK 句柄让文件系统和子进程操作处于同一个远程 Linux 世界。 -
Worker Thread 隔离 :
code-runtime和workflow都使用 Worker Thread 执行不可信代码(模型生成的 JS 脚本),vm 沙箱提供 containment 而非安全边界------这是"隔离但非安全"的明确设计选择。 -
MCP 桥接的命名空间隔离 :MCP 客户端通过
mcp__<serverName>__<rawName>命名约定将外部工具注册到ctx.tools,使用 SHA-256 哈希防碰撞,确保多个 MCP 服务器的工具不会命名冲突。连接监督器管理世代交替和自动重连。