Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@robbyczgw-cla
Copy link
Contributor

@robbyczgw-cla robbyczgw-cla commented Jan 22, 2026

Summary

Fixes #1435 - Model switch via /model command reports success but doesn't actually switch.

Root Cause Analysis

In src/auto-reply/reply/directive-handling.impl.ts, the handleDirectiveOnly function has two separate code blocks:

Block 1 (lines 291-397): Session state persistence

if (sessionEntry && sessionStore && sessionKey) {
  // ... other directives ...
  if (modelSelection) {
    applyModelOverrideToSessionEntry({...});  // Actually saves the model
  }
  // ... persist to disk ...
}

Block 2 (lines 450-463): User feedback message generation

if (modelSelection) {
  parts.push(`Model set to ${label}.`);  // Always shown if modelSelection exists!
}

The bug: Block 2 runs regardless of whether Block 1 executed. So when sessionEntry, sessionStore, or sessionKey is missing:

  • ❌ Model override is NOT persisted
  • ✅ "Model set to X" message IS shown
  • → User sees success, but /status still shows old model

The Fix

Track whether the persist actually happened:

+  let didPersistModel = false;
   if (sessionEntry && sessionStore && sessionKey) {
     ...
     if (modelSelection) {
       applyModelOverrideToSessionEntry({...});
+      didPersistModel = true;
     }
   }
   
   // User feedback - now conditional on actual persist
-  if (modelSelection) {
+  if (modelSelection && didPersistModel) {
     parts.push(`Model set to ${labelWithAlias}.`);
+  } else if (modelSelection && !didPersistModel) {
+    parts.push(`Model switch to ${provider}/${model} failed (session state unavailable).`);
   }

Behavior Change

Scenario Before After
Session state available "Model set to X" ✅ "Model set to X" ✅
Session state missing "Model set to X" ❌ "Model switch failed..." ✅
No /model directive (nothing) (nothing)

Testing

Added unit tests covering all edge cases in directive-handling.impl.model-persist.test.ts:

✓ shows success message when session state is available
✓ shows error message when sessionEntry is missing  
✓ shows error message when sessionStore is missing
✓ shows no model message when no /model directive

Test Files  1 passed (1)
Tests       4 passed (4)

How to Verify

  1. Apply this PR
  2. Simulate missing session state (e.g., fresh session before store is initialized)
  3. Run /model <some-model>
  4. Before fix: "Model set to X" shown, but /status shows old model
  5. After fix: "Model switch failed (session state unavailable)" shown

Files Changed

  • src/auto-reply/reply/directive-handling.impl.ts - 5 lines changed (the fix)
  • src/auto-reply/reply/directive-handling.impl.model-persist.test.ts - new file (174 lines, unit tests)

AI Disclosure

  • 🤖 AI-assisted: Claude Opus 4.5 via Clawdbot
  • 🧪 Testing: Fully tested - 4 unit tests added, all passing
  • Code understanding: Yes, traced through the codebase to find root cause
  • 📝 Prompts/context: Available on request

Minimal, surgical fix. No unrelated changes. Tests cover all edge cases.

Previously, the /model command would display 'Model set to X' even when
the session state wasn't actually persisted (when sessionEntry, sessionStore,
or sessionKey were missing). This caused confusion as users saw success
messages but the model didn't actually change.

This fix:
- Tracks whether the model override was actually persisted
- Only shows success message when persist happened
- Shows a clear error message when persist fails

AI-assisted: Claude Opus 4.5 via Clawdbot
Testing: lightly tested (code review, no runtime test)
Tests verify:
- Success message shown when session state available
- Error message shown when sessionEntry missing
- Error message shown when sessionStore missing
- No model message when no /model directive

Covers edge cases for #1435 fix.
@robbyczgw-cla robbyczgw-cla force-pushed the fix/model-switch-persist-1435 branch from 668d66c to 784ea4f Compare January 22, 2026 20:40
@steipete steipete self-assigned this Jan 22, 2026
@steipete steipete merged commit 13a62d1 into openclaw:main Jan 22, 2026
21 of 23 checks passed
@steipete
Copy link
Contributor

Landed via temp rebase onto main.

  • Gate: pnpm lint && pnpm build && pnpm test
  • Land commit: 784ea4f
  • Merge commit: 13a62d1

Thanks @robbyczgw-cla!

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.

Model switch via /model command reports success but doesn't actually switch

2 participants