Direct model conversations can now execute bounded platform-native processes and delegate one level of programming work without duplicating tools in Agent Runtimes. Process and Subagent activity follows existing workspace, mode, approval, cancellation, and lifecycle boundaries, with chat attribution and complete feature documentation. Remove the static Renderer bundle baseline gate and its build-only manifests; production builds continue to compile all processes and verify the control-plane installer. Also include the pending documentation link normalization. Release note: 直连模型现在可在 Execute 模式运行本机命令,并可委派编程 Subagent 完成修改、测试和复核;构建流程不再因静态 Renderer 包体基线阻塞。
14 KiB
直连模型 Agent 能力技术设计
文档信息
| 项目 | 内容 |
|---|---|
| 状态 | 已实施 |
| 版本 | 0.2 |
| 日期 | 2026-09-01 |
| 关联 PRD | PRD |
| 功能逻辑 | 功能逻辑设计 |
| 相关架构 | 助手工作栏与执行空间、本机工具环境 |
1. 实现基线
当前源码已经实现:
ModelAgentRuntime的多轮工具调用、上下文压缩、取消、用量和有界结果处理。ModelToolProvider的直连模型内置工具、浏览器、Web、知识和自定义 MCP 聚合。WorkspaceAccess的本机和远端工作区抽象。- 跨平台子进程树终止辅助函数。
- 面向用户专家协作的
SubagentScheduler、状态事件和只读模型调用。 - OpenCode、Continue 和 DeepSeek Harness 各自的 Shell/Agent 能力。
- 直连模型
process_execute和subagent_delegate。 - 不创建顶层 Task/Conversation 的编程 Subagent actor 与活动归并。
2. 总体架构
ModelAgentRuntime
└─ ModelToolProvider
├─ WorkspaceAccess
├─ DirectModelProcessService
│ └─ LocalDirectModelProcessService
├─ DirectModelSubagentService
│ ├─ SubagentScheduler
│ └─ 同一 ModelAgentRuntime 的临时子会话
│ └─ 同一 ModelToolProvider(delegationDepth=1 时移除委派)
├─ Browser / Web / Knowledge
└─ assigned MCP
OpenCode、Continue 和 DeepSeek Harness 的创建路径不接收
DirectModelProcessService 或 DirectModelSubagentService。DeepSeek Harness 即使继续使用
ModelToolProvider 代理 Web/MCP,也必须通过明确的工具视图排除直连模型专属工具。
3. 共享工具目录
BuiltinModelToolSummary 增加 programming 分组和 Runtime 可见性:
type BuiltinModelToolSummary = {
name: string
displayName: string
description: string
access: 'read' | 'write'
group: 'filesystem' | 'browser' | 'web' | 'programming'
}
process_execute 标记为 write,只在 Execute 清单中出现。
subagent_delegate 的实际访问级别由父模式决定:
- Ask 清单中提供只读委派定义。
- Execute 清单中提供继承 Execute 的定义。
callTool不依赖静态access单独授权,必须检查父请求上下文。
工具总数和 schema 总字节继续计入直连模型现有 100 个工具与 512 KiB 上限。
4. 进程工具契约
4.1 输入
const processExecuteInputSchema = z.object({
command: z.string().trim().min(1).max(100_000),
cwd: z
.string()
.trim()
.min(1)
.max(4_096)
.optional(),
timeoutMs: z
.number()
.int()
.min(1_000)
.max(10 * 60_000)
.default(120_000)
}).strict()
cwd只接受相对工作区路径。- 首版不接受
env、stdin、background、pty、shell或任意 executable 参数。 - Shell 选择由执行后端决定,防止模型绕过平台契约启动另一套受管接口。
- 命令字符串仍可以调用当前账号本来有权运行的程序;Execute 不增加命令白名单。
4.2 结果
type ProcessExecuteResult = {
shell: {
kind: 'powershell' | 'bash' | 'sh'
label: string
}
cwd: string
exitCode: number | null
signal?: string
terminationReason?: 'timeout' | 'cancelled'
durationMs: number
stdout: string
stderr: string
stdoutTruncated: boolean
stderrTruncated: boolean
}
cwd 返回工作区相对显示值,不把不必要的绝对用户路径送入模型上下文。Shell 在模型结果
中只返回稳定标签;绝对可执行路径只进入 Main 诊断状态。
4.3 输出边界
- stdout 和 stderr 各最多 96 KiB。
- 超限时分别保留前 48 KiB 与最后 48 KiB,中间插入固定截断标记。
- JSON 结果加上元数据后必须低于
ModelToolProvider现有 256 KiB 工具结果上限。 - 流式读取在收到数据时执行边界,不先积累无界 Buffer。
- 输出按 UTF-8 解码,无效序列使用替换字符并保留字节计数。
5. 平台执行
5.1 Shell 探测
启动直连模型执行服务时解析一次 Shell:
Windows: PATH 中 pwsh → Windows PowerShell powershell.exe
macOS: /bin/bash → /bin/sh
Linux: /bin/bash → /bin/sh
Shell 不可用时保留直连模型对话能力,但不注册 process_execute。设置目录继续展示静态能力
说明,实际 Shell 通过每次请求的工具定义和结果可见;当前不增加独立 Shell 诊断 IPC。
不下载或捆绑新的 Bash/PowerShell。
5.2 启动参数
PowerShell:
<shell> -NoLogo -NoProfile -NonInteractive -Command <command>
Bash:
/bin/bash -c <command>
Sh:
/bin/sh -c <command>
使用 spawn(executable, args, { shell: false }),避免 Node 再增加一层平台 Shell。POSIX 子进程
作为独立进程组启动;Windows 记录根 PID。停止时复用现有
terminateProcessTreeAndWait:Windows 使用 taskkill /T /F,POSIX 终止本次进程组并等待
有界退出。
5.3 环境
进程环境由 Main 构造:
- 继承运行普通项目命令所需的当前用户基础变量。
- 当前使用筛选后的用户 PATH;本机工具环境
实施后可通过现有
toolBinDirectory注入口把受管 bin 放在 PATH 前面。 - 排除模型 Provider Key、GoodBuddy 加密设置、调试变量和无关应用凭据。
- 不修改
process.env,不写系统 PATH 或 Shell Profile。 - 每次调用得到独立环境快照;命令内设置的变量不会进入下一次调用。
6. 执行空间绑定
定义一个小型进程后端接口,不把任意进程能力塞进 WorkspaceAccess:
interface ExecutionSpaceProcessExecutor {
getCapability(): Promise<
| { available: true; shell: ProcessShellSummary }
| { available: false; reason: string }
>
execute(
input: ProcessExecuteInput,
context: {
workspace: WorkspaceAccess
signal: AbortSignal
}
): Promise<ProcessExecuteResult>
dispose(): Promise<void>
}
首版只有 LocalProcessExecutor。ExecutionSpaceDescriptor.kind === 'ssh' 时使用不可用实现,
工具清单不注册进程能力。未来远端实现必须新增 Agent 协议、由 Agent 直接拥有命令进程,并
按远端身份、取消和断线语义验证;不得把 SSH 路径传给本机 executor。
工作目录通过 WorkspaceAccess.getIdentity() 和本机真实路径解析共同确认。路径检查与 spawn
之间若目录被外部替换,spawn 失败并返回准确错误;不为此增加持久路径凭据或恢复协议。
7. Subagent 工具契约
7.1 输入
const subagentDelegateInputSchema = z.object({
task: z.string().trim().min(1).max(100_000)
}).strict()
首版一次调用只创建一个子任务。不同父请求可以通过全局调度器并发,不增加批量委派 schema。
7.2 子请求
DirectModelSubagentService 创建临时子请求:
type DirectModelSubagentContext = {
parentRequestId: string
childRunId: string
projectId?: string
conversationId: string
workMode: 'ask' | 'execute'
}
- 子
conversationId只用于 Runtime 内存和工具会话隔离,完成后立即releaseConversation,不保存为用户 Conversation。 - 子 Prompt 使用明确任务和 Main 可信的编程 Subagent 指令,不复制父会话历史。
- 子级使用父请求模型连接,首版不增加单独模型选择设置。
- 子级复用父请求已授权能力快照和知识范围。
- 子级复用父 Provider;Main 写入的
delegationDepth=1同时在清单和调用边界过滤subagent_delegate。 - Ask 子级使用 Ask 清单;Execute 子级使用 Execute 清单。
7.3 调度和结果
- 复用
SubagentScheduler的取消、并发和队列模式。 - 全局最大并发 3,队列最大 20。
- 单个子任务最长 10 分钟;父请求更早取消时立即停止。
- 文本结果最多 192 KiB,错误最多 2 KiB,连同结构化字段保持在 256 KiB 工具结果上限内。
- 模型用量逐事件归属父请求和
childRunId,不能只算入父模型最后一轮。 - 子级失败和取消返回结构化终态及部分输出,让父模型决定下一步。
7.4 领域持久化
当前 SubagentService 为历史专家流程创建隐藏 Child Task。新编程 Subagent 不复制该行为:
- 运行身份使用内部
childRunId。 - 父消息通过现有
subagent活动块保存终态和结果摘要。 - 若通用 Job/Subjob 表已经实现,则记录为所属父 Task/请求的 Subjob/Run。
- 若通用 Job/Subjob 表尚未实现,首版只保存现有消息活动和模型用量,不先创建另一套持久 子任务表、恢复日志或兼容读取器。
可以提取现有 Scheduler、事件归并和用量转发逻辑,但不能把旧数据库字段当成新的产品模型。
8. ModelToolProvider 接入
ModelToolCallContext 增加不可伪造的运行上下文:
type ModelToolCallContext = {
conversationId: string
requestId: string
runtimeTarget: 'model'
workMode: 'ask' | 'execute'
executionSpaceIdentity: string
delegationDepth: 0 | 1
knowledgeCapabilityToken?: string
}
要求:
listTools根据模式、执行空间能力和深度生成快照。getApproval不为两个工具创建第二套逐次确认;沿用父 Execute 授权和现有通道工具策略。callTool再次检查runtimeTarget、模式、执行空间 identity、深度和请求是否活动。releaseConversation取消并释放该会话拥有的浏览器、Subagent 和进程。dispose等待有界清理,不因模型或子进程不响应而阻塞应用退出。
DeepSeek Harness 的 Main 工具代理必须使用仅包含分配 MCP 和 Web 的 Provider 视图,不能因为
共享 ModelToolProvider 类而自动看到直连模型编程工具。
9. 事件与活动
9.1 进程事件
继续使用现有 Runtime tool 事件:
pending:参数已接收。running:Shell 已成功启动。completed:返回 exit 0 或非零退出结果。failed:启动或契约失败。cancelled:父请求取消。
结果摘要包含 Shell、相对目录、退出码、耗时和截断标记。完整有界 stdout/stderr 进入工具 输出字段,不写应用诊断日志。
9.2 Subagent 事件
复用现有 subagent 公开事件和消息块,增加 routingMode: 'native' 表示模型主动委派。
expertId 不再作为编程 Subagent 必填身份;共享 schema 应改为执行者 discriminated union,
而不是伪造一个专家记录:
type SubagentActor =
| { kind: 'expert'; expertId: string; expertName: string }
| { kind: 'direct-model'; label: '编程 Subagent' }
迁移只需让读取器接受旧专家事件和新联合类型,不重写既有消息。
10. 错误处理
| 情况 | 结果 |
|---|---|
| 命令非零退出 | 正常 ProcessExecuteResult |
| 命令不存在 | Shell 非零退出及 stderr |
| Shell 无法启动 | 工具失败 |
| cwd 无效或越界 | 工具调用前失败 |
| 超时/取消 | 终止进程树,返回已有输出和原因 |
| 子级模型失败 | 返回 failed、部分输出和错误 |
| 子级工具失败 | 由子模型处理;最终无法完成时返回子级失败 |
| 父请求已终止 | 拒绝新调用,丢弃迟到内容并清理 |
不要用宽泛 catch 抹掉取消、超时、Provider HTTP 状态或进程退出上下文。
11. 性能
- Shell 探测按执行服务实例缓存,不在每轮模型调用重复探测。
- stdout/stderr 边读边界定,避免大日志进入内存后再截断。
- 子级共享父请求已解析的模型配置和工具服务,不复制 MCP 配置或持久状态。
- 不增加持久 Shell、后台 daemon、工作区快照或恢复状态机。
- 命令执行不使用 PTY,避免普通构建和测试承担终端渲染成本。
12. 测试策略
12.1 单元测试
- 工具可见性矩阵和 Runtime target 过滤。
- Ask 伪造进程调用拒绝。
- Windows PowerShell、POSIX Bash/Sh 选择和参数。
- cwd 默认、合法子目录、越界、符号链接越界和不存在。
- exit 0、非零退出、spawn 失败、超时、取消和输出截断。
- 环境筛选、本机工具 PATH 优先且模型凭据不进入进程。
- 子级模式、模型、项目、执行空间和能力继承。
- 深度 1 过滤、并发 3、队列 20、取消传播和部分输出。
- 编程 Subagent 不创建 Task/Conversation。
- DeepSeek Harness/OpenCode/Continue 不获得本功能工具。
12.2 本机集成测试
- Windows PowerShell 创建临时文件、运行 Node/Python、非零退出和进程树取消。
- macOS/Linux Bash/Sh 执行相同场景。
- 直连模型工具循环执行“修改 → 测试失败 → 修复 → 测试通过”。
- 父模型委派子级修改或验证专用临时项目,并正确综合结果。
- Runtime 切换后工具清单刷新且没有重复 Shell。
- 应用退出后无残留 GoodBuddy 命令进程。
所有测试只在专用临时工作区创建文件,不删除或覆盖用户工作。
12.3 真实模型验证
使用一个最小真实直连文本模型请求:
- Execute 创建一段有缺陷的小程序。
- 调用进程工具运行聚焦测试并观察失败。
- 修改程序并再次运行到通过。
- 委派一个 Subagent 检查实现或补充测试。
- 父模型读取子级结果并给出最终结论。
每个平台一次完整场景即可,不进行批量或高成本调用。记录准确模型调用次数,不记录 API Key。
12.4 项目验证
源码完成后运行:
npm test
npm run typecheck
npm run lint
npm run build
跨平台进程实现必须由 Windows、macOS、Linux x64 和 Linux arm64 CI 验证。首版不改变 GoodBuddy Agent 或桌面到 Agent 生产路径,因此不要求远端 Host 验证;未来增加远端 executor 时必须按远程主机技术设计执行共享 Linux Host 真机验证。
13. 实施顺序
- Shared 工具摘要、schema 和 Runtime target 过滤。
- 本机 Shell 探测、进程执行、输出边界和进程树取消。
ModelToolProviderExecute 接入及 UI 活动。- 编程 Subagent 服务、过滤 Provider、事件和用量。
- 设置能力目录与状态诊断。
- 三平台真实命令、真实模型和完整项目验证。
每一步都必须保持直连模型正常问答可用;Shell 不可用不能阻止普通对话。