Skip to content

fix(ui): show selected agent default model#100719

Merged
steipete merged 1 commit into
mainfrom
codex/fix-control-ui-agent-model-default
Jul 6, 2026
Merged

fix(ui): show selected agent default model#100719
steipete merged 1 commit into
mainfrom
codex/fix-control-ui-agent-model-default

Conversation

@steipete

@steipete steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

The Control UI labels the empty model override as Default (<global model>) even when the selected agent has its own primary model. Clearing a session override therefore shows the wrong effective model. Fixes #77440 and salvages the valid intent from #77690.

Why This Change Was Made

Resolve the selected agent once at the chat-page owner, then pass only its prepared primary model into the model selector. The selector keeps the existing Gateway default as a loading/fallback value and does not reparse session keys or carry the full agents collection into a leaf component.

User Impact

After clearing a per-session override, the model picker now shows the selected agent's effective default model. Explicit overrides and the global fallback remain unchanged.

Evidence

  • Blacksmith Testbox tbx_01kwv3e6wmqvd6m1bsh7x9jcgz: pnpm test ui/src/lib/chat/model-select-state.test.ts — 12 passed.
  • Same Testbox: pnpm test:ui:e2e ui/src/e2e/chat-flow.e2e.test.ts — 25 real-Chromium flows passed, including agent switch, override, clear, and restored label.
  • git diff --check passed.
  • Fresh autoreview: no actionable findings; patch correct, confidence 0.84.

Co-authored-by: Harry Xie [email protected]

@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui size: S maintainer Maintainer-authored PR labels Jul 6, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73b8927905

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1413 to +1418
{
key: "agent:ops:session-a",
kind: "direct",
label: "Operations",
updatedAt: Date.now(),
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cover effective model fields in clear-default test

The mocked sessions.list row here leaves out model/modelProvider, but real Gateway rows include the effective model even when no override is selected (src/gateway/session-utils.ts:2046 and src/gateway/session-utils.ts:2211). After a browser reload following a clear, modelOverrides is empty, so resolveChatModelOverrideValue reads that effective row model and the picker selects it as an explicit override instead of showing Default (agent model); add the real row fields and fix the override/default discrimination so the regression stays fixed beyond the optimistic local null.

Useful? React with 👍 / 👎.

@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime scripts Repository scripts docker Docker and sandbox tooling size: M extensions: openai size: L cli CLI command changes agents Agent runtime and tooling size: XL and removed size: S size: M size: L labels Jul 6, 2026
@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 6, 2026, 4:36 AM ET / 08:36 UTC.

Summary
The PR passes the selected agent's primary model into the chat model selector and adds selector-state plus mocked Chromium coverage for clearing a session model override.

PR surface: Source +15, Tests +126. Total +141 across 5 files.

Reproducibility: yes. The source path shows Gateway rows can carry effective per-agent model fields while the selector treats any row model as a non-empty override unless a local null override cache entry exists.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: vector/embedding metadata: ui/src/e2e/chat-flow.e2e.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #77440
Summary: This PR is the current candidate fix for the WebChat selected-agent default-model label bug; the older draft PR is the same attempted fix path, and the changelog PR is adjacent release-note follow-up.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🌊 off-meta tidepool
Patch quality: 🦐 gold shrimp
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Fix the default/override discrimination for sessions whose row model equals the selected agent default.
  • Update the browser regression so the mocked session row includes the same model/modelProvider fields real Gateway rows provide.

Risk before merge

  • [P1] Merging as-is may only fix the optimistic in-page clear path while leaving a reloaded default-selected session displayed as an explicit selected model because real session rows include model fields.

Maintainer options:

  1. Decide the mitigation before merge
    Finish the selector-state fix so the active agent default drives both the Default label and the selected/default state when the row model equals the effective agent default, then keep the focused unit and browser regression coverage.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] A narrow automated repair could update the selector-state discrimination and strengthen the existing regression coverage without changing product direction.

Security
Cleared: Security review cleared: the diff is limited to Control UI state plumbing and tests, with no dependency, workflow, secret, permission, or package-execution changes.

Review findings

  • [P2] Keep the default selected when the row model is the agent default — ui/src/lib/chat/model-select-state.ts:88-95
Review details

Best possible solution:

Finish the selector-state fix so the active agent default drives both the Default label and the selected/default state when the row model equals the effective agent default, then keep the focused unit and browser regression coverage.

Do we have a high-confidence way to reproduce the issue?

Yes. The source path shows Gateway rows can carry effective per-agent model fields while the selector treats any row model as a non-empty override unless a local null override cache entry exists.

Is this the best way to solve the issue?

No. Passing the selected agent default down from the chat-page owner is the right layer, but the patch also needs to keep the default option selected when the row model is just the effective agent default.

Full review comments:

  • [P2] Keep the default selected when the row model is the agent default — ui/src/lib/chat/model-select-state.ts:88-95
    The new agentDefaultModel only changes defaultLabel; resolveChatModelOverrideValue still returns activeRow.model whenever the local override cache lacks this session. Real sessions.list rows include the effective model even for default-selected sessions, so after reload the picker can select anthropic/claude-opus-4-5 as an explicit override instead of selecting the empty Default option. Please make the default/override discrimination handle the agent-default row case and cover it with row model/modelProvider fields in the browser flow.
    Confidence: 0.87

Overall correctness: patch is incorrect
Overall confidence: 0.87

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against d6c880ae9203.

Label changes

Label changes:

  • add P2: This is a normal-priority WebChat model-selector correctness fix with clear user confusion but limited blast radius.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🌊 off-meta tidepool and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: The PR is maintainer-labeled, so the external-contributor proof gate is not applied; the PR still includes Testbox unit and mocked real-Chromium E2E evidence for the visible UI path.

Label justifications:

  • P2: This is a normal-priority WebChat model-selector correctness fix with clear user confusion but limited blast radius.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🌊 off-meta tidepool and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: The PR is maintainer-labeled, so the external-contributor proof gate is not applied; the PR still includes Testbox unit and mocked real-Chromium E2E evidence for the visible UI path.
Evidence reviewed

PR surface:

Source +15, Tests +126. Total +141 across 5 files.

View PR surface stats
Area Files Added Removed Net
Source 3 15 0 +15
Tests 2 126 0 +126
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 5 141 0 +141

Acceptance criteria:

  • [P1] pnpm test ui/src/lib/chat/model-select-state.test.ts.
  • [P1] pnpm test:ui:e2e ui/src/e2e/chat-flow.e2e.test.ts.
  • [P1] git diff --check.

What I checked:

  • PR diff: The PR adds agentDefaultModel to selector state and passes it from ChatPage through ChatModelControls, but does not change override/default discrimination. (ui/src/lib/chat/model-select-state.ts:88, 07b81bf1088f)
  • Current selector override behavior: On current main, when there is no local model override cache entry, resolveChatModelOverrideValue returns the active session row's model/modelProvider as a non-empty selected override. (ui/src/lib/chat/model-select-state.ts:74, d6c880ae9203)
  • Rendered selected state: The chat control renders the default label only when currentOverride === ""; a non-empty row model selects the concrete model option instead of the default option. (ui/src/pages/chat/components/chat-model-controls.ts:78, d6c880ae9203)
  • Gateway row contract: Session listing rows populate modelProvider and model from selected or runtime/default model identity, so a default-selected session can still arrive in the UI with model fields. (src/gateway/session-utils.ts:2046, d6c880ae9203)
  • Gateway default-row coverage: Existing gateway tests assert rows without runtime model metadata use selected agent defaults, including per-agent model rows. (src/gateway/session-utils.test.ts:2197, d6c880ae9203)
  • Related issue and superseded draft: The PR body links the canonical bug report and replaces the older draft PR that attempted the same WebChat agent default-model label fix.

Likely related people:

  • steipete: Git history shows Peter Steinberger extracted chat model selector state and currently owns the moved selector/chat-page files touched by this PR. (role: introduced selector structure and recent area contributor; confidence: high; commits: 9082795b108b, 1e2e7fb936ad; files: ui/src/lib/chat/model-select-state.ts, ui/src/pages/chat/chat-page.ts, ui/src/pages/chat/components/chat-model-controls.ts)
  • Mulualem Eshetu: Authored merged model-picker metadata preservation work touching selector state, tests, normalization, and gateway session utilities. (role: adjacent model-picker contributor; confidence: medium; commits: 4977c4ab8221; files: ui/src/ui/chat-model-select-state.ts, ui/src/ui/chat-model-select-state.test.ts, ui/src/ui/chat-model-ref.ts)
  • vincentkoc: Recent history includes gateway session/model surface work adjacent to the row model fields the selector consumes. (role: recent adjacent gateway/session contributor; confidence: low; commits: e085fa1a3ffd; files: src/gateway/session-utils.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready verification for 24bebca02786f7cb200b12d6ba225105926aa76c:

Known proof gaps: none for the changed UI behavior. The replacement preserves @hyspacex's co-author and changelog credit from #77690.

@steipete
steipete requested a review from a team as a code owner July 6, 2026 07:59
@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord channel: telegram Channel integration: telegram extensions: codex extensions: openrouter labels Jul 6, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e7ac4b0339

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +724 to +728
restartIntent: {
...currentRestartRequest.restartIntent,
...restartIntent,
force: true,
reason: restartReason,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make update upgrades interrupt the active drain

When an update signal arrives after runAcceptedRequest has already started draining a regular restart, this force: true is only stored on activeRestartRequest; the shutdown loop already captured the original restartIntent before it computes the drain timeout and checks restartIntent?.force, so active task/run waits continue using the old non-update restart policy. In the scenario where a config restart is draining active work and a managed update.run/update.auto arrives, the update can sit behind the old drain or hit the forced-exit watchdog instead of aborting the drain and reaching the clean update handoff path.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the codex/fix-control-ui-agent-model-default branch from e7ac4b0 to c68f7ab Compare July 6, 2026 08:13
@openclaw-barnacle openclaw-barnacle Bot removed channel: discord Channel integration: discord channel: telegram Channel integration: telegram gateway Gateway runtime cli CLI command changes scripts Repository scripts labels Jul 6, 2026
@steipete
steipete force-pushed the codex/fix-control-ui-agent-model-default branch from c68f7ab to 4b7bcbf Compare July 6, 2026 08:23
@steipete
steipete force-pushed the codex/fix-control-ui-agent-model-default branch from 4b7bcbf to 07b81bf Compare July 6, 2026 08:28

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 07b81bf108

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +615 to +617
const agentDefaultModel = this.context.agents.state.agentsList?.agents.find(
(agent) => agent.id === currentAgentId,
)?.model?.primary;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use resolved agent defaults for picker labels

When the selected agent's model.primary is an alias or otherwise normalized by resolveDefaultModelForAgent, this passes the raw config string into the picker. agents.list builds that field from resolveAgentEffectiveModelPrimary (src/gateway/session-utils.ts:1207-1219), while sessions.list rows resolve aliases to the effective provider/model (src/gateway/session-utils.test.ts:2197-2243 covers anthropic/sonnet-4.6 becoming anthropic/claude-sonnet-4-6). After clearing an override, modelOverrides[key] === null makes the picker use this default label, so alias-backed agents show the raw alias instead of the actual catalog/default model; pass the resolved row identity or expose a resolved agent default.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. labels Jul 6, 2026
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready verification for 07b81bf1088f099a3fac7cb7e4f202e2714f661a:

Known proof gaps: none for the changed UI behavior. The replacement preserves @hyspacex's co-author credit from #77690; maintainer changelog credit is isolated in #100740 to avoid coupling this exact-head UI proof to the high-traffic release-notes hunk.

@steipete
steipete merged commit 5f3629e into main Jul 6, 2026
93 of 96 checks passed
@steipete
steipete deleted the codex/fix-control-ui-agent-model-default branch July 6, 2026 08:41
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 7, 2026
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui maintainer Maintainer-authored PR P2 Normal backlog priority with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: S status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: WebChat model selector shows global default instead of agent-specific default model

1 participant