# Runtime 交互边界 本文定义当前原生交互的适配范围,不增加工作模式或第二层 Execute 审批。 | Runtime | 权限确认 | 业务问答 | | --- | --- | --- | | 本机 GoodBuddy 管理的 OpenCode | 内部默认配置允许权限;每个 Ask 请求仍使用 deny-all 与显式只读能力。Execute 自动回复属于当前请求的父、子孙会话权限事件,不处理其他并行请求 | 通过 `question.asked` 转交父、子孙会话问题,支持原生单选、多选、yes/no、自由文本及跳过;使用公开 ID 回传 `question.reply/reject` | | 托管 SSH OpenCode | Agent 按已接受 Prompt 的 Ask/Execute 模式处理 ACP 权限,规则见远程主机技术设计 | 当前 Agent 插件转交原生父、子孙会话 `question.asked`;前台使用同一问答队列,回答和跳过经认证 Agent 控制通道回传,已知 Task 关联显示子任务归属 | | Continue | Execute 启动传入 `--auto`,剩余原生权限请求按当前模式自动答复 | 对接 `1.5.47` QuizService 的扁平 `pendingQuestion`,其中 `question` 是字符串。选项回答与自定义文本分别回传正确的 `isCustomAnswer`;跳过发送拒绝回答的文本 | | DeepSeek Harness | 固定 Host 的 Execute 文件与命令工具不询问目录权限;若收到 ACP 权限请求,活跃 Execute 直接选一次性允许,缺少该选项时使用 Runtime 提供的允许选项,Ask 拒绝,不等待额外 authorizer | 固定 Host 当前未提供通用原生业务问答服务,不把普通模型正文误识别成待答协议。模型以普通回复提问时,用户通过下一条消息回答 | 托管 SSH OpenCode 的权限、原生问题事件与回复链路由 [远程主机技术设计](../remote-host/technical-design.md)定义。该远端业务问答基线需要 Desktop `0.13.0`、Agent `0.11.24` 和新启动的托管 Runtime;请先升级 Desktop,再更新 Host 环境。2026-09-14 的已发布 Desktop `0.13.2` / Agent `0.11.25` 已包含此前问答修复, 但不包含本文末尾尚未发布的进程复用改动。任意第三方 ACP 服务及旧 Agent 不因此获得通用问答接口。 ## 运行与失败 - 结构化 yes/no 是普通选项,不从日志、自然语言或 Shell 输出猜测用户意图。 - 前台同一请求的待答问题按公开 `questionId` 去重,按到达顺序保存在消息的 `pendingQuestions` 中。每次显示队首表单;有多个待答请求时显示数量。后续提问和重复 事件不替换当前表单或清空输入,回答或跳过成功后只移除对应 ID,再显示下一张表单。 提交失败保留队列、输入和重试入口,队列未清空时继续显示“等待你的回答”。 - 本机与托管 SSH OpenCode 在提问到达前已收到原生 Task 的 `metadata.sessionId` 时,将精确匹配的 子会话关联为可选 `childTaskId`。问答卡片显示该任务名称;对应 Task 卡片显示 “等待你的回答”,展开后可点击“前往问答表单”滚动并聚焦当前队首表单,仍按顺序回答。 没有已知关联的子孙会话问题照常排队,不猜测子任务归属,也不从工具名或进度文本构造表单。 - 回答或跳过成功后,会话保留只读的“问题与回答”,显示原问题及对应的选项答案、 自定义文本或“已跳过”。同一任务的多轮问答逐次保留,随本地会话保存,重新打开后仍可查看。 提交失败时保留输入与重试入口,不生成已回答记录;取消未回答的问题不记为主动跳过。 - 提交响应晚于任务结束时仍保存已提交的问答,但不覆盖完成或失败状态;晚于下一轮提问时 不清除新的待答卡片。旧版会话未保存的问题与答案无法从“已提交”状态文案恢复。 - 待答队列仅保存在当前桌面会话内存中,不写入持久会话快照。刷新仍在运行的消息时保留整个 本地队列;完成、失败、取消事件或持久化终态快照清除整个队列。迟到的提交结果可以保存 已回答记录,但不会恢复表单或覆盖终态。本机 Runtime 不恢复重启前未提交的问题;托管 SSH 重新附加同一存活 Agent Prompt 时,由 Agent 当前待答列表补发问题,已回答的历史事件不补发。 - 未发布的进程复用源码在 Desktop 重启后由 Main 并行附加同项目的存活任务,将待答 列表和 Stop 所需的请求 ID 投影到实时 `activeRequest`,不保存该字段或重新发送任务。 回答/跳过成功由 Main 写回原远程助理消息的既有问答历史,Renderer 不覆盖远程正文或终态。 Runtime 设置、定制和能力更新让旧请求在原配置上结束,已有问题仍可回答;新请求使用 新配置。专家团队例外:既有专家调度器在设置替换时取消子任务,团队父请求也随之停止, 不使用替换后的模型汇总旧结果。详细实现见 [恢复与终态投影](./runtime-process-reuse-technical-design.md#63-恢复与终态投影)。 - 后台任务收到结构化提问时,通过现有 Main 路径明确失败并提示改为前台对话,不永久等待。 - 请求结束或取消后清除对应待答映射;过期回答明确报错,不转交给后来的请求。 - 任意终端程序的密码、OAuth 登录、许可证确认或 stdin 提示不自动回复 `yes`。这类程序应 使用其非交互参数,或由用户在终端完成;不能把权限确认和业务决策混为一谈。Shell 工具保留其现有取消与超时,不新增日志解析或通用交互代理。 ## 托管 Runtime 的并行与输出 子任务完整过程的显示与数据库差量存储相互独立,本机和托管 SSH 共用桌面存储层; 旧库升级与空间回收规则见[执行记录存储与升级回收](./execution-history-storage.md)。 - 本机和 Agent 管理的 OpenCode 启动配置都显式设置 `snapshot: false`。GoodBuddy 不消费 原生自动 Git 快照、快照差异摘要或快照撤销;关闭这条内部路径,避免大行级差异的同步 计算阻塞同一原生进程中的其他会话。 - 文件工具、Shell、原生子代理、工作区 Git 状态和单文件差异保持可用;不新增全局会话 队列、请求重放或总执行截止时间。外部 OpenCode Server 的配置不由 GoodBuddy 改写, 已运行的旧原生进程也不会热更新配置。 - Continue 使用 HTTP 传递响应和状态;Electron UtilityProcess 启动后持续排空不用展示的 stdout,避免控制台输出填满管道后阻塞宿主。stderr 的有界错误处理、请求取消与进程 回收保持不变,不把诊断输出复制进聊天或持久日志。 - 远端最终启动配置由[远程主机技术设计](../remote-host/technical-design.md)定义, 模型桥生成最终配置时同样保留上述快照策略。 ## 工具操作摘要 工具记录沿用 [UI 设计系统](../../../UI-DESIGN.md)的折叠布局。Continue、DeepSeek Harness 和直连模型共用 `toolOperationSummary`:优先使用有效原生标题,否则从参数提取命令、 文件路径、搜索条件或 URL,合并空白后最多显示 240 字符。无法识别时保留原有工具名 回退规则;文件正文、整份参数 JSON 不进入标题,参数详情仍可展开查看。 Continue 在宿主截断输入前提取摘要,流式完成与失败事件使用合并后的输入和摘要。 DeepSeek Harness 按调用 ID 保留名称、输入和摘要,结束事件省略输入时仍能显示操作内容。 直连模型从原始参数生成一次摘要,在待执行、执行中和完成时复用;审批失败、拒绝和 执行失败、刷新重试仍保留已有提示。 本机 OpenCode 沿用原生操作标题。远端 ACP 独立使用原生标题作为记录名称,不经过上述 本地转换,本次没有修改 Agent、远程桥或协议。 ## 消息底部请求状态 - 状态属于当前请求,不与顶部 Runtime 的连接中、就绪、不可用混为一谈。提交后先显示 “正在准备请求”;没有更具体的活动事件时显示“等待后续进展”,不声称模型正在思考。 - 本机 OpenCode 只把当前父会话的 `session.status.retry` 映射为等待重试,显示原生 `attempt`、计划重试时间和有界脱敏原因;后续 `busy` 才显示已开始重试。其他会话的 状态不串入当前消息,不猜测总重试次数,不把 SDK 事件流重连当作模型重试。 - 显示优先级为待回答、待确认、进行中的上下文压缩、明确的请求状态、待执行或执行中的 工具、未完成的子任务、等待后续进展。压缩沿用已有活动块,不重复增加底部提示。 正文、推理或工具进展会清除旧状态;子任务更新不覆盖父请求的重试提示。 - 完成、失败、取消后保留真实终态,迟到的状态事件不能把请求恢复成处理中。底部状态点 为静态,不凭请求尚未结束暗示仍有进展;会话列表闪点和发送、停止按钮保持原有行为。 持久化快照中的同一条消息仍为生成中时,也不能覆盖本地已收到的终态,即使快照的 会话更新时间更晚;否则连续发送或刷新会让已结束的请求重新显示停止按钮。 - Continue、DeepSeek Harness 和远端 ACP 保留其已接入的处理与工具事件,不伪造未接入 的原生重试状态。直连模型的重试等待与请求开始文案见 [直连模型 UI 设计](../direct-model-agent/ui-design.md#6-错误与通知);本次不改变任何 Runtime 的重试上限、请求重放或取消策略。 实现与真实 Runtime 验证证据见[进度记录](./progress.md)。 ## Runtime 执行清单 本节为未实现的状态设计,对应 [FR-CL1–FR-CL4、US-CL1–US-CL5](./prd.md#131-runtime-执行清单)。 原始格式和传递边界由[技术设计](./runtime-checklist-technical-design.md)维护。 清单属于一次请求及其助手消息。沿用项目、执行空间、Conversation、Runtime 选择和 原生 Session 到请求的既有映射;远端还需核对 binding/operation。不能仅以原生 Session 或 Conversation 为键更新顶部,因为同一会话会连续执行多轮请求。 | 输入或操作 | 清单与顶部行为 | | --- | --- | | 本轮尚无有效清单 | 隐藏顶部清单,不复制上一轮内容 | | 收到本轮有效完整清单 | 按原生顺序整体替换,包括修改、删除、重排和重复文本;不按条目文本合并 | | 收到有效空数组 | 记录明确清空并隐藏;空数组与缺少清单字段不同 | | CN 调用进行中 | 候选只按该请求的调用 ID 暂存;成功后才提交完整替换 | | CN 调用失败、取消或格式无效 | 丢弃该候选,保留上次有效清单,工具记录保留实际结果 | | 请求完成、失败、取消或中断 | 冻结最新已提交清单,并显示请求真实结果;不推断条目完成,迟到输入不改写已结算清单 | | 同一会话开始下一轮 | 顶部转向新请求,上一轮清单留在原消息;旧轮事件不得归入新轮 | | 切换会话、项目、执行空间或 Runtime | 只读取目标归属的数据;原请求在原归属结算,不把原清单标为新 Runtime 的进度 | | 查看历史或重连 | 从原消息及既有事件恢复;按原请求和远程来源顺序去重,不能用最新原生 Session 快照覆盖历史轮次 | 条目状态支持 `pending`、`in_progress`、`completed`、`cancelled`。OC 原生提供的 priority 保留; CN 未勾选项映射为 `pending`,已勾选项为 `completed`,不推断 `in_progress` 或 priority。 OC 无稳定 item ID,视图索引仅服务本次完整列表渲染,不生成跨更新的条目身份。 清单内容不创建、调度或完成产品 Task,也不改变底部请求状态。清单更新与工具活动可以 同时保留,但顶部计数只来自已确认的结构化清单,不能反向解析普通状态文本、任意 Markdown 或名称含 `list` 的工具。子会话清单不覆盖父请求顶部。 以上产品状态规则已明确;远程 CN 接入、原生格式确认及历史字段选择仍属技术待办,见 [进度记录](./progress.md#2026-09-15-runtime-执行清单设计未实现)。 ## Runtime 资源生命周期 本节对应 [FR-RR1–FR-RR6、US-RR1–US-RR4](./prd.md#141-runtime-资源复用), 定义进程复用的行为规则。当前源码已接入本机共享 owner 和 Agent 共享 ACP; 完整验收状态以[进度记录](./progress.md#2026-09-14-runtime-进程复用实施中)为准,不表示已发布。 具体 owner、兼容键和协议实现见[技术设计](./runtime-process-reuse-technical-design.md)。 资源有三个独立维度:进程是否启动/退役,会话是否仍持有原生上下文,请求是否在途。 “任务完成”“当前没有选中该项目”“工作栏关闭”均不能直接推导进程可以销毁。 | 触发 | 请求与会话行为 | 进程行为 | 对应需求/场景 | | --- | --- | --- | --- | | 被动状态读取 | 不取得新执行会话,已有状态可读取 | 不冷启动,不延长无会话 owner 的空闲期限;不为探测替换服务中的进程 | RR2 / US-RR1 | | 显式测试/原生清单 | 取得临时检查引用;清单带明确工作区 | 与执行共用启动 Promise 和 owner;结束只释放检查引用 | RR1、RR2 / US-RR1 | | 首次或并行 Prompt | 取得对应 execution space + conversation 的绑定 | 同兼容组复用,非兼容组分别启动 | RR1、RR3 / US-RR1、RR2 | | 普通请求完成 | 释放请求订阅、临时 token、问题和 callback,保留可续聊 Session | 不因为一个请求完成关闭整个进程 | RR3、RR4 / US-RR3 | | 取消一个请求 | 取消其模型/工具调用并结算,其他会话继续 | 不以 kill 共享进程代替正常会话取消 | RR3、RR4 / US-RR2 | | 关闭面板/切换项目 | 停止非必要 UI 推送;不取消后台任务或抹掉会话所有权 | 不触发隐式关闭 | RR4 / US-RR3 | | 显式释放/删除会话 | 释放该 Session 与会话工具资源;删除历史仍只由原有明确删除操作决定 | 其他引用仍在则保留 | RR4 / US-RR3 | | 无会话、无请求、无检查引用 | 不存在需要保留的原生上下文 | 进入短空闲等待,再关闭;新使用者到来取消等待 | RR4 / US-RR1、RR3 | | 配置替换 | 已接受请求使用旧配置结算,新请求使用新配置 | 旧 owner 排空后退役;不积累只被历史 ID 持有的旧配置进程 | RR1、RR4 / US-RR4 | | 进程故障/不可响应 | 只给该 owner 下受影响请求明确中断;未知结果不自动重放 | 有界终止失效 owner,不伪造逐会话故障隔离 | RR3、RR4 / US-RR2、RR4 | | SSH detach | 保留 Agent 已接受 Prompt 及既有恢复归属 | 关闭传输不关闭 Agent 或活动 Runtime | RR5 / US-RR4 | 表中 RRn 是 PRD 稳定需求 ID `FR-RRn` 的简写。 不变量: 1. 一条请求始终使用接受时的 execution space、工作模式、配置和归属;不能读取后来 切换的 UI 选择,也不以进程 cwd 表示所有会话的 cwd。 2. 同一会话串行,跨会话不增加全局 Prompt 队列。权限、子代理、问题、用量和最终清理 必须沿同一 Session/请求归属,不因共享进程放宽 Ask 或限制 Execute。 3. owner 的退出条件依据所有使用者,不依据某个 adapter 的空闲状态。 未启动对象的 dispose 不产生冷启动;一个等待者取消不取消其他等待者的初始化。 4. 正常会话仍持有原生上下文时,不用任意 TTL 清掉它来声称“空闲内存已回收”。 无会话 owner 的短空闲等待为 60 秒; 不增加用户配置项。它是进程引用回收,不是聊天历史保留期限。 5. 持久历史不因请求结束、进程 idle、配置变化或测试 cleanup 被删除。 原生进程确实重启后的续聊沿现有历史重建规则,不新增第二套持久会话快照。 已明确普通并行、取消、释放、配置替换及断线行为。各项实际通过的场景及尚未完成的 组合/性能验证以[进度记录](./progress.md#2026-09-14-runtime-进程复用实施中)为准。