Skip to content

fix: resolve per-session model overrides using app session ID#996

Open
Kennems wants to merge 2 commits into
siteboon:mainfrom
Kennems:fix/session-model-override
Open

fix: resolve per-session model overrides using app session ID#996
Kennems wants to merge 2 commits into
siteboon:mainfrom
Kennems:fix/session-model-override

Conversation

@Kennems

@Kennems Kennems commented Jul 11, 2026

Copy link
Copy Markdown

Problem

Selecting a model from the Chat UI (/model) stores the override in session-model-changes.json keyed by the app session ID, but two things prevented it from working:

  1. Display was staleresolveCommandModel (used by /model, /cost, /status) called getCurrentActiveModel which reads from the JSONL file, never checking the stored overrides. The UI always showed the old model after switching.

  2. Runtime lookup key mismatch — All provider runtimes (cursor, codex, opencode) called resolveResumeModel without appSessionId, so the lookup key (provider:providerNativeSessionId) never matched the stored key (provider:appSessionId).

  3. Env vars could override the modelANTHROPIC_MODEL and friends in process.env were forwarded to the SDK subprocess, potentially overriding the explicit model option.

Changes

  • commands.jsresolveCommandModel checks getChangedActiveModel (session-model-changes.json) before falling back to getCurrentActiveModel (JSONL/provider default). Fixes /model, /cost, /status showing stale model.

  • claude-sdk.js, cursor-cli.js, openai-codex.js, opencode-cli.js — Pass appSessionId to resolveResumeModel so the stored override is found.

  • claude-sdk.js — Strip ANTHROPIC_MODEL, ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_SONNET_MODEL, ANTHROPIC_DEFAULT_HAIKU_MODEL from env forwarded to the SDK subprocess so the explicit model argument wins.

  • Test — Existing test resolveResumeModel uses appSessionId for model override lookup covers the core resolution logic.

Fixes #981

Summary by CodeRabbit

  • New Features

    • Improved session-specific model override handling across resumed conversations by using the app-level session id alongside provider session ids.
    • CLI/Provider model selection now preserves an explicit model choice instead of being overridden by Claude-related environment defaults.
  • Bug Fixes

    • Command model resolution now honors valid, user-selected per-session active-model overrides before falling back to the current active model or catalog default.
  • Tests

    • Added a unit test to verify app-level session overrides are correctly used during resume-model resolution.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 34d75b22-6438-4b8d-a1a6-f136de7724a6

📥 Commits

Reviewing files that changed from the base of the PR and between 1e1141b and 03c7f1c.

📒 Files selected for processing (8)
  • server/claude-sdk.js
  • server/cursor-cli.js
  • server/modules/providers/services/provider-models.service.ts
  • server/modules/providers/tests/provider-models.service.test.ts
  • server/modules/websocket/services/chat-websocket.service.ts
  • server/openai-codex.js
  • server/opencode-cli.js
  • server/routes/commands.js
🚧 Files skipped from review as they are similar to previous changes (8)
  • server/openai-codex.js
  • server/cursor-cli.js
  • server/opencode-cli.js
  • server/routes/commands.js
  • server/modules/providers/tests/provider-models.service.test.ts
  • server/modules/providers/services/provider-models.service.ts
  • server/modules/websocket/services/chat-websocket.service.ts
  • server/claude-sdk.js

📝 Walkthrough

Walkthrough

The change propagates application session IDs into provider model resolution, prioritizes per-session overrides, filters conflicting Claude model environment variables, and updates command model selection to honor valid user overrides.

Changes

Session model override handling

Layer / File(s) Summary
Application session model lookup
server/modules/providers/services/provider-models.service.ts, server/modules/providers/tests/provider-models.service.ts, server/modules/websocket/services/chat-websocket.service.ts
Runtime options now carry the application session ID, which resolveResumeModel prefers for override lookup and validates through a new test.
Provider runtime propagation
server/claude-sdk.js, server/cursor-cli.js, server/openai-codex.js, server/opencode-cli.js
Provider entry points pass options.appSessionId into resume-model resolution.
Command and SDK model selection
server/routes/commands.js, server/claude-sdk.js
Command resolution checks valid session overrides first, while Claude SDK environment construction removes model-related variables before forwarding it.

Sequence Diagram(s)

sequenceDiagram
  participant ChatUI
  participant ChatWebSocket
  participant ProviderRuntime
  participant ProviderModelsService
  participant ActiveModelStore
  ChatUI->>ChatWebSocket: send message with sessionId
  ChatWebSocket->>ProviderRuntime: pass appSessionId
  ProviderRuntime->>ProviderModelsService: resolveResumeModel(..., appSessionId)
  ProviderModelsService->>ActiveModelStore: getChangedActiveModel(appSessionId)
  ActiveModelStore-->>ProviderModelsService: model override
  ProviderModelsService-->>ProviderRuntime: resolved model
Loading

Possibly related PRs

  • siteboon/claudecodeui#682: Both changes modify how server/claude-sdk.js builds the SDK subprocess environment and handles model-related environment inputs.

Suggested reviewers: viper151, blackmammoth

Poem

I’m a rabbit with a model to choose,
No session’s preference shall hide or lose.
App IDs hop through the runtime stream,
Overrides now follow their rightful dream.
Conflicting env vars nibble away—
The chosen model leads the way!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: resolving per-session model overrides via app session ID.
Linked Issues check ✅ Passed The changes address #981 by honoring Chat UI model changes through app-session-aware model resolution and runtime propagation.
Out of Scope Changes check ✅ Passed All changes support the stated fix, including session ID propagation, override lookup, tests, and SDK env cleanup.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Kennems and others added 2 commits July 11, 2026 15:18
resolveCommandModel called getCurrentActiveModel which reads from the
JSONL file, never checking session-model-changes.json where the UI
stores per-session model overrides via /active-model. Now checks the
stored overrides first before falling back to the provider default.

Fixes siteboon#981 (display part)

Co-Authored-By: Claude <noreply@anthropic.com>
The /active-model endpoint stores model changes keyed by app session ID,
but provider runtimes called resolveResumeModel with only the provider-
native session ID, so the stored override was never found.

- Update resolveResumeModel to accept optional appSessionId parameter
- Pass appSessionId from handleChatSend to all provider runtimes
- Strip ANTHROPIC_MODEL env vars so explicit model option takes precedence
- Add test verifying appSessionId-based model resolution

Fixes siteboon#981 (runtime part)

Co-Authored-By: Claude <noreply@anthropic.com>
@Kennems Kennems force-pushed the fix/session-model-override branch from 1e1141b to 03c7f1c Compare July 11, 2026 07:18

@Sunjaieks Sunjaieks left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@Kennems
I also made a PR just for your reference: https://github.com/siteboon/claudecodeui/pull/998/changes

Following points are missed in your PR:

  1. https://github.com/siteboon/claudecodeui/pull/998/changes#diff-109e679f789e12dec8fb6884a19ca19526b4e4333fbb8c4d7e02040fda6f6983R146
    because in in claude's Jsonl file, field of model can be "<synthetic>"

2.847c9b7#diff-dda58f7c69e200b74287459fcd373aaf41a5ad0b25d31d91c8db2021a62b27e9R544
it will be better that new session will use the latest model which user selected from other session.

3.847c9b7#diff-109e679f789e12dec8fb6884a19ca19526b4e4333fbb8c4d7e02040fda6f6983R248
for highlighting

  1. maybe anything else?

I am new to this project, so maybe my PR also missed something. you can ask AI to analyze and merge the good point of each other.

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.

Can not change model from Chat UI

2 participants