Skip to content

fix: Orchestrator TUI bugs + infrastructure hardening#1624

Open
wqymi wants to merge 40 commits into
mainfrom
fix/orchestrator-tui-and-infra-bugs
Open

fix: Orchestrator TUI bugs + infrastructure hardening#1624
wqymi wants to merge 40 commits into
mainfrom
fix/orchestrator-tui-and-infra-bugs

Conversation

@wqymi

@wqymi wqymi commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

修复了 Orchestrator 模式相关的多个 TUI/session bug,以及一批 Orchestrator 基础设施问题(它们的根子是 Orchestrator 本身不够健壮 —— prompt 未约束、通知/worktree 机制有缺陷)。全部改动在 packages/opencode

TUI / Session bugs

  • fix(tui): 切到 Orchestrator 模式时不再立即跳转到 session 视图 —— 与其他模式一致,发出第一条消息后才切(暂存 orchestrator 根 session id,提交进该 session,避免重复创建根 session)。
  • fix(tui): 切进子(peer)会话时挂载为完整可写会话而非只读 subagent 分片,up 能返回 Orchestrator(判定收敛为 currentAgentID() !== "main",已在 main)。
  • fix(retry): provider 的 429 limitation 错误体现在被归一化为可重试的限流状态,不再把原始 JSON 透传糊屏。
  • fix(session): session list 排除 checkpoint-writer 等系统 subagent(仅列真正的 peer 子会话)。
  • fix(provider): 发送前压缩超大图片(默认约 4.5MB 上限,复用 pngjs/jpeg-js 无新依赖),覆盖 tool_result 图片,压不下则替换为文字占位 —— 一张 >5MB 的图片不再触发 400 并使会话永久卡死;历史中的"毒图片"下次请求自愈。

Orchestrator 基础设施

  • docs(prompt): 强化 Orchestrator system prompt —— 绝不阻塞当前 turn、绝不用 actor run 干实活(只用非阻塞的 actor send/status relay)、编辑 git 仓库的子会话默认隔离(isolation-first),并补充 idle≠完成 / 游离提交的应对指引。
  • fix(worktree): worktree 原子创建并让 HEAD 挂到分支(单步 checked-out worktree add -b),加 HEAD 附着断言与加宽创建锁 —— 子会话提交现在能正确推进分支 ref,不再产生游离提交。
  • fix(actor): 后台 peer 在被 inbox 唤醒的轮次完成后,会向父 Orchestrator 发送恰好一条 actor_notification(仅限后台 peer、排除系统 subagent、不重复通知)—— 不再"空闲却不通知"需手动 nudge。
  • feat(session): session list 按状态分组并计数(进行中 / 已完成idle / 已取消 / 失败),让用户一眼看清有多少个子会话、哪些在跑。

Verification

  • bun typecheck — 干净(tsgo --noEmit)。
  • 集成测试 test/actor/ test/inbox/ test/tool/session-tool.test.ts test/session/orchestrator-prompt.test.ts test/provider/transform.test.ts — 318 pass / 2 skip / 0 fail。

Co-authored-by: MiMo-Code noreply@mimo.xiaomi.com

wqymi and others added 30 commits July 8, 2026 12:33
Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit e6acae8822451a7256e2054a235c64005773b84a)
…-limit

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit ab0436ba5ce6eb57c9b2e0055f32b78f44b6c743)
… session list

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 460e11292f0df2de81a25e096f8043c69781c5e3)
…MB image can no longer 400 and permanently wedge the session

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 98b9b1ce9df924fdaa0c9460e203a21f7d685e43)
… work, isolate git-repo children by default

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 326267d4b8accdfecada1ffeb12f8d757fe68cb4)
Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 0a8f54d230959353b7cc9cd05f58028146002857)
…ild commits advance the branch ref

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit f7d2447139668b4985127e02a9a3bda24e36aad7)
…turn

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 2182387a5a12a13cd4954ab0926b86834fc5e769)
… instead of a task-bound one

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 6b2decad387ce79d197ff33c052b84fc25adb62c)
… hardcoded 4.5MB

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 953836e84e4aad60066678d1f92885867cc69328)
…reaking unicode escapes

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit d883116c488dc307a4d3a5bc4189b8881cfa7d98)
…tor session via -c (no blackscreen on switch)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
… fix

A 429 APIError the provider marked isRetryable:false fell through the non-retryable bail in retryable() (status 429 < 500), was never retried, and surfaced as a raw provider blob in the TUI terminal error render. Catch 429 by status or a rate-limit signal in the message/body before that bail so it both retries and shows a clean status; widen isRateLimitMessage to underscore variants (rate_limit_error/too_many_requests); and defensively normalize a rate-limit APIError in the TUI errorBody so any 429 reaching terminal render shows clean text instead of raw JSON/HTML.

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
…euse standing session, persistent coordinator)

Co-authored-by: wqymi <wangqiying@xiaomi.com>
(cherry picked from commit 4006b81a18ae862499c05664f67f7703a0d24623)
… seed + session send verb)

Inbox.drain now seeds the synthetic user message's agent+model via a layered, cheapest-first fallback so a woken idle/turnCount-0 persistent peer always converts a queued inbox row into a turn instead of no-op'ing: (1) inherit from any prior real model-bearing message across the whole session (cross-slice findMessage, no new dependency); (2) for a true turnCount-0/empty-slice peer, seed the agent from the actor-registry row and the model from an already-wired default-model resolver ref (populated by SessionPrompt.layer, so Inbox.layer pulls no Provider dependency into the hot path); (3) if neither yields a model, leave the rows durable and log rather than silently drop the task. Adds a first-class 'session send <id> <task>' verb that enqueues into a standing peer's inbox and wakes it, tolerating an idle-but-persistent peer instead of ESRCH-failing.

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
…children honor it

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
… element, not raw text

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 5d776a54d317fda4cdfd2050083de10ba82d4642)
…ldren do not deadlock on external_directory

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
…ession from -c blackscreen fix)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit ff55ac312d42099a7f0accdfdfd88142d0754499)
…reflect real progress

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 6ced0ae183fd491c07bc3d939eea59810ace6de4)
…s that reject assistant prefill (Bedrock)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 75e08765eefbf305b55c3ed86c539fd616e76784)
…or mode (was duplicated)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit ef9e4bd1cd4ae130062c9a97e38f823bc17cb9a0)
…ome (T36 follow-up)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 2288eb72bce75b6180698257a99da10b23bcd4f5)
…r reflex (T45)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit cdf861cd278e76c920523100727d5f22ac2ca8b5)
…ressable immediately (T42)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 54ad612030ba8b51ed02c1b027e954bc9c0f6877)
… render)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 6274e46371e285a10e5a4554675f7f02402008fe)
…ever-run peers

The T12 woken-turn notification test polled only the raw InboxTable row, which
races the parent main runner: inbox.send fork-wakes parent main, whose runLoop
drains the actor_notification row into a synthetic message before the poll sees
it (observed 6/10 flaky failures). Assert delivery on EITHER surface — the raw
inbox row or the drained synthetic <actor-notification> message in the parent
main slice. Notification delivery itself was always correct; only the assertion
was racy. Now 12/12 stable.

Co-authored-by: wqymi <wangqiying@xiaomi.com>
(cherry picked from commit 1f6cddd768a65801143d011c2aff541c4890b1c2)
… bridge (T41)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 4de816861cc2454c820f64db27681b136d4b7fe7)
…e child (T43)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
…erb + list split (T39)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
wqymi and others added 10 commits July 9, 2026 00:14
…ated result when all children terminal (T38)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
… the parent (T40)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit d15bae78e275e2a06c2722f9f2923d8a29fce3ce)
… send/status/join/--topic, event-driven stall) and drop stale relay/known-limitation (T44)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 00b487af054577c169b45b59097267d4779fcbaf)
…ithout a home flash (T50 follow-up)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit f12de43aaf31090a254db9b5f45b6960535adc80)
sweepOrphanAssistants gains an immediate flag; the user-message entry
passes immediate=true when the session is idle (no active runner), so a
dangling assistant left by a hard interruption is completed at once
instead of after the 1h ORPHAN_AGE_MS. This clears the TUI 'pending'
marker so a newly submitted message on an idle session is not rendered
QUEUED. Background spawn/hook callers keep the age guard. Adds tests.

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
…of cancelling them (align session interaction with human↔session)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit fcc28f5ba7f5a0f4eef4cca9568ffff48f6d1c1e)
…dren external_directory asks for granted dirs

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
…in one view

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
(cherry picked from commit 58b44f4a6eed069d14015c6b9c7c91c6f0d14dd1)
…els reached via non-bedrock gateway (T35 follow-up)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
…ay prefill-rejection 400 (error-body driven, T63b follow-up)

Co-authored-by: MiMo-Code <noreply@mimo.xiaomi.com>
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.

1 participant