fix: isolate model selection per chat to prevent cross-chat leakage#8093
fix: isolate model selection per chat to prevent cross-chat leakage#8093octo-patch wants to merge 1 commit into
Conversation
…eakage (fixes janhq#8083) Each CustomChatTransport now locks onto the model/provider that was active when the user submitted a message and reuses it for the entire MCP tool-call chain. Previously, switching the model selector in a second chat tab while an MCP tool chain was running in the first tab would cause all subsequent tool-result follow-up requests in chat 1 to use the model selected in chat 2. The lock is snapshotted at the start of every new user turn (detected by the last message being an assistant message without tool-invocation parts) and held for all downstream sendMessages() calls within that chain. It updates naturally when the user sends a fresh message, so intentional within-thread model changes still take effect on the next turn.
Review: isolate model selection per chatGood fix for a real user-facing bug. The approach of snapshotting the model/provider at the start of each user turn and reusing it for MCP tool-chain continuations is clean and correctly targeted. The implementation reads well and the fallbacks are sensible. Requested Changes
Minor
The fix is solid and addresses the reported issue correctly. With tests added, this is ready to merge. Recommendation: improve needed |
Review: fix: isolate model selection per chat to prevent cross-chat leakageSummary: Fixes a bug where switching the model selector in one chat tab could alter in-flight MCP tool-chain requests in another tab. The fix snapshots Positive observations
Issues and observations
Recommendation: fix needed |
Fixes #8083
Problem
When multiple chats are open simultaneously and MCP tool chains are running,
switching the model selector in one chat tab affects in-flight requests in
other tabs. This happens because
CustomChatTransport.sendMessages()alwaysreads
selectedModelandselectedProviderfrom the global Zustand store atthe time of each call. If the user switches to another tab and picks a
different model mid-chain, the next MCP tool-result follow-up in the original
tab uses the newly selected model instead of the one that started the
conversation.
Solution
Added
_chainModelIdand_chainProviderIdprivate fields toCustomChatTransport. At the start of everysendMessages()call the codedetects whether we are beginning a new user turn (last message is not an
assistant message with tool-invocation parts) or continuing an existing MCP
tool chain. On a new user turn the fields are snapshotted from global state;
on a tool-chain continuation the previously locked values are reused.
The same guard is applied in
refreshTools()so the capabilities check fortool support also uses the chain-locked model.
Intentional within-thread model changes still take effect normally: they are
picked up on the next user message submission, which resets the chain
snapshot.
Testing
calls (e.g. a long multi-step task).
follow-ups.
Previously step 4 would silently switch Chat A's backend requests to Model Y.