From 18e1ac42902a6cbca0e5391963368a28d55df242 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Mon, 7 Sep 2026 12:25:08 +0200 Subject: [PATCH 1/3] fix(agent-manager): preserve explicit branch names and expose naming settings --- .changeset/preserve-agent-manager-branches.md | 5 ++ packages/kilo-vscode/src/KiloProvider.ts | 3 + .../src/agent-manager/WorktreeManager.ts | 32 ++++++++-- .../src/agent-manager/tool-start.ts | 2 +- .../src/kilo-provider/config-snapshot.ts | 8 ++- .../tests/unit/agent-manager-settings.test.ts | 60 +++++++++++++++++++ .../unit/agent-manager-tool-start.test.ts | 22 +++++-- .../kilo-provider-indexing-refresh.test.ts | 2 + .../tests/unit/worktree-manager.test.ts | 34 +++++++++++ .../agent-manager/NewWorktreeDialog.tsx | 26 +------- .../webview-ui/agent-manager/i18n/ar.ts | 6 ++ .../webview-ui/agent-manager/i18n/br.ts | 6 ++ .../webview-ui/agent-manager/i18n/bs.ts | 6 ++ .../webview-ui/agent-manager/i18n/da.ts | 6 ++ .../webview-ui/agent-manager/i18n/de.ts | 6 ++ .../webview-ui/agent-manager/i18n/en.ts | 6 ++ .../webview-ui/agent-manager/i18n/es.ts | 6 ++ .../webview-ui/agent-manager/i18n/fa.ts | 6 ++ .../webview-ui/agent-manager/i18n/fr.ts | 6 ++ .../webview-ui/agent-manager/i18n/it.ts | 6 ++ .../webview-ui/agent-manager/i18n/ja.ts | 6 ++ .../webview-ui/agent-manager/i18n/ko.ts | 6 ++ .../webview-ui/agent-manager/i18n/nl.ts | 6 ++ .../webview-ui/agent-manager/i18n/no.ts | 6 ++ .../webview-ui/agent-manager/i18n/pl.ts | 6 ++ .../webview-ui/agent-manager/i18n/ru.ts | 6 ++ .../webview-ui/agent-manager/i18n/th.ts | 6 ++ .../webview-ui/agent-manager/i18n/tr.ts | 6 ++ .../webview-ui/agent-manager/i18n/uk.ts | 6 ++ .../webview-ui/agent-manager/i18n/zh.ts | 6 ++ .../webview-ui/agent-manager/i18n/zht.ts | 6 ++ .../src/components/settings/Settings.tsx | 27 +++++++++ .../src/kilocode/tool/agent-manager.txt | 2 +- 33 files changed, 310 insertions(+), 39 deletions(-) create mode 100644 .changeset/preserve-agent-manager-branches.md diff --git a/.changeset/preserve-agent-manager-branches.md b/.changeset/preserve-agent-manager-branches.md new file mode 100644 index 000000000000..beea392c4a62 --- /dev/null +++ b/.changeset/preserve-agent-manager-branches.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Preserve explicit Git branch names in Agent Manager and expose automatic branch naming and prefix controls in its settings. diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index c88103f00031..40247b253a3d 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -3906,11 +3906,14 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper } private configSettings() { + const naming = vscode.workspace.getConfiguration("kilo-code.new.agentManager") return { maxCost: this.maxCostSetting(), languageCommitMessage: this.commitMessageLanguageSetting(), multiProject: this.multiProjectSetting(), browserAutomation: this.browserAutomationSetting(), + "agentManager.autoBranchNaming": naming.get("autoBranchNaming", true), + "agentManager.branchPrefix": naming.get("branchPrefix", ""), } } diff --git a/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts b/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts index 2377479c7c41..4a9110a65283 100644 --- a/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts +++ b/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts @@ -8,7 +8,7 @@ import * as path from "path" import * as fs from "fs" -import { randomUUID } from "crypto" +import { createHash, randomUUID } from "crypto" import simpleGit, { type SimpleGit } from "simple-git" import { generateBranchName, sanitizeBranchName } from "./branch-name" import { type GitOps, isKiloOwnedSshCommand, nonInteractiveEnv } from "./GitOps" @@ -32,6 +32,20 @@ import { const TEMP_PREFIX = ".kilo-delete-" const RM_OPTS: fs.RmOptions = { recursive: true, force: true, maxRetries: 3, retryDelay: 200 } +function directory(branch: string): string { + // Keep ordinary directory names, but isolate refs that need filesystem escaping. + if ( + /^[a-zA-Z0-9_-][a-zA-Z0-9._-]{0,99}$/.test(branch) && + !/^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\.|$)/i.test(branch) + ) { + return branch + } + // Hash the original ref to distinguish names that produce the same shortened slug. + const slug = sanitizeBranchName(branch) || "branch" + const hash = createHash("sha256").update(branch).digest("hex").slice(0, 16) + return `${slug}-${hash}` +} + export interface WorktreeInfo { branch: string path: string @@ -227,6 +241,13 @@ export class WorktreeManager { "This folder is not a git repository. Initialize a repository or open a git project to use worktrees.", ) + const requested = params.existingBranch ?? params.branchName + if (requested !== undefined) { + // Validate the literal ref first so --branch cannot expand checkout shorthand. + await this.git.raw(["check-ref-format", `refs/heads/${requested}`]) + await this.git.raw(["check-ref-format", "--branch", requested]) + } + // Git LFS Pre-flight Check if (await this.repoUsesLfs()) { if (!(await this.checkLfsAvailable())) { @@ -273,7 +294,7 @@ export class WorktreeManager { } let branch = await this.resolveBranch(params) - const dirName = branch.replace(/\//g, "-") + const dirName = directory(branch) let worktreePath = path.join(this.dir, dirName) await this.prepareWorktreePath(worktreePath, !!params.existingBranch) @@ -301,7 +322,7 @@ export class WorktreeManager { } // Another process may create the branch after resolveBranch checks it. branch = await this.resolveBranch(params) - const retryDir = branch.replace(/\//g, "-") + const retryDir = directory(branch) worktreePath = path.join(this.dir, retryDir) const retryArgs = params.existingBranch ? ["worktree", "add", worktreePath, branch] @@ -376,15 +397,14 @@ export class WorktreeManager { .raw(["for-each-ref", "--format=%(refname:lstrip=2)", "refs/heads"]) .then((refs) => refs.trim().split(/\r?\n/).filter(Boolean)) .catch(() => [] as string[]) - const sanitized = params.branchName ? sanitizeBranchName(params.branchName) : undefined - const branch = sanitized || generateBranchName(params.prompt || "agent-task", existing) + const branch = params.branchName ?? generateBranchName(params.prompt || "agent-task", existing) return this.availableBranch(branch, existing) } private availableBranch(base: string, existing: string[]): string { const branches = new Set(existing) const available = (branch: string) => { - const dir = path.join(this.dir, branch.replace(/\//g, "-")) + const dir = path.join(this.dir, directory(branch)) return !branches.has(branch) && !fs.existsSync(dir) } if (available(base)) return base diff --git a/packages/kilo-vscode/src/agent-manager/tool-start.ts b/packages/kilo-vscode/src/agent-manager/tool-start.ts index 91af753f991d..c490fd166cfc 100644 --- a/packages/kilo-vscode/src/agent-manager/tool-start.ts +++ b/packages/kilo-vscode/src/agent-manager/tool-start.ts @@ -176,7 +176,7 @@ async function worktree( versions?: boolean, source?: ToolSource, ) { - const baseBranch = branch(task.branchName) ?? branch(task.name) + const baseBranch = task.branchName ?? branch(task.name) const baseLabel = label(task.name) ?? label(task.branchName) ?? label(task.prompt) const version = versionedName(baseBranch, versions ? index : 0, versions ? total : 1) const created = await deps.createWorktree({ diff --git a/packages/kilo-vscode/src/kilo-provider/config-snapshot.ts b/packages/kilo-vscode/src/kilo-provider/config-snapshot.ts index 088c8b3c20d3..0bdcd2590274 100644 --- a/packages/kilo-vscode/src/kilo-provider/config-snapshot.ts +++ b/packages/kilo-vscode/src/kilo-provider/config-snapshot.ts @@ -4,7 +4,13 @@ import { retry } from "../services/cli-backend/retry" import type { ConfigTarget } from "./config-bindings" type Client = Pick -type Settings = { maxCost: number; languageCommitMessage: string; multiProject: boolean } +type Settings = { + maxCost: number + languageCommitMessage: string + multiProject: boolean + "agentManager.autoBranchNaming": boolean + "agentManager.branchPrefix": string +} export async function fetchSnapshot(client: Client, dir: string, settings: () => Settings) { const [{ data: config }, { data: global }, { data: overlay }, capabilities] = await Promise.all([ retry(() => client.config.get({ directory: dir }, { throwOnError: true })), diff --git a/packages/kilo-vscode/tests/unit/agent-manager-settings.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-settings.test.ts index 6e60176f25b4..875038632e65 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-settings.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-settings.test.ts @@ -23,6 +23,14 @@ describe("Agent Manager settings navigation", () => { expect(settings).toContain('type: "configureAgentManagerSetupScript"') }) + it("stages application-wide branch naming controls outside the project selection", () => { + expect(settings).toContain('updateSetting("agentManager.autoBranchNaming", value)') + expect(settings).toContain('updateSetting("agentManager.branchPrefix", value)') + expect(settings.indexOf('title={language.t("agentManager.settings.branchPrefix.title")}')).toBeLessThan( + settings.indexOf(" { expect(settings).toContain(" { expect(settings).toContain(" { + it.each([ + [undefined, undefined, true, ""], + [false, "team/", false, "team/"], + [true, "", true, ""], + ] as const)("loads and saves naming preferences (%s, %s)", async (enabled, prefix, expected, text) => { + const vscode = await import("vscode") + const { KiloProvider } = await import("../../src/KiloProvider") + const original = vscode.workspace.getConfiguration + const values = new Map() + if (enabled !== undefined) values.set("autoBranchNaming", enabled) + if (prefix !== undefined) values.set("branchPrefix", prefix) + const writes: unknown[] = [] + vscode.workspace.getConfiguration = ((section?: string) => ({ + get: (key: string, fallback: unknown) => + section === "kilo-code.new.agentManager" && values.has(key) ? values.get(key) : fallback, + update: async (key: string, value: unknown, target: unknown) => { + writes.push({ section, key, value, target }) + values.set(key, value) + }, + })) as typeof original + try { + const provider = new KiloProvider({} as never, {} as never) as unknown as { + configSettings(): Record + handleUpdateSetting(key: string, value: unknown): Promise + } + expect(provider.configSettings()["agentManager.autoBranchNaming"]).toBe(expected) + expect(provider.configSettings()["agentManager.branchPrefix"]).toBe(text) + await provider.handleUpdateSetting("agentManager.autoBranchNaming", !expected) + await provider.handleUpdateSetting("agentManager.branchPrefix", "") + expect(writes).toEqual([ + { + section: "kilo-code.new.agentManager", + key: "autoBranchNaming", + value: !expected, + target: vscode.ConfigurationTarget.Global, + }, + { + section: "kilo-code.new.agentManager", + key: "branchPrefix", + value: "", + target: vscode.ConfigurationTarget.Global, + }, + ]) + expect(provider.configSettings()["agentManager.autoBranchNaming"]).toBe(!expected) + expect(provider.configSettings()["agentManager.branchPrefix"]).toBe("") + } finally { + vscode.workspace.getConfiguration = original + } + }) +}) diff --git a/packages/kilo-vscode/tests/unit/agent-manager-tool-start.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-tool-start.test.ts index 5db5002a5d83..721ac60f99d4 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-tool-start.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-tool-start.test.ts @@ -220,7 +220,7 @@ describe("agent manager tool start", () => { tasks: [ { prompt: "Fix", - branchName: "fix/one", + branchName: "fix/One_two.3", model: { providerID: "test", modelID: "reasoning/model" }, variant: "low", }, @@ -228,7 +228,7 @@ describe("agent manager tool start", () => { }) expect(c.createWorktree).toHaveBeenCalledWith( - expect.objectContaining({ branchName: "fix-one", name: "fix-one", label: "one" }), + expect.objectContaining({ branchName: "fix/One_two.3", name: "fix/One_two.3", label: "one two 3" }), ) expect(c.setup).toHaveBeenCalled() expect(c.createSessionInWorktree).toHaveBeenCalledWith("/repo/.kilo/worktrees/wt-1", "kilo/test", "wt-1", { @@ -350,7 +350,7 @@ describe("agent manager tool start", () => { }) expect(normal.createWorktree).toHaveBeenNthCalledWith( 2, - expect.objectContaining({ branchName: "fix-two", label: "two" }), + expect.objectContaining({ branchName: "fix/two", label: "two" }), ) const grouped = deps() @@ -365,11 +365,11 @@ describe("agent manager tool start", () => { }) expect(grouped.createWorktree).toHaveBeenNthCalledWith( 2, - expect.objectContaining({ branchName: "try-work_v2", label: "try work v2" }), + expect.objectContaining({ branchName: "try/work_v2", label: "try work v2" }), ) }) - it("sanitizes branch names and keeps card labels short", async () => { + it("passes invalid explicit names to worktree validation and keeps card labels short", async () => { const c = deps() await startFromTool(c, { requestID: "am-name", @@ -385,12 +385,22 @@ describe("agent manager tool start", () => { expect(c.createWorktree).toHaveBeenCalledWith( expect.objectContaining({ - branchName: "fix-command-permissions-persistence", + branchName: "fix command permissions @#$ persistence", label: "command permissions", }), ) }) + it("still sanitizes display names used as automatic branch seeds", async () => { + const c = deps() + await startFromTool(c, { + requestID: "am-seed", + mode: "worktree", + tasks: [{ name: "My Feature" }], + }) + expect(c.createWorktree).toHaveBeenCalledWith(expect.objectContaining({ branchName: "my-feature" })) + }) + it("rejects local sessions for unknown worktree directories", async () => { const client = { session: { diff --git a/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts b/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts index bceb043738fd..657cee6153a8 100644 --- a/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts +++ b/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts @@ -159,6 +159,8 @@ describe("KiloProvider indexing refresh", () => { languageCommitMessage: "sync", multiProject: false, browserAutomation: false, + "agentManager.autoBranchNaming": true, + "agentManager.branchPrefix": "", }) const snapshot = await fetchSnapshot(conn.client as never, "/repo", settings) const provider = new KiloProvider({} as never, conn.service as never) diff --git a/packages/kilo-vscode/tests/unit/worktree-manager.test.ts b/packages/kilo-vscode/tests/unit/worktree-manager.test.ts index 7f0159a24a7c..2b454a48c531 100644 --- a/packages/kilo-vscode/tests/unit/worktree-manager.test.ts +++ b/packages/kilo-vscode/tests/unit/worktree-manager.test.ts @@ -263,6 +263,40 @@ describe("WorktreeStateManager.updateWorktreeLabel", () => { // --------------------------------------------------------------------------- describe("WorktreeManager.createWorktree", () => { + it.each([ + "Feature/My_fix.v2", + "Release_" + "a".repeat(60), + ...(process.platform === "win32" ? [] : ["CON", 'fix/a"bd|e']), + ])("preserves explicit branch %s with a safe directory", async (branch) => { + const root = await createTempRepo() + const result = await createManager(root).createWorktree({ branchName: branch }) + expect(result.branch).toBe(branch) + expect((await simpleGit(result.path).raw(["symbolic-ref", "--short", "HEAD"])).trim()).toBe(branch) + expect(path.dirname(result.path)).toBe(path.join(root, ".kilo", "worktrees")) + expect(path.basename(result.path)).toMatch(/^[a-zA-Z0-9_-][a-zA-Z0-9._-]*$/) + expect(path.basename(result.path)).not.toBe("CON") + }) + + it.each(["../escape", "bad name", "bad..name", "bad.lock", "-option", "@{-1}", "HEAD", ""])( + "rejects invalid explicit branch %s before creating directories", + async (branchName) => { + const root = await createTempRepo() + await expect(createManager(root).createWorktree({ branchName })).rejects.toThrow() + expect(existsSync(path.join(root, ".kilo", "worktrees"))).toBe(false) + }, + ) + + it("keeps slash refs independent from flat refs and preserves collision suffixes", async () => { + const root = await createTempRepo() + const manager = createManager(root) + const first = await manager.createWorktree({ branchName: "Feature/My_fix.v2" }) + const flat = await manager.createWorktree({ branchName: "Feature-My_fix.v2" }) + const second = await manager.createWorktree({ branchName: "Feature/My_fix.v2" }) + expect(flat.branch).toBe("Feature-My_fix.v2") + expect(second.branch).toBe("Feature/My_fix.v2-2") + expect(new Set([first.path, flat.path, second.path]).size).toBe(3) + }) + it("uses a configured Git executable for worktree creation", async () => { const root = await createTempRepo() gitExec(["git", "-C", root, "config", "core.autocrlf", "false"]) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx index 2ba6f0650f50..0854d69bfb3d 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx @@ -93,28 +93,6 @@ function restoreAgent(value: string | undefined, list: Array<{ name: string }>, const isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.userAgent) -function sanitizeSegment(text: string, maxLength = 50): string { - return text - .toLowerCase() - .trim() - .replace(/\s+/g, "-") - .replace(/[^a-z0-9._+@-]/g, "") - .replace(/\.{2,}/g, ".") - .replace(/@\{/g, "@") - .replace(/-+/g, "-") - .replace(/^[-.]|[-.]+$/g, "") - .replace(/\.lock$/g, "") - .slice(0, maxLength) -} - -function sanitizeBranchName(name: string): string { - return name - .split("/") - .map((s) => sanitizeSegment(s)) - .filter(Boolean) - .join("/") -} - export const NewWorktreeDialog: Component<{ onClose: () => void defaultBase?: (projectId: string) => string | undefined @@ -423,7 +401,7 @@ export const NewWorktreeDialog: Component<{ const defaultAgent = session.agents()[0]?.name const selectedAgent = agent() !== defaultAgent ? agent() : undefined const advanced = showAdvanced() - const customBranch = advanced ? branchName().trim() || undefined : undefined + const customBranch = advanced ? branchName() || undefined : undefined const imgs = imageAttach.images() const imgFiles = imgs.length > 0 ? imgs.map((img) => ({ mime: img.mime, url: img.dataUrl })) : undefined @@ -927,7 +905,7 @@ export const NewWorktreeDialog: Component<{ type="text" placeholder={t("agentManager.dialog.branchNamePlaceholder")} value={branchName()} - onInput={(e) => setBranchName(sanitizeBranchName(e.currentTarget.value))} + onInput={(e) => setBranchName(e.currentTarget.value)} />
diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts index 19a409af7da3..621d10f0cd50 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "الجلسات", "agentManager.projects": "المشاريع", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "تسمية الفروع تلقائيًا", + "agentManager.settings.autoBranchNaming.description": + "تسمية الفروع تلقائيًا عندما تصف المحادثة مهمة واضحة. ينطبق على جميع المشاريع. لا تُعاد تسمية الفروع المسماة صراحةً أو المنشورة مطلقًا.", + "agentManager.settings.branchPrefix.title": "بادئة الفرع", + "agentManager.settings.branchPrefix.description": + "بادئة للفروع المسماة تلقائيًا في جميع المشاريع، مثل feature/. لا تنطبق على أسماء الفروع الصريحة. اتركها فارغة لعدم استخدام بادئة.", "agentManager.settings.project.title": "المشروع", "agentManager.settings.project.description": "اختر repository الذي تريد تعديل إعدادات worktree الخاصة به.", "agentManager.settings.project.empty": "لا تتوفر أي مشاريع في Agent Manager.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts index f04dea69837f..54e032a0fb88 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "SESSÕES", "agentManager.projects": "PROJETOS", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Nomeação automática de branches", + "agentManager.settings.autoBranchNaming.description": + "Nomeie branches automaticamente quando a conversa descrever uma tarefa clara. Aplica-se a todos os projetos. Branches nomeadas explicitamente e publicadas nunca são renomeadas.", + "agentManager.settings.branchPrefix.title": "Prefixo da branch", + "agentManager.settings.branchPrefix.description": + "Prefixo para branches nomeadas automaticamente em todos os projetos, por exemplo feature/. Não se aplica a nomes explícitos de branches. Deixe vazio para não usar prefixo.", "agentManager.settings.project.title": "Projeto", "agentManager.settings.project.description": "Escolha o repository cujas configurações de worktree você deseja editar.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts index 1acfa0136c72..d7e9074dd2df 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "SESIJE", "agentManager.projects": "PROJEKTI", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Automatsko imenovanje grana", + "agentManager.settings.autoBranchNaming.description": + "Automatski imenujte grane kada razgovor opisuje jasan zadatak. Primjenjuje se na sve projekte. Izričito imenovane i objavljene grane nikada se ne preimenuju.", + "agentManager.settings.branchPrefix.title": "Prefiks grane", + "agentManager.settings.branchPrefix.description": + "Prefiks za automatski imenovane grane u svim projektima, na primjer feature/. Ne primjenjuje se na izričite nazive grana. Ostavite prazno ako ne želite prefiks.", "agentManager.settings.project.title": "Projekat", "agentManager.settings.project.description": "Izaberite repository čije worktree postavke želite urediti.", "agentManager.settings.project.empty": "Nema dostupnih projekata u Agent Manager.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts index 1d49578f61e3..28ec731aacb8 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "SESSIONER", "agentManager.projects": "PROJEKTER", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Automatisk navngivning af grene", + "agentManager.settings.autoBranchNaming.description": + "Navngiv automatisk grene, når samtalen beskriver en klar opgave. Gælder alle projekter. Eksplicit navngivne og publicerede grene omdøbes aldrig.", + "agentManager.settings.branchPrefix.title": "Grenpræfiks", + "agentManager.settings.branchPrefix.description": + "Præfiks for automatisk navngivne grene i alle projekter, for eksempel feature/. Gælder ikke eksplicitte grennavne. Lad feltet være tomt for intet præfiks.", "agentManager.settings.project.title": "Projekt", "agentManager.settings.project.description": "Vælg det repository, hvis worktree-indstillinger du vil redigere.", "agentManager.settings.project.empty": "Der er ingen tilgængelige projekter i Agent Manager.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts index 9e05bdfcf3e8..a6ce9171122f 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "SITZUNGEN", "agentManager.projects": "PROJEKTE", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Automatische Branch-Benennung", + "agentManager.settings.autoBranchNaming.description": + "Branches automatisch benennen, wenn die Unterhaltung eine klare Aufgabe beschreibt. Gilt für alle Projekte. Explizit benannte und veröffentlichte Branches werden nie umbenannt.", + "agentManager.settings.branchPrefix.title": "Branch-Präfix", + "agentManager.settings.branchPrefix.description": + "Präfix für automatisch benannte Branches in allen Projekten, zum Beispiel feature/. Gilt nicht für explizite Branch-Namen. Für kein Präfix leer lassen.", "agentManager.settings.project.title": "Projekt", "agentManager.settings.project.description": "Wählen Sie das repository aus, dessen worktree-Einstellungen Sie bearbeiten möchten.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts index 7e90f06cffb8..f12ce8484a80 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "SESSIONS", "agentManager.projects": "PROJECTS", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Automatic branch naming", + "agentManager.settings.autoBranchNaming.description": + "Automatically name branches when the conversation describes a clear task. Applies to all projects. Explicitly named and published branches are never renamed.", + "agentManager.settings.branchPrefix.title": "Branch prefix", + "agentManager.settings.branchPrefix.description": + "Prefix for automatically named branches in all projects, for example feature/. Does not apply to explicit branch names. Leave empty for no prefix.", "agentManager.settings.project.title": "Project", "agentManager.settings.project.description": "Choose the repository whose worktree settings you want to edit.", "agentManager.settings.project.empty": "No Agent Manager projects are available.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts index b3ccc60214b2..3554371ef584 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "SESIONES", "agentManager.projects": "PROYECTOS", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Nombres automáticos de ramas", + "agentManager.settings.autoBranchNaming.description": + "Asigna nombres a las ramas automáticamente cuando la conversación describa una tarea clara. Se aplica a todos los proyectos. Las ramas con nombres explícitos y las publicadas nunca se renombran.", + "agentManager.settings.branchPrefix.title": "Prefijo de rama", + "agentManager.settings.branchPrefix.description": + "Prefijo para las ramas nombradas automáticamente en todos los proyectos, por ejemplo feature/. No se aplica a nombres de rama explícitos. Déjalo vacío para no usar prefijo.", "agentManager.settings.project.title": "Proyecto", "agentManager.settings.project.description": "Elige el repository cuyos ajustes de worktree quieres editar.", "agentManager.settings.project.empty": "No hay proyectos de Agent Manager disponibles.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts index 187728d1e460..1380e4bb604d 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "جلسات", "agentManager.projects": "پروژه‌ها", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "نام‌گذاری خودکار شاخه‌ها", + "agentManager.settings.autoBranchNaming.description": + "وقتی گفتگو یک کار مشخص را توصیف می‌کند، شاخه‌ها را خودکار نام‌گذاری کنید. برای همه پروژه‌ها اعمال می‌شود. نام شاخه‌های صریحاً نام‌گذاری‌شده و منتشرشده هرگز تغییر نمی‌کند.", + "agentManager.settings.branchPrefix.title": "پیشوند شاخه", + "agentManager.settings.branchPrefix.description": + "پیشوند شاخه‌هایی که در همه پروژه‌ها خودکار نام‌گذاری می‌شوند، برای مثال feature/. برای نام‌های صریح شاخه‌ها اعمال نمی‌شود. برای نداشتن پیشوند، خالی بگذارید.", "agentManager.settings.project.title": "پروژه", "agentManager.settings.project.description": "repository موردنظر را انتخاب کنید تا تنظیمات worktree آن را ویرایش کنید.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts index 4ffe20f32e78..157c7eb6e1bc 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "SESSIONS", "agentManager.projects": "PROJETS", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Nommage automatique des branches", + "agentManager.settings.autoBranchNaming.description": + "Nomme automatiquement les branches lorsque la conversation décrit une tâche claire. S’applique à tous les projets. Les branches nommées explicitement et les branches publiées ne sont jamais renommées.", + "agentManager.settings.branchPrefix.title": "Préfixe de branche", + "agentManager.settings.branchPrefix.description": + "Préfixe des branches nommées automatiquement dans tous les projets, par exemple feature/. Ne s’applique pas aux noms de branches explicites. Laissez vide pour ne pas utiliser de préfixe.", "agentManager.settings.project.title": "Projet", "agentManager.settings.project.description": "Choisissez le repository dont vous souhaitez modifier les paramètres du worktree.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts index 2376f0d53952..3bfeb29bd490 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "SESSIONI", "agentManager.projects": "PROGETTI", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Denominazione automatica dei branch", + "agentManager.settings.autoBranchNaming.description": + "Assegna automaticamente un nome ai branch quando la conversazione descrive un'attività chiara. Si applica a tutti i progetti. I branch denominati esplicitamente e quelli pubblicati non vengono mai rinominati.", + "agentManager.settings.branchPrefix.title": "Prefisso del branch", + "agentManager.settings.branchPrefix.description": + "Prefisso per i branch denominati automaticamente in tutti i progetti, ad esempio feature/. Non si applica ai nomi espliciti dei branch. Lascia vuoto per non usare un prefisso.", "agentManager.settings.project.title": "Progetto", "agentManager.settings.project.description": "Scegli il repository di cui vuoi modificare le impostazioni del worktree.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts index 3af0ce6cd14c..3fb42e8768db 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "セッション", "agentManager.projects": "プロジェクト", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "ブランチの自動命名", + "agentManager.settings.autoBranchNaming.description": + "会話で明確なタスクが説明されると、ブランチに自動で名前を付けます。すべてのプロジェクトに適用されます。明示的に命名されたブランチと公開済みのブランチは変更されません。", + "agentManager.settings.branchPrefix.title": "ブランチのプレフィックス", + "agentManager.settings.branchPrefix.description": + "すべてのプロジェクトで自動命名されるブランチのプレフィックスです(例:feature/)。明示的なブランチ名には適用されません。プレフィックスを使わない場合は空欄にしてください。", "agentManager.settings.project.title": "プロジェクト", "agentManager.settings.project.description": "編集する worktree 設定の repository を選択してください。", "agentManager.settings.project.empty": "利用可能な Agent Manager プロジェクトはありません。", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts index 299dbe9e0f09..a06a5ceef91f 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "세션", "agentManager.projects": "프로젝트", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "자동 브랜치 이름 지정", + "agentManager.settings.autoBranchNaming.description": + "대화에서 명확한 작업을 설명하면 브랜치 이름을 자동으로 지정합니다. 모든 프로젝트에 적용됩니다. 명시적으로 이름을 지정한 브랜치와 게시된 브랜치의 이름은 변경되지 않습니다.", + "agentManager.settings.branchPrefix.title": "브랜치 접두사", + "agentManager.settings.branchPrefix.description": + "모든 프로젝트에서 자동으로 이름이 지정되는 브랜치의 접두사입니다(예: feature/). 명시적인 브랜치 이름에는 적용되지 않습니다. 접두사를 사용하지 않으려면 비워 두세요.", "agentManager.settings.project.title": "프로젝트", "agentManager.settings.project.description": "편집하려는 worktree 설정의 repository를 선택하세요.", "agentManager.settings.project.empty": "사용 가능한 Agent Manager 프로젝트가 없습니다.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts index 8fc97a6e3d48..7524b7237e03 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "SESSIES", "agentManager.projects": "PROJECTEN", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Automatische branchnamen", + "agentManager.settings.autoBranchNaming.description": + "Geef branches automatisch een naam wanneer het gesprek een duidelijke taak beschrijft. Geldt voor alle projecten. Expliciet benoemde en gepubliceerde branches worden nooit hernoemd.", + "agentManager.settings.branchPrefix.title": "Branchprefix", + "agentManager.settings.branchPrefix.description": + "Prefix voor automatisch benoemde branches in alle projecten, bijvoorbeeld feature/. Geldt niet voor expliciete branchnamen. Laat leeg om geen prefix te gebruiken.", "agentManager.settings.project.title": "Project", "agentManager.settings.project.description": "Kies de repository waarvan je de worktree-instellingen wilt bewerken.", "agentManager.settings.project.empty": "Er zijn geen Agent Manager-projecten beschikbaar.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts index b5df4ea937e5..25a78a8b189a 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "ØKTER", "agentManager.projects": "PROSJEKTER", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Automatisk navngivning av grener", + "agentManager.settings.autoBranchNaming.description": + "Gi grener navn automatisk når samtalen beskriver en tydelig oppgave. Gjelder alle prosjekter. Eksplisitt navngitte og publiserte grener får aldri nytt navn.", + "agentManager.settings.branchPrefix.title": "Grenprefiks", + "agentManager.settings.branchPrefix.description": + "Prefiks for automatisk navngitte grener i alle prosjekter, for eksempel feature/. Gjelder ikke eksplisitte grennavn. La feltet stå tomt for å ikke bruke prefiks.", "agentManager.settings.project.title": "Prosjekt", "agentManager.settings.project.description": "Velg repository hvis worktree-innstillinger du vil redigere.", "agentManager.settings.project.empty": "Ingen Agent Manager-prosjekter er tilgjengelige.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts index 2c68e1877d66..5f1a56a2d44c 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "SESJE", "agentManager.projects": "PROJEKTY", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Automatyczne nazwy gałęzi", + "agentManager.settings.autoBranchNaming.description": + "Automatycznie nadawaj nazwy gałęziom, gdy rozmowa opisuje konkretne zadanie. Dotyczy wszystkich projektów. Nazwy gałęzi nazwanych jawnie i opublikowanych nigdy nie są zmieniane.", + "agentManager.settings.branchPrefix.title": "Prefiks gałęzi", + "agentManager.settings.branchPrefix.description": + "Prefiks automatycznie nazywanych gałęzi we wszystkich projektach, na przykład feature/. Nie dotyczy jawnych nazw gałęzi. Pozostaw puste, aby nie używać prefiksu.", "agentManager.settings.project.title": "Projekt", "agentManager.settings.project.description": "Wybierz repository, którego ustawienia worktree chcesz edytować.", "agentManager.settings.project.empty": "Brak dostępnych projektów Agent Manager.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts index ec68cd70ee99..38c918d557df 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "СЕССИИ", "agentManager.projects": "ПРОЕКТЫ", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Автоматическое именование веток", + "agentManager.settings.autoBranchNaming.description": + "Автоматически именовать ветки, когда в разговоре описана чёткая задача. Применяется ко всем проектам. Ветки с явно заданными именами и опубликованные ветки никогда не переименовываются.", + "agentManager.settings.branchPrefix.title": "Префикс ветки", + "agentManager.settings.branchPrefix.description": + "Префикс автоматически именуемых веток во всех проектах, например feature/. Не применяется к явно заданным именам веток. Оставьте пустым, чтобы не использовать префикс.", "agentManager.settings.project.title": "Проект", "agentManager.settings.project.description": "Выберите repository, настройки worktree которого хотите изменить.", "agentManager.settings.project.empty": "Нет доступных проектов Agent Manager.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts index 342a9778cc3b..1715f80c85a1 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "เซสชัน", "agentManager.projects": "โปรเจกต์", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "ตั้งชื่อบรานช์อัตโนมัติ", + "agentManager.settings.autoBranchNaming.description": + "ตั้งชื่อบรานช์โดยอัตโนมัติเมื่อบทสนทนาอธิบายงานที่ชัดเจน ใช้กับทุกโปรเจกต์ บรานช์ที่ตั้งชื่อไว้อย่างชัดเจนและบรานช์ที่เผยแพร่แล้วจะไม่ถูกเปลี่ยนชื่อ", + "agentManager.settings.branchPrefix.title": "คำนำหน้าบรานช์", + "agentManager.settings.branchPrefix.description": + "คำนำหน้าสำหรับบรานช์ที่ตั้งชื่ออัตโนมัติในทุกโปรเจกต์ เช่น feature/ ไม่ใช้กับชื่อบรานช์ที่ระบุไว้อย่างชัดเจน เว้นว่างไว้หากไม่ต้องการคำนำหน้า", "agentManager.settings.project.title": "โปรเจกต์", "agentManager.settings.project.description": "เลือก repository ที่มีการตั้งค่า worktree ที่คุณต้องการแก้ไข", "agentManager.settings.project.empty": "ไม่มีโปรเจกต์ Agent Manager ที่พร้อมใช้งาน", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts index 3b0ebf68d8a8..61d907721205 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "OTURUMLAR", "agentManager.projects": "PROJELER", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Otomatik dal adlandırma", + "agentManager.settings.autoBranchNaming.description": + "Konuşma net bir görevi tanımladığında dalları otomatik olarak adlandırır. Tüm projelere uygulanır. Açıkça adlandırılmış ve yayımlanmış dallar asla yeniden adlandırılmaz.", + "agentManager.settings.branchPrefix.title": "Dal öneki", + "agentManager.settings.branchPrefix.description": + "Tüm projelerde otomatik adlandırılan dallar için önek, örneğin feature/. Açıkça belirtilen dal adlarına uygulanmaz. Önek kullanmamak için boş bırakın.", "agentManager.settings.project.title": "Proje", "agentManager.settings.project.description": "Worktree ayarlarını düzenlemek istediğiniz repository'yi seçin.", "agentManager.settings.project.empty": "Kullanılabilir Agent Manager projesi yok.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts index a343e4af3a4c..72283df4705d 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "СЕСІЇ", "agentManager.projects": "ПРОЄКТИ", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "Автоматичне іменування гілок", + "agentManager.settings.autoBranchNaming.description": + "Автоматично іменувати гілки, коли розмова описує чітке завдання. Застосовується до всіх проєктів. Гілки з явно заданими назвами та опубліковані гілки ніколи не перейменовуються.", + "agentManager.settings.branchPrefix.title": "Префікс гілки", + "agentManager.settings.branchPrefix.description": + "Префікс автоматично іменованих гілок у всіх проєктах, наприклад feature/. Не застосовується до явно заданих назв гілок. Залиште порожнім, щоб не використовувати префікс.", "agentManager.settings.project.title": "Проєкт", "agentManager.settings.project.description": "Виберіть repository, налаштування worktree якого потрібно змінити.", "agentManager.settings.project.empty": "Немає доступних проєктів Agent Manager.", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts index f752324bd76a..3106622a53b2 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "会话", "agentManager.projects": "项目", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "自动命名分支", + "agentManager.settings.autoBranchNaming.description": + "当对话描述了明确的任务时,自动为分支命名。适用于所有项目。明确命名的分支和已发布的分支永远不会被重命名。", + "agentManager.settings.branchPrefix.title": "分支前缀", + "agentManager.settings.branchPrefix.description": + "所有项目中自动命名分支的前缀,例如 feature/。不适用于明确指定的分支名称。留空则不使用前缀。", "agentManager.settings.project.title": "项目", "agentManager.settings.project.description": "选择要编辑其 worktree 设置的 repository。", "agentManager.settings.project.empty": "没有可用的 Agent Manager 项目。", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts index 3552d72e0e33..f09bfcf2bf59 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts @@ -6,6 +6,12 @@ export const dict = { "agentManager.section.sessions": "工作階段", "agentManager.projects": "專案", "agentManager.settings.title": "Agent Manager", + "agentManager.settings.autoBranchNaming.title": "自動命名分支", + "agentManager.settings.autoBranchNaming.description": + "當對話描述了明確的任務時,自動為分支命名。適用於所有專案。明確命名的分支和已發佈的分支永遠不會被重新命名。", + "agentManager.settings.branchPrefix.title": "分支前綴", + "agentManager.settings.branchPrefix.description": + "所有專案中自動命名分支的前綴,例如 feature/。不適用於明確指定的分支名稱。留空則不使用前綴。", "agentManager.settings.project.title": "專案", "agentManager.settings.project.description": "選擇要編輯其 worktree 設定的 repository。", "agentManager.settings.project.empty": "沒有可用的 Agent Manager 專案。", diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/Settings.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/Settings.tsx index dace3609b1d1..d624fc2f0e49 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/Settings.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/Settings.tsx @@ -39,6 +39,8 @@ import type { import { Select } from "@kilocode/kilo-ui/select" import { Card } from "@kilocode/kilo-ui/card" import { Spinner } from "@kilocode/kilo-ui/spinner" +import { Switch } from "@kilocode/kilo-ui/switch" +import { TextField } from "@kilocode/kilo-ui/text-field" import SettingsRow from "./SettingsRow" import { ProjectBranchDialog } from "../../../agent-manager/ProjectBranchDialog" @@ -52,6 +54,7 @@ export interface SettingsProps { const AgentManagerTab: Component<{ projectId?: string }> = (props) => { const language = useLanguage() + const { settings, updateSetting } = useConfig() const vscode = useVSCode() const dialog = useDialog() const [projects, setProjects] = createSignal([]) @@ -152,6 +155,30 @@ const AgentManagerTab: Component<{ projectId?: string }> = (props) => { }>
+ + updateSetting("agentManager.autoBranchNaming", value)} + hideLabel + > + {language.t("agentManager.settings.autoBranchNaming.title")} + + + + updateSetting("agentManager.branchPrefix", value)} + /> + Date: Mon, 7 Sep 2026 12:46:56 +0200 Subject: [PATCH 2/3] fix(agent-manager): guard explicit branch naming edge cases --- .../src/agent-manager/WorktreeManager.ts | 23 +++- .../agent-manager/provider-multi-version.ts | 8 +- .../tests/unit/new-worktree-branch.test.ts | 100 ++++++++++++++++++ .../tests/unit/provider-multi-version.test.ts | 24 +++++ .../tests/unit/worktree-manager.test.ts | 27 +++++ .../agent-manager/NewWorktreeDialog.tsx | 13 ++- .../webview-ui/agent-manager/i18n/ar.ts | 1 + .../webview-ui/agent-manager/i18n/br.ts | 1 + .../webview-ui/agent-manager/i18n/bs.ts | 1 + .../webview-ui/agent-manager/i18n/da.ts | 1 + .../webview-ui/agent-manager/i18n/de.ts | 2 + .../webview-ui/agent-manager/i18n/en.ts | 1 + .../webview-ui/agent-manager/i18n/es.ts | 2 + .../webview-ui/agent-manager/i18n/fa.ts | 1 + .../webview-ui/agent-manager/i18n/fr.ts | 2 + .../webview-ui/agent-manager/i18n/it.ts | 2 + .../webview-ui/agent-manager/i18n/ja.ts | 2 + .../webview-ui/agent-manager/i18n/ko.ts | 1 + .../webview-ui/agent-manager/i18n/nl.ts | 1 + .../webview-ui/agent-manager/i18n/no.ts | 1 + .../webview-ui/agent-manager/i18n/pl.ts | 1 + .../webview-ui/agent-manager/i18n/ru.ts | 1 + .../webview-ui/agent-manager/i18n/th.ts | 1 + .../webview-ui/agent-manager/i18n/tr.ts | 1 + .../webview-ui/agent-manager/i18n/uk.ts | 1 + .../webview-ui/agent-manager/i18n/zh.ts | 1 + .../webview-ui/agent-manager/i18n/zht.ts | 1 + .../agent-manager/new-worktree-branch.ts | 7 ++ 28 files changed, 219 insertions(+), 9 deletions(-) create mode 100644 packages/kilo-vscode/tests/unit/new-worktree-branch.test.ts create mode 100644 packages/kilo-vscode/webview-ui/agent-manager/new-worktree-branch.ts diff --git a/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts b/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts index 4a9110a65283..564c4b996816 100644 --- a/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts +++ b/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts @@ -297,7 +297,7 @@ export class WorktreeManager { const dirName = directory(branch) let worktreePath = path.join(this.dir, dirName) - await this.prepareWorktreePath(worktreePath, !!params.existingBranch) + worktreePath = await this.prepareWorktreePath(worktreePath, params.existingBranch) params.onProgress?.("creating", `Creating worktree for ${branch}...`) @@ -375,11 +375,26 @@ export class WorktreeManager { return branch } - private async prepareWorktreePath(worktreePath: string, reuse: boolean): Promise { - if (!fs.existsSync(worktreePath)) return - if (!reuse) throw new Error(`Worktree path already exists: ${worktreePath}`) + private async prepareWorktreePath(worktreePath: string, branch?: string): Promise { + if (!fs.existsSync(worktreePath)) return worktreePath + if (!branch) throw new Error(`Worktree path already exists: ${worktreePath}`) + const entries = parseWorktreeList(await this.git.raw(["worktree", "list", "--porcelain"])) + const canonical = normalizePath(await fs.promises.realpath(worktreePath)) + const entry = entries.find((entry) => normalizePath(entry.path) === canonical) + if (entry && (entry.branch !== branch || entry.detached || entry.bare)) { + // A literal branch can match another ref's hashed directory name. + const parent = await fs.promises.realpath(path.dirname(worktreePath)) + for (let suffix = 2; ; suffix++) { + const candidate = `${worktreePath}-${suffix}` + const canonical = normalizePath(path.join(parent, path.basename(candidate))) + if (!fs.existsSync(candidate) && !entries.some((entry) => normalizePath(entry.path) === canonical)) { + return candidate + } + } + } this.log(`Worktree directory exists, cleaning up before re-creation: ${worktreePath}`) await this.removeWorktreeImpl(worktreePath) + return worktreePath } private async resolveBranch(params: { diff --git a/packages/kilo-vscode/src/agent-manager/provider-multi-version.ts b/packages/kilo-vscode/src/agent-manager/provider-multi-version.ts index 2897d1c33b94..7abf7834d77a 100644 --- a/packages/kilo-vscode/src/agent-manager/provider-multi-version.ts +++ b/packages/kilo-vscode/src/agent-manager/provider-multi-version.ts @@ -2,7 +2,7 @@ import { getErrorMessage } from "../kilo-provider-utils" import { PLATFORM } from "./constants" import type { ProjectContext } from "./project/context" import type { AgentManagerInMessage } from "./types" -import { versionedName } from "./branch-name" +import { sanitizeBranchName, versionedName } from "./branch-name" import { resolveVersionModels, buildInitialMessages, type CreatedVersion } from "./multi-version" import { ensureSandbox } from "./sandbox-bootstrap" import type { LifecycleHost } from "./provider-lifecycle" @@ -37,7 +37,7 @@ export async function createMultiVersion( const agent = msg.agent const files = msg.files const baseBranch = msg.baseBranch - const branchName = msg.branchName?.trim() || undefined + const branchName = msg.branchName || undefined const fallback = msg.providerID && msg.modelID ? { providerID: msg.providerID, modelID: msg.modelID } : undefined const resolved = resolveVersionModels(msg.modelAllocations, fallback, Number(msg.versions) || 1) @@ -157,10 +157,12 @@ async function prepareVersion(host: MultiVersionHost, spec: VersionSpec): Promis host.log(`Creating worktree ${spec.index + 1}/${spec.versions}`) const version = versionedName(spec.branchName || spec.worktreeName, spec.index, spec.versions) + // Display names retain automatic slugging; explicit Git branches stay literal. + const branch = spec.branchName ? version.branch : sanitizeBranchName(version.branch ?? "") || undefined const wt = await host.createOnDisk({ groupId: spec.groupId, baseBranch: spec.baseBranch, - branchName: version.branch, + branchName: branch, name: version.branch, label: version.label, }) diff --git a/packages/kilo-vscode/tests/unit/new-worktree-branch.test.ts b/packages/kilo-vscode/tests/unit/new-worktree-branch.test.ts new file mode 100644 index 000000000000..3c72d7c80913 --- /dev/null +++ b/packages/kilo-vscode/tests/unit/new-worktree-branch.test.ts @@ -0,0 +1,100 @@ +import { describe, expect, it } from "bun:test" +import { readFileSync } from "node:fs" +import { join } from "node:path" +import { validBranch } from "../../webview-ui/agent-manager/new-worktree-branch" + +describe("new worktree branch validation", () => { + it("allows automatic naming when no explicit branch is supplied", () => { + expect(validBranch(undefined)).toBe(true) + }) + it.each([ + "Feature/My_fix.v2", + "main", + "@", + "HEAD_v2", + "feature/HEAD", + "fix+login", + "fix#123", + "日本語", + "foo/.hidden", + "foo/bar.lock", + "foo.lock/bar", + "foo//bar", + "/foo", + "foo/", + "foo.", + "foo..bar", + "foo@{bar", + "@{-1}", + "HEAD", + "-foo", + "", + " ", + " foo", + "foo ", + "foo bar", + "foo\tbar", + "foo\nbar", + "foo\0bar", + "foo\x7fbar", + "foo~bar", + "foo^bar", + "foo:bar", + "foo?bar", + "foo*bar", + "foo[bar", + "foo\\bar", + "foo]bar", + "foo.locked", + "foo./bar", + "foo.LOCK", + "foo/@", + "foo/-bar", + ])("matches literal Git branch validation for %j", (name) => { + if (name.includes("\0")) { + expect(validBranch(name)).toBe(false) + return + } + const ref = Bun.spawnSync(["git", "check-ref-format", `refs/heads/${name}`]) + const branch = Bun.spawnSync(["git", "check-ref-format", "--branch", name]) + expect(validBranch(name)).toBe(ref.exitCode === 0 && branch.exitCode === 0) + }) + + it("rejects invalid input before starting, submitting, clearing drafts, or closing", () => { + const src = readFileSync(join(__dirname, "../../webview-ui/agent-manager/NewWorktreeDialog.tsx"), "utf8") + const submit = src.slice(src.indexOf("const handleSubmit ="), src.indexOf("const handleKeyDown =")) + const messages: unknown[] = [] + const run = new Function( + "canSubmit", + "showAdvanced", + "branchName", + "validBranch", + "showToast", + "t", + submit.slice(submit.indexOf("{") + 1, submit.lastIndexOf("}")), + ) + // Execute the real handler. Any submission side effect would access an unbound dependency and fail. + run( + () => true, + () => true, + () => "../escape", + validBranch, + (msg: unknown) => messages.push(msg), + (key: string) => key, + ) + expect(messages).toHaveLength(1) + const guard = submit.indexOf("if (!validBranch(customBranch))") + expect(guard).toBeGreaterThan(-1) + expect(submit.slice(guard, submit.indexOf("setStarting(true)"))).toContain("return") + for (const effect of [ + "setStarting(true)", + "props.onCreate", + "vscode.postMessage", + 'persistPrompt("")', + "persistImages([])", + "props.onClose()", + ]) + expect(submit.indexOf(effect)).toBeGreaterThan(guard) + expect(submit).toContain("const customBranch = advanced ? branchName() || undefined : undefined") + }) +}) diff --git a/packages/kilo-vscode/tests/unit/provider-multi-version.test.ts b/packages/kilo-vscode/tests/unit/provider-multi-version.test.ts index df0ec2d53b9c..0b6a7e76c71b 100644 --- a/packages/kilo-vscode/tests/unit/provider-multi-version.test.ts +++ b/packages/kilo-vscode/tests/unit/provider-multi-version.test.ts @@ -5,6 +5,30 @@ import type { ProjectContext } from "../../src/agent-manager/project/context" import type { CreateWorktreeOnDiskResult } from "../../src/agent-manager/worktree-create" describe("multi-version provisioning", () => { + it.each([ + { name: "Fix login", branches: ["fix-login", "fix-login-v2"] }, + { name: "!!!", branches: [undefined, "v2"] }, + { name: "a".repeat(60), branches: ["a".repeat(50), "a".repeat(50)] }, + { name: undefined, branches: [undefined, undefined] }, + { name: "Fix login", branchName: "Feature/My_fix.v2", branches: ["Feature/My_fix.v2", "Feature/My_fix.v2_v2"] }, + { name: "Fix login", branchName: " invalid ", branches: [" invalid ", " invalid _v2"] }, + ])("keeps automatic display-name slugging separate from explicit refs: %j", async (input) => { + const create = mock(async (_opts: { branchName?: string }) => null) + const host = { + createOnDisk: create, + log: () => {}, + post: () => {}, + error: () => {}, + } as unknown as MultiVersionHost + await createMultiVersion({ id: "project-1" } as ProjectContext, host, { + type: "agentManager.createMultiVersion", + versions: 2, + name: input.name, + branchName: "branchName" in input ? input.branchName : undefined, + }) + expect(create.mock.calls.map(([opts]) => opts.branchName)).toEqual(input.branches) + }) + it("finishes git creation before provisioning at bounded concurrency", async () => { const flow: string[] = [] const gates = [Promise.withResolvers(), Promise.withResolvers()] diff --git a/packages/kilo-vscode/tests/unit/worktree-manager.test.ts b/packages/kilo-vscode/tests/unit/worktree-manager.test.ts index 2b454a48c531..536b11a37e36 100644 --- a/packages/kilo-vscode/tests/unit/worktree-manager.test.ts +++ b/packages/kilo-vscode/tests/unit/worktree-manager.test.ts @@ -781,6 +781,7 @@ describe("WorktreeManager.createWorktree cleanup", () => { const second = await mgr.createWorktree({ existingBranch: branch }) expect(second.branch).toBe(branch) + expect(second.path).toBe(first.path) const gitFile = await fs.stat(path.join(second.path, ".git")) expect(gitFile.isFile()).toBe(true) @@ -1017,6 +1018,32 @@ describe("WorktreeManager.renameBranch", () => { // --------------------------------------------------------------------------- describe("WorktreeManager.createWorktree branch collision", () => { + it("preserves an unrelated dirty worktree when an existing slash branch hashes to its literal name", async () => { + const root = await createTempRepo() + const mgr = createManager(root) + const branch = "Feature/My_fix.v2" + const original = await mgr.createWorktree({ branchName: branch }) + const literal = path.basename(original.path) + await mgr.removeWorktree(original.path) + const other = await mgr.createWorktree({ branchName: literal }) + const file = path.join(other.path, "draft.txt") + await fs.writeFile(file, "uncommitted work") + const occupied = `${other.path}-2` + await fs.mkdir(occupied) + await fs.writeFile(path.join(occupied, "keep.txt"), "keep") + + const result = await mgr.createWorktree({ existingBranch: branch }) + + expect(result.branch).toBe(branch) + expect(result.path).toBe(`${other.path}-3`) + expect((await simpleGit(result.path).raw(["symbolic-ref", "HEAD"])).trim()).toBe(`refs/heads/${branch}`) + expect((await simpleGit(other.path).raw(["symbolic-ref", "HEAD"])).trim()).toBe(`refs/heads/${literal}`) + expect(await fs.readFile(file, "utf8")).toBe("uncommitted work") + expect(await changedFiles(other.path)).toEqual(["?? draft.txt"]) + expect(await fs.readFile(path.join(occupied, "keep.txt"), "utf8")).toBe("keep") + expect(await mgr.checkedOutBranches()).toEqual(new Set(["main", literal, branch])) + }) + it("creates a suffixed worktree without replacing an active explicitly named worktree", async () => { const root = await createTempRepo() const mgr = createManager(root) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx index 0854d69bfb3d..c29d3f7ac036 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx @@ -52,6 +52,7 @@ import { cycleAgent } from "../src/context/session-agent" import type { ModeRouter } from "./mode-router" import { ProjectSelect } from "./ProjectSelect" import { createDialogModels } from "./new-worktree-models" +import { validBranch } from "./new-worktree-branch" type VersionCount = 1 | 2 | 3 | 4 const VERSION_OPTIONS: VersionCount[] = [1, 2, 3, 4] @@ -395,13 +396,21 @@ export const NewWorktreeDialog: Component<{ const handleSubmit = () => { if (!canSubmit()) return + const advanced = showAdvanced() + const customBranch = advanced ? branchName() || undefined : undefined + if (!validBranch(customBranch)) { + showToast({ + variant: "error", + title: t("agentManager.dialog.branchName"), + description: t("agentManager.dialog.invalidBranch"), + }) + return + } setStarting(true) const text = prompt().trim() || undefined const defaultAgent = session.agents()[0]?.name const selectedAgent = agent() !== defaultAgent ? agent() : undefined - const advanced = showAdvanced() - const customBranch = advanced ? branchName() || undefined : undefined const imgs = imageAttach.images() const imgFiles = imgs.length > 0 ? imgs.map((img) => ({ mime: img.mime, url: img.dataUrl })) : undefined diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts index 621d10f0cd50..10a3ed3a0d3e 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "أدخل اسم فرع Git صالحًا. تم الاحتفاظ بالمطالبة والمرفقات.", "agentManager.local": "محلي", "agentManager.sidebar.collapse": "طي الشريط الجانبي", "agentManager.sidebar.expand": "إظهار الشريط الجانبي", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts index 54e032a0fb88..74ad895dc749 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "Insira um nome de branch Git válido. Seu prompt e anexos foram mantidos.", "agentManager.local": "local", "agentManager.sidebar.collapse": "Recolher barra lateral", "agentManager.sidebar.expand": "Mostrar barra lateral", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts index d7e9074dd2df..8b18750aef34 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "Unesite važeći naziv Git grane. Vaš upit i prilozi su sačuvani.", "agentManager.local": "lokalno", "agentManager.sidebar.collapse": "Skupi bočnu traku", "agentManager.sidebar.expand": "Prikaži bočnu traku", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts index 28ec731aacb8..16c309f39ff2 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "Indtast et gyldigt Git-grennavn. Din prompt og dine vedhæftninger er bevaret.", "agentManager.local": "lokal", "agentManager.sidebar.collapse": "Skjul sidebjælke", "agentManager.sidebar.expand": "Vis sidebjælke", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts index a6ce9171122f..0a91371bf224 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts @@ -1,4 +1,6 @@ export const dict = { + "agentManager.dialog.invalidBranch": + "Gib einen gültigen Git-Branch-Namen ein. Dein Prompt und deine Anhänge wurden beibehalten.", "agentManager.local": "lokal", "agentManager.sidebar.collapse": "Seitenleiste einklappen", "agentManager.sidebar.expand": "Seitenleiste anzeigen", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts index f12ce8484a80..2083cff31f50 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "Enter a valid Git branch name. Your prompt and attachments have been kept.", "agentManager.local": "local", "agentManager.sidebar.collapse": "Collapse sidebar", "agentManager.sidebar.expand": "Show sidebar", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts index 3554371ef584..535665bb29f4 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts @@ -1,4 +1,6 @@ export const dict = { + "agentManager.dialog.invalidBranch": + "Introduce un nombre de rama Git válido. Se han conservado tu prompt y tus archivos adjuntos.", "agentManager.local": "local", "agentManager.sidebar.collapse": "Contraer barra lateral", "agentManager.sidebar.expand": "Mostrar barra lateral", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts index 1380e4bb604d..929eddefb434 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "یک نام معتبر برای شاخه Git وارد کنید. پیام و پیوست‌های شما حفظ شده‌اند.", "agentManager.local": "محلی", "agentManager.sidebar.collapse": "بستن نوار کناری", "agentManager.sidebar.expand": "نمایش نوار کناری", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts index 157c7eb6e1bc..b33e71821adb 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts @@ -1,4 +1,6 @@ export const dict = { + "agentManager.dialog.invalidBranch": + "Saisissez un nom de branche Git valide. Votre prompt et vos pièces jointes ont été conservés.", "agentManager.local": "local", "agentManager.sidebar.collapse": "Réduire la barre latérale", "agentManager.sidebar.expand": "Afficher la barre latérale", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts index 3bfeb29bd490..6b9d07df5597 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts @@ -1,4 +1,6 @@ export const dict = { + "agentManager.dialog.invalidBranch": + "Inserisci un nome di ramo Git valido. Il prompt e gli allegati sono stati conservati.", "agentManager.local": "locale", "agentManager.sidebar.collapse": "Comprimi barra laterale", "agentManager.sidebar.expand": "Mostra barra laterale", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts index 3fb42e8768db..9021a9dddbad 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts @@ -1,4 +1,6 @@ export const dict = { + "agentManager.dialog.invalidBranch": + "有効なGitブランチ名を入力してください。プロンプトと添付ファイルは保持されています。", "agentManager.local": "ローカル", "agentManager.sidebar.collapse": "サイドバーを折りたたむ", "agentManager.sidebar.expand": "サイドバーを表示", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts index a06a5ceef91f..27ac9ebd2e54 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "유효한 Git 브랜치 이름을 입력하세요. 프롬프트와 첨부 파일은 보존되었습니다.", "agentManager.local": "로컬", "agentManager.sidebar.collapse": "사이드바 접기", "agentManager.sidebar.expand": "사이드바 표시", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts index 7524b7237e03..681b8a16982c 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "Voer een geldige Git-branchnaam in. Je prompt en bijlagen zijn behouden.", "agentManager.local": "lokaal", "agentManager.sidebar.collapse": "Zijbalk inklappen", "agentManager.sidebar.expand": "Zijbalk tonen", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts index 25a78a8b189a..4316e10d9cef 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "Skriv inn et gyldig Git-grennavn. Prompten og vedleggene dine er bevart.", "agentManager.local": "lokal", "agentManager.sidebar.collapse": "Skjul sidefelt", "agentManager.sidebar.expand": "Vis sidefelt", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts index 5f1a56a2d44c..a04a716580d8 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "Wpisz prawidłową nazwę gałęzi Git. Twój prompt i załączniki zostały zachowane.", "agentManager.local": "lokalne", "agentManager.sidebar.collapse": "Zwiń pasek boczny", "agentManager.sidebar.expand": "Pokaż pasek boczny", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts index 38c918d557df..b6311146cf85 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "Введите допустимое имя ветки Git. Ваш запрос и вложения сохранены.", "agentManager.local": "локальный", "agentManager.sidebar.collapse": "Свернуть боковую панель", "agentManager.sidebar.expand": "Показать боковую панель", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts index 1715f80c85a1..918dc50e6ae9 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "ป้อนชื่อสาขา Git ที่ถูกต้อง พรอมต์และไฟล์แนบของคุณยังคงอยู่", "agentManager.local": "ในเครื่อง", "agentManager.sidebar.collapse": "ย่อแถบด้านข้าง", "agentManager.sidebar.expand": "แสดงแถบด้านข้าง", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts index 61d907721205..f485153cb405 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "Geçerli bir Git dalı adı girin. İsteminiz ve ekleriniz korundu.", "agentManager.local": "yerel", "agentManager.sidebar.collapse": "Kenar çubuğunu daralt", "agentManager.sidebar.expand": "Kenar çubuğunu göster", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts index 72283df4705d..137db13ac375 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "Введіть допустиму назву гілки Git. Ваш запит і вкладення збережено.", "agentManager.local": "локальний", "agentManager.sidebar.collapse": "Згорнути бічну панель", "agentManager.sidebar.expand": "Показати бічну панель", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts index 3106622a53b2..65cf2f523baa 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "请输入有效的 Git 分支名称。您的提示词和附件已保留。", "agentManager.local": "本地", "agentManager.sidebar.collapse": "折叠侧边栏", "agentManager.sidebar.expand": "显示侧边栏", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts index f09bfcf2bf59..fcc20774e538 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts @@ -1,4 +1,5 @@ export const dict = { + "agentManager.dialog.invalidBranch": "請輸入有效的 Git 分支名稱。您的提示詞和附件已保留。", "agentManager.local": "本機", "agentManager.sidebar.collapse": "收合側邊欄", "agentManager.sidebar.expand": "顯示側邊欄", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/new-worktree-branch.ts b/packages/kilo-vscode/webview-ui/agent-manager/new-worktree-branch.ts new file mode 100644 index 000000000000..e3bebcaedb1a --- /dev/null +++ b/packages/kilo-vscode/webview-ui/agent-manager/new-worktree-branch.ts @@ -0,0 +1,7 @@ +/** Literal branch rules used by Git's check-ref-format, without checkout shorthand expansion. */ +export function validBranch(name: string | undefined): boolean { + if (name === undefined) return true + if (!name || name === "HEAD" || name.startsWith("-") || name.endsWith(".")) return false + if (/[\x00-\x20\x7f~^:?*\[\\]/.test(name) || name.includes("..") || name.includes("@{")) return false + return name.split("/").every((part) => !!part && !part.startsWith(".") && !part.endsWith(".lock")) +} From e9db162914a45cba8895d2e7d4a25599b0787ea1 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Mon, 7 Sep 2026 12:58:20 +0200 Subject: [PATCH 3/3] test(vscode): isolate naming settings snapshot fixture --- .../tests/unit/kilo-provider-indexing-refresh.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts b/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts index 657cee6153a8..86be92cf0f04 100644 --- a/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts +++ b/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts @@ -167,7 +167,7 @@ describe("KiloProvider indexing refresh", () => { const internal = provider as unknown as Internals const sent: Array> = [] provider.postMessage = (message) => void sent.push(message as Record) - Object.assign(internal, { connectionState: "connected", commitMessageLanguageSetting: () => "sync" }) + Object.assign(internal, { connectionState: "connected", configSettings: settings }) await internal.fetchAndSendConfig() await internal.fetchAndSendConfigUpdated() // Save against the binding the latest config load issued, like the webview