mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
feat(vscode): add settings export/import to About tab (#7794)
Add Export and Import buttons in the About Kilo Code settings tab so users can transfer settings between VS Code instances (closes #7755). - Export fetches global-only config (not merged/project-level) to avoid promoting project-level agent definitions to global config - All fields exported as-is including secrets for complete transfers - Import populates the draft for review before saving via existing save bar flow - KNOWN_KEYS drift guard test catches newly added Config fields - 40 unit tests covering export, import, merge, round-trip, and constants - i18n keys translated for all 17 locales
This commit is contained in:
@@ -652,6 +652,9 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
case "requestConfig":
|
||||
this.fetchAndSendConfig().catch((e) => console.error("[Kilo New] fetchAndSendConfig failed:", e))
|
||||
break
|
||||
case "requestGlobalConfig":
|
||||
this.fetchAndSendGlobalConfig().catch((e) => console.error("[Kilo New] fetchAndSendGlobalConfig failed:", e))
|
||||
break
|
||||
case "updateConfig":
|
||||
await this.handleUpdateConfig(message.config)
|
||||
break
|
||||
@@ -1739,6 +1742,17 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
}
|
||||
}
|
||||
|
||||
/** Fetch global-only config (no project/managed layers) for settings export. */
|
||||
private async fetchAndSendGlobalConfig(): Promise<void> {
|
||||
if (!this.client || this.connectionState !== "connected") return
|
||||
try {
|
||||
const { data: config } = await this.client.global.config.get({ throwOnError: true })
|
||||
this.postMessage({ type: "globalConfigLoaded", config })
|
||||
} catch (error) {
|
||||
console.error("[Kilo New] KiloProvider: Failed to fetch global config:", error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed sessionStatusMap with current session statuses on connect.
|
||||
* Without this, the Settings panel (which has no tracked sessions) would see
|
||||
|
||||
@@ -276,12 +276,14 @@ export class AgentManagerProvider implements Disposable {
|
||||
// already emitted before the webview was ready to receive messages.
|
||||
if (this.cachedWorktreeStats) this.postToWebview(this.cachedWorktreeStats)
|
||||
if (this.cachedLocalStats) this.postToWebview(this.cachedLocalStats)
|
||||
// Always refresh sessions after pushState so the webview receives
|
||||
// a sessionsLoaded message. Without this unconditional call, closing
|
||||
// and reopening the panel (or recovering from a backend crash) can
|
||||
// leave sessionsLoaded stuck on false because the initial
|
||||
// refreshSessions() in initializeState() raced ahead of mount.
|
||||
this.panel?.sessions.refreshSessions()
|
||||
// Refresh sessions after pushState so the webview's sessionsLoaded
|
||||
// handler is guaranteed to be registered (requestState fires from
|
||||
// onMount). Without this, the initial refreshSessions() in
|
||||
// initializeState() can race ahead of webview mount, causing
|
||||
// sessionsLoaded to never flip to true.
|
||||
if (this.state.getSessions().length > 0) {
|
||||
this.panel?.sessions.refreshSessions()
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
this.log("initializeState failed, pushing partial state:", err)
|
||||
|
||||
@@ -321,12 +321,13 @@ describe("Agent Manager Webview — non-git sessionsLoaded fix", () => {
|
||||
/**
|
||||
* Regression: when isGitRepo is false, the Kilo server never sends a
|
||||
* "sessionsLoaded" message, so the skeleton was stuck forever.
|
||||
* The fix must set sessionsLoaded(true) from the state-application path
|
||||
* when isGitRepo === false.
|
||||
* The fix must set sessionsLoaded(true) when receiving a state message
|
||||
* with isGitRepo === false.
|
||||
*/
|
||||
it("sets sessionsLoaded when agentManager.state arrives with isGitRepo false", () => {
|
||||
const start = tsx.indexOf("const applyState =")
|
||||
expect(start, "applyState helper must exist").toBeGreaterThan(-1)
|
||||
// Find the agentManager.state handler block
|
||||
const start = tsx.indexOf('"agentManager.state"')
|
||||
expect(start, "agentManager.state handler must exist").toBeGreaterThan(-1)
|
||||
const snippet = tsx.slice(start, start + 800)
|
||||
expect(snippet, "must call setSessionsLoaded in the non-git branch").toContain("setSessionsLoaded")
|
||||
expect(snippet, "must check isGitRepo === false before setting sessionsLoaded").toMatch(
|
||||
|
||||
@@ -0,0 +1,397 @@
|
||||
import { describe, it, expect } from "bun:test"
|
||||
import {
|
||||
buildExport,
|
||||
parseImport,
|
||||
mergeConfig,
|
||||
MAX_IMPORT_SIZE,
|
||||
KNOWN_KEYS,
|
||||
META_VERSION,
|
||||
} from "../../webview-ui/src/components/settings/settings-io"
|
||||
import type { Config } from "../../webview-ui/src/types/messages"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// buildExport
|
||||
// ---------------------------------------------------------------------------
|
||||
describe("buildExport", () => {
|
||||
it("wraps config in _meta envelope", () => {
|
||||
const cfg: Config = { model: "anthropic/claude-sonnet-4-20250514" }
|
||||
const result = buildExport(cfg)
|
||||
expect(result._meta).toBeDefined()
|
||||
expect(result._meta.version).toBe(META_VERSION)
|
||||
expect(typeof result._meta.exportedAt).toBe("string")
|
||||
expect(result.model).toBe("anthropic/claude-sonnet-4-20250514")
|
||||
})
|
||||
|
||||
it("preserves provider fields including secrets", () => {
|
||||
const cfg: Config = {
|
||||
provider: {
|
||||
openai: { name: "OpenAI", api_key: "sk-secret-123" },
|
||||
custom: { name: "Custom", options: { apiKey: "secret", baseURL: "https://example.com" } },
|
||||
},
|
||||
}
|
||||
const result = buildExport(cfg)
|
||||
expect(result.provider.openai.api_key).toBe("sk-secret-123")
|
||||
expect(result.provider.openai.name).toBe("OpenAI")
|
||||
expect(result.provider.custom.options.apiKey).toBe("secret")
|
||||
expect(result.provider.custom.options.baseURL).toBe("https://example.com")
|
||||
})
|
||||
|
||||
it("preserves mcp fields including env and headers", () => {
|
||||
const cfg: Config = {
|
||||
mcp: {
|
||||
github: {
|
||||
type: "local" as const,
|
||||
command: "npx",
|
||||
env: { GITHUB_TOKEN: "ghp_secret123" },
|
||||
enabled: true,
|
||||
},
|
||||
server: {
|
||||
type: "local" as const,
|
||||
command: "node",
|
||||
environment: { SECRET: "val" },
|
||||
},
|
||||
remote: {
|
||||
type: "remote" as const,
|
||||
url: "https://mcp.example.com",
|
||||
headers: { Authorization: "Bearer secret-token" },
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
const result = buildExport(cfg)
|
||||
expect(result.mcp.github.env.GITHUB_TOKEN).toBe("ghp_secret123")
|
||||
expect(result.mcp.github.command).toBe("npx")
|
||||
expect(result.mcp.server.environment.SECRET).toBe("val")
|
||||
expect(result.mcp.remote.headers.Authorization).toBe("Bearer secret-token")
|
||||
expect(result.mcp.remote.url).toBe("https://mcp.example.com")
|
||||
})
|
||||
|
||||
it("preserves all config fields", () => {
|
||||
const cfg: Config = {
|
||||
model: "test-model",
|
||||
small_model: "test-small",
|
||||
default_agent: "coder",
|
||||
agent: { coder: { mode: "primary", prompt: "Code stuff" } },
|
||||
permission: { read: "allow" },
|
||||
instructions: ["rule1.md"],
|
||||
snapshot: true,
|
||||
share: "manual",
|
||||
}
|
||||
const result = buildExport(cfg)
|
||||
expect(result.model).toBe("test-model")
|
||||
expect(result.small_model).toBe("test-small")
|
||||
expect(result.default_agent).toBe("coder")
|
||||
expect(result.agent).toEqual({ coder: { mode: "primary", prompt: "Code stuff" } })
|
||||
expect(result.permission).toEqual({ read: "allow" })
|
||||
expect(result.instructions).toEqual(["rule1.md"])
|
||||
expect(result.snapshot).toBe(true)
|
||||
expect(result.share).toBe("manual")
|
||||
})
|
||||
|
||||
it("handles empty config", () => {
|
||||
const result = buildExport({})
|
||||
expect(result._meta).toBeDefined()
|
||||
expect(Object.keys(result).length).toBe(1) // only _meta
|
||||
})
|
||||
|
||||
it("handles config with no providers or mcp", () => {
|
||||
const cfg: Config = { model: "test" }
|
||||
const result = buildExport(cfg)
|
||||
expect(result.model).toBe("test")
|
||||
expect(result.provider).toBeUndefined()
|
||||
expect(result.mcp).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// parseImport
|
||||
// ---------------------------------------------------------------------------
|
||||
describe("parseImport", () => {
|
||||
it("rejects non-JSON", () => {
|
||||
const result = parseImport("not json at all")
|
||||
expect(result.ok).toBe(false)
|
||||
if (!result.ok) expect(result.error).toBe("invalidJson")
|
||||
})
|
||||
|
||||
it("rejects JSON null", () => {
|
||||
const result = parseImport("null")
|
||||
expect(result.ok).toBe(false)
|
||||
if (!result.ok) expect(result.error).toBe("invalidJson")
|
||||
})
|
||||
|
||||
it("rejects JSON array", () => {
|
||||
const result = parseImport("[]")
|
||||
expect(result.ok).toBe(false)
|
||||
if (!result.ok) expect(result.error).toBe("invalidJson")
|
||||
})
|
||||
|
||||
it("rejects JSON string", () => {
|
||||
const result = parseImport('"hello"')
|
||||
expect(result.ok).toBe(false)
|
||||
if (!result.ok) expect(result.error).toBe("invalidJson")
|
||||
})
|
||||
|
||||
it("rejects JSON number", () => {
|
||||
const result = parseImport("42")
|
||||
expect(result.ok).toBe(false)
|
||||
if (!result.ok) expect(result.error).toBe("invalidJson")
|
||||
})
|
||||
|
||||
it("rejects empty object (no known keys)", () => {
|
||||
const result = parseImport("{}")
|
||||
expect(result.ok).toBe(false)
|
||||
if (!result.ok) expect(result.error).toBe("invalidConfig")
|
||||
})
|
||||
|
||||
it("rejects object with only unknown keys", () => {
|
||||
const result = parseImport(JSON.stringify({ foo: "bar", baz: 42 }))
|
||||
expect(result.ok).toBe(false)
|
||||
if (!result.ok) expect(result.error).toBe("invalidConfig")
|
||||
})
|
||||
|
||||
it("accepts valid partial config (just agent)", () => {
|
||||
const json = JSON.stringify({
|
||||
agent: { coder: { mode: "primary", prompt: "Code things" } },
|
||||
})
|
||||
const result = parseImport(json)
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) {
|
||||
expect(result.config.agent).toEqual({ coder: { mode: "primary", prompt: "Code things" } })
|
||||
}
|
||||
})
|
||||
|
||||
it("accepts valid partial config (just model)", () => {
|
||||
const json = JSON.stringify({ model: "test-model" })
|
||||
const result = parseImport(json)
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) expect(result.config.model).toBe("test-model")
|
||||
})
|
||||
|
||||
it("strips _meta before returning config", () => {
|
||||
const json = JSON.stringify({
|
||||
_meta: { version: 1, exportedAt: "2026-01-01", secretsStripped: true },
|
||||
model: "test",
|
||||
})
|
||||
const result = parseImport(json)
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) {
|
||||
expect((result.config as Record<string, unknown>)._meta).toBeUndefined()
|
||||
expect(result.config.model).toBe("test")
|
||||
}
|
||||
})
|
||||
|
||||
it("strips unknown top-level keys", () => {
|
||||
const json = JSON.stringify({
|
||||
model: "test",
|
||||
unknownField: "should be stripped",
|
||||
anotherUnknown: 42,
|
||||
})
|
||||
const result = parseImport(json)
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) {
|
||||
expect(result.config.model).toBe("test")
|
||||
expect((result.config as Record<string, unknown>).unknownField).toBeUndefined()
|
||||
expect((result.config as Record<string, unknown>).anotherUnknown).toBeUndefined()
|
||||
}
|
||||
})
|
||||
|
||||
it("returns warning when _meta.version > current", () => {
|
||||
const json = JSON.stringify({
|
||||
_meta: { version: 999 },
|
||||
model: "test",
|
||||
})
|
||||
const result = parseImport(json)
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) {
|
||||
expect(result.warning).toBe("newerVersion")
|
||||
}
|
||||
})
|
||||
|
||||
it("returns no warning when _meta.version <= current", () => {
|
||||
const json = JSON.stringify({
|
||||
_meta: { version: META_VERSION },
|
||||
model: "test",
|
||||
})
|
||||
const result = parseImport(json)
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) {
|
||||
expect(result.warning).toBeUndefined()
|
||||
}
|
||||
})
|
||||
|
||||
it("returns no warning when _meta is absent", () => {
|
||||
const json = JSON.stringify({ model: "test" })
|
||||
const result = parseImport(json)
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) {
|
||||
expect(result.warning).toBeUndefined()
|
||||
}
|
||||
})
|
||||
|
||||
it("accepts config with all known keys", () => {
|
||||
const cfg: Record<string, unknown> = {}
|
||||
for (const key of KNOWN_KEYS) {
|
||||
cfg[key] = key === "instructions" ? ["rule.md"] : key === "snapshot" ? true : "value"
|
||||
}
|
||||
const json = JSON.stringify(cfg)
|
||||
const result = parseImport(json)
|
||||
expect(result.ok).toBe(true)
|
||||
})
|
||||
|
||||
it("preserves provider and mcp fields as-is (including secrets on import)", () => {
|
||||
const json = JSON.stringify({
|
||||
provider: { openai: { name: "OpenAI", api_key: "sk-123" } },
|
||||
mcp: { gh: { command: "npx", env: { TOKEN: "secret" } } },
|
||||
})
|
||||
const result = parseImport(json)
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) {
|
||||
expect(result.config.provider?.openai?.api_key).toBe("sk-123")
|
||||
expect(result.config.mcp?.gh?.env?.TOKEN).toBe("secret")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// mergeConfig
|
||||
// ---------------------------------------------------------------------------
|
||||
describe("mergeConfig", () => {
|
||||
it("merges imported agents with existing agents", () => {
|
||||
const existing: Config = {
|
||||
agent: {
|
||||
coder: { mode: "primary", prompt: "Code" },
|
||||
reviewer: { mode: "primary", prompt: "Review" },
|
||||
},
|
||||
}
|
||||
const imported: Config = {
|
||||
agent: {
|
||||
reviewer: { mode: "primary", prompt: "Updated review" },
|
||||
planner: { mode: "primary", prompt: "Plan" },
|
||||
},
|
||||
}
|
||||
const result = mergeConfig(existing, imported)
|
||||
expect(result.agent?.coder?.prompt).toBe("Code")
|
||||
expect(result.agent?.reviewer?.prompt).toBe("Updated review")
|
||||
expect(result.agent?.planner?.prompt).toBe("Plan")
|
||||
})
|
||||
|
||||
it("imported values override existing for same keys", () => {
|
||||
const existing: Config = { model: "old-model", default_agent: "coder" }
|
||||
const imported: Config = { model: "new-model" }
|
||||
const result = mergeConfig(existing, imported)
|
||||
expect(result.model).toBe("new-model")
|
||||
expect(result.default_agent).toBe("coder")
|
||||
})
|
||||
|
||||
it("existing values not in import are preserved", () => {
|
||||
const existing: Config = {
|
||||
model: "test",
|
||||
permission: { read: "allow" },
|
||||
instructions: ["old.md"],
|
||||
}
|
||||
const imported: Config = { model: "updated" }
|
||||
const result = mergeConfig(existing, imported)
|
||||
expect(result.model).toBe("updated")
|
||||
expect(result.permission).toEqual({ read: "allow" })
|
||||
expect(result.instructions).toEqual(["old.md"])
|
||||
})
|
||||
|
||||
it("merges providers without losing existing ones", () => {
|
||||
const existing: Config = {
|
||||
provider: {
|
||||
openai: { name: "OpenAI", api_key: "sk-existing" },
|
||||
anthropic: { name: "Anthropic", api_key: "sk-ant" },
|
||||
},
|
||||
}
|
||||
const imported: Config = {
|
||||
provider: {
|
||||
openai: { name: "OpenAI Updated", base_url: "https://new.api" },
|
||||
},
|
||||
}
|
||||
const result = mergeConfig(existing, imported)
|
||||
expect(result.provider?.openai?.name).toBe("OpenAI Updated")
|
||||
expect(result.provider?.openai?.base_url).toBe("https://new.api")
|
||||
expect(result.provider?.anthropic?.name).toBe("Anthropic")
|
||||
expect(result.provider?.anthropic?.api_key).toBe("sk-ant")
|
||||
})
|
||||
|
||||
it("handles empty existing config", () => {
|
||||
const imported: Config = { model: "test", agent: { coder: { mode: "primary" } } }
|
||||
const result = mergeConfig({}, imported)
|
||||
expect(result.model).toBe("test")
|
||||
expect(result.agent?.coder?.mode).toBe("primary")
|
||||
})
|
||||
|
||||
it("handles empty imported config", () => {
|
||||
const existing: Config = { model: "test" }
|
||||
const result = mergeConfig(existing, {})
|
||||
expect(result.model).toBe("test")
|
||||
})
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Round-trip
|
||||
// ---------------------------------------------------------------------------
|
||||
describe("round-trip", () => {
|
||||
it("export then import preserves all fields including secrets", () => {
|
||||
const original: Config = {
|
||||
model: "test-model",
|
||||
agent: { coder: { mode: "primary", prompt: "Code" } },
|
||||
provider: { openai: { name: "OpenAI", api_key: "sk-secret" } },
|
||||
mcp: { gh: { command: "npx", env: { TOKEN: "secret" } } },
|
||||
permission: { read: "allow" },
|
||||
instructions: ["rules.md"],
|
||||
}
|
||||
const exported = buildExport(original)
|
||||
const json = JSON.stringify(exported)
|
||||
const result = parseImport(json)
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) {
|
||||
expect(result.config.model).toBe("test-model")
|
||||
expect(result.config.agent).toEqual({ coder: { mode: "primary", prompt: "Code" } })
|
||||
expect(result.config.provider?.openai?.name).toBe("OpenAI")
|
||||
expect(result.config.provider?.openai?.api_key).toBe("sk-secret")
|
||||
expect(result.config.mcp?.gh?.command).toBe("npx")
|
||||
expect(result.config.mcp?.gh?.env?.TOKEN).toBe("secret")
|
||||
expect(result.config.permission).toEqual({ read: "allow" })
|
||||
expect(result.config.instructions).toEqual(["rules.md"])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Constants
|
||||
// ---------------------------------------------------------------------------
|
||||
describe("constants", () => {
|
||||
it("MAX_IMPORT_SIZE is 1 MB", () => {
|
||||
expect(MAX_IMPORT_SIZE).toBe(1_048_576)
|
||||
})
|
||||
|
||||
it("META_VERSION is 1", () => {
|
||||
expect(META_VERSION).toBe(1)
|
||||
})
|
||||
|
||||
it("KNOWN_KEYS includes core config keys", () => {
|
||||
expect(KNOWN_KEYS).toContain("agent")
|
||||
expect(KNOWN_KEYS).toContain("provider")
|
||||
expect(KNOWN_KEYS).toContain("mcp")
|
||||
expect(KNOWN_KEYS).toContain("permission")
|
||||
expect(KNOWN_KEYS).toContain("model")
|
||||
expect(KNOWN_KEYS).toContain("instructions")
|
||||
})
|
||||
|
||||
it("KNOWN_KEYS matches all keys in the Config interface (drift guard)", async () => {
|
||||
// Read the Config interface from messages.ts and extract its keys.
|
||||
// If someone adds a new field to Config, this test fails as a reminder
|
||||
// to also add it to KNOWN_KEYS in settings-io.ts.
|
||||
const src = await Bun.file(require("path").join(__dirname, "../../webview-ui/src/types/messages.ts")).text()
|
||||
const match = src.match(/export interface Config \{([^}]+)\}/)
|
||||
expect(match).not.toBeNull()
|
||||
const body = match![1]
|
||||
const keys = [...body.matchAll(/^\s+(\w+)\??:/gm)].map((m) => m[1])
|
||||
expect(keys.length).toBeGreaterThan(0)
|
||||
|
||||
const sorted = (arr: readonly string[]) => [...arr].sort()
|
||||
expect(sorted(KNOWN_KEYS)).toEqual(sorted(keys))
|
||||
})
|
||||
})
|
||||
@@ -74,7 +74,7 @@ import { ProviderProvider } from "../src/context/provider"
|
||||
import { ConfigProvider } from "../src/context/config"
|
||||
import { NotificationsProvider } from "../src/context/notifications"
|
||||
import { SessionProvider, useSession } from "../src/context/session"
|
||||
import { WorktreeModeProvider, useWorktreeMode } from "../src/context/worktree-mode"
|
||||
import { WorktreeModeProvider } from "../src/context/worktree-mode"
|
||||
import { ChatView } from "../src/components/chat"
|
||||
import { NewWorktreeDialog } from "./NewWorktreeDialog"
|
||||
import { LanguageBridge, DataBridge } from "../src/App"
|
||||
@@ -312,44 +312,6 @@ const AgentManagerContent: Component = () => {
|
||||
const repoDefaultBranch = () => defaultBaseBranch() ?? repoDetectedBranch() ?? "main"
|
||||
const hasConfiguredBranch = () => !!defaultBaseBranch()
|
||||
|
||||
const applyState = (state: AgentManagerStateMessage) => {
|
||||
setWorktrees(state.worktrees)
|
||||
setManagedSessions(state.sessions)
|
||||
setStaleWorktreeIds(new Set(state.staleWorktreeIds ?? []))
|
||||
if (state.isGitRepo !== undefined) setIsGitRepo(state.isGitRepo)
|
||||
if (!worktreesLoaded()) setWorktreesLoaded(true)
|
||||
if (state.isGitRepo === false && !sessionsLoaded()) setSessionsLoaded(true)
|
||||
if (state.tabOrder) setWorktreeTabOrder(state.tabOrder)
|
||||
if (state.worktreeOrder) setSidebarWorktreeOrder(state.worktreeOrder)
|
||||
if (state.reviewDiffStyle === "split" || state.reviewDiffStyle === "unified") {
|
||||
setReviewDiffStyle(state.reviewDiffStyle)
|
||||
}
|
||||
if ("defaultBaseBranch" in state) setDefaultBaseBranch(state.defaultBaseBranch || undefined)
|
||||
const current = session.currentSessionID()
|
||||
if (current) {
|
||||
const ms = state.sessions.find((s) => s.id === current)
|
||||
if (ms?.worktreeId) setSelection(ms.worktreeId)
|
||||
}
|
||||
const localOrder = state.tabOrder?.[LOCAL]
|
||||
if (localOrder && localSessionIDs().length > 0) {
|
||||
const reordered = applyTabOrder(
|
||||
localSessionIDs().map((id) => ({ id })),
|
||||
localOrder,
|
||||
).map((item) => item.id)
|
||||
setLocalSessionIDs(reordered)
|
||||
}
|
||||
if (state.sessionsCollapsed !== undefined) setSessionsCollapsed(state.sessionsCollapsed)
|
||||
const ids = new Set(state.worktrees.map((wt) => wt.id))
|
||||
setBusyWorktrees((prev) => {
|
||||
const next = new Map([...prev].filter(([id]) => ids.has(id)))
|
||||
return next.size === prev.size ? prev : next
|
||||
})
|
||||
}
|
||||
|
||||
const requestState = () => {
|
||||
vscode.postMessage({ type: "agentManager.requestState" })
|
||||
}
|
||||
|
||||
const DEFAULT_SIDEBAR_WIDTH = 260
|
||||
const MIN_SIDEBAR_WIDTH = 200
|
||||
const MAX_SIDEBAR_WIDTH_RATIO = 0.4
|
||||
@@ -397,10 +359,6 @@ const AgentManagerContent: Component = () => {
|
||||
const PENDING_PREFIX = "pending:"
|
||||
const [activePendingId, setActivePendingId] = createSignal<string | undefined>()
|
||||
|
||||
// Sync activePendingId into WorktreeMode context so PromptInput can key drafts per pending tab
|
||||
const worktreeCtx = useWorktreeMode()
|
||||
createEffect(() => worktreeCtx?.setPendingId(activePendingId()))
|
||||
|
||||
// Inline delete confirmation: tracks which worktree is awaiting a second click/press
|
||||
const [pendingDelete, setPendingDelete] = createSignal<string | null>(null)
|
||||
let pendingDeleteTimer: ReturnType<typeof setTimeout> | undefined
|
||||
@@ -1039,41 +997,6 @@ const AgentManagerContent: Component = () => {
|
||||
if (agent) session.selectAgent(agent.name)
|
||||
}
|
||||
|
||||
// Subscribe outside onMount so early sessionsLoaded messages (posted before
|
||||
// the component mounts) are not missed. This matches the codebase pattern for
|
||||
// loaded-message listeners and prevents the loading skeleton from persisting
|
||||
// after a backend crash/restart + panel reopen.
|
||||
const unsubState = vscode.onMessage((msg) => {
|
||||
if (msg.type !== "agentManager.state") return
|
||||
applyState(msg as AgentManagerStateMessage)
|
||||
})
|
||||
onCleanup(unsubState)
|
||||
|
||||
const unsubSessions = vscode.onMessage((msg) => {
|
||||
if (msg.type !== "sessionsLoaded") return
|
||||
if (!sessionsLoaded()) setSessionsLoaded(true)
|
||||
})
|
||||
onCleanup(unsubSessions)
|
||||
|
||||
// Retry state requests while the panel is bootstrapping so reopening after a
|
||||
// backend restart cannot get stuck behind a missed requestState/refresh race.
|
||||
const retryMs = 500
|
||||
const maxRetries = 10
|
||||
let retries = 0
|
||||
const retry = setInterval(() => {
|
||||
if (worktreesLoaded() && sessionsLoaded()) {
|
||||
clearInterval(retry)
|
||||
return
|
||||
}
|
||||
retries++
|
||||
if (retries >= maxRetries) {
|
||||
clearInterval(retry)
|
||||
return
|
||||
}
|
||||
requestState()
|
||||
}, retryMs)
|
||||
onCleanup(() => clearInterval(retry))
|
||||
|
||||
onMount(() => {
|
||||
const handler = (event: MessageEvent) => {
|
||||
const msg = event.data as ExtensionMessage
|
||||
@@ -1177,6 +1100,11 @@ const AgentManagerContent: Component = () => {
|
||||
}
|
||||
})
|
||||
|
||||
// Mark sessions loaded as soon as the session context receives data (even if empty)
|
||||
const unsubSessions = vscode.onMessage((msg) => {
|
||||
if (msg.type === "sessionsLoaded" && !sessionsLoaded()) setSessionsLoaded(true)
|
||||
})
|
||||
|
||||
const unsub = vscode.onMessage((msg) => {
|
||||
if (msg.type === "agentManager.repoInfo") {
|
||||
const info = msg as AgentManagerRepoInfoMessage
|
||||
@@ -1250,6 +1178,46 @@ const AgentManagerContent: Component = () => {
|
||||
setKb(ev.bindings)
|
||||
}
|
||||
|
||||
if (msg.type === "agentManager.state") {
|
||||
const state = msg as AgentManagerStateMessage
|
||||
setWorktrees(state.worktrees)
|
||||
setManagedSessions(state.sessions)
|
||||
setStaleWorktreeIds(new Set(state.staleWorktreeIds ?? []))
|
||||
if (state.isGitRepo !== undefined) setIsGitRepo(state.isGitRepo)
|
||||
if (!worktreesLoaded()) setWorktreesLoaded(true)
|
||||
// When not a git repo, also mark sessions as loaded since the Kilo
|
||||
// server won't connect to send the sessionsLoaded message.
|
||||
if (state.isGitRepo === false && !sessionsLoaded()) setSessionsLoaded(true)
|
||||
if (state.tabOrder) setWorktreeTabOrder(state.tabOrder)
|
||||
if (state.worktreeOrder) setSidebarWorktreeOrder(state.worktreeOrder)
|
||||
if (state.reviewDiffStyle === "split" || state.reviewDiffStyle === "unified") {
|
||||
setReviewDiffStyle(state.reviewDiffStyle)
|
||||
}
|
||||
if ("defaultBaseBranch" in state) setDefaultBaseBranch(state.defaultBaseBranch || undefined)
|
||||
const current = session.currentSessionID()
|
||||
if (current) {
|
||||
const ms = state.sessions.find((s) => s.id === current)
|
||||
if (ms?.worktreeId) setSelection(ms.worktreeId)
|
||||
}
|
||||
// Recover local tab order from persisted state
|
||||
const localOrder = state.tabOrder?.[LOCAL]
|
||||
if (localOrder && localSessionIDs().length > 0) {
|
||||
const reordered = applyTabOrder(
|
||||
localSessionIDs().map((id) => ({ id })),
|
||||
localOrder,
|
||||
).map((item) => item.id)
|
||||
setLocalSessionIDs(reordered)
|
||||
}
|
||||
// Recover sessions collapsed state from extension-persisted state
|
||||
if (state.sessionsCollapsed !== undefined) setSessionsCollapsed(state.sessionsCollapsed)
|
||||
// Clear busy state for worktrees that have been removed
|
||||
const ids = new Set(state.worktrees.map((wt) => wt.id))
|
||||
setBusyWorktrees((prev) => {
|
||||
const next = new Map([...prev].filter(([id]) => ids.has(id)))
|
||||
return next.size === prev.size ? prev : next
|
||||
})
|
||||
}
|
||||
|
||||
// When a multi-version progress update arrives, mark newly created worktrees as loading
|
||||
if ((msg as { type: string }).type === "agentManager.multiVersionProgress") {
|
||||
const ev = msg as unknown as AgentManagerMultiVersionProgressMessage
|
||||
@@ -1417,6 +1385,7 @@ const AgentManagerContent: Component = () => {
|
||||
window.removeEventListener("keydown", deleteKeyHandler)
|
||||
window.removeEventListener("focus", onWindowFocus)
|
||||
unsubCreate()
|
||||
unsubSessions()
|
||||
unsub()
|
||||
})
|
||||
})
|
||||
@@ -1426,7 +1395,7 @@ const AgentManagerContent: Component = () => {
|
||||
selectLocal()
|
||||
// Request worktree/session state from extension — handles race where
|
||||
// initializeState() pushState fires before the webview is mounted
|
||||
requestState()
|
||||
vscode.postMessage({ type: "agentManager.requestState" })
|
||||
// Open a pending "New Session" tab if there are no persisted local sessions
|
||||
if (localSessionIDs().length === 0) {
|
||||
addPendingTab()
|
||||
|
||||
@@ -78,7 +78,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
||||
})
|
||||
const history = usePromptHistory()
|
||||
|
||||
const sessionKey = () => session.currentSessionID() ?? worktree?.pendingId() ?? "__new__"
|
||||
const sessionKey = () => session.currentSessionID() ?? "__new__"
|
||||
|
||||
const [text, setText] = createSignal("")
|
||||
const [reviewComments, setReviewComments] = createSignal<ReviewComment[]>([])
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { Component } from "solid-js"
|
||||
import { Component, createSignal, onCleanup } from "solid-js"
|
||||
import { Button } from "@kilocode/kilo-ui/button"
|
||||
import { Icon } from "@kilocode/kilo-ui/icon"
|
||||
import { showToast } from "@kilocode/kilo-ui/toast"
|
||||
import { useLanguage } from "../../context/language"
|
||||
import { useVSCode } from "../../context/vscode"
|
||||
import type { ConnectionState } from "../../types/messages"
|
||||
import { useConfig } from "../../context/config"
|
||||
import type { ConnectionState, ExtensionMessage } from "../../types/messages"
|
||||
import { buildExport, parseImport, MAX_IMPORT_SIZE } from "./settings-io"
|
||||
|
||||
export interface AboutKiloCodeTabProps {
|
||||
port: number | null
|
||||
@@ -13,11 +18,96 @@ export interface AboutKiloCodeTabProps {
|
||||
const AboutKiloCodeTab: Component<AboutKiloCodeTabProps> = (props) => {
|
||||
const language = useLanguage()
|
||||
const vscode = useVSCode()
|
||||
const { updateConfig } = useConfig()
|
||||
const [importing, setImporting] = createSignal(false)
|
||||
const [exporting, setExporting] = createSignal(false)
|
||||
let epoch = 0
|
||||
|
||||
const open = (url: string) => {
|
||||
vscode.postMessage({ type: "openExternal", url })
|
||||
}
|
||||
|
||||
// Listen for globalConfigLoaded response
|
||||
const handler = (event: MessageEvent) => {
|
||||
const msg = event.data as ExtensionMessage
|
||||
if (msg.type !== "globalConfigLoaded" || !exporting()) return
|
||||
setExporting(false)
|
||||
epoch++
|
||||
const payload = buildExport(msg.config)
|
||||
const json = JSON.stringify(payload, null, 2)
|
||||
const blob = new Blob([json], { type: "application/json" })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement("a")
|
||||
a.href = url
|
||||
a.download = "kilo-settings.json"
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
window.addEventListener("message", handler)
|
||||
onCleanup(() => window.removeEventListener("message", handler))
|
||||
|
||||
// ----- Export -----
|
||||
const handleExport = () => {
|
||||
if (exporting()) return
|
||||
setExporting(true)
|
||||
const token = ++epoch
|
||||
vscode.postMessage({ type: "requestGlobalConfig" })
|
||||
setTimeout(() => {
|
||||
if (epoch === token) setExporting(false)
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
// ----- Import -----
|
||||
const handleImport = () => {
|
||||
if (importing()) return
|
||||
const input = document.createElement("input")
|
||||
input.type = "file"
|
||||
input.accept = ".json"
|
||||
input.style.display = "none"
|
||||
input.addEventListener("change", () => {
|
||||
const file = input.files?.[0]
|
||||
if (!file) return
|
||||
if (file.size > MAX_IMPORT_SIZE) {
|
||||
showToast({ variant: "error", title: language.t("settings.aboutKiloCode.importSettings.tooLarge") })
|
||||
return
|
||||
}
|
||||
setImporting(true)
|
||||
const reader = new FileReader()
|
||||
reader.onload = () => {
|
||||
setImporting(false)
|
||||
const text = reader.result as string
|
||||
const result = parseImport(text)
|
||||
if (!result.ok) {
|
||||
const key =
|
||||
result.error === "invalidJson"
|
||||
? "settings.aboutKiloCode.importSettings.invalidJson"
|
||||
: "settings.aboutKiloCode.importSettings.invalidConfig"
|
||||
showToast({ variant: "error", title: language.t(key) })
|
||||
return
|
||||
}
|
||||
if (result.warning === "newerVersion") {
|
||||
showToast({
|
||||
variant: "default",
|
||||
title: language.t("settings.aboutKiloCode.importSettings.newerVersion"),
|
||||
})
|
||||
}
|
||||
updateConfig(result.config)
|
||||
showToast({
|
||||
variant: "success",
|
||||
title: language.t("settings.aboutKiloCode.importSettings.success"),
|
||||
})
|
||||
}
|
||||
reader.onerror = () => {
|
||||
setImporting(false)
|
||||
showToast({ variant: "error", title: language.t("settings.aboutKiloCode.importSettings.invalidJson") })
|
||||
}
|
||||
reader.readAsText(file)
|
||||
})
|
||||
document.body.appendChild(input)
|
||||
input.click()
|
||||
document.body.removeChild(input)
|
||||
}
|
||||
|
||||
const getStatusColor = () => {
|
||||
switch (props.connectionState) {
|
||||
case "connected":
|
||||
@@ -158,6 +248,31 @@ const AboutKiloCodeTab: Component<AboutKiloCodeTabProps> = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Settings Transfer */}
|
||||
<div style={sectionStyle}>
|
||||
<h4 style={headingStyle}>{language.t("settings.aboutKiloCode.settingsTransfer.title")}</h4>
|
||||
<p
|
||||
style={{
|
||||
"font-size": "12px",
|
||||
color: "var(--vscode-descriptionForeground)",
|
||||
margin: "0 0 12px 0",
|
||||
"line-height": "1.5",
|
||||
}}
|
||||
>
|
||||
{language.t("settings.aboutKiloCode.settingsTransfer.description")}
|
||||
</p>
|
||||
<div style={{ display: "flex", gap: "8px" }}>
|
||||
<Button variant="secondary" size="small" onClick={handleExport}>
|
||||
<Icon name="cloud-upload" />
|
||||
{language.t("settings.aboutKiloCode.exportSettings")}
|
||||
</Button>
|
||||
<Button variant="secondary" size="small" onClick={handleImport} disabled={importing()}>
|
||||
<Icon name="download" />
|
||||
{language.t("settings.aboutKiloCode.importSettings")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* legacy-migration start */}
|
||||
<div style={{ ...sectionStyle, "margin-bottom": "0" }}>
|
||||
<h4 style={headingStyle}>{language.t("settings.aboutKiloCode.legacyMigration.title")}</h4>
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
import type { Config } from "../../types/messages"
|
||||
import { deepMerge } from "../../utils/config-utils"
|
||||
|
||||
/** Maximum import file size in bytes (1 MB). */
|
||||
export const MAX_IMPORT_SIZE = 1_048_576
|
||||
|
||||
/** Current export format version. */
|
||||
export const META_VERSION = 1
|
||||
|
||||
/** Top-level keys recognised as valid Config fields. */
|
||||
export const KNOWN_KEYS: ReadonlyArray<string> = [
|
||||
"permission",
|
||||
"model",
|
||||
"small_model",
|
||||
"default_agent",
|
||||
"agent",
|
||||
"provider",
|
||||
"disabled_providers",
|
||||
"enabled_providers",
|
||||
"mcp",
|
||||
"command",
|
||||
"instructions",
|
||||
"skills",
|
||||
"snapshot",
|
||||
"share",
|
||||
"username",
|
||||
"watcher",
|
||||
"formatter",
|
||||
"lsp",
|
||||
"compaction",
|
||||
"tools",
|
||||
"layout",
|
||||
"experimental",
|
||||
]
|
||||
|
||||
export type ImportError = "invalidJson" | "invalidConfig" | "tooLarge"
|
||||
export type ImportWarning = "newerVersion"
|
||||
|
||||
export type ImportResult = { ok: true; config: Config; warning?: ImportWarning } | { ok: false; error: ImportError }
|
||||
|
||||
interface ExportMeta {
|
||||
version: number
|
||||
exportedAt: string
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Export
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Build a JSON-serialisable export payload from the current config.
|
||||
* All fields are included as-is so the export is a complete snapshot
|
||||
* that can be imported on another instance without re-entering secrets.
|
||||
*/
|
||||
export function buildExport(cfg: Config): Record<string, unknown> {
|
||||
const meta: ExportMeta = {
|
||||
version: META_VERSION,
|
||||
exportedAt: new Date().toISOString(),
|
||||
}
|
||||
|
||||
const out: Record<string, unknown> = { _meta: meta }
|
||||
|
||||
for (const [key, value] of Object.entries(cfg)) {
|
||||
if (value === undefined || value === null) continue
|
||||
out[key] = value
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Import
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parse a raw JSON string into a validated Config.
|
||||
* Unknown keys and `_meta` are stripped. Returns an error tag on failure
|
||||
* or a warning when the file was exported from a newer version.
|
||||
*/
|
||||
export function parseImport(json: string): ImportResult {
|
||||
let data: unknown
|
||||
try {
|
||||
data = JSON.parse(json)
|
||||
} catch {
|
||||
return { ok: false, error: "invalidJson" }
|
||||
}
|
||||
|
||||
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
||||
return { ok: false, error: "invalidJson" }
|
||||
}
|
||||
|
||||
const obj = data as Record<string, unknown>
|
||||
|
||||
// Check for newer version warning
|
||||
let warning: ImportWarning | undefined
|
||||
const meta = obj._meta
|
||||
if (typeof meta === "object" && meta !== null && !Array.isArray(meta)) {
|
||||
const version = (meta as Record<string, unknown>).version
|
||||
if (typeof version === "number" && version > META_VERSION) {
|
||||
warning = "newerVersion"
|
||||
}
|
||||
}
|
||||
|
||||
// Keep only known config keys
|
||||
const config: Record<string, unknown> = {}
|
||||
for (const key of KNOWN_KEYS) {
|
||||
if (key in obj && obj[key] !== undefined) {
|
||||
config[key] = obj[key]
|
||||
}
|
||||
}
|
||||
|
||||
// Must have at least one known key
|
||||
if (Object.keys(config).length === 0) {
|
||||
return { ok: false, error: "invalidConfig" }
|
||||
}
|
||||
|
||||
return warning ? { ok: true, config: config as Config, warning } : { ok: true, config: config as Config }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Merge
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Deep-merge imported config on top of existing config.
|
||||
* Imported values take precedence; existing values not in import are preserved.
|
||||
*/
|
||||
export function mergeConfig(existing: Config, imported: Config): Config {
|
||||
return deepMerge(existing, imported)
|
||||
}
|
||||
@@ -14,22 +14,14 @@ export type SessionMode = "local" | "worktree"
|
||||
interface WorktreeModeContextValue {
|
||||
mode: Accessor<SessionMode>
|
||||
setMode: (mode: SessionMode) => void
|
||||
/** Active pending tab ID (e.g. "pending:1") — set by Agent Manager so PromptInput can key drafts per tab. */
|
||||
pendingId: Accessor<string | undefined>
|
||||
setPendingId: (id: string | undefined) => void
|
||||
}
|
||||
|
||||
const WorktreeModeContext = createContext<WorktreeModeContextValue>()
|
||||
|
||||
export const WorktreeModeProvider: ParentComponent = (props) => {
|
||||
const [mode, setMode] = createSignal<SessionMode>("local")
|
||||
const [pendingId, setPendingId] = createSignal<string | undefined>()
|
||||
|
||||
return (
|
||||
<WorktreeModeContext.Provider value={{ mode, setMode, pendingId, setPendingId }}>
|
||||
{props.children}
|
||||
</WorktreeModeContext.Provider>
|
||||
)
|
||||
return <WorktreeModeContext.Provider value={{ mode, setMode }}>{props.children}</WorktreeModeContext.Provider>
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -968,6 +968,16 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"إعادة تعيين جميع إعدادات إضافة Kilo Code إلى قيمها الافتراضية. لا يؤثر هذا على تكوين CLI أو الواجهة الخلفية.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "إعادة تعيين جميع الإعدادات",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "نقل الإعدادات",
|
||||
"settings.aboutKiloCode.settingsTransfer.description": "تصدير أو استيراد إعداداتك لنقلها بين نُسخ VS Code.",
|
||||
"settings.aboutKiloCode.exportSettings": "تصدير",
|
||||
"settings.aboutKiloCode.importSettings": "استيراد",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "ملف JSON غير صالح. يرجى اختيار ملف إعدادات صالح.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "الملف لا يحتوي على إعدادات Kilo صالحة.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "الملف كبير جدًا. يجب أن تكون ملفات الإعدادات أقل من 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"تم تصدير هذا الملف من إصدار أحدث من Kilo. قد يتم تجاهل بعض الإعدادات.",
|
||||
"settings.aboutKiloCode.importSettings.success": "تم استيراد الإعدادات. راجع التغييرات أعلاه، ثم انقر على حفظ.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "الأوضاع",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -977,6 +977,20 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Redefinir todas as configurações da extensão Kilo Code para os valores padrão. Isso não afeta a configuração do CLI ou do backend.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Redefinir Todas as Configurações",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Transferência de configurações",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Exporte ou importe suas configurações para transferi-las entre instâncias do VS Code.",
|
||||
"settings.aboutKiloCode.exportSettings": "Exportar",
|
||||
"settings.aboutKiloCode.importSettings": "Importar",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson":
|
||||
"Arquivo JSON inválido. Selecione um arquivo de configurações válido.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "O arquivo não contém configurações válidas do Kilo.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge":
|
||||
"O arquivo é muito grande. Arquivos de configurações devem ter menos de 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Este arquivo foi exportado de uma versão mais recente do Kilo. Algumas configurações podem ser ignoradas.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Configurações importadas. Revise as alterações acima e clique em Salvar.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modos",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -981,6 +981,18 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Resetujte sve postavke Kilo Code ekstenzije na zadane vrijednosti. Ovo ne utiče na CLI ili backend konfiguraciju.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Resetuj sve postavke",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Prijenos postavki",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Izvezite ili uvezite postavke za prijenos između VS Code instanci.",
|
||||
"settings.aboutKiloCode.exportSettings": "Izvezi",
|
||||
"settings.aboutKiloCode.importSettings": "Uvezi",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "Nevažeći JSON fajl. Odaberite važeći fajl s postavkama.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "Fajl ne sadrži važeće Kilo postavke.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "Fajl je prevelik. Fajlovi s postavkama moraju biti manji od 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Ovaj fajl je izvezen iz novije verzije Kilo-a. Neke postavke mogu biti zanemarene.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Postavke su uvezene. Pregledajte promjene iznad, a zatim kliknite Sačuvaj.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modovi",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -975,6 +975,18 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Nulstil alle Kilo Code-udvidelsesindstillinger til standardværdierne. Dette påvirker ikke CLI- eller backend-konfiguration.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Nulstil alle indstillinger",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Overførsel af indstillinger",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Eksportér eller importér dine indstillinger for at overføre dem mellem VS Code-instanser.",
|
||||
"settings.aboutKiloCode.exportSettings": "Eksportér",
|
||||
"settings.aboutKiloCode.importSettings": "Importér",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "Ugyldig JSON-fil. Vælg venligst en gyldig indstillingsfil.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "Filen indeholder ikke gyldige Kilo-indstillinger.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "Filen er for stor. Indstillingsfiler skal være under 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Denne fil blev eksporteret fra en nyere version af Kilo. Nogle indstillinger kan blive ignoreret.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Indstillinger importeret. Gennemgå ændringerne ovenfor, og klik derefter på Gem.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Tilstande",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -988,6 +988,20 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Alle Kilo Code-Erweiterungseinstellungen auf Standardwerte zurücksetzen. Dies hat keinen Einfluss auf die CLI- oder Backend-Konfiguration.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Alle Einstellungen zurücksetzen",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Einstellungen übertragen",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Exportieren oder importieren Sie Ihre Einstellungen, um sie zwischen VS Code-Instanzen zu übertragen.",
|
||||
"settings.aboutKiloCode.exportSettings": "Exportieren",
|
||||
"settings.aboutKiloCode.importSettings": "Importieren",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson":
|
||||
"Ungültige JSON-Datei. Bitte wählen Sie eine gültige Einstellungsdatei aus.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "Die Datei enthält keine gültigen Kilo-Einstellungen.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge":
|
||||
"Die Datei ist zu groß. Einstellungsdateien müssen kleiner als 1 MB sein.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Diese Datei wurde mit einer neueren Version von Kilo exportiert. Einige Einstellungen werden möglicherweise ignoriert.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Einstellungen importiert. Überprüfen Sie die obigen Änderungen und klicken Sie dann auf Speichern.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modi",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -974,6 +974,17 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Reset all Kilo Code extension settings to their default values. This does not affect CLI or backend configuration.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Reset All Settings",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Settings Transfer",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Export or import your settings to transfer them between VS Code instances.",
|
||||
"settings.aboutKiloCode.exportSettings": "Export",
|
||||
"settings.aboutKiloCode.importSettings": "Import",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "Invalid JSON file. Please select a valid settings file.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "File does not contain valid Kilo settings.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "File is too large. Settings files must be under 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"This file was exported from a newer version of Kilo. Some settings may be ignored.",
|
||||
"settings.aboutKiloCode.importSettings.success": "Settings imported. Review the changes above, then click Save.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modes",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -982,6 +982,20 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Restablecer todas las configuraciones de la extensión Kilo Code a sus valores predeterminados. Esto no afecta la configuración del CLI o del backend.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Restablecer toda la configuración",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Transferencia de ajustes",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Exporta o importa tus ajustes para transferirlos entre instancias de VS Code.",
|
||||
"settings.aboutKiloCode.exportSettings": "Exportar",
|
||||
"settings.aboutKiloCode.importSettings": "Importar",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson":
|
||||
"Archivo JSON no válido. Seleccione un archivo de ajustes válido.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "El archivo no contiene ajustes válidos de Kilo.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge":
|
||||
"El archivo es demasiado grande. Los archivos de ajustes deben ser menores de 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Este archivo fue exportado desde una versión más reciente de Kilo. Algunos ajustes podrían ignorarse.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Ajustes importados. Revise los cambios anteriores y luego haga clic en Guardar.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modos",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -990,6 +990,20 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Réinitialiser tous les paramètres de l'extension Kilo Code à leurs valeurs par défaut. Cela n'affecte pas la configuration CLI ou backend.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Réinitialiser tous les paramètres",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Transfert des paramètres",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Exportez ou importez vos paramètres pour les transférer entre instances VS Code.",
|
||||
"settings.aboutKiloCode.exportSettings": "Exporter",
|
||||
"settings.aboutKiloCode.importSettings": "Importer",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson":
|
||||
"Fichier JSON invalide. Veuillez sélectionner un fichier de paramètres valide.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "Le fichier ne contient pas de paramètres Kilo valides.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge":
|
||||
"Le fichier est trop volumineux. Les fichiers de paramètres doivent faire moins de 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Ce fichier a été exporté depuis une version plus récente de Kilo. Certains paramètres pourraient être ignorés.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Paramètres importés. Vérifiez les modifications ci-dessus, puis cliquez sur Enregistrer.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modes",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -974,6 +974,19 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Kilo Code拡張機能のすべての設定をデフォルト値にリセットします。CLIやバックエンドの設定には影響しません。",
|
||||
"settings.aboutKiloCode.resetSettings.button": "すべての設定をリセット",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "設定の移行",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"VS Code インスタンス間で設定を転送するには、エクスポートまたはインポートしてください。",
|
||||
"settings.aboutKiloCode.exportSettings": "エクスポート",
|
||||
"settings.aboutKiloCode.importSettings": "インポート",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson":
|
||||
"無効な JSON ファイルです。有効な設定ファイルを選択してください。",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "ファイルに有効な Kilo の設定が含まれていません。",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "ファイルが大きすぎます。設定ファイルは 1 MB 以下にしてください。",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"このファイルはより新しいバージョンの Kilo からエクスポートされたものです。一部の設定が無視される場合があります。",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"設定をインポートしました。上記の変更内容を確認してから、保存をクリックしてください。",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "モード",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -973,6 +973,18 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Kilo Code 확장 프로그램의 모든 설정을 기본값으로 초기화합니다. CLI 또는 백엔드 구성에는 영향을 미치지 않습니다.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "모든 설정 초기화",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "설정 이전",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"VS Code 인스턴스 간에 설정을 전송하려면 내보내기 또는 가져오기하세요.",
|
||||
"settings.aboutKiloCode.exportSettings": "내보내기",
|
||||
"settings.aboutKiloCode.importSettings": "가져오기",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson":
|
||||
"유효하지 않은 JSON 파일입니다. 올바른 설정 파일을 선택해 주세요.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "파일에 유효한 Kilo 설정이 포함되어 있지 않습니다.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "파일이 너무 큽니다. 설정 파일은 1 MB 이하여야 합니다.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"이 파일은 더 최신 버전의 Kilo에서 내보낸 것입니다. 일부 설정이 무시될 수 있습니다.",
|
||||
"settings.aboutKiloCode.importSettings.success": "설정을 가져왔습니다. 위의 변경 사항을 확인한 후 저장을 클릭하세요.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "모드",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -975,6 +975,20 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Reset alle instellingen van de Kilo Code extensie naar hun standaardwaarden. Dit heeft geen invloed op CLI of backend configuratie.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Alle instellingen resetten",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Instellingen overdragen",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Exporteer of importeer uw instellingen om ze tussen VS Code-instanties over te dragen.",
|
||||
"settings.aboutKiloCode.exportSettings": "Exporteren",
|
||||
"settings.aboutKiloCode.importSettings": "Importeren",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson":
|
||||
"Ongeldig JSON-bestand. Selecteer een geldig instellingenbestand.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "Het bestand bevat geen geldige Kilo-instellingen.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge":
|
||||
"Het bestand is te groot. Instellingenbestanden moeten kleiner zijn dan 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Dit bestand is geëxporteerd vanuit een nieuwere versie van Kilo. Sommige instellingen worden mogelijk genegeerd.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Instellingen geïmporteerd. Controleer de bovenstaande wijzigingen en klik vervolgens op Opslaan.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modi",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -978,6 +978,18 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Tilbakestill alle Kilo Code-utvidelsesinnstillinger til standardverdier. Dette påvirker ikke CLI- eller backend-konfigurasjon.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Tilbakestill alle innstillinger",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Overføring av innstillinger",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Eksporter eller importer innstillingene dine for å overføre dem mellom VS Code-instanser.",
|
||||
"settings.aboutKiloCode.exportSettings": "Eksporter",
|
||||
"settings.aboutKiloCode.importSettings": "Importer",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "Ugyldig JSON-fil. Vennligst velg en gyldig innstillingsfil.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "Filen inneholder ikke gyldige Kilo-innstillinger.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "Filen er for stor. Innstillingsfiler må være under 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Denne filen ble eksportert fra en nyere versjon av Kilo. Noen innstillinger kan bli ignorert.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Innstillinger importert. Gjennomgå endringene ovenfor, og klikk deretter på Lagre.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Moduser",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -979,6 +979,18 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Zresetuj wszystkie ustawienia rozszerzenia Kilo Code do wartości domyślnych. Nie wpływa to na konfigurację CLI ani backendu.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Resetuj wszystkie ustawienia",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Przenoszenie ustawień",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Eksportuj lub importuj ustawienia, aby przenosić je między instancjami VS Code.",
|
||||
"settings.aboutKiloCode.exportSettings": "Eksportuj",
|
||||
"settings.aboutKiloCode.importSettings": "Importuj",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "Nieprawidłowy plik JSON. Wybierz prawidłowy plik ustawień.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "Plik nie zawiera prawidłowych ustawień Kilo.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "Plik jest za duży. Pliki ustawień muszą mieć mniej niż 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Ten plik został wyeksportowany z nowszej wersji Kilo. Niektóre ustawienia mogą zostać zignorowane.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Ustawienia zaimportowane. Przejrzyj powyższe zmiany, a następnie kliknij Zapisz.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Tryby",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -981,6 +981,18 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Сбросить все настройки расширения Kilo Code до значений по умолчанию. Это не влияет на конфигурацию CLI или бэкенда.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Сбросить все настройки",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Перенос настроек",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Экспортируйте или импортируйте настройки для переноса между экземплярами VS Code.",
|
||||
"settings.aboutKiloCode.exportSettings": "Экспорт",
|
||||
"settings.aboutKiloCode.importSettings": "Импорт",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "Недопустимый файл JSON. Выберите корректный файл настроек.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "Файл не содержит допустимых настроек Kilo.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "Файл слишком большой. Файлы настроек должны быть менее 1 MB.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Этот файл был экспортирован из более новой версии Kilo. Некоторые настройки могут быть проигнорированы.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Настройки импортированы. Просмотрите изменения выше и нажмите «Сохранить».",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Режимы",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -969,6 +969,17 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"รีเซ็ตการตั้งค่าส่วนขยาย Kilo Code ทั้งหมดเป็นค่าเริ่มต้น ไม่ส่งผลกระทบต่อการกำหนดค่า CLI หรือแบ็กเอนด์",
|
||||
"settings.aboutKiloCode.resetSettings.button": "รีเซ็ตการตั้งค่าทั้งหมด",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "ถ่ายโอนการตั้งค่า",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"ส่งออกหรือนำเข้าการตั้งค่าเพื่อถ่ายโอนระหว่างอินสแตนซ์ VS Code",
|
||||
"settings.aboutKiloCode.exportSettings": "ส่งออก",
|
||||
"settings.aboutKiloCode.importSettings": "นำเข้า",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "ไฟล์ JSON ไม่ถูกต้อง กรุณาเลือกไฟล์การตั้งค่าที่ถูกต้อง",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "ไฟล์ไม่มีการตั้งค่า Kilo ที่ถูกต้อง",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "ไฟล์มีขนาดใหญ่เกินไป ไฟล์การตั้งค่าต้องมีขนาดไม่เกิน 1 MB",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"ไฟล์นี้ถูกส่งออกจาก Kilo เวอร์ชันใหม่กว่า การตั้งค่าบางรายการอาจถูกข้ามไป",
|
||||
"settings.aboutKiloCode.importSettings.success": "นำเข้าการตั้งค่าแล้ว ตรวจสอบการเปลี่ยนแปลงด้านบน จากนั้นคลิกบันทึก",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "โหมด",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -978,6 +978,18 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"Tüm Kilo Code uzantı ayarlarını varsayılan değerlerine sıfırla. Bu, CLI veya arka uç yapılandırmasını etkilemez.",
|
||||
"settings.aboutKiloCode.resetSettings.button": "Tüm Ayarları Sıfırla",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "Ayar Aktarımı",
|
||||
"settings.aboutKiloCode.settingsTransfer.description":
|
||||
"Ayarlarınızı VS Code örnekleri arasında aktarmak için dışa veya içe aktarın.",
|
||||
"settings.aboutKiloCode.exportSettings": "Dışa Aktar",
|
||||
"settings.aboutKiloCode.importSettings": "İçe Aktar",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "Geçersiz JSON dosyası. Lütfen geçerli bir ayar dosyası seçin.",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "Dosya geçerli Kilo ayarları içermiyor.",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "Dosya çok büyük. Ayar dosyaları 1 MB altında olmalıdır.",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion":
|
||||
"Bu dosya Kilo'nun daha yeni bir sürümünden dışa aktarılmış. Bazı ayarlar göz ardı edilebilir.",
|
||||
"settings.aboutKiloCode.importSettings.success":
|
||||
"Ayarlar içe aktarıldı. Yukarıdaki değişiklikleri gözden geçirin, ardından Kaydet'e tıklayın.",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "Modlar",
|
||||
"settings.agentBehaviour.subtab.agents": "Ajanlar",
|
||||
|
||||
@@ -961,6 +961,15 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"将所有 Kilo Code 扩展设置重置为默认值。这不会影响 CLI 或后端配置。",
|
||||
"settings.aboutKiloCode.resetSettings.button": "重置所有设置",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "设置迁移",
|
||||
"settings.aboutKiloCode.settingsTransfer.description": "导出或导入设置,以便在 VS Code 实例之间传输。",
|
||||
"settings.aboutKiloCode.exportSettings": "导出",
|
||||
"settings.aboutKiloCode.importSettings": "导入",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "无效的 JSON 文件。请选择有效的设置文件。",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "文件不包含有效的 Kilo 设置。",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "文件过大。设置文件必须小于 1 MB。",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion": "此文件由较新版本的 Kilo 导出。部分设置可能会被忽略。",
|
||||
"settings.aboutKiloCode.importSettings.success": "设置已导入。请查看上方的更改,然后点击保存。",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "模式",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -963,6 +963,15 @@ export const dict = {
|
||||
"settings.aboutKiloCode.resetSettings.description":
|
||||
"將所有 Kilo Code 擴充功能設定重置為預設值。這不會影響 CLI 或後端設定。",
|
||||
"settings.aboutKiloCode.resetSettings.button": "重置所有設定",
|
||||
"settings.aboutKiloCode.settingsTransfer.title": "設定轉移",
|
||||
"settings.aboutKiloCode.settingsTransfer.description": "匯出或匯入設定,以便在 VS Code 實例之間轉移。",
|
||||
"settings.aboutKiloCode.exportSettings": "匯出",
|
||||
"settings.aboutKiloCode.importSettings": "匯入",
|
||||
"settings.aboutKiloCode.importSettings.invalidJson": "無效的 JSON 檔案。請選擇有效的設定檔。",
|
||||
"settings.aboutKiloCode.importSettings.invalidConfig": "檔案不包含有效的 Kilo 設定。",
|
||||
"settings.aboutKiloCode.importSettings.tooLarge": "檔案過大。設定檔必須小於 1 MB。",
|
||||
"settings.aboutKiloCode.importSettings.newerVersion": "此檔案由較新版本的 Kilo 匯出。部分設定可能會被忽略。",
|
||||
"settings.aboutKiloCode.importSettings.success": "設定已匯入。請檢視上方的變更,然後點擊儲存。",
|
||||
|
||||
"settings.agentBehaviour.subtab.modes": "模式",
|
||||
"settings.agentBehaviour.subtab.agents": "Agents",
|
||||
|
||||
@@ -722,6 +722,11 @@ export interface ConfigUpdatedMessage {
|
||||
config: Config
|
||||
}
|
||||
|
||||
export interface GlobalConfigLoadedMessage {
|
||||
type: "globalConfigLoaded"
|
||||
config: Config
|
||||
}
|
||||
|
||||
export interface NotificationSettingsLoadedMessage {
|
||||
type: "notificationSettingsLoaded"
|
||||
settings: {
|
||||
@@ -1260,6 +1265,7 @@ export type ExtensionMessage =
|
||||
| BrowserSettingsLoadedMessage
|
||||
| ConfigLoadedMessage
|
||||
| ConfigUpdatedMessage
|
||||
| GlobalConfigLoadedMessage
|
||||
| NotificationSettingsLoadedMessage
|
||||
| NotificationsLoadedMessage
|
||||
| AgentManagerSessionMetaMessage
|
||||
@@ -1568,6 +1574,10 @@ export interface RequestConfigMessage {
|
||||
type: "requestConfig"
|
||||
}
|
||||
|
||||
export interface RequestGlobalConfigMessage {
|
||||
type: "requestGlobalConfig"
|
||||
}
|
||||
|
||||
export interface UpdateConfigMessage {
|
||||
type: "updateConfig"
|
||||
config: Partial<Config>
|
||||
@@ -1998,6 +2008,7 @@ export type WebviewMessage =
|
||||
| UpdateSettingRequest
|
||||
| RequestBrowserSettingsMessage
|
||||
| RequestConfigMessage
|
||||
| RequestGlobalConfigMessage
|
||||
| UpdateConfigMessage
|
||||
| RequestNotificationSettingsMessage
|
||||
| ResetAllSettingsRequest
|
||||
|
||||
Reference in New Issue
Block a user