feat(chat): model chip in chat header + mobile menu info row; remove New conversation and Show thinking (ADR-grilled #68) #69

Merged
dominik.polakovics merged 1 commit from afk/68 into main 2026-07-09 13:43:46 +02:00

Closes #68

What

  • Desktop (≥640px): a read-only, muted model · effort chip in the chat header beside the state chip — provider-catalog pretty labels (GET /providersmodels/efforts option labels, same source as the NewRun composer chips) with the raw id as fallback; hidden entirely when run.model is empty (legacy rows). If effort is empty, the chip shows just the model label with no dangling separator.
  • Mobile (<640px): the same string as a non-interactive info row pinned atop the ••• menu panel — role="none" div (not a menuitem, not focusable, no hover affordance), set off from the action items by a bottom border. Renders regardless of liveness (spawn-time truth) and hides with an empty model.
  • Removed "New conversation" and "Show thinking" from both surfaces, plus the dead plumbing: showThinking signal, clearConfirming/clearing confirm state, clearCommand/canClear/sendClear wiring, and composerLocked (its only caller was canClear). Thinking blocks are now permanently dropped at paint — in the stream and inside expanded tool groups — while grouping still runs over the full list so tool-run boundaries and seq keys stay stable.
  • Truth source is the spawn-time run.model/run.effort from the run row; a mid-session /model switch is knowingly not reflected (per the grilled decision — no backend work).
  • Backend clear endpoint / provider clear capability untouched; the role=clear catalog entry still feeds the composer autocomplete (/clear remains typeable).

Acceptance mapping

  • rg -n "showThinking|clearConfirming|canClear|onToggleThinking" web/src → no matches.
  • Tests cover: raw-id fallback (opus[1m] · max), catalog pretty labels, legacy empty-model hiding (chip AND menu row), empty-effort no-separator, info row as first panel child with role=none excluded from [role=menuitem], thinking never rendering (stream + opened tool group), and No-New-conversation-anywhere with autocomplete intact.

Verification

  • npm run test — 546/546 across 37 files (RunChat suite: 86, incl. 5 new model-chip tests).
  • npm run build (tsc --noEmit + vite) clean; npm run lint clean; prettier clean.
  • web/-only diff: RunChat.tsx, RunChat.test.tsx, base.css. No browser available in this sandbox, so behavior is proven by the jsdom component suite that mounts the full route and asserts the rendered DOM.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PtNDPVuKWBtwxZLcTVwCTh

Closes #68 ## What - **Desktop (≥640px):** a read-only, muted `model · effort` chip in the chat header beside the state chip — provider-catalog pretty labels (`GET /providers` → `models`/`efforts` option labels, same source as the NewRun composer chips) with the raw id as fallback; hidden entirely when `run.model` is empty (legacy rows). If effort is empty, the chip shows just the model label with no dangling separator. - **Mobile (<640px):** the same string as a non-interactive info row pinned atop the ••• menu panel — `role="none"` div (not a `menuitem`, not focusable, no hover affordance), set off from the action items by a bottom border. Renders regardless of liveness (spawn-time truth) and hides with an empty model. - **Removed** "New conversation" and "Show thinking" from both surfaces, plus the dead plumbing: `showThinking` signal, `clearConfirming`/`clearing` confirm state, `clearCommand`/`canClear`/`sendClear` wiring, and `composerLocked` (its only caller was `canClear`). Thinking blocks are now permanently dropped at paint — in the stream and inside expanded tool groups — while grouping still runs over the full list so tool-run boundaries and seq keys stay stable. - Truth source is the spawn-time `run.model`/`run.effort` from the run row; a mid-session `/model` switch is knowingly not reflected (per the grilled decision — no backend work). - Backend clear endpoint / provider clear capability untouched; the `role=clear` catalog entry still feeds the composer autocomplete (`/clear` remains typeable). ## Acceptance mapping - `rg -n "showThinking|clearConfirming|canClear|onToggleThinking" web/src` → no matches. - Tests cover: raw-id fallback (`opus[1m] · max`), catalog pretty labels, legacy empty-model hiding (chip AND menu row), empty-effort no-separator, info row as first panel child with `role=none` excluded from `[role=menuitem]`, thinking never rendering (stream + opened tool group), and No-New-conversation-anywhere with autocomplete intact. ## Verification - `npm run test` — 546/546 across 37 files (RunChat suite: 86, incl. 5 new model-chip tests). - `npm run build` (tsc --noEmit + vite) clean; `npm run lint` clean; prettier clean. - `web/`-only diff: `RunChat.tsx`, `RunChat.test.tsx`, `base.css`. No browser available in this sandbox, so behavior is proven by the jsdom component suite that mounts the full route and asserts the rendered DOM. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01PtNDPVuKWBtwxZLcTVwCTh
feat(chat): spawn-time model chip + menu info row; drop New conversation and Show thinking (#68)
All checks were successful
ci / native (pull_request) Successful in 4m39s
dc66f7ec68
Show the run's spawn-time model in the chat UI (issue #68):

- Desktop (>=640px): a read-only muted `model · effort` chip beside the
  state chip, using provider-catalog pretty labels with the raw id as
  fallback; hidden entirely for legacy rows with no model.
- Mobile (<640px): a non-interactive info row (role=none, not a menuitem,
  no hover affordance) pinned atop the ••• menu panel, separated from the
  action items. A mid-session /model switch is knowingly not reflected —
  the run row's spawn-time model is the truth source.

Remove "New conversation" and "Show thinking" from both surfaces, plus the
dead plumbing: the showThinking signal, clearConfirming/clearing confirm
state, and the clearCommand/canClear/sendClear/composerLocked wiring.
Thinking blocks are now permanently dropped at paint (stream and expanded
tool groups); transcripts on disk keep everything. The role=clear catalog
entry still feeds the composer autocomplete; the backend clear path is
untouched (web-only diff).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtNDPVuKWBtwxZLcTVwCTh
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/coding-lab!69
No description provided.