From 58f8b02520b816a02a3acd9fad38042c6e693f24 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 6 Aug 2026 08:56:34 +0200 Subject: [PATCH 1/2] fix(vscode): persist Agent Manager dialog selections --- .../cache-worktree-dialog-selections.md | 5 ++ .../agent-manager/NewWorktreeDialog.tsx | 52 +++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 .changeset/cache-worktree-dialog-selections.md diff --git a/.changeset/cache-worktree-dialog-selections.md b/.changeset/cache-worktree-dialog-selections.md new file mode 100644 index 00000000000..f13128f7b9c --- /dev/null +++ b/.changeset/cache-worktree-dialog-selections.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Remember Agent Manager worktree dialog model, variant, mode, and sandbox selections when reopened. diff --git a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx index 3a3a08869b3..b8629048b7e 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx @@ -57,6 +57,34 @@ const WORKTREE_PROMPT_SCOPE = "agent-manager-worktree-prompt" type DialogTab = "new" | "import" +type DialogSelections = { + agent?: string + model?: { providerID: string; modelID: string } + variant?: string + sandbox?: boolean +} + +function readDialogSelections(value: unknown): DialogSelections { + if (!value || typeof value !== "object" || Array.isArray(value)) return {} + const data = value as Record + const raw = data.model + const model = raw && typeof raw === "object" && !Array.isArray(raw) ? (raw as Record) : undefined + + return { + agent: typeof data.agent === "string" ? data.agent : undefined, + model: + typeof model?.providerID === "string" && typeof model.modelID === "string" + ? { providerID: model.providerID, modelID: model.modelID } + : undefined, + variant: typeof data.variant === "string" ? data.variant : undefined, + sandbox: typeof data.sandbox === "boolean" ? data.sandbox : undefined, + } +} + +function fallback(value: T | undefined, get: () => T): T { + return value === undefined ? get() : value +} + const isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.userAgent) function sanitizeSegment(text: string, maxLength = 50): string { @@ -110,9 +138,10 @@ export const NewWorktreeDialog: Component<{ const [name, setName] = createSignal("") const cached = vscode.getState>() const [prompt, setPrompt] = createSignal((cached?.advancedDialogPrompt as string) ?? "") + const saved = readDialogSelections(cached?.advancedDialogSelections) const [versions, setVersions] = createSignal(1) - const initialAgent = session.selectedAgent() - const initialModel = session.modelForAgent(initialAgent) + const initialAgent = fallback(saved.agent, () => session.selectedAgent()) + const initialModel = fallback(saved.model, () => session.modelForAgent(initialAgent)) const [model, setModel] = createSignal<{ providerID: string; modelID: string } | null>(initialModel) const [compareMode, setCompareMode] = createSignal(false) const [modelAllocations, setModelAllocations] = createSignal(new Map()) @@ -125,8 +154,10 @@ export const NewWorktreeDialog: Component<{ const [baseBranchOpen, setBaseBranchOpen] = createSignal(false) const [compareOpen, setCompareOpen] = createSignal(false) const [highlightedIndex, setHighlightedIndex] = createSignal(0) - const [variant, setVariant] = createSignal(session.variantForAgent(initialAgent, initialModel)) - const [sandbox, setSandbox] = createSignal() + const [variant, setVariant] = createSignal( + fallback(saved.variant, () => session.variantForAgent(initialAgent, initialModel)), + ) + const [sandbox, setSandbox] = createSignal(saved.sandbox) const [sandboxDefault, setSandboxDefault] = createSignal() const [sandboxOverride, setSandboxOverride] = createSignal() const [sandboxAvailable, setSandboxAvailable] = createSignal(true) @@ -285,6 +316,19 @@ export const NewWorktreeDialog: Component<{ vscode.setState({ ...state, advancedDialogImages: imgs.length > 0 ? imgs : undefined }) } + createEffect(() => { + const state = vscode.getState>() ?? {} + vscode.setState({ + ...state, + advancedDialogSelections: { + agent: agent(), + model: model(), + variant: variant(), + sandbox: sandbox(), + }, + }) + }) + // Auto-persist images to webview state on any change createEffect(() => persistImages(imageAttach.images())) From f46c8e179c8d9c3f930602d9d3c32b9bdf6f055a Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 6 Aug 2026 09:16:03 +0200 Subject: [PATCH 2/2] fix(vscode): validate restored dialog selections --- .../agent-manager/NewWorktreeDialog.tsx | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx index b8629048b7e..bb216b39eec 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx @@ -56,10 +56,11 @@ const WORKTREE_PROMPT_COMMANDS = new Set(["models", "agents", "variant", "sandbo const WORKTREE_PROMPT_SCOPE = "agent-manager-worktree-prompt" type DialogTab = "new" | "import" +type Model = { providerID: string; modelID: string } type DialogSelections = { agent?: string - model?: { providerID: string; modelID: string } + model?: Model variant?: string sandbox?: boolean } @@ -81,6 +82,18 @@ function readDialogSelections(value: unknown): DialogSelections { } } +function restoreAgent(value: string | undefined, list: Array<{ name: string }>, base: string): string { + if (!value) return base + if (list.length === 0) return value + return list.some((item) => item.name === value) ? value : base +} + +function restoreModel(value: Model | undefined, providers: Record, valid: (value: Model) => boolean) { + if (!value) return undefined + if (Object.keys(providers).length === 0) return value + return valid(value) ? value : undefined +} + function fallback(value: T | undefined, get: () => T): T { return value === undefined ? get() : value } @@ -140,9 +153,12 @@ export const NewWorktreeDialog: Component<{ const [prompt, setPrompt] = createSignal((cached?.advancedDialogPrompt as string) ?? "") const saved = readDialogSelections(cached?.advancedDialogSelections) const [versions, setVersions] = createSignal(1) - const initialAgent = fallback(saved.agent, () => session.selectedAgent()) - const initialModel = fallback(saved.model, () => session.modelForAgent(initialAgent)) - const [model, setModel] = createSignal<{ providerID: string; modelID: string } | null>(initialModel) + const initialAgent = restoreAgent(saved.agent, session.agents(), session.selectedAgent()) + const initialModel = fallback( + restoreModel(saved.model, provider.providers(), (value) => provider.isModelValid(value)), + () => session.modelForAgent(initialAgent), + ) + const [model, setModel] = createSignal(initialModel) const [compareMode, setCompareMode] = createSignal(false) const [modelAllocations, setModelAllocations] = createSignal(new Map()) const [agent, setAgent] = createSignal(initialAgent)