feat(code): persist and restore last selected model on task create#2354
feat(code): persist and restore last selected model on task create#2354Basit-Balogun10 wants to merge 1 commit into
Conversation
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
apps/code/src/renderer/features/task-detail/hooks/usePreviewConfig.ts:190-201
**Restored model doesn't recalculate effort options**
`withModel` updates the model's `currentValue` but leaves the effort option's `.options` array and `currentValue` as the server returned them — calibrated to the server's default model, not the restored one. Because `getReasoningEffortOptions` returns model-specific sets (e.g. `null` for `claude-haiku-4-5`, 3 entries for `claude-sonnet-4-6`, 5 for `claude-opus-4-6`), a user who last picked `claude-haiku-4-5` will see the effort selector the server injected for the default model, and a user who last picked `claude-sonnet-4-6` when the server defaulted to an Opus model will see `xhigh`/`max` effort choices that Sonnet doesn't support. The interactive path in `setConfigOption` already handles this correctly by calling `getReasoningEffortOptions(adapter, value)` — the same call needs to happen here after the model is resolved, updating `options` and clamping `currentValue` (or removing the effort option entirely when the restored model returns `null`).
Reviews (1): Last reviewed commit: "feat(code): persist and restore last sel..." | Re-trigger Greptile |
| const withModel = withEffort.map((opt) => { | ||
| if (opt.category !== "model" || opt.type !== "select") return opt; | ||
| if (!lastUsedModel) return opt; | ||
| const validValues = flattenValues( | ||
| opt.options as Array<{ | ||
| value?: string; | ||
| options?: Array<{ value: string }>; | ||
| }>, | ||
| ); | ||
| if (!validValues.includes(lastUsedModel)) return opt; | ||
| return { ...opt, currentValue: lastUsedModel } as SessionConfigOption; | ||
| }); |
There was a problem hiding this comment.
Restored model doesn't recalculate effort options
withModel updates the model's currentValue but leaves the effort option's .options array and currentValue as the server returned them — calibrated to the server's default model, not the restored one. Because getReasoningEffortOptions returns model-specific sets (e.g. null for claude-haiku-4-5, 3 entries for claude-sonnet-4-6, 5 for claude-opus-4-6), a user who last picked claude-haiku-4-5 will see the effort selector the server injected for the default model, and a user who last picked claude-sonnet-4-6 when the server defaulted to an Opus model will see xhigh/max effort choices that Sonnet doesn't support. The interactive path in setConfigOption already handles this correctly by calling getReasoningEffortOptions(adapter, value) — the same call needs to happen here after the model is resolved, updating options and clamping currentValue (or removing the effort option entirely when the restored model returns null).
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/task-detail/hooks/usePreviewConfig.ts
Line: 190-201
Comment:
**Restored model doesn't recalculate effort options**
`withModel` updates the model's `currentValue` but leaves the effort option's `.options` array and `currentValue` as the server returned them — calibrated to the server's default model, not the restored one. Because `getReasoningEffortOptions` returns model-specific sets (e.g. `null` for `claude-haiku-4-5`, 3 entries for `claude-sonnet-4-6`, 5 for `claude-opus-4-6`), a user who last picked `claude-haiku-4-5` will see the effort selector the server injected for the default model, and a user who last picked `claude-sonnet-4-6` when the server defaulted to an Opus model will see `xhigh`/`max` effort choices that Sonnet doesn't support. The interactive path in `setConfigOption` already handles this correctly by calling `getReasoningEffortOptions(adapter, value)` — the same call needs to happen here after the model is resolved, updating `options` and clamping `currentValue` (or removing the effort option entirely when the restored model returns `null`).
How can I resolve this? If you propose a fix, please make it concise.Wire up the existing but unused `lastUsedModel` / `setLastUsedModel` in settingsStore so the model picker remembers the user's choice across task creations — same pattern already used for reasoning effort and mode. Closes PostHog#1839
3791f7c to
e76fdb2
Compare
Problem
When you pick a non-default model (e.g. Opus over Sonnet) in the task creation UI, the next task creation reverts to the server default. We already persist and restore
lastUsedAdapter,lastUsedReasoningEffort, andlastUsedInitialTaskMode- butlastUsedModelwas wired into the settings store and never actually used.Closes #1839
Changes
Two files, following the exact same pattern as reasoning effort persistence:
Save (
TaskInput.tsx): CallsetLastUsedModel(value)inhandleModelChange- same ashandleThoughtChangealready callssetLastUsedReasoningEffort.Restore (
usePreviewConfig.ts): After fetching config options from the server and applying mode/effort preferences, check iflastUsedModelis set and valid for the current adapter's available models. If so, use it ascurrentValue; otherwise fall through to the server default (handles adapter switches cleanly - a stored Claude model won't get forced onto Codex).No new state, types, or store fields -
lastUsedModel,setLastUsedModel, and the persistence config all existed already.How did you test this?
Typecheck passes. Manual test plan:
basic-model-persistence-model-posthog-code-model-persistence-on-task-creation.webm
model-change-without-creating-a-task-posthog-code-model-persistence-on-task-creation.webm
lastUsedModelis now the Codex model you last picked.switching-adapters-posthog-code-model-persistence-on-task-creation.webm
switching-model-mid-task-doesnt-persist-on-task-creation-posthog-code-model-persistence-on-task-creation.webm
Publish to changelog?
no