refactor(desktop): make composer model picker sticky session state
The picker no longer touches the profile default. Model/effort/fast live as plain UI state persisted in localStorage, so a pick follows across Cmd+N and restarts instead of snapping back. New chats ship that state through session.create as per-session overrides; live chats still scope switches to the current session. Settings -> Model remains the only surface that writes the profile default. The gateway now accepts those session.create overrides, builds the agent with them directly, reflects them in the immediate session.info payload, and writes the chat's own model_config into the lazy DB row so reconnect/resume restores that chat instead of the global default.
This commit is contained in:
@@ -11,7 +11,6 @@ import { startManualOnboarding } from '../store/onboarding'
|
||||
|
||||
import { InlineNotice } from './notifications'
|
||||
import { Button } from './ui/button'
|
||||
import { Checkbox } from './ui/checkbox'
|
||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from './ui/command'
|
||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from './ui/dialog'
|
||||
import { Skeleton } from './ui/skeleton'
|
||||
@@ -23,7 +22,7 @@ interface ModelPickerDialogProps {
|
||||
sessionId?: string | null
|
||||
currentModel: string
|
||||
currentProvider: string
|
||||
onSelect: (selection: { provider: string; model: string; persistGlobal: boolean }) => void
|
||||
onSelect: (selection: { provider: string; model: string }) => void
|
||||
/**
|
||||
* Optional class to apply to DialogContent. Use to override z-index when
|
||||
* stacking the picker on top of another fixed overlay (e.g. the desktop
|
||||
@@ -45,7 +44,6 @@ export function ModelPickerDialog({
|
||||
}: ModelPickerDialogProps) {
|
||||
const { t } = useI18n()
|
||||
const copy = t.modelPicker
|
||||
const [persistGlobal, setPersistGlobal] = useState(!sessionId)
|
||||
// Own the search term so we can filter manually. cmdk's built-in
|
||||
// shouldFilter reorders items by its fuzzy-match score (≈alphabetical with
|
||||
// an empty query), which destroys the backend's curated order. We disable
|
||||
@@ -79,11 +77,7 @@ export function ModelPickerDialog({
|
||||
: null
|
||||
|
||||
const selectModel = (provider: ModelOptionProvider, model: string) => {
|
||||
onSelect({
|
||||
provider: provider.slug,
|
||||
model,
|
||||
persistGlobal: persistGlobal || !sessionId
|
||||
})
|
||||
onSelect({ provider: provider.slug, model })
|
||||
onOpenChange(false)
|
||||
}
|
||||
|
||||
@@ -128,24 +122,13 @@ export function ModelPickerDialog({
|
||||
</CommandList>
|
||||
</Command>
|
||||
|
||||
<DialogFooter className="flex-row items-center justify-between gap-3 bg-card p-3 sm:justify-between">
|
||||
<label className="flex cursor-pointer select-none items-center gap-2 text-xs text-muted-foreground">
|
||||
<Checkbox
|
||||
checked={persistGlobal || !sessionId}
|
||||
disabled={!sessionId}
|
||||
onCheckedChange={checked => setPersistGlobal(checked === true)}
|
||||
/>
|
||||
{sessionId ? copy.persistGlobalSession : copy.persistGlobal}
|
||||
</label>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Button onClick={addProvider} variant="ghost">
|
||||
{copy.addProvider}
|
||||
</Button>
|
||||
<Button onClick={() => onOpenChange(false)} variant="outline">
|
||||
{t.common.cancel}
|
||||
</Button>
|
||||
</div>
|
||||
<DialogFooter className="flex-row items-center justify-end gap-2 bg-card p-3">
|
||||
<Button onClick={addProvider} variant="ghost">
|
||||
{copy.addProvider}
|
||||
</Button>
|
||||
<Button onClick={() => onOpenChange(false)} variant="outline">
|
||||
{t.common.cancel}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
Reference in New Issue
Block a user