From 8a087b68195bd031ca890a7d700f6f5f0048a4ef Mon Sep 17 00:00:00 2001 From: Peter Kirkham Date: Wed, 6 May 2026 19:23:29 +0000 Subject: [PATCH] fix: default reasoning to high and respect last-used choice Default reasoning level for the claude adapter was "medium". Restore the prior "high" default and persist the user's last-selected reasoning so subsequent task creations respect their choice across adapters and models (validating against the available options for the active model). Generated-By: PostHog Code Task-Id: a03c75c5-ae2f-470b-a9c2-856a62bfa72e --- apps/code/src/main/services/agent/service.ts | 2 +- .../features/settings/stores/settingsStore.ts | 6 ++ .../task-detail/components/TaskInput.tsx | 4 +- .../task-detail/hooks/usePreviewConfig.ts | 69 ++++++++++++++----- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/apps/code/src/main/services/agent/service.ts b/apps/code/src/main/services/agent/service.ts index d934259ee..0add0f735 100644 --- a/apps/code/src/main/services/agent/service.ts +++ b/apps/code/src/main/services/agent/service.ts @@ -1749,7 +1749,7 @@ For git operations while detached: id: adapter === "codex" ? "reasoning_effort" : "effort", name: adapter === "codex" ? "Reasoning Level" : "Effort", type: "select", - currentValue: adapter === "codex" ? "high" : "medium", + currentValue: "high", options: effortOpts, category: "thought_level", description: diff --git a/apps/code/src/renderer/features/settings/stores/settingsStore.ts b/apps/code/src/renderer/features/settings/stores/settingsStore.ts index 963b9cfa9..1ea969bf2 100644 --- a/apps/code/src/renderer/features/settings/stores/settingsStore.ts +++ b/apps/code/src/renderer/features/settings/stores/settingsStore.ts @@ -38,6 +38,7 @@ interface SettingsStore { lastUsedWorkspaceMode: WorkspaceMode; lastUsedAdapter: AgentAdapter; lastUsedModel: string | null; + lastUsedReasoningEffort: string | null; lastUsedCloudRepository: string | null; lastUsedEnvironments: Record; desktopNotifications: boolean; @@ -71,6 +72,7 @@ interface SettingsStore { setLastUsedWorkspaceMode: (mode: WorkspaceMode) => void; setLastUsedAdapter: (adapter: AgentAdapter) => void; setLastUsedModel: (model: string) => void; + setLastUsedReasoningEffort: (effort: string) => void; setLastUsedCloudRepository: (repo: string | null) => void; setLastUsedEnvironment: ( repoPath: string, @@ -103,6 +105,7 @@ export const useSettingsStore = create()( lastUsedWorkspaceMode: "local", lastUsedAdapter: "claude", lastUsedModel: null, + lastUsedReasoningEffort: null, lastUsedCloudRepository: null, lastUsedEnvironments: {}, desktopNotifications: true, @@ -159,6 +162,8 @@ export const useSettingsStore = create()( setLastUsedWorkspaceMode: (mode) => set({ lastUsedWorkspaceMode: mode }), setLastUsedAdapter: (adapter) => set({ lastUsedAdapter: adapter }), setLastUsedModel: (model) => set({ lastUsedModel: model }), + setLastUsedReasoningEffort: (effort) => + set({ lastUsedReasoningEffort: effort }), setLastUsedCloudRepository: (repo) => set({ lastUsedCloudRepository: repo }), setLastUsedEnvironment: (repoPath, environmentId) => @@ -208,6 +213,7 @@ export const useSettingsStore = create()( lastUsedWorkspaceMode: state.lastUsedWorkspaceMode, lastUsedAdapter: state.lastUsedAdapter, lastUsedModel: state.lastUsedModel, + lastUsedReasoningEffort: state.lastUsedReasoningEffort, lastUsedCloudRepository: state.lastUsedCloudRepository, lastUsedEnvironments: state.lastUsedEnvironments, desktopNotifications: state.desktopNotifications, diff --git a/apps/code/src/renderer/features/task-detail/components/TaskInput.tsx b/apps/code/src/renderer/features/task-detail/components/TaskInput.tsx index ab2fa468a..01e12aa77 100644 --- a/apps/code/src/renderer/features/task-detail/components/TaskInput.tsx +++ b/apps/code/src/renderer/features/task-detail/components/TaskInput.tsx @@ -89,6 +89,7 @@ export function TaskInput({ getLastUsedEnvironment, defaultInitialTaskMode, lastUsedInitialTaskMode, + setLastUsedReasoningEffort, } = useSettingsStore(); const editorRef = useRef(null); @@ -493,9 +494,10 @@ export function TaskInput({ (value: string) => { if (thoughtOption) { setConfigOption(thoughtOption.id, value); + setLastUsedReasoningEffort(value); } }, - [thoughtOption, setConfigOption], + [thoughtOption, setConfigOption, setLastUsedReasoningEffort], ); const { isOnline } = useConnectivity(); diff --git a/apps/code/src/renderer/features/task-detail/hooks/usePreviewConfig.ts b/apps/code/src/renderer/features/task-detail/hooks/usePreviewConfig.ts index 86b6c80c9..02a0aa2d0 100644 --- a/apps/code/src/renderer/features/task-detail/hooks/usePreviewConfig.ts +++ b/apps/code/src/renderer/features/task-detail/hooks/usePreviewConfig.ts @@ -27,6 +27,14 @@ function getOptionByCategory( ); } +function flattenValues( + options: Array<{ value?: string; options?: Array<{ value: string }> }>, +): string[] { + return options.flatMap((o) => + o.options ? o.options.map((go) => go.value) : o.value ? [o.value] : [], + ); +} + /** * Fetches config options (models, modes, effort levels) for the task input * page via a lightweight tRPC query. No agent session is created. @@ -59,8 +67,11 @@ export function usePreviewConfig( .then((options) => { if (abort.signal.aborted) return; - const { defaultInitialTaskMode, lastUsedInitialTaskMode } = - useSettingsStore.getState(); + const { + defaultInitialTaskMode, + lastUsedInitialTaskMode, + lastUsedReasoningEffort, + } = useSettingsStore.getState(); // Use the mode option's existing currentValue (set by the server // based on the adapter) when the user hasn't chosen a preference, @@ -70,17 +81,11 @@ export function usePreviewConfig( const serverDefault = modeOpt?.currentValue; const availableValues: string[] = modeOpt?.type === "select" - ? ( + ? flattenValues( modeOpt.options as Array<{ value?: string; options?: Array<{ value: string }>; - }> - ).flatMap((o) => - o.options - ? o.options.map((go) => go.value) - : o.value - ? [o.value] - : [], + }>, ) : []; @@ -106,7 +111,29 @@ export function usePreviewConfig( : opt, ); - setConfigOptions(withMode); + const withEffort = withMode.map((opt) => { + if (opt.category !== "thought_level" || opt.type !== "select") { + return opt; + } + const validValues = flattenValues( + opt.options as Array<{ + value?: string; + options?: Array<{ value: string }>; + }>, + ); + if ( + lastUsedReasoningEffort && + validValues.includes(lastUsedReasoningEffort) + ) { + return { + ...opt, + currentValue: lastUsedReasoningEffort, + } as SessionConfigOption; + } + return opt; + }); + + setConfigOptions(withEffort); setIsLoading(false); }) .catch((error) => { @@ -141,27 +168,33 @@ export function usePreviewConfig( ? "reasoning_effort" : "effort"; - const defaultEffort = adapter === "codex" ? "high" : "medium"; + const { lastUsedReasoningEffort } = useSettingsStore.getState(); + const isValidEffort = (effort: unknown): effort is string => + typeof effort === "string" && + !!effortOpts?.some((e) => e.value === effort); if (effortOpts && existingIdx >= 0) { const currentEffort = updated[existingIdx].currentValue; - const validEffort = effortOpts.some( - (e) => e.value === currentEffort, - ) + const nextEffort = isValidEffort(currentEffort) ? currentEffort - : defaultEffort; + : isValidEffort(lastUsedReasoningEffort) + ? lastUsedReasoningEffort + : "high"; updated[existingIdx] = { ...updated[existingIdx], - currentValue: validEffort, + currentValue: nextEffort, options: effortOpts, } as SessionConfigOption; } else if (effortOpts && existingIdx === -1) { + const nextEffort = isValidEffort(lastUsedReasoningEffort) + ? lastUsedReasoningEffort + : "high"; updated = [ ...updated, { id: effortOptionId, name: adapter === "codex" ? "Reasoning Level" : "Effort", type: "select", - currentValue: defaultEffort, + currentValue: nextEffort, options: effortOpts, category: "thought_level", description: