Skip to content

fix(client-ui): reconcile a stale model selection, uncap the status line, add a CDP helper - #383

Open
Kunstderfug wants to merge 3 commits into
dataelement:mainfrom
Kunstderfug:fix/client-ui-followups
Open

fix(client-ui): reconcile a stale model selection, uncap the status line, add a CDP helper#383
Kunstderfug wants to merge 3 commits into
dataelement:mainfrom
Kunstderfug:fix/client-ui-followups

Conversation

@Kunstderfug

Copy link
Copy Markdown

What

Three follow-ups left over from the work in #381 and #382. The two fixes are independent of each other and of that pair; the third commit is the dev tooling used to verify all of it. Happy to split any of them out on request.

1. The model selector kept naming a model that Settings had removed

A Session's model selection is durable; the catalog is not. Removing or renaming a model in Settings left the composer rendering the bare provider/model identifier — which looks exactly like the previously selected model, because it literally is it, with nothing left able to resolve the name. It reads as "the selector didn't update", and it never repaired itself: the client fetched the catalog on every save, but never reconciled the selection against it.

The directory now reconciles on every catalog push. When the catalog stops serving the pinned selection it adopts the deployment default (the model a new Session would get), falling back to the first served model if that default went stale in the same edit. Only routable providers are offered, so the Host cannot reject the replacement and strand the Session on the same dead name. The replacement is recorded as a normal selection, so neither the Session nor the stored default keeps naming a model that no longer exists.

Two traps, both of which I hit while building it and both of which the tests now pin:

  • One attempt per catalog value. The first version marked the catalog as reconciled after starting the replacement, so an identical catalog push re-ran adoption every time. The marker is now written before the replacement starts.
  • A loading catalog is not an empty one. Treating status !== 'ready' as "serves nothing" made the selector rewrite itself on a cold load.

test/model-selection-refresh.test.ts — 15 tests. It loads the real client bundle and drives the real ModelDirectory against the real store engine: adoption, one attempt per catalog value, no repair while the selection is served, the loading-catalog hold, and that an unroutable catalog default never wins.

2. The status line was capped to the message column

The token/cost line under the conversation inherited the chat content width cap and ellipsized inside it: 782px of text in a 704px box. With the cap lifted, the same content fits on one line in the 1092px actually available. Only that line's own root rule changes (max-width:none); its box-sizing, padding, ellipsis behaviour, and centered separators are untouched.

test/stats-line-width.test.ts — 3 tests.

3. A CDP helper for measuring the live window (tooling)

Judging client-plugin styling by eye is unreliable — a theme override that silently resolves to its light branch looks like a working fix in a screenshot, and I shipped exactly that mistake once while doing #382. scripts/cdp-eval.sh '<expression>' evaluates an expression inside the running renderer over the Chrome DevTools Protocol, so computed styles, geometry, and console output come from the real window. Requires the app started with --remote-debugging-port=9222; DSH_CDP_PORT selects another port and DSH_NODE another node binary.

Verification

  • npx vitest run test/model-selection-refresh.test.ts test/stats-line-width.test.ts — 18 passed on this branch alone.
  • npm test — 810 passed / 95 files. npm run typecheck clean.
  • scripts/cdp-eval.sh exercised against a running dev app after making its node resolution portable.
  • cdp-eval.sh committed 100755, cdp-eval.mjs 100644.

Note

Adoption goes through the normal selection path, so the adopted model's settings travel with it — including reasoningEffort when the deployment default carries one. In our install that rewrote the stored default's reasoning effort. That is the intent (stop naming a dead model) but it is a persisted side effect worth knowing before merging.

…el disappears

A Session's model selection is durable; the catalog is not. Editing models
in Settings removes and renames entries beneath a selection made earlier,
and the composer then rendered the bare "provider/model" identifier -- which
looks like the previously selected model because it literally is it, with
nothing left able to resolve the name.

The directory now reconciles on every catalog push: when the catalog stops
serving the selection a Session pins, it adopts the deployment default (the
model a new Session would get), falling back to the first served model when
that default went stale in the same edit, and only ever offering a routable
provider so the Host cannot reject the replacement and strand the Session on
the same dead name. The replacement is recorded as a normal selection, so
neither the Session nor the stored deployment default keeps naming a model
that no longer exists.

One attempt is made per catalog value, so a rejected replacement cannot
loop, and a still-loading catalog is never mistaken for an empty one.

The test drives the real ModelDirectory against the real store engine and
covers adoption, one attempt per catalog value, no repair while the
selection is served, and the loading-catalog hold.
… column

The token and cost status line under the conversation inherited the chat
content width cap, so it was truncated to the message column and ellipsized
even with the window far wider. It measured 782px of text in a 704px box;
with the cap lifted the same content fits on one line in the 1092px that are
actually available.

Only the status line's own root rule changes (max-width:none). Its
box-sizing, padding, ellipsis behaviour, and centered separators are
untouched.
Judging client-plugin styling by eye is unreliable: a theme override that
silently resolves to its light branch looks like a working fix in a
screenshot. This helper evaluates one expression inside the running renderer
over the Chrome DevTools Protocol, so computed styles, geometry, and console
output are read from the real window.

Start the app with --remote-debugging-port=9222 and run
scripts/cdp-eval.sh '<expression>'. DSH_CDP_PORT selects another port and
DSH_NODE another node binary.
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