mirror of
https://github.com/stablyai/orca.git
synced 2026-10-02 16:02:15 +00:00
* feat(native-chat): register Codex default-mode helpers as subagents Codex's default multi-agent mode announces a helper only as the collabAgentToolCall that spawned it; it sends no subAgentActivity. The roster and the background-task tracker registered children only from subAgentActivity, so such a helper had no record, no strip row and no roster row, and its commands read as the session's own. One announcement reader now yields a child from either wire shape, and both the journal roster and the tracker register through it into the same executions, so a session sending both keeps one child per thread. A finished closeAgent ends the helper's running turn as stopped through the executions, beside the child's own turn and thread frames. Each collab call renders as a tool row (spawn_agent, wait_agent, close_agent, ...) naming the helper the way the roster does, with what the helper said back as its output, instead of the raw provider row. * fix(native-chat): name a spawn row by its prompt until the roster holds its helper Also pin that the roster row appears when the helper's first turn arrives before the spawn call finishes. * test(native-chat): a spawn call keeps its own row beside the roster row it starts * fix(native-chat): pair a structured tool row's output with its own call A run paired results to calls by position alone, so once one call finished with no output (a Codex spawn_agent row) every later output drew under the call before its own. A structured row carries its call and output together, so the projected result now names its call id and pairing honors it, falling back to position for results that name none. * fix(native-chat): the Codex roster row follows the executions, so every child ending settles it The subagent-group row was rewritten only on a child's turn/started and turn/completed. A child turn ended any other way — a fatal error, its thread closing, its caller closing it — settled the strip and the host record through the executions but left the transcript row reading working until the session ended. The executions now say when a child's execution changes, and the roster revises its row from that, whichever frame changed it. handleTurn still re-derives to hand back its write admission; the revision is idempotent. * fix(native-chat): a restored Codex call row names its helper, not its thread id History replay never runs the live item router, so the roster never learned the helpers a restored thread had spawned, and a restored wait_agent, close_agent or send_input row labelled its helper with the raw thread id. Replay now registers each announced helper for its name and membership only: register starts no execution, so no strip entry, record or roster row claims the helper runs until a live turn of its own says so. The replayed-item handling moves into the restore module beside the replay that calls it. Also name the roster's render contract in handleItem, and say why the collab tool-name map is not a spelling fix. * fix(native-chat): register a Codex helper whose spawn call failed but created its thread Codex reports a spawn as failed when the helper it created errored at birth, yet the call still names the thread it created, and that thread can run. The spawn was registered only when the call completed, so such a helper existed nowhere and its shell read as the session's own bare command: the original default-mode bug. A spawn now registers whenever it names a receiver; one in progress, or one that created nothing, names none. A failed closeAgent still ends nothing, because the helper was not closed. * refactor(native-chat): each Codex thread's latest token total gets its own home Every thread's running total, member or not, with the rule that the newest frame replaces the last and the recency-ordered cap, moves out of the roster into codex-thread-token-totals.ts. The roster still selects its children's totals at write time. With the producer linkage the roster now builds, it was past the size limit. * refactor(native-chat): the messages a session list quotes get their own module The readers of a session's newest own prompt and own assistant prose move from the status projection into structured-agent-session-latest-messages.ts, and are re-exported so their consumers keep one import site. With the status clock the projection now carries, a tool result naming its call put it past the size limit. * test(native-chat): a Codex helper's command is a live record until its process reports its exit A helper's in-turn shell is a live command record owned by the helper and is also its open Bash operation; its exit removes the record. A caller's closeAgent kills the helper's processes, and each still reports its exit on the helper's thread, so the close leaves the command to that exit rather than ending it itself. * fix(native-chat): every reader of a tool run pairs a result with the call it names The folded desktop run now pairs a result with the call it names, but mobile's tool run, the desktop edit cards and the task lists still paired by position through `pairToolBlocks`. In a Codex default-mode session the new `spawn_agent` row finishes with no output, so on mobile the helper's reply drew under `spawn_agent` and `wait_agent` showed none, and a desktop edit card could take the next command's output as its own. `pairToolBlocks` now follows the same rule as `pairNativeChatToolResults`: a result that names its call answers that call, and one that names none answers the oldest unanswered call as before. * fix(native-chat): a Codex helper's turn ends on its own frames, not on its caller's closeAgent A finished `closeAgent` call ended the helper's running turn as `stopped`. But the call's status is not the close's outcome: Codex sets it from the helper's own agent status, so a close that errors on a running helper still reports `completed`. Orca then marked a helper that was still running as cancelled in the strip, the host record and the roster row, and because the first ending a turn gets stands, its real ending could never correct it. A close that works does not need the edge either. Codex's shutdown of the helper aborts its running turn, and the app-server reports that as the helper's own `turn/completed` with status `interrupted`, which Orca already maps to `stopped`. So a helper's turn now ends only on its own frames (its `turn/completed`, a fatal `error`, `thread/closed`) or the session ending, and the close is only its call row. This also drops the child-work evidence re-keying that existed only for the close: every remaining frame names the thread that sent it. * fix(native-chat): a tool result that names a call is never given to a different call A result that named a call id with no unanswered match fell back to the oldest unanswered call. On mobile, a run shows at most six calls, so a command past that window whose output named its own call gave that output to an earlier call that finished with none, such as `spawn_agent`. A result that names its call now answers only that call and otherwise stays unpaired. A result that names no call still answers the oldest unanswered one. Both pairing readers share the one rule through `answeredToolCallIndex`. * test(native-chat): name the Codex default-mode test file after the subagents it covers * fix(native-chat): a Codex helper is known from any call that names it, not only its spawn A helper whose spawn Orca never saw (history replay after compaction dropped the spawn, or a resume or message to a helper from earlier) stayed unregistered, so its shell read as the session's own command: the bug this PR fixes, in another shape. Every collab call now announces each helper it names, skipping a receiver the finished call reports notFound. The spawn's prompt still labels a helper when it was seen; otherwise the helper has no label and reads as any unnamed subagent does. A send_input, like the spawn, names the parent turn the helper's next run belongs to. The session's own thread is excluded once, in the reader, instead of at each of its three callers. * fix(native-chat): every finished Codex collab call row carries what the call reports A client that predates result call ids (an older mobile app, or an older desktop reading a newer host) projects the journal itself and pairs each tool result with the oldest unanswered call. This PR publishes collab calls as tool rows, and a finished spawn_agent, send_input, close_agent or resume_agent on a running helper had no output, so such a client drew each later output in the run under the call before its own (the parent's shell output under spawn_agent, the helper's reply under the shell). Every finished call now has an output taken from the item: a wait's reply from each helper that finished (an errored helper's error), and for every other call the helper's reported status in Codex's own words (Pending init, Running, Completed, ...). A close or resume no longer shows the helper's last reply as if the call returned it. A wait whose end names no helper (it timed out, or v2) reads Finished waiting; any other call with no state reads its own status. A call also keeps naming the helpers its started item named: Codex ends a timed-out wait with no receivers, so its row lost the helper's name when it finished. * refactor(native-chat): the desktop run's tool pairing is a view of pairToolBlocks Desktop runs and every other reader (mobile, edit cards, task lists, the ask row) each had their own pairing loop sharing one index rule. The desktop's pairNativeChatToolResults now reads the pairs pairToolBlocks makes, so a run is paired by one loop and a new reader cannot add a third. No behaviour change. * test(native-chat): type the positional-client pairs without assertions * fix(native-chat): a finished Codex collab call row says what the call did, in Codex's own words A close_agent row read `Running` and a spawn_agent row `Pending init`: each showed the helper's status snapshot from before the call took effect, so a close that stopped its helper read as though it had not worked. Each finished call's output now follows Codex's own client: spawn reads `Spawned` (or `Agent spawn failed` when no helper was created), send_input `Sent input`, close `Closed`, and resume the helper's status summary. A wait keeps each finished helper's reply, with other statuses in Codex's summary wording (`Error - <message>`). The row label already names the helper, so the output does not repeat it. * docs(native-chat): the collab call reader says which calls show the helper's snapshot as output Since spawn, send_input and close rows say what the call did, the reader's header was wrong to claim every call row shows the reported snapshot as its output: only a wait or resume does. * fix(native-chat): a Codex spawn call no longer claims it ran an agent Codex's spawn_agent call ends as soon as the helper starts, so counting it as running an agent drew "Ran 1 agent" directly above "Kicked off 1 subagent · working" while the helper was still working, and "Ran 1 agent · 1 failed" when Stop cancelled a spawn before any helper existed. Claude's Task call lasts as long as its subagent, so it keeps the agent category; the Codex spawn row is now a plain tool call and the roster row alone stands for the helper. * test(native-chat): a Codex helper's row settles on the failed completion that follows a fatal error Codex follows every turn-ending `error` with the turn's failed `turn/completed`, on a helper's thread as on the primary, and only that completion ends the turn. The roster test now sends both and checks the row, strip and record stay working through the error and settle on the completion. * fix(native-chat): a Codex helper's section opens while the parent spawns, waits on or messages it A running chat holds a subagent's section open while the parent's newest row delegates to that subagent. For Codex that rule only knew the raw collab status row; this PR writes each collab call as a tool row (spawn_agent, wait_agent, send_input, close_agent, ...) naming its helpers in `input.agents`, so a default-mode helper's section stayed shut for its whole run while Claude's opened. The delegation reader now reads a Codex collab tool row as a delegation to the first helper it names, the same rule the raw row keeps for journals written before this change; a call naming no helper stays ordinary output. The row names and the `agents` key live in one shared module the host writes from and the reader reads, instead of a second list. The new test drives the real adapter's rows through the transcript projection to the delegation; the collab frame harness moves to a fixture shared with the positional-clients test. * fix(native-chat): a Codex collab call with a long prompt still names its helper A collab call row bounded its whole input as one value, so a spawn or send_input whose prompt passed the 16 KB journal limit was stored as a clipped wrapper: the row lost the helper's name and thread ids, and with them the label and the delegation that opens the helper's section. The prompt is now clipped on its own with the journal's inline-text bound, marker included; the helper's name, ids, model and effort are bounded as before and always survive.
24 lines
835 B
JSON
24 lines
835 B
JSON
{
|
|
"extends": "@electron-toolkit/tsconfig/tsconfig.node.json",
|
|
"include": [
|
|
"../electron.vite.config.*",
|
|
"./build-plugins/**/*",
|
|
"./scripts/vitest-host-ports-setup.ts",
|
|
"./scripts/vitest-caller-identity-env-setup.ts",
|
|
"./scripts/vitest-real-agent-home-write-guard.ts",
|
|
"../src/main/**/*",
|
|
"../src/renderer/src/lib/skill-freshness-display-status.ts",
|
|
"../src/renderer/src/components/native-chat/native-chat-resolution-receipt.ts",
|
|
"../src/renderer/src/components/native-chat/structured-agent-question-projection.ts",
|
|
"../src/renderer/src/components/native-chat/native-chat-subagent-delegation.ts",
|
|
"../src/preload/**/*",
|
|
"../src/shared/**/*",
|
|
"../src/relay/**/*",
|
|
"../src/types/**/*"
|
|
],
|
|
"compilerOptions": {
|
|
"composite": true,
|
|
"types": ["electron-vite/node"]
|
|
}
|
|
}
|