fix: remove avoidable model runtime limits

Preserve long histories and parsed attachments, expose paged process and Subagent output, isolate MCP discovery failures, and expand browser snapshots and knowledge result selection. Remove fixed Harness output and updated remote Runtime duration limits.

Keep released Agent profile and v1 bridge compatibility while enabling larger framed exchanges and optional limits for updated peers. Document remote coverage requirements and real-model boundary validation.

Release note: Long model tasks can retain more context and continue reading complete tool output; remote execution preserves compatibility with released Agents. Updated remote limits require an updated Agent and Runtime bundle.
This commit is contained in:
mesalogo
2026-09-10 03:01:21 +08:00
parent 80b0b18712
commit b01a856bae
62 changed files with 1285 additions and 465 deletions
+5 -2
View File
@@ -24,6 +24,7 @@
| 进程执行 | GoodBuddy 在当前执行空间启动一个前台 Shell 命令并返回有界结果 |
| 工作区搜索 | 通过安装包内置 ripgrep 搜索内容或列出文件,并返回紧凑结果 |
| 工作区补丁 | 通过 `*** Begin Patch` 格式新增、修改或删除工作区文本文件 |
| 输出续读 | 通过 `output_read` 分页读取当前会话保留的进程或 Subagent 输出 |
| 平台 Shell | Windows 上的 PowerShell,macOS/Linux 上的 Bash 或 POSIX Sh |
| 编程 Subagent | 由直连模型临时委派、使用直连模型 Runtime 执行一个有界子任务的执行者 |
| 父请求 | 发起进程调用或 Subagent 委派的当前直连模型请求 |
@@ -35,13 +36,15 @@ Task、Job、Subjob、Run 和 Subagent 的对象关系以
## 功能边界
- `workspace_rg`、`workspace_read_text`、`workspace_apply_patch`、`process_execute` 和
`subagent_delegate` 是 GoodBuddy 直连模型内置工具,不是外部 MCP。
- `workspace_rg`、`workspace_read_text`、`workspace_apply_patch`、`process_execute`、
`subagent_delegate` 和 `output_read` 是 GoodBuddy 直连模型内置工具,不是外部 MCP。
- 直连文本模型的普通问答、工具轮次和上下文摘要会在尚无可见输出时,对瞬时网络错误或
单次请求超时最多自动重试 3 次。
- OpenCode、Continue 和 DeepSeek Harness 继续使用各自原生执行与委派能力。
- Ask 可搜索和分页读取工作区,但不允许补丁写入或进程执行;Subagent 若在 Ask 中使用,
只能继承 Ask 的只读能力。
- 进程和 Subagent 的长输出返回预览与续读位置,完整内容保留到所属会话或 Runtime 释放。
Ask 和 Execute 均可续读当前会话已取得的输出,详见 [输出契约](./technical-design.md#43-输出边界)。
- Execute 表示用户授权当前执行空间账号的完整能力,不增加第二套工具审批或权限档位。
- 首版跨平台指桌面本机 Windows、macOS 和 Linux。托管 SSH 项目当前继续使用远端
OpenCode;未来若向远端直连模型开放本工具,命令必须由 Host Agent 执行,绝不能回退到
@@ -27,6 +27,8 @@
12. Ask 可调用 `workspace_rg` 和 `workspace_read_text`,但不能调用
`workspace_apply_patch`;Execute 可调用三者。
13. 工作区搜索固定使用随包 ripgrep 的结构化输出,不把任意 ripgrep 参数转成命令执行。
14. FR-7 / US-A6:预览之外的进程和 Subagent 输出保留在所属会话下,分页续读不启动新命令。
会话释放先停止活动工作,再删除输出;子会话结束不删除父会话拥有的 Subagent 结果。
## 2. 状态维度
@@ -53,6 +55,10 @@
工具清单隐藏不是最终授权边界。`callTool` 仍须重新验证 Runtime、工作模式、执行空间和父请求
是否活动,以拒绝旧快照或伪造调用。
`output_read` 在直连模型拥有进程或 Subagent 服务时提供,Ask/Execute 均可用,不取决于
本轮 Shell 可用性、是否允许再次委派或委派深度。读取只接受当前会话的句柄;其他 Runtime
不注册该工具,调用边界同样拒绝。
## 4. 进程状态机
```text
@@ -71,7 +77,7 @@ validating
规则:
- `completed_nonzero` 仍产生正常工具结果。
- 超时和取消结果包含已经取得的有界输出。
- 超时和取消结果包含已取得输出的预览;超出预览的内容按 FR-7 继续保留,直到所属会话释放。
- 进入 `terminating` 后不再接受新输入,也不启动替代命令。
- 终止只针对本次调用记录的进程树。
- 迟到的 `close` 只用于清理,不得覆盖已提交的取消或超时原因。
+7 -4
View File
@@ -113,8 +113,8 @@ Ask 禁止命令和写入。Execute 是用户对当前执行空间账号的完
### FR-1 直连模型专属可用性
- 两个工具只由 Runtime provider `model` 注册。
- Agent Runtime 切换为 OpenCode、Continue 或 DeepSeek Harness 后不再显示这两个工具。
- 进程、编程 Subagent 和输出续读工具只由 Runtime provider `model` 注册。
- Agent Runtime 切换为 OpenCode、Continue 或 DeepSeek Harness 后不再显示这些工具。
- 图像生成连接不获得文本 Agent 工具。
- 能力不可用时返回准确原因,不以其他 Runtime 或本机 Shell 静默代替。
@@ -159,8 +159,10 @@ Ask 禁止命令和写入。Execute 是用户对当前执行空间账号的完
- 父请求取消必须传播到活动 Subagent 和其当前进程。
- Runtime 替换、会话释放和应用退出必须停止 GoodBuddy 创建的活动子进程。
- 命令、标准输出、标准错误、Subagent 提示、结果、队列和并发全部有界。
- 截断必须明确标记,不能把不完整输出伪装为完整结果。
- 命令、Subagent 提示、单次返回的输出预览、队列和并发有界;完整输出不因超过预览容量而丢弃。
- 预览省略内容时明确标记并提供续读位置。模型可用 `output_read` 逐页取得完整日志及
Subagent 结果,包括失败或取消前已取得的部分输出。
- Ask 和 Execute 均可续读当前会话的输出。会话或 Runtime 释放后,临时输出删除,旧句柄失效。
### FR-8 环境和凭据
@@ -212,6 +214,7 @@ Ask 禁止命令和写入。Execute 是用户对当前执行空间账号的完
- [ ] Subagent 不能递归委派,不能切换父请求工作区、模式或模型。
- [ ] 切换到 OpenCode、Continue 或 DeepSeek Harness 后不出现本功能工具。
- [ ] 非零退出、超时、取消和输出截断均准确展示。
- [ ] 模型能续读长输出中未出现在预览内的中间与结尾内容,中文和表情不会导致分页停滞。
- [ ] 取消父请求和退出应用后没有残留 GoodBuddy 命令进程。
- [ ] 本机工具环境选择对新命令生效,Main 持有的模型凭据不进入子进程。
- [ ] 子任务不进入 Task Center,不创建独立可导航 Conversation。
+24 -3
View File
@@ -13,9 +13,10 @@
## 当前结论
本机生产路径已经完成源码接线:直连模型 Execute 可运行平台 Shell,Ask/Execute 均可按
父模式委派单层编程 Subagent;OpenCode、Continue、DeepSeek Harness 和托管 SSH 路径不注入
这两个工具。Windows 本机、真实模型和全量项目验证已通过;macOS 与 Linux 真机验证仍需
由对应平台完成。
父模式委派单层编程 Subagent;长输出可通过 `output_read` 续读。OpenCode、Continue、
DeepSeek Harness 和托管 SSH 路径不注入这些工具。既有功能的 Windows 本机、真实模型和
全量项目验证已通过;本次分页验证记录见下方 2026-09-10 条目。macOS 与 Linux 真机验证
仍需由对应平台完成。
## 已确认的当前基线
@@ -182,6 +183,26 @@
- 全量 `npm test`:`3493 passed, 55 skipped`。
- `npm run typecheck`、`npm run lint` 和 `npm run build`:通过。
## 2026-09-10 进程与 Subagent 完整输出续读
- FR-7 / US-A6:`PagedOutputStore` 完整写入临时输出文件,进程和 Subagent 返回前缀预览
与续读引用。JSON 转义计入预览预算,避免 Provider 二次裁剪后丢失续读位置。
- `ModelToolProvider` 已注册并分发 `output_read`,Ask/Execute 均可读取所属会话输出。
工具数量预留一个槽位,页结果不再裁剪。详细字段以 [技术设计](./technical-design.md#44-输出续读)
为准。
- Provider、进程、Subagent、分页存储及共享工具目录五个测试文件共 `73 passed`。
覆盖真实 PowerShell stdout/stderr、Subagent 父会话归属、JSON 转义、Unicode 小页面前进、
句柄失效、活动调用取消和资源清理。`npm run typecheck`、`npm run lint` 通过。
- `runtime-e2e.manual.test.ts` 新增真实模型边界场景:运行一次输出超过 96 KiB 的 Node
脚本,随机中间与结尾标记均不在预览中;模型经 `output_read` 读到 EOF 后准确返回两个标记。
最终带报告的运行 `1 passed, 19 skipped`,上游模型请求精确为 4 次,进程调用 1 次,续读
调用 2 次。先前同场景也通过,但其控制台计数未保留,不据此推算两次运行的精确累计调用数。
- 真实调用使用现有 `RuntimeSettingsStore` 与 Electron `safeStorage` 解密已配置文本连接,
凭据仅经测试子进程环境传递。`GOODBUDDY_E2E_OUTPUT_REPORT` 可记录不含凭据、Prompt
或输出正文的调用计数;测试工作区和输出存储在结束后释放。
- 本目录中文文档已按 `deai-writing` 审校,扫描阻断项为 0;保留技术枚举、权限限制和历史
验证记录中的明确边界。本次未运行全量测试或生产构建,也不作为其他平台真机验收。
## 进度维护要求
- 只有真实生产路径完成并验证后才能勾选实施项。
@@ -24,7 +24,7 @@
直连模型 Runtime,继承父请求 Ask/Execute 及 authorizer,工具事件记入子任务;
Ask 保持只读,不把这些本机工具表述为远程 OpenCode 子会话。
- OpenCode、Continue 和 DeepSeek Harness 各自的 Shell/Agent 能力。
- 直连模型 `process_execute` 和 `subagent_delegate`。
- 直连模型 `process_execute`、`subagent_delegate` 和 `output_read`。
- 不创建顶层 Task/Conversation 的编程 Subagent actor 与活动归并。
## 2. 总体架构
@@ -138,6 +138,8 @@ type ProcessExecuteResult = {
stderr: string
stdoutTruncated: boolean
stderrTruncated: boolean
stdoutReference?: PagedOutputReference
stderrReference?: PagedOutputReference
}
```
@@ -146,12 +148,31 @@ type ProcessExecuteResult = {
### 4.3 输出边界
- stdout 和 stderr 各最多 96 KiB。
- 超限时分别保留前 48 KiB 与最后 48 KiB,中间插入固定截断标记。
- stdout 和 stderr 各返回最多 96 KiB 的前缀预览,JSON 转义后的内容也计入预览预算。
- `PagedOutputStore` 将流式输出完整写入系统临时目录,内存只保留预览;超限后继续写盘。
存储失败明确报错,不把缺失内容标记为完整结果。
- 预览省略内容时返回 `stdoutReference` 或 `stderrReference`,包含 `handle`、`nextCursor`
和 `totalBytes`。短输出返回完整文本并删除临时文件,不附带句柄。
- JSON 结果加上元数据后必须低于 `ModelToolProvider` 现有 256 KiB 工具结果上限。
- 流式读取在收到数据时执行边界,不先积累无界 Buffer。
- 输出按 UTF-8 解码,无效序列使用替换字符并保留字节计数。
### 4.4 输出续读
`output_read` 接受严格对象 `{ handle, cursor?, limitBytes? }`:`cursor` 为从 0 开始的 UTF-8
字节位置,省略时从头读取;`limitBytes` 为 1 至 32,768 的整数,默认 32,768。页面返回
`{ handle, content, cursor, nextCursor, totalBytes, eof }`,模型沿 `nextCursor` 读取至 `eof`。
页面在字符边界结束;若请求大小容不下首个完整字符,最多扩展到 4 字节,保证续读前进。
位于 UTF-8 延续字节的输入 cursor、负数、越界和未知字段均拒绝。
Provider 根据 `process:` 或 `subagent:` 前缀选择服务,以当前 `conversationId` 校验所有者,
不接受模型另传 owner。Ask/Execute 均可用,工具总数为此预留一个槽位;不要求本轮能够启动
命令或再次委派。分页结果直接 JSON 序列化,不进行二次文本裁剪,以免 cursor 与内容不一致。
32 KiB 的页面即使全部需要 JSON 转义,也能保留在现有工具结果容量内。
进程输出归属调用会话,Subagent 最终输出归属父会话。子级临时会话释放后,父模型仍能续读
Subagent 结果。会话释放会等待活动调用结算再删除所属文件;服务退出关闭写入句柄并删除临时
目录。输出不写入 SQLite,不跨 Runtime 重启恢复。
## 5. 平台执行
### 5.1 Shell 探测
@@ -265,7 +286,8 @@ type DirectModelSubagentContext = {
- 复用 `SubagentScheduler` 的取消、并发和队列模式。
- 全局最大并发 3,队列最大 20。
- 单个子任务最长 10 分钟;父请求更早取消时立即停止。
- 文本结果最多 192 KiB,错误最多 2 KiB,连同结构化字段保持在 256 KiB 工具结果上限内。
- 文本预览最多 192 KiB,JSON 转义也计入预算;错误最多 2 KiB。省略的正文通过
`outputReference` 续读,字段与生命周期沿用第 4.4 节,完整输出不受预览容量限制。
- 模型用量逐事件归属父请求和 `childRunId`,不能只算入父模型最后一轮。
- 子级失败和取消返回结构化终态及部分输出,让父模型决定下一步。
@@ -320,8 +342,8 @@ DeepSeek Harness 的 Main 工具代理必须使用仅包含分配 MCP 和 Web
- `failed`:启动或契约失败。
- `cancelled`:父请求取消。
结果摘要包含 Shell、工作目录、退出码、耗时和截断标记。完整有界 stdout/stderr 进入工具
输出字段,不写应用诊断日志。
结果包含 Shell、工作目录、退出码、耗时、输出预览和续读引用,不写应用诊断日志。
通用工具活动仍显示有界摘要,模型通过 `output_read` 取得的页面记为后续工具活动。
### 9.2 Subagent 事件
@@ -363,10 +385,15 @@ type SubagentActor =
结果总量都由请求超时、取消和上下文压缩控制,长回复和大工具结果不会被中断。图像生成
响应仍按可解码图片大小校验。
会话历史在请求校验、Renderer 发送与保存、SQLite 读写和直连模型缓存中均保留完整消息,
不按消息条数、单条文本长度或累计文本量裁剪。上下文大小由现有压缩策略和模型上下文窗口
处理。Continue 接收完整历史,已有有效摘要只替换其覆盖的前缀,剩余消息全部交给原生
Runtime;GoodBuddy 不再额外保留最后 20 条或限制为 128,000 字符。
## 11. 性能
- Shell 探测按执行服务实例缓存,不在每轮模型调用重复探测。
- stdout/stderr 边读边界定,避免大日志进入内存后再截断。
- stdout/stderr 边读边写入临时文件,内存仅保存有界预览;续读每次只读取一页。
- 子级共享父请求已解析的模型配置和工具服务,不复制 MCP 配置或持久状态。
- 不增加持久 Shell、后台 daemon、工作区快照或恢复状态机。
- 命令执行不使用 PTY,避免普通构建和测试承担终端渲染成本。
@@ -380,6 +407,8 @@ type SubagentActor =
- Windows PowerShell、POSIX Bash/Sh 选择和参数。
- cwd 默认、相对子目录、绝对路径、工作区外目录、指向外部的符号链接和不存在的目录。
- exit 0、非零退出、spawn 失败、超时、取消和输出截断。
- 输出预览加分页能还原全文,包括 JSON 转义文本、中文、表情和字面替换字符;覆盖一字节
页面前进、跨会话拒绝、活动调用释放、短输出删除及服务退出清理。
- 环境筛选、本机工具 PATH 优先且模型凭据不进入进程。
- 子级模式、模型、项目、执行空间和能力继承。
- 深度 1 过滤、并发 3、队列 20、取消传播和部分输出。
@@ -411,6 +440,11 @@ type SubagentActor =
每个平台一次完整场景即可,不进行批量或高成本调用。记录准确模型调用次数,不记录 API Key。
输出边界场景复用 `runtime-e2e.manual.test.ts`:真实模型运行一次专用 Node 脚本,输出超过
96 KiB,并在预览之后生成随机中间与结尾标记。模型必须通过生产 `output_read` 连续读到 EOF,
最终回答包含两个标记。测试限制工具为进程与续读,记录上游请求数和工具调用数;凭据由现有
加密设置解密后仅在内存及测试子进程环境中传递。
### 12.4 项目验证
源码完成后运行:
@@ -84,11 +84,14 @@ GoodBuddy 服务崩溃。
1. Shell、工作目录、耗时和退出码。
2. stdout。
3. stderr。
4. 截断提示。
4. 预览省略提示与工具结果中的续读引用。
日志使用共享等宽字体和可选择文本。长输出在活动块内折叠,展开后仍保持工作栏和聊天布局
可用;不把完整日志复制为应用通知。
模型使用 `output_read` 续读时显示普通工具活动“续读工具输出”。活动展开只展示该次返回的
摘要,不等同于自动加载完整日志;当前不增加手动分页按钮。
## 4. Subagent 活动块
复用现有 `subagent` 消息块,并将系统执行者显示为“编程 Subagent”,不要求用户预先创建
@@ -102,7 +105,7 @@ GoodBuddy 服务崩溃。
终态:
- 完成:显示有界结果摘要,可展开查看完整返回。
- 完成:显示有界结果摘要,可展开查看当前预览;完整正文由模型通过输出续读工具取得。
- 失败:保留部分输出和错误。
- 取消:显示“父请求已取消”或准确取消原因。
- 排队:显示当前处于并发队列,不显示虚假百分比。
@@ -64,12 +64,13 @@ Given 测试命令退出码非零,When 进程结束,Then 工具正常返回
Given 命令仍在运行,When 用户取消父请求,Then 当前 Shell 及其由本次命令创建的子进程树
停止,And 活动状态显示“已取消”,And 其他用户进程不受影响。
### US-A6 看懂截断结果
### US-A6 续读长输出
关联:FR-7、FR-9。
Given 命令输出超过上限,When 工具返回结果,Then 保留有用的开头和结尾并明确
`truncated: true`,And 模型与用户都不会把结果理解为完整日志。
Given 命令或 Subagent 输出超过单次预览容量,When 工具返回结果,Then 明确标记省略并提供
续读位置,And 模型可逐页读取中间与结尾内容,直到取得完整输出。Given 输出包含中文或表情,
Then 即使请求很小的页面,续读仍会前进。Given 所属会话已释放,Then 旧句柄不能继续读取。
### US-A7 从瞬时模型网络故障恢复