Skip to content

feat(chat): render read-only OpenCode child session trees - #697

Merged
EricWvi merged 9 commits into
ora-space:mainfrom
wanglongan587:feat/302-subagent-details
Oct 21, 2026
Merged

EricWvi merged 9 commits into
ora-space:mainfrom
wanglongan587:feat/302-subagent-details

Conversation

@wanglongan587

@wanglongan587 wanglongan587 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

在父时间线展示 OpenCode 子代理的只读详情树,按显式 id / parentID 连接并发与嵌套来源,展开查看文本、思考、plan 和工具输入/输出。元数据与注解贯穿实时批处理及重载;缺父、循环和冲突仍保持可读。

父时间线
├─ 父代理内容
├─ 子代理卡片 → 自身详情和嵌套子代理
└─ 父代理回答

父回合结束后,仅当同一来源流中最晚一次可关联委托同时满足 ACP completed、provider rawOutput.metadata.status = "completed",且 sessionID 等于该子组 id 时,卡片显示「委托已返回结果」;其余显示「后续未知(投影已停止)」。跨回合续接不改写先前回合,两种文案均不代表子代理终态。

本轮按 review 修复 settleActiveToolCalls:只把有效 childSessionSource 的未结算工具标为 unknown。来源被清空或无效时按父工具结算;history 的 Rust 解析与 TS 对齐(空白 id / parentID、整数形式的浮点 depth、JS safe integer 范围)。补齐实时、暖加载、冷加载及后台委托与跨回合续接断言。

堆叠同步:desktop#695(merge be72c252)与 desktop#696(merge 5a022b04)均已合并。本分支已 rebase 到 desktop main 42f224ac,分支上只保留本 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

  • Before: 来源被显式置为 null 或无效时,实时在 end_turn 后将工具标为「结果未知」,history 重载后却显示「已完成」。
  • After: 有效来源统一由 childSessionSource 判断;清空或无效来源在实时、暖加载和冷加载下均为 completed。Rust JSONL history 回读覆盖同一边界。
  • 在 addc621b(rebase 后新 head)上重跑:@ora/chat 55 passed;ora-history 57 passed;ora-agent-runtime 123 passed;@ora/app-shell 全套 227 files / 2157 tests passed。
  • 静态检查:@ora/chat 的 tsc、ESLint、Prettier 通过;@ora/app-shell 的 tsc、ESLint 通过;变更文件 Prettier 通过;Rust cargo 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 改动范围内。
  • 基线为 desktop main 42f224ac(含 desktop#695、feat(chat): expose run diagnostics without child-driven parent keepalive #696、test(scheduled-task): prove committed ownership survives reopen #716);本分支 head addc621b。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 协商。

@ObsisMc ObsisMc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查 head 804b8df,范围为本 PR 自有提交(09f534c5..804b8df,16 个文件);合并提交 09f534c 与 #695/#696 两侧 diff 一致,未夹带其他内容。

阻塞:

  1. 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。

@ObsisMc ObsisMc left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审 head 9589200(相对上轮 804b8df 新增 2cd29e4、9589200f),基于 desktop main 9774456。

上轮意见的处理:

  1. 阻塞项已解决:settleActiveToolCalls 改为 childSessionSource(item.metadata) !== undefined,来源被显式清空或无效时,实时与 history 都按父工具结算为 completed;projection.test.ts 覆盖了实时、暖重载、冷重载。Rust child_source_id 已与 TS 对齐:id/parentID trim 后判空,depth 接受 1.0,超过 JS safe integer 的拒绝,都有测试。
  2. 已补:后台委托与跨回合续接都加了暖/冷重载 UI 断言,回合 1 重载后仍为「Delegation returned」。委托 rawOutput.metadata 经 HistoryAssembler 和 JSONL 落盘后的保留由 projection_tests.rs 覆盖,两侧合起来可以接受。
  3. 无边界事件时的 stopReason 仍为待确认项,不阻塞。
  4. 小问题(可不改):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),不是原先写的仍在运行。

@wanglongan587
wanglongan587 force-pushed the feat/302-subagent-details branch from 9589200 to e8b69ba Compare October 21, 2026 08:02
@wanglongan587

Copy link
Copy Markdown
Contributor Author

CI note on e8b69bad: crates (ubuntu-latest) failed on ora_git::tests::hostile_checkout_configuration_has_no_effect_through_the_socket (apps/ora-node/src/ora_git/tests.rs:769) with Failed { code: Busy, message: "another ora-git request of this session is running" }.

  • This PR does not touch apps/ora-node; the same ora-node tree passed CI on feat(chat): expose run diagnostics without child-driven parent keepalive #696 at e988bee9 minutes earlier.
  • The failing assertion is the follow-up fetch after a push reply, so the session lock looks like it is still held when the next request arrives — an unrelated ora-git race, not something this branch changes.
  • Members cannot re-run workflows on this repository, so I am re-triggering the same SHA by reopening the PR. The commit is unchanged.

@ObsisMc ObsisMc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审 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.
@wanglongan587
wanglongan587 force-pushed the feat/302-subagent-details branch from e8b69ba to addc621 Compare October 21, 2026 09:10

@ObsisMc ObsisMc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审 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。

@EricWvi
EricWvi merged commit cf0c7a6 into ora-space:main Oct 21, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants