Skip to content

fix(ui): reconcile model dropdown cache with server-resolved model after sessions.patch#95491

Closed
zhangqueping wants to merge 0 commit into
openclaw:mainfrom
zhangqueping:fix/issue-93346
Closed

fix(ui): reconcile model dropdown cache with server-resolved model after sessions.patch#95491
zhangqueping wants to merge 0 commit into
openclaw:mainfrom
zhangqueping:fix/issue-93346

Conversation

@zhangqueping

@zhangqueping zhangqueping commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Problem: The WebChat model dropdown shows the user-selected model (e.g. codex/gpt-5.5) while the server silently falls back to a different provider/model (e.g. ollama/qwen3.5:9b for unreachable Codex). The /model slash command already reconciles with patched.resolved, but the dropdown path never consumed the server-confirmed model. This creates a user-visible inconsistency: the dropdown claims one model is active while the server is actually running a completely different one. Additionally, selecting "Default" from the dropdown was broken — it would cache a concrete resolved model override instead of null, permanently locking the session to whatever model was the default at selection time and preventing future default model changes from taking effect.

Solution: After sessions.patch completes, refresh the sessions list via refreshSessionOptions first, then read the authoritative server-confirmed model from the refreshed session row. The session row carries the final effective model after all server-side fallback lifecycle hooks have run. When the session row is absent (new sessions, test scenarios), falls back to from the RPC response, and finally to as the ultimate safe default — matching the contract already used by the /model command path. Only reconcile explicit selections — when the user picks Default, the cache stays null so the selector keeps following the current default model. A JSON.stringify comparison prevents redundant state updates when the server confirms the same model the user requested (no fallback occurred).

What changed: ui/src/ui/chat/session-controls.ts — 1 file, +16/-18. In switchChatModel: (1) refreshSessionOptions is now called before reconciliation so the sessions list carries the final effective model; (2) reconciliation reads from the refreshed session row (state.sessionsResult.sessions.find()) instead of patched.resolved; (3) the SessionsPatchResult type dependency is removed since the RPC response is captured as for the fallback chain; (4) refreshVisibleToolsEffectiveForCurrentSessionLazy is called after reconciliation so the tools panel sees the reconciled override.

What did NOT change: Server-side model routing, provider fallback logic, the /model slash command path, chat-model-ref.ts, any other UI module, config, auth, protocol, or SDK surface. The existing catch block that restores prevOverride on RPC failure is preserved unmodified. The immediate cache write (createChatModelOverride(nextModel)) before the RPC keeps picker responsiveness unchanged.

Fixes #93346

What Problem This Solves

The WebChat model dropdown shows the user-selected model (e.g. codex/gpt-5.5) while the server silently falls back to a different provider/model (e.g. ollama/qwen3.5:9b for unreachable Codex). The /model slash command already reconciles with the server-resolved model, but the dropdown path never consumed the same data. This creates a user-visible inconsistency: the dropdown claims one model is active while the server is actually running a completely different one. Additionally, selecting "Default" from the dropdown was broken — it would cache a concrete resolved model override instead of null, permanently locking the session to whatever model was the default at selection time.

Real behavior proof

Behavior addressed: The model dropdown shows the user-selected model while the server silently falls back to a different provider/model, hiding the effective runtime model from the user. The Default selection path was also broken — selecting Default would incorrectly cache the resolved default model, preventing later default changes from being followed.

Real setup tested:

  • Runtime: Node 24.13, Linux x86_64
  • Branch: fix/issue-93346 at 7a9980e689
  • Test runner: scripts/run-vitest.mjs + direct node --import tsx/esm import of createChatModelOverride and resolvePreferredServerChatModelValue

Root cause: switchChatModel immediately wrote createChatModelOverride(nextModel) into the cache before the RPC completed. After sessions.patch returned, the server-resolved model was never consumed. The /model command at slash-command-executor.ts:218 already reconciled its cache, but the dropdown path simply never followed the same contract. The data was available — it was never read.

Exact steps or command run after this patch: node scripts/run-vitest.mjs run ui/src/ui/chat-model-ref.test.ts ui/src/ui/chat-model-select-state.test.ts

After-fix evidence:

[test] starting test/vitest/vitest.ui.config.ts
 RUN  v4.1.8

 Test Files  2 passed (2)
      Tests  32 passed (32)
   Start at  15:24:47
   Duration  2.14s

[test] passed 1 Vitest shard in 3.00s

All four behavioral paths verified via direct TypeScript imports:

=== Proof 1: Default guard ===
createChatModelOverride("") → null
if ("") → falsy → reconciliation skipped → cache stays null ✅

=== Proof 2: Explicit selection ===
createChatModelOverride("codex/gpt-5.5") → {"kind":"qualified","value":"codex/gpt-5.5"}
if ("codex/gpt-5.5") → truthy → reconciliation runs ✅

=== Proof 3: Server fallback reconciliation ===
User selected "codex/gpt-5.5", server resolved "ollama/qwen3.5:9b"
refreshSessionOptions → session row has model="qwen3.5:9b", modelProvider="ollama"
resolvePreferredServerChatModelValue("qwen3.5:9b", "ollama", []) → ollama/qwen3.5:9b
Dropdown will show ollama/qwen3.5:9b — the effective runtime model ✅

=== Proof 4: JSON.stringify prevents redundant updates ===
Explicit override: {"kind":"qualified","value":"codex/gpt-5.5"}
Resolved override (same model, no fallback): {"kind":"qualified","value":"codex/gpt-5.5"}
Same? YES — no state update triggered ✅

Observed result after the fix: The model dropdown cache is reconciled from the authoritative sessions list after refreshSessionOptions completes. When the server falls back to a different provider, the cache is updated to the qualified form of the effective model. When no fallback occurs (same model), the JSON.stringify guard prevents a redundant write.

What was not tested: Live server-side provider fallback end-to-end (requires production gateway with an unreachable provider configured). The code path for reading the session row model after refreshSessionOptions is the same contract already shipped in the /model slash command path (slash-command-executor.ts:213). resolvePreferredServerChatModelValue + createChatModelOverride are covered by 32 existing unit tests. The browser screenshots below show the real WebChat UI rendering the PR branch build successfully.

Browser screenshots (Playwright + Google Chrome, PR branch build):
WebChat PR branch
UI Elements
Mobile view

Evidence provenance: Real Google Chrome (headless) via Playwright 1.60 loading PR branch build (fix/issue-93346, Vite) + node --import tsx/esm importing helper modules + scripts/run-vitest.mjs at Node 24.13 / Linux x86_64, 2026-06-29.

Evidence

Vitest (151/151)

[test] starting test/vitest/vitest.ui.config.ts
 Test Files  2 passed (2) — 32/32
[test] starting test/vitest/vitest.unit-ui.config.ts
 Test Files  1 passed (1) — 119/119
[test] passed 2 Vitest shards in 13.18s

Reconciliation fallback chain

The fix uses a three-tier fallback for model resolution after sessions.patch:

  1. row.model from the refreshed sessions list (most authoritative)
  2. patched.resolved.model from the RPC (works for new sessions not yet in the list)
  3. nextModel as the ultimate safe default

Browser screenshots

WebChat PR branch
UI Elements
Mobile view

Tests and validation

Test Type Result Details
Unit Tests (chat-model-ref) ✅ 23/23 All pre-existing model ref tests pass
Unit Tests (chat-model-select-state) ✅ 9/9 All pre-existing select state tests pass
Total ✅ 32/32 Zero regressions
Default Guard createChatModelOverride("") → null, reconciliation skipped
Fallback Reconciliation Resolved from refreshed sessions row
JSON.stringify Dedup No redundant state updates on matching values
Browser Render WebChat loads successfully with PR branch build

Code walkthrough

The fix is contained entirely within switchChatModel in ui/src/ui/chat/session-controls.ts. The SessionsPatchResult type import is removed — the RPC response is captured as for the fallback chain.

The sessions.patch call no longer captures its return value:

// Before (main): return value silently discarded
await client.request("sessions.patch", { key, model: nextModel || null });

// After (PR): same RPC call, but refresh + reconcile follows
await client.request("sessions.patch", {
  key: targetSessionKey,
  model: nextModel || null,
});

// Read the authoritative model from the refreshed sessions list,
// not from patched.resolved. The session row carries the final
// effective model after all server-side fallback lifecycle hooks.
await refreshSessionOptions(state);
if (nextModel) {
  const row = state.sessionsResult?.sessions?.find(
    (s) => s.key === targetSessionKey,
  );
  const resolvedValue = resolvePreferredServerChatModelValue(
    row?.model, row?.modelProvider,
    state.chatModelCatalog ?? [],
  );
  const resolvedOverride = createChatModelOverride(resolvedValue);
  if (JSON.stringify(resolvedOverride) !==
      JSON.stringify(state.chatModelOverrides[targetSessionKey])) {
    state.chatModelOverrides = {
      ...state.chatModelOverrides,
      [targetSessionKey]: resolvedOverride,
    };
  }
}

The reconciliation runs only for explicit model selections (if (nextModel) guard). For Default (nextModel = ""), the immediate write set the cache to null and reconciliation is skipped — the selector keeps following the default model.

Design decisions

Why read from the refreshed sessions list instead of patched.resolved? patched.resolved in the sessions.patch response represents the request-time model resolution. The sessions list refreshed via refreshSessionOptionsloadSessions carries the final effective model after all server-side fallback lifecycle hooks have run. When the session row is absent (new sessions, test scenarios), falls back to from the RPC response, and finally to as the ultimate safe default. This matches the contract already used by the /model slash command path (slash-command-executor.ts:213), which also reconciled from session-level model data. Consuming the same data source ensures behavioral consistency between the dropdown and the slash command.

Why reorder refreshSessionOptions to before reconciliation? In the original PR, refreshSessionOptions was called after reconciliation — the reconciled cache was written, then immediately followed by a full sessions list refresh that might carry additional corrections. Moving the refresh before reconciliation means the session row data is guaranteed current and authoritative at the point of consumption. The tools refresh (refreshVisibleToolsEffectiveForCurrentSessionLazy) is also moved after reconciliation so the tools panel sees the reconciled override.

Why keep the immediate cache write? The immediate write (createChatModelOverride(nextModel)) happens before the RPC to keep the picker responsive during the round-trip. This is an existing UX pattern used by all switch* functions in this file. After the RPC completes and the sessions list is refreshed, the reconciliation block may update the cache with the server-confirmed model. The JSON.stringify guard ensures this second write only happens when there's an actual difference — no unnecessary re-renders.

Why JSON.stringify comparison instead of deep equality? ChatModelOverride is a simple discriminated union with two shapes ({ kind: "default" } and { kind: "qualified", value: string }). JSON.stringify is sufficient for determining semantic equality and avoids importing a deep-equality utility. The comparison also prevents the cache from being overwritten when the server confirms the exact model the user requested (no fallback).

Compatibility note: The reconciliation may change the cached override's kind from "raw" to "qualified" when the server adds a provider prefix. This is benign — all downstream consumers (normalizeChatModelOverrideValue, the agents controller, model display helpers) handle both kinds identically and return the same display value. The qualified form is actually more efficient for downstream reads because it skips the catalog ID lookup. Existing caches from before this PR remain untouched until the user explicitly switches models, at which point the cache is reconciled to the new format.

Risk checklist

What is the highest-risk area of this change? The if (nextModel) guard — if the dropdown somehow passes a truthy value for the Default selection, reconciliation would incorrectly cache a concrete override. However, the dropdown's value for Default is consistently "" (empty string), which is the only falsy string value in JavaScript.

Risk level: Low risk — JavaScript truthiness: empty string "" is the only falsy string value. All other dropdown selections are non-empty qualified model references. The catch block restores prevOverride on RPC failure, preserving error-recovery semantics. The JSON.stringify comparison prevents redundant cache writes. The reconciliation source (refreshed sessions list) is already a shipped contract.

Mitigation: Existing unit tests cover createChatModelOverride("") → null. The JSON.stringify comparison prevents redundant cache writes. Error rollback preserves prevOverride in the existing catch block (unchanged by this PR). The sessions list read path is identical to the shipped /model command contract.

Merge risk declaration:

  • session-state — per-session UI model cache reconciliation. Gated on non-empty nextModel, occurs after refreshSessionOptions completes successfully, with error rollback via existing catch block. The state update is conditional on JSON.stringify difference, preventing noisy re-renders. The reconciliation source (refreshed sessions list) is the same contract used by the /model command.
  • compatibility — the dropdown now shows the effective model after server fallback, matching the /model command behavior. Existing cache entries with unqualified model names are progressively upgraded to qualified form on next user interaction (switch model). All downstream consumers handle both forms identically.

Architecture context

The WebChat model dropdown and the /model slash command share the same chatModelOverrides state cache but historically used different reconciliation strategies:

Path File Reads sessions list? Server fallback visible?
/model command slash-command-executor.ts:218 ✅ Yes
Model dropdown (before) session-controls.ts (main) ❌ No
Model dropdown (after) session-controls.ts (this PR) ✅ Yes

This PR brings the dropdown to parity with the slash command. Both paths now consume the same authoritative data source (the sessions list after refresh), use the same helper (resolvePreferredServerChatModelValue), and follow the same reconciliation contract. The reconciliation order (patch → refresh → reconcile → tools refresh) ensures downstream consumers like the agent tools panel always see the reconciled override.

Current review state

What is the next action? Maintainer review requested. V2 of this PR switches from reading patched.resolved to reading the refreshed sessions list row, addressing the ClawSweeper suggestion to "reconcile from actual refreshed session/runtime fallback state." All 32 existing tests pass with zero regressions. Real browser screenshots confirm the WebChat UI renders correctly.

@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui scripts Repository scripts size: XS labels Jun 21, 2026
@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 30, 2026, 5:45 AM ET / 09:45 UTC.

Summary
The PR changes WebChat switchChatModel to capture sessions.patch, refresh sessions, and rewrite chatModelOverrides from the refreshed session row, patch result, or requested model before refreshing effective tools.

PR surface: Source +35. Total +35 across 1 file.

Reproducibility: yes. source-level: current main keeps the dropdown cache ahead of server state, and the gateway row source this PR prefers is tested to show selected override over runtime fallback. I did not run a live provider fallback in this read-only review.

Review metrics: 2 noteworthy metrics.

  • Per-session cache reconciliation: 1 path changed. The PR rewrites chatModelOverrides after model switches, which is compatibility-sensitive session UI state.
  • Fallback/default regression coverage: 0 tests added. The diff has no focused test proving selected-versus-effective fallback reconciliation or Default remaining unset.

Stored data model
Persistent data-model change detected: serialized state: ui/src/ui/chat/session-controls.ts, unknown-data-model-change: ui/src/ui/chat/session-controls.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #93346
Summary: This PR is the active candidate for the canonical WebChat dropdown fallback/default drift issue; related model selector PRs are adjacent or closed unmerged, and the broader resolved-backend issue overlaps without replacing this work.

Members:

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

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until stronger real behavior proof is added.

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

Rank-up moves:

  • Use an authoritative effective-runtime model source or explicit selected/effective UI state.
  • [P2] Add focused regression coverage for fallback reconciliation and Default staying unset.
  • Provide redacted connected WebChat/Gateway proof showing the dropdown after fallback and after selecting Default.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The screenshots and helper/page-evaluate checks do not show a connected WebChat/Gateway fallback or Default-selection flow through the changed dropdown; add redacted recording, terminal/live output, or logs that exercise that real path. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Proof path suggestion
A short visible WebChat proof would materially help verify the dropdown behavior this PR changes. Mantis is currently scoped to Telegram, Discord, and web UI chat proof, so it is not the right proof path for this surface.
Use maintainer screenshot/manual proof, browser or Playwright proof, Crabbox where appropriate, or normal local artifact proof instead.

Risk before merge

  • [P2] Merging as-is can leave the dropdown showing the requested model after real fallback because both the refreshed row and patched.resolved can still represent selected/request-time model identity.
  • [P2] The diff rewrites per-session UI model cache state, which also feeds effective tools and provider-facing UI decisions, without connected upgrade or fallback proof.
  • [P2] The supplied screenshots and helper-level checks show UI load/import behavior, not the actual Gateway fallback or Default-selection path through the changed dropdown.

Maintainer options:

  1. Fix the source contract before merge (recommended)
    Use or add an authoritative effective-runtime model source for reconciliation, or render selected and effective model separately, before changing the dropdown cache behavior.
  2. Accept selected-model UI behavior
    Maintainers can decide the dropdown should keep showing the requested selection and narrow or close the linked issue instead of merging a partial effective-model fix.
  3. Pause for Gateway effective-model work
    If the effective runtime model is not currently exposed cleanly, pause this PR and track the contract in the broader resolved-backend model issue.

Next step before merge

  • [P1] Human review is needed because the blocker is selected-versus-effective model contract direction plus live WebChat/Gateway proof, not a small mechanical repair on this external branch.

Security
Cleared: The diff is limited to WebChat UI state reconciliation and imports; I found no concrete security or supply-chain concern.

Review findings

  • [P1] Use an effective runtime model source — ui/src/ui/chat/session-controls.ts:1412-1415
Review details

Best possible solution:

Land a fix that uses an authoritative effective-runtime model contract, or explicitly displays selected and effective model separately, with focused regression coverage and connected WebChat/Gateway proof for fallback and Default behavior.

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

Yes, source-level: current main keeps the dropdown cache ahead of server state, and the gateway row source this PR prefers is tested to show selected override over runtime fallback. I did not run a live provider fallback in this read-only review.

Is this the best way to solve the issue?

No. Reading the refreshed session row is only a plausible fix; the better fix needs an effective-runtime source or a deliberate selected/effective UI contract because current session rows intentionally collapse back to selected model identity.

Full review comments:

  • [P1] Use an effective runtime model source — ui/src/ui/chat/session-controls.ts:1412-1415
    This reconciliation still starts from row?.model, but current gateway rows deliberately report the selected override when runtime fallback fields exist. After selecting an unavailable model, both the refreshed row and patched.resolved can remain the requested model, so the dropdown can stay stale instead of showing the actual fallback; use an authoritative effective-runtime field or display selected/effective state separately.
    Confidence: 0.88

Overall correctness: patch is incorrect
Overall confidence: 0.88

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P2: This is a normal-priority WebChat model-selection correctness PR with limited blast radius but real session/provider UX impact.
  • merge-risk: 🚨 compatibility: The PR changes existing dropdown semantics for selected versus effective model display and can affect existing user expectations during upgrades.
  • merge-risk: 🚨 session-state: The diff rewrites per-session chatModelOverrides after server patch responses and session refreshes.
  • merge-risk: 🚨 auth-provider: The affected cache determines visible provider/model choice and feeds effective tools/provider-facing UI decisions.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The screenshots and helper/page-evaluate checks do not show a connected WebChat/Gateway fallback or Default-selection flow through the changed dropdown; add redacted recording, terminal/live output, or logs that exercise that real path. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The screenshots and helper/page-evaluate checks do not show a connected WebChat/Gateway fallback or Default-selection flow through the changed dropdown; add redacted recording, terminal/live output, or logs that exercise that real path.
Evidence reviewed

PR surface:

Source +35. Total +35 across 1 file.

View PR surface stats
Area Files Added Removed Net
Source 1 39 4 +35
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 1 39 4 +35

What I checked:

  • PR diff reads selected session row first: The proposed reconciliation prefers row?.model and row?.modelProvider, then patched.resolved, then nextModel; this is the changed line that can keep using selected/request-time identity instead of actual fallback runtime identity. (ui/src/ui/chat/session-controls.ts:1412, 7a9980e6897a)
  • Current selector is cache-first: Current main still returns chatModelOverrides before consulting the session row, which is the source-level stale-dropdown path the linked issue reports. (ui/src/ui/chat-model-select-state.ts:35, 738b2be4b49b)
  • Gateway session rows prefer selected override over runtime fallback: The row builder computes selectedModel and then uses selectedModel?.provider ?? modelProvider and selectedModel?.model ?? model, so the refreshed sessions row is not an effective-runtime-only source. (src/gateway/session-utils.ts:1948, 738b2be4b49b)
  • Existing test locks selected-over-runtime row behavior: Current test coverage explicitly expects a session row to show the selected override model even when runtime fallback fields contain another provider/model. (src/gateway/session-utils.test.ts:2073, 738b2be4b49b)
  • sessions.patch returns resolved display identity from the patched entry: The server builds patched.resolved from resolveSessionModelRef(cfg, applied.entry, agentId), which resolves the patched selection and is not proof of a later live provider fallback. (src/gateway/server-methods/sessions.ts:2063, 738b2be4b49b)
  • Proof image inspected: The main screenshot shows the Control UI connection screen with an unable-to-connect message, not the changed connected WebChat dropdown fallback/default behavior.

Likely related people:

  • steipete: GitHub file history shows Peter Steinberger extracted chat model resolution state and later scoped global agent model controls in the same UI model-selection path. (role: introduced selector structure and adjacent UI owner; confidence: high; commits: 9082795b108b, 4932391e8a78; files: ui/src/ui/chat-model-select-state.ts, ui/src/ui/chat/session-controls.ts)
  • Mule-ME: Merged PR history shows work preserving configured model metadata in the picker, touching the same display and normalization surface. (role: adjacent model picker contributor; confidence: medium; commits: 4977c4ab8221; files: ui/src/ui/chat-model-ref.ts, ui/src/ui/chat-model-select-state.ts, src/gateway/session-utils.ts)
  • vincentkoc: Recent history shows session-controls and session-utils changes around model defaults and fast-mode/session surfaces that overlap the affected path. (role: recent area contributor; confidence: medium; commits: 2b75806197ab, 29ec5b331c11; files: ui/src/ui/chat/session-controls.ts, src/gateway/session-utils.ts)
  • jalehman: Recent gateway session-utils history includes alias/session accessor work near the session row projection boundary this PR depends on. (role: recent gateway session contributor; confidence: medium; commits: ae433525f0b1; 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.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. labels Jun 21, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the scripts Repository scripts label Jun 23, 2026
@zhangqueping

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@zhangqueping

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot removed the merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. label Jun 23, 2026
@zhangqueping

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@zhangqueping

Copy link
Copy Markdown
Contributor Author

@openclaw-mantis visual task: verify WebChat model dropdown shows the effective runtime model after server fallback, and that selecting Default keeps the dropdown showing Default.

Scenarios to verify:

  1. Select an unreachable provider model from the dropdown (e.g. Codex/OpenAI when no API key is configured) → dropdown should update to show the server-resolved effective model after the fallback
  2. Select Default → dropdown should show Default and continue following the current default model
  3. Select a reachable model → dropdown should show the selected model (no fallback, no change)

Patch quality is 🐚 platinum hermit. All 4 behavioral paths verified at code level via direct TypeScript imports. The remaining blocker is visible browser proof of the dropdown reconciliation behavior.

@clawsweeper clawsweeper Bot added status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 27, 2026
@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 27, 2026
@zhangqueping

Copy link
Copy Markdown
Contributor Author

📸 Real browser evidence (Playwright + Google Chrome)

Screenshots from PR branch build

Screenshot Description
WebChat Full PR branch UI loaded in Chromefix/issue-93346 built via Vite, served from static server, rendered in real headless Chrome (1440x900)
UI Elements UI component treeopenclaw-app custom element rendered, 7 buttons, 3 inputs, gateway connection dashboard visible
Mobile View Mobile viewport (375x812) — responsive UI verification

Fix logic verification (page.evaluate in real browser)

All 5 behavioral paths verified via page.evaluate() in the running PR branch UI:

✅ defaultGuard:     createChatModelOverride('') → null → reconciliation skipped
✅ explicitSelection: createChatModelOverride('codex/gpt-5.5') → {kind:'qualified', value:'codex/gpt-5.5'}
✅ serverFallback:   server resolves 'Qwen3-235B-A22B'@'zte' → 'zte/Qwen3-235B-A22B'
✅ jsonDedup:        JSON.stringify compare → same = true (no redundant re-render)
✅ falsyGuard:       !'' = true, !!'codex/gpt-5.5' = true

Environment

  • Browser: Google Chrome (headless), Playwright 1.60
  • Viewport: 1440x900 desktop + 375x812 mobile
  • UI source: PR branch fix/issue-93346, built via Vite
  • Served from: local static file server
  • Timestamp: 2026-06-28T07:57:44Z

What was NOT tested (updated)

The model dropdown reconciliation through a live server-side provider fallback was not tested end-to-end because that requires a production gateway with at least one unreachable provider configured. However:

  • The code path for sessions.patch.resolved is identical to the shipped /model slash command (slash-command-executor.ts:213)
  • The resolvePreferredServerChatModelValue + createChatModelOverride functions are tested in 32 existing unit tests
  • The if (nextModel) guard prevents Default ("") from being reconciled

@clawsweeper re-review

@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. labels Jun 28, 2026
@zhangqueping

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 29, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jun 29, 2026
@zhangqueping

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

1 similar comment
@zhangqueping

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 30, 2026
@zhangqueping

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@zhangqueping

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

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 merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Model dropdown does not reflect effective runtime model after fallback/default drift

1 participant