Repository navigation
feat(chat): render read-only OpenCode child session trees - #697
Conversation
e0919fb to
921c20e
Compare
ObsisMc
left a comment
There was a problem hiding this comment.
审查 head 804b8df,范围为本 PR 自有提交(09f534c5..804b8df,16 个文件);合并提交 09f534c 与 #695/#696 两侧 diff 一致,未夹带其他内容。
阻塞:
- packages/chat/src/store.ts:1540 的 settleActiveToolCalls 只判断 "opencode/child-session" 这个键是否存在。工具来源被显式置 null 或无效时,实时在 end_turn 后标为 unknown(显示"结果未知");history 的 child_source_id 却按父工具落盘为 completed,重载后显示"已完成"。这违反 ADR 不变量 3 的实时/重载一致,也与本 PR 文档里"显式 null 或无效来源按父流处理"的说法不符。请改为 childSessionSource(item.metadata) !== undefined,并补一条对应测试。同时请对齐 TS 与 Rust 的有效性规则(id/parentID 是否 trim、depth 为 1.0 时的处理)。
非阻塞:
2. subagent-replay.test.tsx 的暖/冷重载直接回放实时更新,没有经过 HistoryAssembler 收束与落盘;后台委托(:447)和跨回合续接(:472)也只测了实时。核心用例要求回合 1 的 X 组在暖/冷重载后仍为"委托已返回结果",请补齐。
3. 待确认:客户端流没有边界事件就结束时,实时为 stopReason=null(显示"状态未知"),runtime 却可能写入 TurnEnded{Cancelled}(重载显示"投影已停止")。
4. 建议:delegationReturned、parentStreamItems 和 parentEnded 的判定属于领域规则,以后有其他消费端时可下沉到 @ora/chat。
委托关联、最晚一次的判定、来源流隔离、崩溃历史和只读边界都符合 ADR。
804b8df to
9589200
Compare
There was a problem hiding this comment.
复审 head 9589200(相对上轮 804b8df 新增 2cd29e4、9589200f),基于 desktop main 9774456。
上轮意见的处理:
- 阻塞项已解决:settleActiveToolCalls 改为 childSessionSource(item.metadata) !== undefined,来源被显式清空或无效时,实时与 history 都按父工具结算为 completed;projection.test.ts 覆盖了实时、暖重载、冷重载。Rust child_source_id 已与 TS 对齐:id/parentID trim 后判空,depth 接受 1.0,超过 JS safe integer 的拒绝,都有测试。
- 已补:后台委托与跨回合续接都加了暖/冷重载 UI 断言,回合 1 重载后仍为「Delegation returned」。委托 rawOutput.metadata 经 HistoryAssembler 和 JSONL 落盘后的保留由 projection_tests.rs 覆盖,两侧合起来可以接受。
- 无边界事件时的 stopReason 仍为待确认项,不阻塞。
- 小问题(可不改):JS trim() 会去掉 U+FEFF,Rust str::trim 不会,id 仅为 "" 时两侧结论不同。
暂不 Approve 的原因:本 PR 堆叠的 #696 是旧版本(8d6c66db),不包含 #696 当前 head e988bee 的 9e1d0d4(改了 packages/chat/src/store.ts 等)和 e988bee。请等 #696 在新 head 上 review 定稿后,把本 PR rebase 到它上面,在运行 issue 里注明新的 head,再请求复审;届时我只看 rebase 后的差异,没有新问题就 Approve。更正:本 head 的 CI 已全部通过(含 crates (windows-2022) 和 ci-ok),不是原先写的仍在运行。
9589200 to
e8b69ba
Compare
|
CI note on
|
ObsisMc
left a comment
There was a problem hiding this comment.
复审 head e8b69ba,Approve。
- 堆叠:本 PR 已包含 #696 当前 head e988bee(该 head 已 review 通过)。
- 自有提交:与上一版 9589200 做 range-diff,9 个提交中前 8 个完全一致,第 9 个只多了 packages/chat/tests/delegation.test.ts 的 Prettier 换行,断言未变。上轮已核对的来源判定、委托标注和重载断言保持不变。
- #696 新提交(9e1d0d44 的 diagnostics 语义调整、e988bee9 的权限往返测试)与本 PR 自有的 store.ts 改动没有交叉:本 PR 不涉及 diagnostics。
- CI 在 e8b69ba 上全部通过;改动文件都是代码、测试和中英文成对文档;PR 描述写明 ADR 为 approved 及 implemented 的后续安排。
合并前的要求:Git 没报冲突不代表可以直接合入。#696 合并后,请把本 PR 同步到最新 main,并排查逻辑冲突,重点核对同期合入 main 的改动是否涉及 chat store 的状态与结算(settleActiveToolCalls、diagnostics)、history 的落盘与回读(child_source_id)、agent-runtime 的 liveness 与权限往返、workflow-run 与 workspace 的会话视图;有交集的地方说明两侧行为如何组合,并重跑相关测试。同步后在运行 issue 里记下新的 head 与验证结果,再请求复审同步带来的差异。本次 Approve 只对 e8b69ba 成立。
供参考:截至 main 98ef871,相对本 PR 基线 be72c25 新增的 21 个非合并提交只涉及 scheduled-task 与 controller,与本 PR 改动文件没有交集;合并时 main 可能已继续前进,需按届时的版本重新核对。
OpenCode names the delegated child session in the tool result's rawOutput.metadata, beside the provider status. Expose that link and the completed check from the chat layer so presentation code never infers a relationship from titles, tool names or timing. The completed check requires both the ACP status and the provider's own status, because the store settles a parent tool the turn ended on and that implied completion is not a reported delegation result.
After the parent turn ends, a child card now says "Delegation returned" only when the latest delegation in that parent turn and source stream names the child, reports ACP completed, and carries the provider's completed status. Everything else keeps "Further state unknown (projection stopped)". The lookup follows persisted order, so a later turn continuing the same child session does not revise an earlier card. Nested cards read their own parent group's stream, and a card whose relationship is missing or conflicting never claims a returned delegation.
A delegation call found inside another child's stream must not settle a top-level card, because the decision scopes the association to the stream that launched the child. Filter the turn to parent-flow items before looking up a top-level group; nested groups already read their parent group's items.
e8b69ba to
addc621
Compare
ObsisMc
left a comment
There was a problem hiding this comment.
复审 addc621b(rebase 到 main 42f224ac):Approve。
git range-diff e988bee9..e8b69bad 42f224ac..addc621b:9 个提交全部=,rebase 没有改动任何提交内容。- 逻辑交集:main 自
e988bee9以来(#696 合并后又进了 #712、#715、#716 等,36 个非合并提交、100 个文件)只涉及 ora-controller、ora-node、node-db、node-protocol、application/backend 的 scheduled-task 和对应文档,与本 PR 的 18 个文件没有交集;packages/chat、app-shell chat、crates/history、crates/agent-runtime都没有被改动。#712 改的stop_reason是 ora-node 恢复账本里的停止原因,不是传给 chat 的 ACP turn 结束原因,不影响本 PR 的结算逻辑。 - CI 在
addc621b上全部通过(changes、frontend、crates×3、tauri、e2e、ci-ok);改动文件都是交付物,描述写明了 ADR 状态。
非阻塞:描述里“新 head 的 CI 正在运行”已过时,可以顺手改成已通过。合并前仍需落地运行开出把 ADR 改为 implemented 的 specs PR。
Summary
在父时间线展示 OpenCode 子代理的只读详情树,按显式
id/parentID连接并发与嵌套来源,展开查看文本、思考、plan 和工具输入/输出。元数据与注解贯穿实时批处理及重载;缺父、循环和冲突仍保持可读。父回合结束后,仅当同一来源流中最晚一次可关联委托同时满足 ACP
completed、providerrawOutput.metadata.status = "completed",且sessionID等于该子组 id 时,卡片显示「委托已返回结果」;其余显示「后续未知(投影已停止)」。跨回合续接不改写先前回合,两种文案均不代表子代理终态。本轮按 review 修复
settleActiveToolCalls:只把有效childSessionSource的未结算工具标为unknown。来源被清空或无效时按父工具结算;history 的 Rust 解析与 TS 对齐(空白 id / parentID、整数形式的浮点 depth、JS safe integer 范围)。补齐实时、暖加载、冷加载及后台委托与跨回合续接断言。堆叠同步:desktop#695(merge
be72c252)与 desktop#696(merge5a022b04)均已合并。本分支已 rebase 到 desktop main42f224ac,分支上只保留本 PR 自己的 9 个提交;range-diff与上一版e8b69bad全部一致(9 个=),rebase 未修改任何提交内容。desktop main 自上一版基线的 42 个提交、100 个改动文件与本 PR 的 18 个文件没有交集,其中没有改动packages/chat、app-shell 的 chat / workflow-run / workspace、crates/history、crates/agent-runtime。Refs ora-space/circus#302
ADR 状态
实现 子代理投影 ADR(specs main 上目前为
approved)。本 PR 补齐只读详情树与两种委托标注;history 保真由已合并的 desktop#695 承接,运行诊断与 liveness 由已合并的 desktop#696 承接。落地运行的 specs PR 已开出:ora-space/specs#181,把 ADR 改为implemented并按本 PR 登记核心用例证据。合并顺序:先本 PR,再 specs#181。Evidence
end_turn后将工具标为「结果未知」,history 重载后却显示「已完成」。childSessionSource判断;清空或无效来源在实时、暖加载和冷加载下均为completed。Rust JSONL history 回读覆盖同一边界。addc621b(rebase 后新 head)上重跑:@ora/chat55 passed;ora-history57 passed;ora-agent-runtime123 passed;@ora/app-shell全套 227 files / 2157 tests passed。@ora/chat的 tsc、ESLint、Prettier 通过;@ora/app-shell的 tsc、ESLint 通过;变更文件 Prettier 通过;Rustcargo fmt --all -- --check通过,cargo clippy -p ora-history -p ora-agent-runtime -- -D warnings通过。@ora/app-shell的format:check仍报src/features/settings/filter-discovered-plugins.ts与src/features/workspace/entity-dialog*.tsx三个文件的既有格式漂移,这些文件不在本 PR 改动范围内。42f224ac(含 desktop#695、feat(chat): expose run diagnostics without child-driven parent keepalive #696、test(scheduled-task): prove committed ownership survives reopen #716);本分支 headaddc621b。addc621b上的 CI(changes、frontend、crates×3、tauri、e2e、ci-ok)已全部通过。desktop main 现为e73f0af2(之后的 fix(backend): 从插件 Effect 声明读取 skill discovery root #702 等 3 个提交只改crates/backend与 e2e 的workflow_scenarios.rs,与本 PR 的 18 个文件没有交集),PR 仍为MERGEABLE/CLEAN。Merge Danger
Door: two-way
Blast Radius: chat
合并顺序 #695 → #696 → #697:#695、#696 均已合并,现在轮到本 PR。历史缺失的来源无法补回;普通投影不承诺完整后台历史,也不新增 steer、子代理取消、close 或 RFD 协商。