@volter/supercode-frontend-vscode 0.1.63 → 0.1.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -180,7 +180,10 @@ default is never stored as a choice (a pick equal to the default follows the def
180
180
  changes), and an Auto approve is never stored for a conversation that cannot answer. Conversations opened before 0.1.36 saved their picker's
181
181
  **Ask** when opened and keep it. Auto approve approves the requests the harness would ask you about, including requests to run
182
182
  outside its sandbox (Codex's approval requests are its sandbox escalations); the harness's deny
183
- rules still apply. Each request it answers is noted in the turn ("auto-approved: …"). A turn
183
+ rules still apply. A request it answers adds no line of its own: the call's row is the record, as in Code-OSS's own
184
+ agent host, whose Auto approve answers a harness's call with no reason on its row; a card already shown loses its
185
+ buttons where the host can retire it (`chatConfirmationResolution`), else gets its answer as a line beneath it, and an
186
+ approval it could not answer has its card drawn again for the person to answer. A turn
184
187
  re-joined after a page reload (the conversation's active response) is answered the same way. Unsupported modes are refused. Unanswerable
185
188
  harnesses show **Harness permissions**. Previously answered requests cannot affect another
186
189
  connection. Native command-button fallback limitations are documented below.
@@ -296,7 +299,7 @@ Fresh snapshots also restore retained `history_events` before replay at the
296
299
  runtime's cursor. Their original sequences and payloads are preserved. Recovered
297
300
  unseen events reach existing response listeners, and an authoritative idle
298
301
  snapshot releases a restored response even when its terminal event is no longer
299
- retained. Chat states when older events are outside the bounded display window.
302
+ retained.
300
303
  An unavailable saved runtime returns an error in Chat instead of a blank draft.
301
304
  These are implemented source paths; real editor recovery and pending approval
302
305
  interaction remain unqualified.
@@ -310,7 +313,9 @@ the frontend does not coerce them into JavaScript's object label.
310
313
  record this history path. The original Windows approval-row report remains
311
314
  unattributed, and native approval behavior is separate.
312
315
 
313
- The extension asks for five proposals. A host grants them through
316
+ The extension asks for eight proposals. Three of them (`chatSessionResponses`, `chatSystemNotification`,
317
+ `chatConfirmationResolution`) exist only in Volter's Code-OSS fork (volter-ai/code-oss, from `cb0c38b5`); a host
318
+ without one drops its name as a proposal that does not exist. A host grants them through
314
319
  `product.json#extensionEnabledApiProposals` (a Code-OSS derivative that bundles this extension) or
315
320
  `--enable-proposed-api volter-ai-dev.supercode-frontend-vscode`. **Stock VS Code grants none, and
316
321
  everything below still works there** — the granted set is read back from the extension host at
@@ -322,53 +327,79 @@ request), and each part declares its own fallback.
322
327
  | `defaultChatParticipant` | `isDefault` — Volter Harness answers the Chat view with no `@` mention | the ordinary `@supercode` participant; a mention is required |
323
328
  | `chatParticipantAdditions` | `ChatToolInvocationPart` (with its terminal, todo-list and subagent data), `ChatResponseConfirmationPart`, `ChatResponseWarningPart`, `codeblockUri`, `ChatResponseThinkingProgressPart`, `ChatResponseHookPart`, `questionCarousel` | progress lines, labeled Markdown results, typed replies, plain fenced diffs, blockquoted reasoning, quoted hook lines, answer buttons |
324
329
  | `chatSessionsProvider` | the runtime's sessions in the Chat view's session picker, each reopening with its history | the participant still attaches; there is no session list |
325
- | `chatParticipantPrivate` | dynamic participant identity with the harness and provider icon | static participant identity |
330
+ | `chatParticipantPrivate` | dynamic participant identity with the harness and provider icon; an interrupted turn's error at warning level | static participant identity; the interruption is an ordinary error |
326
331
  | `chatProvider` | native fixed-model identity and provider icon | host new-chat configuration |
327
-
328
- ### Parity with Code-OSS's own chat parts
329
-
330
- Every chat response part and tool-row kind the pinned Code-OSS (`4a7cd45`, `src/vscode-dts`) offers an extension,
331
- and what this frontend does with it. **Native**: the harness's event is drawn as VS Code draws its own.
332
- **Fallback**: drawn, but with a plainer part than VS Code's own (why given). **Not used**: no harness event this
333
- frontend receives carries what the part shows. **Gap**: the event exists and the native part is not built yet.
334
- This count is the measure of done; a change that moves a row says so here.
335
-
336
- | Part / tool data | Status | What draws it, or why not |
337
- |---|---|---|
338
- | `ChatResponseMarkdownPart` | native | the agent's text |
339
- | `ChatResponseProgressPart` | native | status lines; a finished subagent task as one line |
340
- | `ChatResponseWarningPart` | native | warnings, failed turns, usage limits |
341
- | `ChatResponseThinkingProgressPart` | native | the agent's reasoning (a subagent's is not shown, as VS Code shows none) |
342
- | `ChatResponseReferencePart` | native | each file a Codex diff names |
343
- | `ChatResponseCommandButtonPart` | native | approval answers; Stop for a background task |
344
- | `ChatToolInvocationPart` | native | every tool call, updated in place with its result |
345
- | ↳ terminal data | native | shell calls: command and output |
346
- | ↳ todo-list data | native | Claude Code's TodoWrite and its task tools (TaskCreate, TaskUpdate, TaskList), and supercode's own `update_plan`, shown in VS Code's todo list. Codex app-server's plan (`turn/plan/updated`, not a tool call) is still a status line: fallback |
347
- | ↳ subagent data, `subAgentInvocationId` | native | Claude Code's Agent/Task call is the subagent row; its own calls are grouped under it (`parent_tool_use_id`) |
348
- | ↳ simple input/output data | native | any other finished call |
349
- | ↳ MCP data | fallback | an MCP call's result arrives as text, so it is the simple input/output |
350
- | ↳ resources data | not used | no tool event lists resources as such |
351
- | `ChatResponseHookPart` | native | a blocked prompt, a blocked tool call, a hook that failed (Claude Code). The extension API cannot place a hook inside a subagent row |
352
- | `ChatResponseQuestionCarouselPart` | native | an elicitation of questions (`ask_user`, Claude Code's AskUserQuestion) on a turn this window runs; command buttons on a re-joined response, where the pinned host never delivers the carousel's answer |
353
- | `ChatResponseConfirmationPart` | native / fallback | approvals, where the host advertises in-turn approval cards; command buttons otherwise (a stock confirmation answers with a new request) |
354
- | `ChatResponseCodeblockUriPart` | fallback | a Codex diff: `codeblockUri` with a fenced diff, not an edit (see *Why `diff_updated` is not an edit part*) |
355
- | `ChatResponseTextEditPart`, `ChatResponseNotebookEditPart`, `ChatResponseWorkspaceEditPart`, `ChatResponseMultiDiffPart`, `ChatResponseExternalEditPart` | **gap (known)** | native file edits with Keep/Undo and the multi-file diff: the harness has already written the files, and no event carries the before/after the editor needs |
356
- | `ChatResponseAnchorPart` | not used | no event names a location inline in text |
357
- | `ChatResponseFileTreePart` | not used | no event lists a file tree |
358
- | `ChatResponseMarkdownWithVulnerabilitiesPart` | not used | no harness reports vulnerabilities |
359
- | `ChatResponseCodeCitationPart` | not used | no harness reports a licensed citation |
360
- | `ChatResponseMovePart` | not used | no event moves a range |
361
- | `ChatResponseExtensionsPart` | not used | no harness recommends extensions |
362
- | `ChatResponsePullRequestPart` | not used | no structured event announces a pull request |
363
- | `ChatResponseInfoPart` | not used | informational records are warnings or are dropped as telemetry |
364
- | `ChatResponseAutoModeResolutionPart` | not used | the harness's model is the one chosen; there is no automatic routing to report |
365
- | `ChatResponseProgressPart2`, `ChatResponseReferencePart2` | not used | no event carries a resolvable task or a reference status |
366
- | `ChatResponseVoiceProgressPart` (`chatParticipantPrivate`) | not used | voice is not a harness event |
367
- | `stream.usage` | gap | token counts are dropped from the transcript; VS Code's own context indicator could show them and does not yet |
368
-
369
- Count, by row: 14 native (the confirmation card only where the host advertises it), 2 fallback (and Codex's plan
370
- inside the todo-list row), 12 not used, 2 gaps — native edits (the known gap, five parts in one row) and
371
- `stream.usage`.
332
+ | `chatSessionResponses` | the `ChatResult` a re-joined response resolves with and a saved turn's `result.errorDetails` as the response's error; the question carousel on a re-joined response; a conversation that could not be opened anchored to the system-initiated request "Couldn't open session" (`ChatRequestTurn.systemInitiatedLabel`) | a re-joined or saved response's error as a warning part, `Answer…` buttons on a re-joined response, that conversation's error under the marker request |
333
+ | `chatSystemNotification` | `ChatResponseSystemNotificationPart` for a harness notice, with its icon, live and saved | the notice as a plain line |
334
+ | `chatConfirmationResolution` | `ChatResponseConfirmationPart.isUsed`: an approval card answered elsewhere loses its buttons | one plain line beneath the card says the answer |
335
+
336
+ ### Parity with Code-OSS's own chat
337
+
338
+ The measure is the event, not the API part: **does this event look as Code-OSS draws its own equivalent
339
+ event?** The citations are read from Volter's Code-OSS fork at the editor's `FORK.json` pin; the workbench archives
340
+ this product ships are cut from earlier fork commits until they are re-cut at it: `4a7cd45` on macOS arm64, `4782d9a2`
341
+ on Linux x64 and Windows x64. Using a native part for something VS Code never draws is not
342
+ parity. Each row names what Code-OSS itself draws, with its source, and what this frontend draws on the product's
343
+ host (all eight proposals granted). **Native**: drawn as Code-OSS draws it. **Fallback**: drawn, but plainer than
344
+ Code-OSS's own (why given). **Gap (API)**: Code-OSS's own drawing is not reachable through the extension API at the
345
+ pin; the row names the fork change that would reach it. **Gap**: reachable, not built. This count is the measure of
346
+ done; a change that moves a row says so here. Paths are under `src/vs/` unless they start with `src/vscode-dts`.
347
+
348
+ | Event | Code-OSS draws its own as | This frontend | Status |
349
+ |---|---|---|---|
350
+ | The agent's text | markdown (`chatMarkdownContentPart.ts`) | `ChatResponseMarkdownPart`; a subagent's own text is not shown | native |
351
+ | The agent's reasoning, live and saved | thinking (`chatThinkingContentPart.ts`) | `ChatResponseThinkingProgressPart`, in history too | native |
352
+ | A tool call, started then finished | one tool row updated in place (`chatToolInvocationPart.ts`) | `ChatToolInvocationPart` with `enablePartialUpdate` | native |
353
+ | A shell call | the terminal row: command and output (`chatTerminalToolProgressPart.ts`) | terminal tool data | native |
354
+ | A call's work left running in the background (a background Bash, a Monitor, a subagent sent to the background) | Code-OSS's own Claude host (`platform/agentHost/node/claude/claudeToolDisplay.ts` `TOOL_ROWS`, lines 100-102) sets no `isBackground`: a background `Bash` is a terminal row that completes with its launch result; `BashOutput` ("Reading shell output") and `KillBash` ("Kill shell command") are terminal rows of their own. The person stops a task by asking the agent; current Claude Code (2.1.312) then calls `TaskStop` (which still answers to the old names `KillShell` and `KillBash`), which Code-OSS's table does not list, so it is an ordinary tool row there and here | the same: the Bash row completes with its launch result, and BashOutput and KillBash are terminal rows with Code-OSS's titles; the harness's listing of its background tasks draws nothing | native |
355
+ | Output a background-status call drained (`background_output`) | that call's own row (`get_terminal_output`'s row) | nothing more: the status call's row result already carries it | native |
356
+ | A plan (TodoWrite, the task tools, `update_plan`) | the todo list (`chatTodoListWidget.ts`) | todo-list tool data | native |
357
+ | Codex's plan (`turn/plan/updated`, not a call) | the todo list | a status line | fallback: no call carries it, and a todo list is a tool row |
358
+ | A subagent and its calls | the subagent row with its calls grouped under it (`chatSubagentContentPart.ts`) | subagent tool data, `subAgentInvocationId` | native |
359
+ | A hook that blocked or warned | the hook row (`chatHookContentPart.ts`) | `ChatResponseHookPart` | native; **gap (API)** inside a subagent: the part carries no subagent id |
360
+ | An approval | the confirmation card, answered in the running turn (`chatConfirmationContentPart.ts`; the fork's `volter.chat.inTurnApprovalCapability`, `volterHarness/volterChat.ts`) | `ChatResponseConfirmationPart` where the host advertises in-turn cards (this product's host does); command buttons on a stock host, whose confirmation answers with a new request | native; fallback on a stock host |
361
+ | A harness's questions | the question carousel (`chatQuestionCarouselPart.ts`), in its turn's response | the carousel, on a turn this window runs and on a re-joined response (`chatSessionResponses`: `mainThreadChatSessions.ts` forwards the answer to the session's stream by its `resolveId`); `Answer…` buttons on a re-joined response on a host without it | native; fallback on a re-joined response without `chatSessionResponses` |
362
+ | A request answered through its own card in this window | the card or carousel shows what was chosen (`chatConfirmationContentPart.ts`, `chatQuestionCarouselPart.ts`); the call's row carries on or ends denied | the same; a stock host's buttons stay, inert, and the status bar says what was sent | native |
363
+ | A request answered any other way (another window, Auto approve turned on after its card showed, a typed reply) | the request's card retires itself: the call's row carries on or ends denied (`agentHostSessionHandler.ts` `IChatToolInvocation.confirmWith`); a carousel answered elsewhere is marked used with its answers (`answeredExternally`) | an approval card loses its buttons (`chatConfirmationResolution`: the same `ChatResponseConfirmationPart` pushed with `isUsed`, which `chatModel.ts` matches by its `data`); the call's row carries the outcome. A question carousel stays live, with one plain line beneath it saying the answer | native for an approval card; **gap (API)** for a question carousel: an extension cannot mark a carousel it pushed answered. Fork: let the extension resolve a pushed carousel with the answers given elsewhere (`answeredExternally`) |
364
+ | An approval answered automatically (Auto approve) | the call's row alone: Code-OSS's own agent host answers a harness's call under its Auto approve with `confirmed: NotNeeded` and no reason (`platform/agentHost/node/sessionPermissions.ts` `createToolReadyAction`, after `agentSideEffects.ts` strips the confirmation), so `getApprovalMessageFromReason` (`chatToolPartUtilities.ts`) has nothing to say. Only a client tool the workbench runs itself is "Auto approved by `autoApprove`" (`agentHostSessionHandler.ts` `getClientToolPreApproval`) | the call's row alone; an answer that fails or does not settle draws the approval's card again, as the one still waiting | native |
365
+ | A request this window cannot answer (another client holds it) | no read-only confirmation: another client's call is its row, "Running {0} on another client…", with a cancel action (`stateToProgressAdapter.ts` `toolCallStateToInvocation`) | its title and summary as words, no controls; its answer as a line beneath it | fallback: the extension API cannot draw another client's call |
366
+ | A turn that failed | the response's error (`agentHostSessionHandler.ts` `_getTurnErrorDetails`, `errorDetails`) | the request handler's `ChatResult.errorDetails`; on a re-joined response the `ChatResult` its `activeResponseCallback` resolves with, and in history the saved turn's `result.errorDetails` (`chatSessionResponses`: `extHostChatSessions.ts` passes both on, and `chatServiceImpl.ts` sets the result on the response as it completes); on a host without it, VS Code's warning part with the error's words there | native; fallback on a re-joined response and in history without `chatSessionResponses` |
367
+ | A turn interrupted from elsewhere | the response's warning-level, expected error (`_getTurnErrorDetails`, `executionInterrupted`) | `errorDetails` with `level: Warning`, `isExpectedError`, on the same paths | native; fallback without `chatSessionResponses`, as above |
368
+ | A turn the person stopped | VS Code marks the response stopped | nothing more | native |
369
+ | A request Chat cannot run (no sign-in, no runtime, a refused send) | the request's error | a thrown error, which the workbench writes as the response's error | native |
370
+ | A transport or stream error while a turn may still run (`stream_error`, `transport_error`, `watch_error`, `runtime_disconnected`) | the response's error | VS Code's warning part with the error's words | fallback: the turn may still be running, so it is not ended with an error |
371
+ | A re-joined stream that fails; a conversation that cannot be recovered | the response's error; a session that cannot be loaded is the system-initiated request "Couldn't open session" with that error (`agentHostSessionHandler.ts` `sessionLoadFailed`, `sessionLoadFailedLabel`) | the re-joined response's result carries the error; the conversation's marker request is the system-initiated "Couldn't open session" and its saved response's result carries the error (`chatSessionResponses`); VS Code's warning part under the marker request on a host without it | native; fallback without `chatSessionResponses` |
372
+ | A harness warning (`cache_warning`, `warning`, a usage limit) | the warning part (`chatErrorContentPart.ts`, warning level) | `ChatResponseWarningPart` | native |
373
+ | A harness record that is not the person's words (a background task's notification, live or saved; an interruption record) | a system notification row, its icon picked per notification kind with the completion check as default (`stateToProgressAdapter.ts` `systemNotificationToChatPart`; `claudeReplayMapper.ts` keeps `compact_boundary` and `notification`) | `ChatResponseSystemNotificationPart` with the notice's own words (`chatSystemNotification`, converted to `{kind: 'systemNotification'}` in `extHostTypeConverters.ts`), live and saved, once per task (Claude Code reports a finished task both as `system/task_notification` and as the user-role record that wakes the agent; the saved transcript keeps only the latter, a `queued_command` attachment). "Turn interrupted." and a background task that failed or was stopped carry `warning`, by analogy with the icon upstream gives an automatic-approval review that was interrupted: upstream draws neither as a notification of its own. A plain line on a host without it, never a progress part, which Code-OSS hides once any other part follows it (`chatProgressContentPart.ts`) | native; fallback without `chatSystemNotification` |
374
+ | A status line (`status`) | the progress message, hidden once another part follows (`chatProgressContentPart.ts`) | `ChatResponseProgressPart` | native |
375
+ | Input arriving from elsewhere while a turn runs | the running turn's pending Steering message until the turn takes it in, then nothing: the turn keeps its response and no request turn opens (`agentHostSessionHandler.ts` `_applyRemotePendingMessages` → `syncPendingRequestsFromRemote`; `removePendingRequest` once taken in) | **Additional input** and the words, inside the running response, once the turn takes it in | **gap (runtime)**: the runtime announces no input waiting to be taken in (no frontend event carries it), and the runtime must echo a client-chosen input id on `user_message` and `turn_started`, and return it from `submit` and `steer` (`sdk/frontend/contract.json` carries no turn or input id, so which input started which turn is only a guess by text and order). Then a proposed API with which a session's provider sets and removes its pending Steering messages, mirroring those two calls |
376
+ | A message sent from this window while a turn it follows runs (a re-joined response) | a pending Steering message, which the workbench dispatches to a streamed session's provider at once (`chatServiceImpl.ts`, mid-turn steering); the turn keeps its response | the request handler's own turn, which the runtime refuses while a turn runs | **gap (runtime)**: steering it into the running turn without drawing its runtime echo a second time needs to know which `user_message` is that echo: the runtime must echo a client-chosen input id on `user_message` and `turn_started`, and return it from `submit` and `steer` (`sdk/frontend/contract.json` carries no turn or input id, so which input started which turn is only a guess by text and order) |
377
+ | A turn the runtime starts on its own (input that starts a turn while none runs, a turn after the previous one ended) | a request turn of its own (`agentHostSessionHandler.ts`, a changed active turn id: `startServerRequest`) | drawn inside the response of this window that follows the conversation, which follows to idle (a re-joined response), or only when the conversation reopens | **gap (runtime)**: opening it as a request turn of its own needs to know which input started it: the runtime must echo a client-chosen input id on `user_message` and `turn_started`, and return it from `submit` and `steer` (`sdk/frontend/contract.json` carries no turn or input id, so which input started which turn is only a guess by text and order) |
378
+ | A prompt the runtime's scheduler starts | a system-initiated request turn: a notification row with its label (`chatListRenderer.ts` `renderSystemInitiatedRequest`) | a notice, "Scheduled prompt: …", inside the response this window follows, or nothing until the conversation reopens; the same in saved history. Nothing in this repository produces `scheduled_prompt_started` (it is declared by `agent-runtime-host.mjs` `displayKinds` and read by `frontend-transcript.mjs` and the browser client), so its payload is not known; the prompt is read from `prompt`, `name` or `message` | **gap (runtime)**: a producer, and the turn attribution above, so that its turn opens as its own system-initiated request without also drawing the runtime's `user_message` for it |
379
+ | A Codex diff | file edits with Keep/Undo and the multi-file diff (`chatTextEditContentPart.ts`, `chatMultiDiffContentPart.ts`) | `codeblockUri` with a fenced diff, plus one reference per file | **gap (known)**: the harness has already written the files and no event carries the before/after the editor needs (see *Why `diff_updated` is not an edit part*) |
380
+ | An MCP call | the MCP input/output row | the simple input/output row | fallback: its result arrives as text |
381
+ | Token usage | the context-window indicator (`stream.usage`) | not shown | **gap** |
382
+ | A protocol record (`native_event`, a kind this version does not know, a malformed request) | nothing | nothing; an unknown kind and a malformed request go to the output channel | native |
383
+ | Saved history | the same parts a live response draws | the same converter: tool rows, hooks, warnings, reasoning | native |
384
+ | History past its bound | left out without a word; a turn without its request gets "Message content could not be retrieved" (`claudeReplayMapper.ts` `missingPromptPlaceholder`) | the same | native |
385
+ | A call waiting on approval in re-joined history | its row, with its card on the active response | the same | native |
386
+
387
+ Count, by row (36), on this product's host (Volter's Code-OSS fork at the editor's `FORK.json` pin, with all eight
388
+ proposals granted; a stock host draws the fallbacks above): 26 native, of which hooks are an API gap inside a
389
+ subagent and a request answered elsewhere an API gap for a question carousel; 4 fallback; 4 gaps that wait on the
390
+ runtime's turn attribution (input from elsewhere while a turn runs, a message this window sends into a turn it
391
+ follows, a turn the runtime starts on its own, a scheduled prompt, which also has no producer yet); 1 known gap
392
+ (native edits); 1 gap not built (`stream.usage`). The rows marked native for a harness's questions on a re-joined
393
+ response, harness records, a failed or interrupted turn on a re-joined or saved response, a conversation that cannot
394
+ be recovered, and a card answered elsewhere rest on the fork's proposals `chatSessionResponses`,
395
+ `chatSystemNotification` and `chatConfirmationResolution`; an automatic approval is native because Code-OSS's own
396
+ agent host draws that call's row alone.
397
+
398
+ Parts the extension API offers that no harness event this frontend receives carries, so not used:
399
+ `ChatResponseAnchorPart`, `ChatResponseFileTreePart`, `ChatResponseMarkdownWithVulnerabilitiesPart`,
400
+ `ChatResponseCodeCitationPart`, `ChatResponseMovePart`, `ChatResponseExtensionsPart`, `ChatResponsePullRequestPart`,
401
+ `ChatResponseInfoPart`, `ChatResponseAutoModeResolutionPart`, `ChatResponseProgressPart2`,
402
+ `ChatResponseReferencePart2`, `ChatResponseVoiceProgressPart`, and the resources tool data.
372
403
 
373
404
  The session participant uses the exact session type id (`supercode`). With
374
405
  `chatParticipantPrivate`, the extension registers its dynamic identity directly and keeps
@@ -402,24 +433,25 @@ it needs and the fallback it degrades to. Each arm names the producer it reads.
402
433
  | Event kind | Producer | Rendered as |
403
434
  |---|---|---|
404
435
  | `text_delta` | `crates/runtime/src/event.rs` `AgentEvent::TextDelta` | `response.markdown` (streamed) |
405
- | `user_message` | `sdk/interchange/agent-runtime-host.mjs` accepted-turn projection; `runtime-native-projection.mjs` `claudeBlocks` for Claude's own user-role records (`source: harness`) | the request turn in history; dropped live (VS Code already shows it); a harness record shows its `notice` or nothing |
436
+ | `user_message` | `sdk/interchange/agent-runtime-host.mjs` accepted-turn projection; `runtime-native-projection.mjs` `claudeBlocks` for Claude's own user-role records (`source: harness`) | the request turn in history; dropped live before `turn_started` (VS Code already shows it); after it, **Additional input** inside the response; a harness record shows its `notice` as a system notification row (`chatSystemNotification`) → a plain line, or nothing |
406
437
  | `turn_started` / `turn_completed` / `turn_succeeded` | `submit_claimed`; `AgentEvent::TurnCompleted` | lifecycle only — the handler resolves, nothing renders |
407
- | `turn_interrupted` | `submit_claimed` | an italic notice |
408
- | `turn_failed` | `submit_claimed` | `ChatResponseWarningPart` → blockquote |
438
+ | `turn_interrupted` | `submit_claimed` | the response's result: `errorDetails` at warning level (a re-joined or saved response needs `chatSessionResponses`); else `ChatResponseWarningPart` → its words |
439
+ | `turn_failed` | `submit_claimed` | the response's result: `errorDetails` (a re-joined or saved response needs `chatSessionResponses`); else `ChatResponseWarningPart` → blockquote |
409
440
  | `tool_call_started` / `tool_call_completed` | `AgentEvent::ToolCallStarted` / `ToolCallCompleted` | one `ChatToolInvocationPart` per call, updated in place with its result (`enablePartialUpdate`) → a progress line plus a labeled Markdown result |
410
441
  | `diff_updated` | `crates/codex-frontend/src/codex_app_server_v0_144.rs` (stock Codex `turn/diff/updated`) | `codeblockUri` + a fenced `diff` block, plus one stable `reference` per file the diff names → the fenced block alone |
411
- | `request` | `sdk/interchange/frontend-request-bridge.mjs` request publication | a titled markdown block plus one **command button per answer** — stable API, no proposal |
442
+ | `request` | `sdk/interchange/frontend-request-bridge.mjs` request publication | `ChatResponseConfirmationPart` where the host advertises in-turn cards, the question carousel for questions; else a titled markdown block plus one **command button per answer**. Read-only (title and summary) for a request this window cannot answer |
443
+ | `request_resolved` | `FrontendRequestBroker::respond` | nothing for a card answered through itself in this window; a native approval card answered elsewhere loses its buttons (`chatConfirmationResolution`); else one plain line beneath the card naming the answer |
412
444
  | `cache_warning` | `AgentEvent::CacheWarning` | `ChatResponseWarningPart` → blockquote |
413
445
  | `hook` | `runtime-native-projection.mjs` from Claude Code's failed `hook_response`, its blocked-prompt `informational` record, and a tool result in its own `PreToolUse:<tool> hook error:` words | `ChatResponseHookPart` ("Blocked by" / "Warning from" the hook) → blockquote |
414
- | `background_tasks` | `runtime-native-projection.mjs` from Claude Code's `background_tasks_changed` | nothing in the transcript: the turn lists them with a Stop each |
446
+ | `background_tasks` | `runtime-native-projection.mjs` from Claude Code's `background_tasks_changed` | nothing: a background command is its call's row, as in Code-OSS's own Claude host |
415
447
  | any event with `parent_id` | `runtime-native-projection.mjs` from Claude Code's `parent_tool_use_id` | a subagent's calls are grouped under its call; its own text, reasoning and input are not shown |
416
- | `usage` | `AgentEvent::Usage` | a progress line |
417
- | `background_output` | `AgentEvent::BackgroundOutput` | a fenced block, saying so when the runtime stopped retaining |
418
- | `scheduled_prompt_started` / `_deferred` / `_completed` | declared by `frontend_descriptor`'s `display.event_kinds` | a progress line |
419
- | `scheduler_error` | same | `ChatResponseWarningPart` → blockquote |
448
+ | `usage` | `AgentEvent::Usage` | nothing (see `stream.usage` in the parity table) |
449
+ | `background_output` | `sdk/interchange/agent-background.mjs` `status` | nothing: the status call's own row carries the output |
450
+ | `scheduled_prompt_started` / `_deferred` / `_completed` | declared by `agent-runtime-host.mjs` `displayKinds`; no producer here | started: a notice, "Scheduled prompt: …"; deferred and completed: lifecycle only |
451
+ | `scheduler_error` | same | `ChatResponseWarningPart` with its words → blockquote |
420
452
  | `reasoning` / `thinking` | no producer in this repository; read because `sdk/interchange/frontend-transcript.mjs` reads them | `ChatResponseThinkingProgressPart` → blockquote |
421
- | `stream_error` / `transport_error` / `watch_error` / `runtime_disconnected` | `crates/opencode-frontend/src/server.rs`; `crates/interchange/src/watch.rs`; synthesized by a frontend (`sdk/interchange/frontend-app.mjs`); `stream_error` has no producer here | `ChatResponseWarningPart` → blockquote |
422
- | anything else | opaque by contract | one **bounded** markdown cell that names the kind and shows the payload — never dropped |
453
+ | `stream_error` / `transport_error` / `watch_error` / `runtime_disconnected` | `crates/opencode-frontend/src/server.rs`; `crates/interchange/src/watch.rs`; synthesized by a frontend (`sdk/interchange/frontend-app.mjs`); `stream_error` has no producer here | `ChatResponseWarningPart` with its words → blockquote |
454
+ | anything else | opaque by contract | nothing in the transcript; written to the output channel |
423
455
 
424
456
  **Why `diff_updated` is not an edit part.** Measured: the payload carries one unified-diff *string*
425
457
  and nothing else. `ChatResponseTextEditPart` wants ranges and the runtime has already written the
@@ -446,16 +478,18 @@ invisible is one nobody can trust. A pushed command button cannot be withdrawn
446
478
  enables on `!isStale` and carries no used-state, and only `confirmation`, `mcpAuthenticationRequired`,
447
479
  `planReview` and `questionCarousel` have one — so the buttons stay visible after the answer. They are
448
480
  inert: the command refuses a request the runtime no longer holds and says "already resolved", and the
449
- resolution sentence lands directly beneath them. An elicitation that carries a `requested_schema` gets an
481
+ status bar says what was sent. An elicitation that carries a `requested_schema` gets an
450
482
  `Answer…` button that asks for the value first; a request still pending while the session is idle
451
483
  can also be answered by typing.
452
484
 
453
485
  **A harness's questions are VS Code's question carousel.** Why the carousel once swallowed its answer, read
454
- from the pinned Code-OSS (`4a7cd45`): `questionCarousel` resolves through the resolver map of the stream it
486
+ from Code-OSS at `4a7cd45`, the fork commit the macOS arm64 archive is still cut from (Linux and Windows: `4782d9a2`): `questionCarousel` resolves through the resolver map of the stream it
455
487
  was called on, and `$handleQuestionCarouselAnswer` reads only the participant's map
456
488
  (`extHostChatAgents2.ts`). A session's *re-joined* response (`activeResponseCallback`) gets a stream with a
457
- map of its own (`extHostChatSessions.ts`) that no answer ever reaches. So the carousel is used only on a
458
- turn this window's request handler is running; a re-joined response keeps the buttons above. The design:
489
+ map of its own (`extHostChatSessions.ts`) that no answer reached at that pin. The fork's `chatSessionResponses`
490
+ routes a carousel answer to a session's stream by its `resolveId` (`mainThreadChatSessions.ts` →
491
+ `$handleQuestionCarouselAnswer`), so on the product's host the carousel is used on a re-joined response too;
492
+ a host without it keeps the buttons above on a re-joined response. The design:
459
493
 
460
494
  - *The question reaches Chat as a request.* Supercode's own `ask_user` already asks through an `elicitation`
461
495
  whose `requested_schema.properties.qN` carry `title`, `description`, `x-options` (`[{label, description}]`)
@@ -470,7 +504,8 @@ turn this window's request handler is running; a re-joined response keeps the bu
470
504
  alone as `x-question`, and `x-options`) is one `ChatQuestion` per property: single or multi select with
471
505
  free text allowed, or text when it has no options; Skip is allowed. Any other form (an MCP server's own
472
506
  schema, with its `enum`, `format` or `required`) keeps the `Answer…` door, which honours them. Without the
473
- carousel (no `chatParticipantAdditions`, or a re-joined response) it is the `Answer…` button.
507
+ carousel (no `chatParticipantAdditions`, or a re-joined response on a host without `chatSessionResponses`) it is
508
+ the `Answer…` button.
474
509
  - *The answer reaches the harness in its own format.* The carousel's answers become the elicitation's
475
510
  `{action:'accept', content:{qN: label | [labels] | text}}`, or `decline` when skipped or submitted with
476
511
  nothing chosen; a stopped turn sends nothing (Stop cancels its requests). A reply typed into Chat instead
@@ -488,14 +523,16 @@ own envelope, which for Claude Code is `{behavior:'allow'}` / `{behavior:'deny',
488
523
  request states which decisions its harness protocol actually carries, so this view offers exactly
489
524
  those and no button the runtime would refuse — Claude Code has an allow and a deny and no
490
525
  always-allow *behavior* at all, so it gets two. A harness with no translation keeps
491
- `actions.respond: false`, and then the request is rendered as an observation naming who answers it,
492
- because a control appears only for an action the descriptor advertises. Tool completions name only
526
+ `actions.respond: false`, and then the request is drawn read-only, its title and summary with no controls,
527
+ because a control appears only for an action the descriptor advertises; Code-OSS likewise draws another
528
+ client's pending call for every observer. Tool completions name only
493
529
  the call they answer (Claude Code's `tool_result` block carries just a `tool_use_id`), so an unnamed
494
530
  completion keeps the name the start stated rather than becoming a tool called `tool`.
495
531
 
496
532
  **Bounds.** The projection is bounded like `@volter/supercode-frontend-browser`'s: 64 KiB per
497
- part, 256 characters per title, 2 KiB for an opaque payload, 500 history turns. When turns are
498
- omitted the view says so; the runtime's own history is unchanged and authoritative. Terminal control
533
+ part, 256 characters per title, 2 KiB for an opaque payload, 500 history turns. Turns past the bound are
534
+ left out without a word, as VS Code's own agent host shows a transcript its harness truncated; the
535
+ runtime's own history is unchanged and authoritative. Terminal control
499
536
  characters never reach a rendered part.
500
537
 
501
538
  **The turn.** A chat request submits through `frontend.v2.send_input` and resolves on the first
@@ -527,7 +564,7 @@ create no person-message bubble, live or restored; ordinary quoted text
527
564
  without those flags stays a person message. A task notification becomes a
528
565
  short background-task notice, and Claude's unmarked, exact interruption
529
566
  records (`[Request interrupted by user]`, `… for tool use]`) a short turn
530
- interruption notice. The native transcript remains authoritative and unchanged.
567
+ interruption notice, each a plain line of its own words (see the parity table's harness-record row). The native transcript remains authoritative and unchanged.
531
568
  [Source evidence and remaining qualification](../../docs/evidence/chat-native-notices-20261013.md).
532
569
 
533
570
  **Session times are real or nothing.** `frontend.v2` carries no session timestamp, and the editor's
@@ -541,8 +578,9 @@ not supported by native history rendering. A saved call is labeled neutrally bec
541
578
  a recorded invocation does not prove that permission was granted. VS Code's chat history is request/response **pairs** and drops a response turn with no
542
579
  request before it. A runtime transcript legitimately opens with assistant or system content — the
543
580
  runtime compacts, so its canonical history can begin `[earlier conversation compacted: N messages]`
544
- with no user turn left. Rather than drop it, the projection pairs it with a marker turn,
545
- `⟨supercode runtime history⟩`, which names itself: nothing is presented as a person's words.
581
+ with no user turn left. Rather than drop it, the projection pairs it with a marker turn whose prompt is
582
+ Code-OSS's own for a turn whose request is missing, "Message content could not be retrieved"
583
+ (`claudeReplayMapper.ts` `missingPromptPlaceholder`): nothing is presented as a person's words.
546
584
 
547
585
  ## Building and packaging
548
586