Skip to content

fix: keep chat choices in the host status stream - #27641

Draft
brennanb2025 wants to merge 6 commits into
brennanb2025/agent-publish-before-handshakefrom
brennanb2025/agent-current-selection
Draft

brennanb2025 wants to merge 6 commits into
brennanb2025/agent-publish-before-handshakefrom
brennanb2025/agent-current-selection

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 16 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1481 $\color{#cf222e}{\Huge{\mathbf{−}}}$​127 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1354
Prod 14 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​316 $\color{#cf222e}{\Huge{\mathbf{−}}}$​180 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​136

ELI5

After choosing a model or reasoning effort, sending the next message could briefly replace that choice with the default because older options replies competed with the saved choice. Separately, the first chat for an agent could lose all picker pills when its options read answered before the model list finished loading; the empty answer then prevented the later list from updating the picker. Both problems are fixed: choices follow the conversation's host, and a fresh chat keeps the existing placeholder or known default until its model list arrives, without sending a message or switching tabs.

What Changed

The existing host status stream carries the conversation's saved choices in an optional optionSelection field. One pending-pick record shows a requested value and prevents overlapping requests; the reply or a runtime restart clears it, and a late reply from another conversation or runtime cannot overwrite the current choice or settings. When no choice has been saved, the picker derives the configured default from the latest catalog for this folder and host. Later folder and account changes refresh it.

An options read at rest now adds an optional modelsKnown field. It says false when the host has no loaded catalog, including when only Claude's built-in fallback exists. Desktop and shared desktop/mobile option application retain their existing catalog in that case; the later host listing can fill it in. Commands, image support and other metadata still arrive, and the legacy selection path still applies saved choices. Real provider lists retain their existing authority. The options result type is moved to its own module because the existing wire module was at its line limit; existing imports continue to work.

The chat subscribes only to changes in startup phase, Stop and choices. Tool and message activity keep the same selection object. Existing options reads continue supplying commands, goals, context, images, rewind support and catalog labels; older hosts keep the read-based selection path.

Why

The host already owns the choices used by the next start. Publishing those choices removes competing selected values, and deriving defaults from the existing scoped catalog avoids storing another copy. Marking an unloaded catalog at its source distinguishes missing data from an authoritative empty list without changing existing wire fields or adding another retry or tab-switch workaround.

Differences from the common pattern:

  • Intended — Execution host owns choices: the host running the agent owns saved choices, including SSH conversations; losing contact does not undo accepted work.
  • Intended — Metadata read retained: the existing read still supplies commands, goals, context, images and rewind support. Their replies cannot replace the host's choices.
  • Temporary — Choices attached to each message: queued messages still use the latest accepted picks when they reach the agent. A future change would bind choices to each submitted message; no follow-up ticket or PR exists yet.

Linked Issue

Maintainer follow-up to #26561; no separate issue.

Visual Proof

Pending coordinator-owned rendered QA on this exact draft head. This worker added no new notice or UI surface.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated

Final focused validation passed 132 tests across 17 files on macOS. The new real-host/catalog regression holds the first listing open, completes the options read first, then resolves the listing and checks that both model and effort appear in place. It covers Codex, Grok, Pi and Claude, with a starting child and at rest, and verifies that the second chat uses the loaded catalog without another probe. All eight cases fail on the previous head b0a16e7a423 and on the PR base 34e53888a3d before the fix.

The React tests cover the same four agents with both host-status and read-based choices, assert that no completed-read frame loses its model pill, then check the model and effort after the joined listing resolves and on the second chat's first frame. A shared-state test keeps an already-known default during an unloaded options answer and still applies its saved effort. Existing tests retain older-host and authoritative-empty-list behavior, both catalog reply orders, updated defaults, pending and late replies, startup picks and selection stability.

Web and Node typechecks passed through the machine queues. All required static checks pass with CI's pinned Bun 1.4.3 and its dependency-install order, including all four CI compiler projects. The worker ran no real agent, Electron app, native-focus or SSH transport QA; rendered QA remains coordinator-owned. The single fail-fast CI watch stopped on Windows packaging: two unchanged batch-hook tests for Unicode profile paths exceeded their 60-second timeout. CI static/typechecking, mobile verification and bundle, Linux packaging and relay integration passed; the five main unit shards and cross-version wire job were still pending when the watch stopped. CI is not yet green; this worker made no unrelated hook-test change.

Review

Production is +308/-177 = +131 net lines across fourteen files against #26561, excluding tests: +20 over the previous +111. The additional work corrects catalog authority and separates the options result type; it adds no persisted state or polling.

The earlier chat-switch test guards a regression in an intermediate draft; it was already handled by the earlier submitted implementation. Passing tests verify these behaviors and do not substitute for rendered QA.

Agent skill upstream boundary

  • Not applicable; no upstream skill-installer source is copied or translated.

Notes

Both new fields are optional for independently updated clients and hosts. Older clients ignore modelsKnown; hosts that omit it retain existing options-list behavior, including the pre-existing cold-start limitation. The new distinction is used when both peers support it. Existing models and current values, capabilities and stream operations are unchanged. Folder workspaces use the same scoped catalog path as git worktrees; nothing assumes local execution.

Checklist

  • Explained the problem, user-facing change, mechanism and approach
  • Before/after visual proof attached
  • Self-reviewed source and focused correctness controls
  • Cross-platform, SSH, folder and older-peer compatibility considered
  • Required local tests, typechecks and static checks complete
  • Final-head CI complete

@brennanb2025 brennanb2025 changed the title fix: keep model and effort picks stable through startup fix: keep chat choices in the host status stream Oct 12, 2026

This branch has not been deployed

No deployments
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