Skip to content

Commit af267a6

Browse files
committed
🤖 fix: restore thinking level when model changes
ThinkingProvider was reading the model non-reactively, so when the model changed (e.g., via Cycle Model), the thinking level wasn't updated. Fix: Subscribe to model changes via usePersistedState with listener mode, so when the model changes, we derive the new thinking key and load the correct stored value for that model. --- _Generated with `mux` • Model: `anthropic:claude-sonnet-4-20250514` • Thinking: `low`_
1 parent 8c52449 commit af267a6

File tree

1 file changed

+20
-20
lines changed

1 file changed

+20
-20
lines changed

src/browser/contexts/ThinkingContext.tsx

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { ReactNode } from "react";
2-
import React, { createContext, useContext } from "react";
2+
import React, { createContext, useContext, useMemo } from "react";
33
import type { ThinkingLevel } from "@/common/types/thinking";
4-
import { usePersistedState, readPersistedState } from "@/browser/hooks/usePersistedState";
4+
import { usePersistedState } from "@/browser/hooks/usePersistedState";
55
import { getThinkingLevelByModelKey, getModelKey } from "@/common/constants/storage";
66
import { getDefaultModel } from "@/browser/hooks/useModelsFromSettings";
77
import { migrateGatewayModel } from "@/browser/hooks/useGatewayModels";
@@ -20,37 +20,37 @@ interface ThinkingProviderProps {
2020
}
2121

2222
/**
23-
* Reads the current model from localStorage for the given scope.
24-
* Returns canonical model format (after gateway migration).
23+
* Hook to get the model key for the current scope.
2524
*/
26-
function getScopedModel(workspaceId?: string, projectPath?: string): string {
27-
const defaultModel = getDefaultModel();
28-
// Use workspace-scoped model key if available, otherwise project-scoped
29-
const modelKey = workspaceId
25+
function useModelKey(workspaceId?: string, projectPath?: string): string | null {
26+
return workspaceId
3027
? getModelKey(workspaceId)
3128
: projectPath
3229
? getModelKey(`__project__/${projectPath}`)
3330
: null;
34-
35-
if (!modelKey) {
36-
return defaultModel;
37-
}
38-
39-
const rawModel = readPersistedState<string>(modelKey, defaultModel);
40-
// Normalize to canonical format (e.g., strip legacy gateway prefix)
41-
return migrateGatewayModel(rawModel || defaultModel);
4231
}
4332

4433
export const ThinkingProvider: React.FC<ThinkingProviderProps> = ({
4534
workspaceId,
4635
projectPath,
4736
children,
4837
}) => {
49-
// Read current model from localStorage (non-reactive, re-reads on each render)
50-
const modelString = getScopedModel(workspaceId, projectPath);
51-
const key = getThinkingLevelByModelKey(modelString);
38+
const defaultModel = getDefaultModel();
39+
const modelKey = useModelKey(workspaceId, projectPath);
40+
41+
// Subscribe to model changes so we update thinking level when model changes
42+
const [rawModel] = usePersistedState<string>(modelKey ?? "model:__unused__", defaultModel, {
43+
listener: true,
44+
});
45+
46+
// Derive the thinking level key from the current model
47+
const thinkingKey = useMemo(() => {
48+
const model = migrateGatewayModel(rawModel || defaultModel);
49+
return getThinkingLevelByModelKey(model);
50+
}, [rawModel, defaultModel]);
51+
5252
const [thinkingLevel, setThinkingLevel] = usePersistedState<ThinkingLevel>(
53-
key,
53+
thinkingKey,
5454
"off",
5555
{ listener: true } // Listen for changes from command palette and other sources
5656
);

0 commit comments

Comments
 (0)