Skip to content

Thread the live model into the picker instead of inferring it - #367

Merged
TheGreatAxios merged 4 commits into
mainfrom
cl-5597-model-picker-infers-the-current-model-from-recents-and-can
Aug 7, 2026
Merged

Thread the live model into the picker instead of inferring it#367
TheGreatAxios merged 4 commits into
mainfrom
cl-5597-model-picker-infers-the-current-model-from-recents-and-can

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Summary

The model picker marked "(current)" on recentModels[0] — the model
most recently switched to via /model — instead of the model the
session was actually running. A session that starts on
defaultProvider from settings and never opens the picker gets
mislabeled whenever a previous session's recents point elsewhere: the
wrong row reads (current), and the real model gets no marker at all.

Fixes CL-5597 by threading the live provider/model down through
RunnerHostDeps.activeModelProductHostConfig.activeModelId, read
fresh on every picker open. The recents-based guess in
product-host.ts is deleted, not kept alongside the real value.

Net diff: +63/-6 lines, mostly test coverage (two new/updated tests);
production code (product-host.ts, runner-host.ts, runner.ts) is
net smaller than before — it deletes the inference helper and adds one
line of live wiring.

Verification

  • bun run typecheck — passes

  • bun run build — passes

  • bun run test — 4038 pass, 0 fail

  • bun test ./src ./tests ./evals --randomize --seed 42 — 4038 pass, 0 fail

  • Confirmed red: with the fix's activeModelId wiring reverted, the new
    product-host.test.ts case fails (xai/thegreataxios / grok-4.5 (current)
    shown instead of the live codex/abk-labs), then passes after restoring
    the fix.

  • Rendered a real frame: recents hold xai/thegreataxios / grok-4.5 from a
    prior session; this session runs codex/abk-labs / gpt-5.5 and never
    opened /model. The picker now marks the live model, not the stale
    recent:

    ┌──────────────────────────────────────────────────────────────────────────┐
    │ model / provider · Esc cancel · Enter choose                             │
    │ > xai/thegreataxios / grok-4.5                                           │
    │   codex/abk-labs (current)                                               │
    │ ──────────────────────────────────────────────────────────────────────── │
    └──────────────────────────────────────────────────────────────────────────┘
    

Closes CL-5597

The picker marks "(current)" on recents[0], which only moves on an
explicit /model pick. A session that never switches models, with
recents naming a different model, gets no marker on its real model
and a wrong one on a stale recent.
recentModels[0] only updates on an explicit /model pick, so a
session running on defaultProvider from settings, having never
switched via the picker, got the wrong row marked "(current)" (or
none at all) whenever recents pointed elsewhere.

Runner.ts now passes the session's live provider+model down through
RunnerHostDeps.activeModel and ProductHostConfig.activeModelId, read
fresh on every picker open. The recents-based guess is gone.
The picker no longer infers "(current)" from recents[0]; the test
now supplies activeModel explicitly, matching how runner.ts wires it.
@linear-code

linear-code Bot commented Aug 7, 2026

Copy link
Copy Markdown

CL-5597

@TheGreatAxios

Copy link
Copy Markdown
Collaborator Author

Independent review — ready to merge

Verified by running, not by reading. Held open for human review, not merged.

The stale-recents bug is fixed. A real rendered frame with recents holding xai/thegreataxios / grok-4.5 and the live session on codex/abk-labs / gpt-5.5, picker never opened: the stale row is not marked, and gpt-5.5 (current) renders correctly.

Degrades sanely when the live model is absent from the catalog. No test covered this, so the reviewer wrote one: an activeModelId pointing at a model not in the catalog neither throws nor marks an arbitrary row. annotateCurrent short-circuits on undefined and its equality branch simply never hits.

One path, not two. grep -rn 'section === "recent"' src/ finds only unrelated assertions about recents-list contents — nothing decides (current) anymore. The old inference helper has no surviving caller.

The optional config degrades to no marker, not to the old behavior. A host omitting activeModel/activeModelId yields undefined and renders no marker — an honest absence rather than a silent revert to the stale inference.

The threaded values are genuinely live. src/tui/runner.ts:381 declares let config, onModelSelect at :1943 reassigns it, and the activeModel closure at :1935 reads the same binding — so it observes a mid-session model switch rather than a startup snapshot.

Red/green is real. 7a6e03a (failing test) precedes 5ecfb4d (fix), and checking out the earlier commit produces a genuine failure — a TS2353 type error, because the test referenced a ProductHostConfig field production code did not yet expose.

Typecheck and build clean. 4038 pass / 0 fail, identical under --randomize --seed 42. Commit hygiene clean: three verb-first subjects, no over-length lines, no ticket IDs or filenames, no any, no vendor/ changes.

One trivial note, deliberately not sent back to the author: product-host.ts:578-579 keeps a one-line activeModelId wrapper that callers could inline. Too small to be worth a round trip.

@TheGreatAxios
TheGreatAxios merged commit 0f57090 into main Aug 7, 2026
3 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.

1 participant