diff --git a/.changeset/hitl-onboarding-preferences.md b/.changeset/hitl-onboarding-preferences.md new file mode 100644 index 00000000000..087650bde8a --- /dev/null +++ b/.changeset/hitl-onboarding-preferences.md @@ -0,0 +1,5 @@ +--- +"kilo-code": minor +--- + +Support choosing an agent autonomy preset during VS Code onboarding. diff --git a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/agent-behaviour-workflows-empty-chromium-linux.png b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/agent-behaviour-workflows-empty-chromium-linux.png index d9796b01032..e588cecbdd7 100644 --- a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/agent-behaviour-workflows-empty-chromium-linux.png +++ b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/agent-behaviour-workflows-empty-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b70543ee69296913543f8de0f1b1d4787fb6be8a9e410423073b0a84a6da6305 -size 21290 +oid sha256:fe0ed476823eb03bc50fec4e9cdb656552aab3b07ee6ed3c30265ed41f0bfda0 +size 21344 diff --git a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/work-style-onboarding-200-chromium-linux.png b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/work-style-onboarding-200-chromium-linux.png new file mode 100644 index 00000000000..ade4c0398da --- /dev/null +++ b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/work-style-onboarding-200-chromium-linux.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:001db2cec148c97a321076e45ec4478beced1bd18f0f4347927419d7194d6a43 +size 31986 diff --git a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/work-style-onboarding-default-chromium-linux.png b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/work-style-onboarding-default-chromium-linux.png new file mode 100644 index 00000000000..2597a60c84d --- /dev/null +++ b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/work-style-onboarding-default-chromium-linux.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3f86dabc39700b3a86508c1e6499a546eeabf720832b62c9ce12f2d97378ebd +size 34649 diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 8627c3cb179..4d62a50689a 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -989,6 +989,24 @@ "default": true, "description": "Show the task timeline graph in the chat header" }, + "kilo-code.new.agentWorkStyle": { + "type": "string", + "scope": "application", + "default": "unset", + "enum": [ + "unset", + "human-in-the-loop", + "autonomous", + "skipped" + ], + "enumDescriptions": [ + "Show work style onboarding so you can choose again", + "Human in the Loop: review agent actions as they happen", + "High autonomy: let Kilo take most actions with fewer interruptions", + "Onboarding was skipped without changing work style settings" + ], + "description": "Preferred agent work style. Set to Unset to show the onboarding flow again." + }, "kilo-code.new.diff.renderMarkdown": { "type": "boolean", "default": false, diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index b332128d12c..a9e8d675a89 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -30,7 +30,6 @@ import { sessionPatchToWebview, indexProvidersById, filterVisibleAgents, - buildSettingPath, mapSSEEventToWebviewMessage, getErrorMessage, getConfigErrorDetails, @@ -44,6 +43,7 @@ import { resolveWorkspaceDirectory, sameDirectory, SessionStreamScheduler, + buildSettingPath, type SessionRefreshContext, } from "./kilo-provider-utils" import { GitOps } from "./agent-manager/GitOps" @@ -81,6 +81,12 @@ import { routeEarlyMessage } from "./kilo-provider/early-message" import * as ModelState from "./kilo-provider/model-state" import { handleForkSession } from "./kilo-provider/fork-session" import { openConfig } from "./kilo-provider/open-config" +import { + getWorkStylePayload, + handleWorkStyleMessage, + isWorkStyleSetting, + watchWorkStyleConfig, +} from "./kilo-provider/work-style" import * as McpOAuth from "./kilo-provider/mcp-oauth" import { retryable, backoff, MAX_RETRIES } from "./util/retry" import { hasGit } from "./kilo-provider/git-status" @@ -737,6 +743,15 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper return } if (this.handleEditorOpenMessage(message)) return + if ( + await handleWorkStyleMessage({ + message, + connection: this.connectionService, + directory: this.getWorkspaceDirectory(this.currentSession?.id), + post: (msg) => this.postMessage(msg), + }) + ) + return if ( await handleSidebarWorktreeMessage(message, { post: (msg) => this.postMessage(msg), @@ -1200,6 +1215,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper } }) this.webviewMessageDisposable = watchFontSizeConfig((msg) => this.postMessage(msg), this.webviewMessageDisposable) + this.webviewMessageDisposable = watchWorkStyleConfig((msg) => this.postMessage(msg), this.webviewMessageDisposable) } private handleEditorOpenMessage(message: Parameters[0]): boolean { @@ -2326,6 +2342,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper }) } + private sendWorkStyle(): void { + this.postMessage(getWorkStylePayload()) + } + /** Returns the number of sessions currently in "busy" state. */ private getBusySessionCount(): number { return getBusySessionCount(this.sessionStatusMap) @@ -2884,6 +2904,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper // lets the runtime fall back to the resolved default. const next = value === null ? undefined : value await config.update(leaf, next, vscode.ConfigurationTarget.Global) + if (isWorkStyleSetting(key)) this.sendWorkStyle() } /** @@ -2926,6 +2947,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.sendBrowserSettings() this.sendNotificationSettings() this.sendTimelineSetting() + this.sendWorkStyle() await ModelState.reset(this.client, (msg) => this.postMessage(msg)) // Re-send globalState items to the webview diff --git a/packages/kilo-vscode/src/kilo-provider/work-style-apply-handler.ts b/packages/kilo-vscode/src/kilo-provider/work-style-apply-handler.ts new file mode 100644 index 00000000000..a8c6611eeeb --- /dev/null +++ b/packages/kilo-vscode/src/kilo-provider/work-style-apply-handler.ts @@ -0,0 +1,59 @@ +import * as vscode from "vscode" +import type { Config } from "@kilocode/sdk/v2/client" +import type { KiloConnectionService } from "../services/cli-backend/connection-service" +import type { WorkStyle, WorkStyleConfig, WorkStyleState } from "../shared/work-style-presets" +import { applyWorkStyle, type WorkStyleSettingSnapshot } from "./work-style-apply" + +function inspect(config: vscode.WorkspaceConfiguration, key: string): WorkStyleSettingSnapshot { + const info = config.inspect(key) + return { + global: info?.globalValue, + customized: + info?.globalValue !== undefined || info?.workspaceValue !== undefined || info?.workspaceFolderValue !== undefined, + } +} + +async function apply(connection: KiloConnectionService, directory: string, style: WorkStyle) { + const settings = vscode.workspace.getConfiguration("kilo-code.new") + return applyWorkStyle(style, { + read: async () => { + const client = await connection.getClientAsync(directory) + const { data } = await client.config.get({ directory }, { throwOnError: true }) + return (data ?? {}) as WorkStyleConfig + }, + inspect: (key) => inspect(settings, key), + write: async (key, value) => { + await settings.update(key, value, vscode.ConfigurationTarget.Global) + }, + patch: async (config) => { + const client = await connection.getClientAsync(directory) + await client.global.config.update({ config: config as Config }, { throwOnError: true }) + }, + }) +} + +export async function handleWorkStyleApplyMessage(input: { + message: { type?: string; style?: WorkStyleState } + connection: KiloConnectionService + directory: string + post: (message: unknown) => void +}): Promise { + if (input.message.type !== "applyWorkStyle") return false + if (input.message.style !== "human-in-the-loop" && input.message.style !== "autonomous") { + console.error("[Kilo New] Invalid style in applyWorkStyle message") + input.post({ type: "workStyleApplyFailed", message: "Invalid work style", rollbackFailed: false }) + return true + } + + const result = await apply(input.connection, input.directory, input.message.style) + input.post( + result.ok + ? { type: "workStyleApplied", style: input.message.style } + : { + type: "workStyleApplyFailed", + message: result.error, + rollbackFailed: result.rollback.length > 0, + }, + ) + return true +} diff --git a/packages/kilo-vscode/src/kilo-provider/work-style-apply.ts b/packages/kilo-vscode/src/kilo-provider/work-style-apply.ts new file mode 100644 index 00000000000..52b40f29c38 --- /dev/null +++ b/packages/kilo-vscode/src/kilo-provider/work-style-apply.ts @@ -0,0 +1,63 @@ +import { + buildWorkStyleApplyPlan, + type WorkStyle, + type WorkStyleConfig, + type WorkStyleSettings, +} from "../shared/work-style-presets" + +type Setting = keyof WorkStyleSettings | "agentWorkStyle" + +export interface WorkStyleSettingSnapshot { + customized: boolean + global: unknown +} + +export interface WorkStyleStore { + read: () => Promise + inspect: (key: Setting) => WorkStyleSettingSnapshot + write: (key: Setting, value: unknown) => Promise + patch: (config: WorkStyleConfig) => Promise +} + +type WorkStyleApplyResult = + | { ok: true } + | { + ok: false + error: string + rollback: Setting[] + } + +function message(err: unknown): string { + if (err instanceof Error) return err.message + return String(err) +} + +export async function applyWorkStyle(style: WorkStyle, store: WorkStyleStore): Promise { + const completed: Array<{ key: Setting; value: unknown }> = [] + + try { + const config = await store.read() + const plan = buildWorkStyleApplyPlan({ + style, + config, + settingDefault: (key) => !store.inspect(key).customized, + }) + const writes: Array<{ key: Setting; value: unknown }> = [ + ...Object.entries(plan.settings).map(([key, value]) => ({ key: key as keyof WorkStyleSettings, value })), + { key: "agentWorkStyle", value: style }, + ] + + for (const write of writes) { + completed.push({ key: write.key, value: store.inspect(write.key).global }) + await store.write(write.key, write.value) + } + if (Object.keys(plan.config).length > 0) await store.patch(plan.config) + return { ok: true } + } catch (err) { + const rollback: Setting[] = [] + for (const write of [...completed].reverse()) { + await store.write(write.key, write.value).catch(() => rollback.push(write.key)) + } + return { ok: false, error: message(err), rollback } + } +} diff --git a/packages/kilo-vscode/src/kilo-provider/work-style.ts b/packages/kilo-vscode/src/kilo-provider/work-style.ts new file mode 100644 index 00000000000..36edccb4782 --- /dev/null +++ b/packages/kilo-vscode/src/kilo-provider/work-style.ts @@ -0,0 +1,87 @@ +import * as vscode from "vscode" +import type { KiloConnectionService } from "../services/cli-backend/connection-service" +import { getInitialWorkStyle, type WorkStyleState } from "../shared/work-style-presets" +import { handleWorkStyleApplyMessage } from "./work-style-apply-handler" + +export const WORK_STYLE_SETTING_KEYS = ["showTaskTimeline"] as const + +function getConfig() { + return vscode.workspace.getConfiguration("kilo-code.new") +} + +function isWorkStyleConfigured(): boolean { + return getConfig().inspect("agentWorkStyle")?.globalValue !== undefined +} + +export function getWorkStylePayload() { + return { + type: "workStyleLoaded" as const, + style: getConfig().get("agentWorkStyle", "unset"), + } +} + +export function isWorkStyleSetting(key: string): boolean { + return WORK_STYLE_SETTING_KEYS.includes(key as (typeof WORK_STYLE_SETTING_KEYS)[number]) || key === "agentWorkStyle" +} + +export function watchWorkStyleConfig(post: (message: unknown) => void, next?: vscode.Disposable) { + const keys = ["agentWorkStyle", ...WORK_STYLE_SETTING_KEYS] + const watcher = vscode.workspace.onDidChangeConfiguration((event) => { + if (keys.some((key) => event.affectsConfiguration(`kilo-code.new.${key}`))) post(getWorkStylePayload()) + }) + return next ? vscode.Disposable.from(watcher, next) : watcher +} + +export async function setWorkStyle(style: WorkStyleState) { + await getConfig().update("agentWorkStyle", style, vscode.ConfigurationTarget.Global) +} + +async function hasAnySession(connection: KiloConnectionService, directory: string): Promise { + const client = await connection.getClientAsync(directory) + const { data } = await client.experimental.session.list( + { + roots: true, + limit: 1, + archived: true, + }, + { throwOnError: true }, + ) + return data.length > 0 +} + +async function initializeWorkStyle(connection: KiloConnectionService, directory: string): Promise { + if (isWorkStyleConfigured()) return + + const hasSessions = await hasAnySession(connection, directory) + + if (isWorkStyleConfigured()) return + await setWorkStyle(getInitialWorkStyle(hasSessions)) +} + +export async function handleWorkStyleMessage(input: { + message: { type?: string; style?: WorkStyleState } + connection: KiloConnectionService + directory: string + post: (message: unknown) => void +}): Promise { + if (input.message.type === "requestWorkStyle") { + const initialized = await initializeWorkStyle(input.connection, input.directory) + .then(() => true) + .catch((err: unknown) => { + console.error("[Kilo New] Failed to initialize work style:", err) + return false + }) + const payload = getWorkStylePayload() + input.post(initialized ? payload : { ...payload, style: "skipped" }) + return true + } + if (await handleWorkStyleApplyMessage(input)) return true + if (input.message.type !== "setWorkStyle") return false + if (!input.message.style) { + console.error("[Kilo New] Missing style in setWorkStyle message") + return true + } + await setWorkStyle(input.message.style) + input.post(getWorkStylePayload()) + return true +} diff --git a/packages/kilo-vscode/src/services/telemetry/types.ts b/packages/kilo-vscode/src/services/telemetry/types.ts index 5993151d037..928170b19a4 100644 --- a/packages/kilo-vscode/src/services/telemetry/types.ts +++ b/packages/kilo-vscode/src/services/telemetry/types.ts @@ -29,6 +29,8 @@ export enum TelemetryEventName { // UI Interactions TAB_SHOWN = "Tab Shown", TITLE_BUTTON_CLICKED = "Title Button Clicked", + WORK_STYLE_ONBOARDING_SHOWN = "Work Style Onboarding Shown", + WORK_STYLE_SELECTED = "Work Style Selected", PROMPT_ENHANCED = "Prompt Enhanced", // Marketplace diff --git a/packages/kilo-vscode/src/shared/work-style-presets.ts b/packages/kilo-vscode/src/shared/work-style-presets.ts new file mode 100644 index 00000000000..4bcfecc6748 --- /dev/null +++ b/packages/kilo-vscode/src/shared/work-style-presets.ts @@ -0,0 +1,160 @@ +type PermissionLevel = "allow" | "ask" | "deny" +type PermissionRule = PermissionLevel | null | Record +type PermissionConfig = Partial> + +export interface WorkStyleConfig { + permission?: PermissionConfig + terminal_command_display?: "expanded" | "collapsed" + auto_collapse_reasoning?: boolean +} + +export type WorkStyle = "human-in-the-loop" | "autonomous" +export type WorkStyleState = WorkStyle | "skipped" | "unset" + +export interface WorkStyleSettings { + showTaskTimeline: boolean +} + +export interface WorkStylePreset { + style: WorkStyle + config: WorkStyleConfig + settings: WorkStyleSettings +} + +export interface WorkStyleApplyPlan { + config: WorkStyleConfig + settings: Partial +} + +const BASH: Record = { + "*": "ask", + "cat *": "allow", + "head *": "allow", + "tail *": "allow", + "less *": "allow", + "ls *": "allow", + "tree *": "allow", + "pwd *": "allow", + "echo *": "allow", + "wc *": "allow", + "which *": "allow", + "type *": "allow", + "file *": "allow", + "diff *": "allow", + "du *": "allow", + "df *": "allow", + "date *": "allow", + "uname *": "allow", + "whoami *": "allow", + "printenv *": "allow", + "man *": "allow", + "grep *": "allow", + "rg *": "allow", + "ag *": "allow", + "uniq *": "allow", + "cut *": "allow", + "tr *": "allow", + "jq *": "allow", + "*>*": "ask", +} + +export const WORK_STYLE_CHOICES: WorkStyle[] = ["human-in-the-loop", "autonomous"] + +export const WORK_STYLE_PRESETS: Record = { + "human-in-the-loop": { + style: "human-in-the-loop", + config: { + terminal_command_display: "expanded", + auto_collapse_reasoning: false, + permission: { + "*": "ask", + read: { + "*": "allow", + "*.env": "ask", + "*.env.*": "ask", + "*.env.example": "allow", + }, + grep: "allow", + glob: "allow", + list: "allow", + question: "allow", + webfetch: "allow", + websearch: "allow", + codesearch: "allow", + external_directory: "ask", + edit: "ask", + bash: BASH, + doom_loop: "ask", + }, + }, + settings: { + showTaskTimeline: true, + }, + }, + autonomous: { + style: "autonomous", + config: { + terminal_command_display: "collapsed", + auto_collapse_reasoning: true, + }, + settings: { + showTaskTimeline: false, + }, + }, +} + +export function getWorkStylePreset(style: WorkStyle): WorkStylePreset { + return WORK_STYLE_PRESETS[style] +} + +export function getInitialWorkStyle(hasSessions: boolean): WorkStyleState { + return hasSessions ? "skipped" : "unset" +} + +export function hasPermissionConfig(config: WorkStyleConfig): boolean { + return Object.keys(config.permission ?? {}).length > 0 +} + +function stripPermission(config: PermissionConfig): PermissionConfig { + const result: PermissionConfig = {} + for (const [key, rule] of Object.entries(config)) { + if (rule === null || rule === undefined) continue + if (typeof rule === "string") { + result[key] = rule + continue + } + const next: Record = {} + for (const [pattern, action] of Object.entries(rule)) { + if (action !== null && action !== undefined) next[pattern] = action + } + if (Object.keys(next).length > 0) result[key] = next as PermissionRule + } + return result +} + +export function buildWorkStyleApplyPlan(input: { + style: WorkStyle + config: WorkStyleConfig + settingDefault?: (key: keyof WorkStyleSettings) => boolean +}): WorkStyleApplyPlan { + const preset = getWorkStylePreset(input.style) + const next: WorkStyleConfig = {} + + if (preset.config.permission && !hasPermissionConfig(input.config)) { + next.permission = stripPermission(preset.config.permission) + } + if (input.config.terminal_command_display === undefined) { + next.terminal_command_display = preset.config.terminal_command_display + } + if (input.config.auto_collapse_reasoning === undefined) { + next.auto_collapse_reasoning = preset.config.auto_collapse_reasoning + } + + const settingDefault = input.settingDefault ?? (() => true) + return { + config: next, + settings: { + ...(settingDefault("showTaskTimeline") ? { showTaskTimeline: preset.settings.showTaskTimeline } : {}), + }, + } +} diff --git a/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts index a0c196bfc09..d45c3873e2e 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts @@ -784,6 +784,8 @@ describe("Agent Manager — provider chain parity with sidebar", () => { // which the agent manager already includes in its provider chain. "LanguageProvider", "DataProvider", + // Work-style onboarding is injected only into the sidebar empty state. + "WorkStyleProvider", ] it("agent manager includes all context providers from sidebar App.tsx", () => { diff --git a/packages/kilo-vscode/tests/unit/work-style-apply.test.ts b/packages/kilo-vscode/tests/unit/work-style-apply.test.ts new file mode 100644 index 00000000000..2822494cc3a --- /dev/null +++ b/packages/kilo-vscode/tests/unit/work-style-apply.test.ts @@ -0,0 +1,97 @@ +import { describe, expect, it } from "bun:test" +import { applyWorkStyle, type WorkStyleStore } from "../../src/kilo-provider/work-style-apply" +import type { WorkStyleConfig } from "../../src/shared/work-style-presets" + +function setup(input?: { + config?: WorkStyleConfig + customized?: boolean + failPatch?: boolean + failWrite?: (key: string, value: unknown) => boolean +}) { + const settings = new Map([["agentWorkStyle", "unset"]]) + const events: string[] = [] + const store: WorkStyleStore = { + read: async () => input?.config ?? {}, + inspect: (key) => ({ + customized: key === "showTaskTimeline" && (input?.customized ?? false), + global: settings.get(key), + }), + write: async (key, value) => { + events.push(`write:${key}:${String(value)}`) + settings.set(key, value) + if (input?.failWrite?.(key, value)) throw new Error(`Failed to write ${key}`) + }, + patch: async (config) => { + events.push(`patch:${Object.keys(config).sort().join(",")}`) + if (input?.failPatch) throw new Error("Failed to patch config") + }, + } + return { store, settings, events } +} + +describe("applyWorkStyle", () => { + it("applies extension settings before the CLI config in one operation", async () => { + const state = setup() + + const result = await applyWorkStyle("human-in-the-loop", state.store) + + expect(result).toEqual({ ok: true }) + expect(state.settings.get("showTaskTimeline")).toBe(true) + expect(state.settings.get("agentWorkStyle")).toBe("human-in-the-loop") + expect(state.events).toEqual([ + "write:showTaskTimeline:true", + "write:agentWorkStyle:human-in-the-loop", + "patch:auto_collapse_reasoning,permission,terminal_command_display", + ]) + }) + + it("rolls extension settings back when the CLI config update fails", async () => { + const state = setup({ failPatch: true }) + + const result = await applyWorkStyle("autonomous", state.store) + + expect(result).toEqual({ ok: false, error: "Failed to patch config", rollback: [] }) + expect(state.settings.get("showTaskTimeline")).toBeUndefined() + expect(state.settings.get("agentWorkStyle")).toBe("unset") + expect(state.events).toEqual([ + "write:showTaskTimeline:false", + "write:agentWorkStyle:autonomous", + "patch:auto_collapse_reasoning,terminal_command_display", + "write:agentWorkStyle:unset", + "write:showTaskTimeline:undefined", + ]) + }) + + it("rolls back earlier writes when persisting the style fails", async () => { + const state = setup({ failWrite: (key, value) => key === "agentWorkStyle" && value === "human-in-the-loop" }) + + const result = await applyWorkStyle("human-in-the-loop", state.store) + + expect(result).toEqual({ ok: false, error: "Failed to write agentWorkStyle", rollback: [] }) + expect(state.settings.get("showTaskTimeline")).toBeUndefined() + expect(state.settings.get("agentWorkStyle")).toBe("unset") + expect(state.events).not.toContain("patch:auto_collapse_reasoning,permission,terminal_command_display") + }) + + it("continues rollback and reports settings that could not be restored", async () => { + const state = setup({ + failPatch: true, + failWrite: (key, value) => key === "agentWorkStyle" && value === "unset", + }) + + const result = await applyWorkStyle("human-in-the-loop", state.store) + + expect(result).toEqual({ ok: false, error: "Failed to patch config", rollback: ["agentWorkStyle"] }) + expect(state.settings.get("showTaskTimeline")).toBeUndefined() + }) + + it("preserves customized extension settings", async () => { + const state = setup({ customized: true }) + + const result = await applyWorkStyle("autonomous", state.store) + + expect(result).toEqual({ ok: true }) + expect(state.events[0]).toBe("write:agentWorkStyle:autonomous") + expect(state.events.some((event) => event.startsWith("write:showTaskTimeline"))).toBe(false) + }) +}) diff --git a/packages/kilo-vscode/tests/unit/work-style-presets.test.ts b/packages/kilo-vscode/tests/unit/work-style-presets.test.ts new file mode 100644 index 00000000000..f34df1f9edd --- /dev/null +++ b/packages/kilo-vscode/tests/unit/work-style-presets.test.ts @@ -0,0 +1,61 @@ +import { describe, expect, it } from "bun:test" +import { buildWorkStyleApplyPlan, getInitialWorkStyle, WORK_STYLE_PRESETS } from "../../src/shared/work-style-presets" + +describe("work style presets", () => { + it("shows onboarding for users without sessions", () => { + expect(getInitialWorkStyle(false)).toBe("unset") + }) + + it("skips onboarding for users with existing sessions", () => { + expect(getInitialWorkStyle(true)).toBe("skipped") + }) + + it("uses ask-first permissions for human in the loop", () => { + const cfg = WORK_STYLE_PRESETS["human-in-the-loop"].config + const bash = cfg.permission?.bash as Record + expect(cfg.terminal_command_display).toBe("expanded") + expect(cfg.auto_collapse_reasoning).toBe(false) + expect(cfg.permission?.["*"]).toBe("ask") + expect(cfg.permission?.edit).toBe("ask") + expect(bash).toMatchObject({ "*": "ask", "rg *": "allow", "*>*": "ask" }) + expect(Object.keys(bash).at(-1)).toBe("*>*") + for (const command of [ + "touch *", + "mkdir *", + "cp *", + "mv *", + "sort *", + "tsc *", + "tsgo *", + "tar *", + "unzip *", + "gzip *", + "gunzip *", + ]) { + expect(command in bash).toBe(false) + } + expect("git diff *" in bash).toBe(false) + expect(WORK_STYLE_PRESETS["human-in-the-loop"].settings).toEqual({ + showTaskTimeline: true, + }) + }) + + it("does not loosen permissions for high autonomy", () => { + const cfg = WORK_STYLE_PRESETS.autonomous.config + expect(cfg.terminal_command_display).toBe("collapsed") + expect(cfg.auto_collapse_reasoning).toBe(true) + expect(cfg.permission).toBeUndefined() + expect(WORK_STYLE_PRESETS.autonomous.settings).toEqual({ + showTaskTimeline: false, + }) + }) + + it("does not overwrite existing new-user settings", () => { + const plan = buildWorkStyleApplyPlan({ + style: "human-in-the-loop", + config: { permission: { edit: "allow" }, terminal_command_display: "collapsed", auto_collapse_reasoning: true }, + settingDefault: () => false, + }) + expect(plan).toEqual({ config: {}, settings: {} }) + }) +}) diff --git a/packages/kilo-vscode/tests/unit/work-style-state.test.ts b/packages/kilo-vscode/tests/unit/work-style-state.test.ts new file mode 100644 index 00000000000..57e10040fef --- /dev/null +++ b/packages/kilo-vscode/tests/unit/work-style-state.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from "bun:test" +import { resolveWorkStyleOnboarding } from "../../webview-ui/src/context/work-style-state" + +describe("work style onboarding state", () => { + it("shows onboarding while the work style is unset", () => { + expect(resolveWorkStyleOnboarding(false, "unset")).toBe(true) + }) + + it("does not show onboarding when skipped was already persisted", () => { + expect(resolveWorkStyleOnboarding(false, "skipped")).toBe(false) + }) + + it("hides onboarding after a work style is selected", () => { + expect(resolveWorkStyleOnboarding(true, "human-in-the-loop")).toBe(false) + expect(resolveWorkStyleOnboarding(true, "autonomous")).toBe(false) + }) +}) diff --git a/packages/kilo-vscode/webview-ui/src/App.tsx b/packages/kilo-vscode/webview-ui/src/App.tsx index e2a3c40bac9..fea5116d915 100644 --- a/packages/kilo-vscode/webview-ui/src/App.tsx +++ b/packages/kilo-vscode/webview-ui/src/App.tsx @@ -17,10 +17,12 @@ import { ServerProvider, useServer } from "./context/server" import { ProviderProvider, useProvider } from "./context/provider" import { ConfigProvider } from "./context/config" import { DisplayProvider } from "./context/display" +import { WorkStyleProvider } from "./context/work-style" import { IndexingProvider } from "./context/indexing" import { SessionProvider, useSession } from "./context/session" import { LanguageBridge } from "./context/language-bridge" import { ChatView } from "./components/chat" +import { SidebarEmptyState } from "./components/chat/SidebarEmptyState" import { registerExpandedTaskTool } from "./components/chat/TaskToolExpanded" import { registerVscodeToolOverrides } from "./components/chat/VscodeToolOverrides" @@ -287,6 +289,10 @@ const AppContent: Component = () => { vscode.postMessage({ type: "forkSession", sessionId, messageId }) } + const emptyState = () => ( + setCurrentView("history")} /> + ) + return (
{/* legacy-migration start — state-driven overlay, independent of currentView */} @@ -299,6 +305,7 @@ const AppContent: Component = () => { continueInWorktree onForkMessage={session.status() === "idle" ? handleForkMessage : undefined} promptBoxId="sidebar:fallback" + emptyState={emptyState} /> } > @@ -309,6 +316,7 @@ const AppContent: Component = () => { onForkMessage={session.status() === "idle" ? handleForkMessage : undefined} continueInWorktree promptBoxId="sidebar:new-task" + emptyState={emptyState} /> @@ -360,19 +368,21 @@ const App: Component = () => { - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/ChatView.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/ChatView.tsx index a0d09a9a629..f721e33de46 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/ChatView.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/ChatView.tsx @@ -5,7 +5,7 @@ * Main chat container that combines all chat components */ -import { type Component, Show, createEffect, createMemo, createSignal, onCleanup, onMount } from "solid-js" +import { type Component, type JSX, Show, createEffect, createMemo, createSignal, onCleanup, onMount } from "solid-js" import { Button } from "@kilocode/kilo-ui/button" import { Icon } from "@kilocode/kilo-ui/icon" import { Spinner } from "@kilocode/kilo-ui/spinner" @@ -34,6 +34,7 @@ interface ChatViewProps { continueInWorktree?: boolean promptBoxId?: string pendingSessionID?: string + emptyState?: () => JSX.Element } export const ChatView: Component = (props) => { @@ -330,6 +331,7 @@ export const ChatView: Component = (props) => { questions={standaloneQuestions} suggestions={standaloneSuggestions} readonly={props.readonly} + emptyState={props.emptyState} />
diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx index fcdcb17c94a..f3406c86754 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx @@ -9,17 +9,14 @@ * Shows recent sessions in the empty state for quick resumption. */ -import { type Component, For, Show, createEffect, createMemo, createSignal, on, onCleanup, JSX } from "solid-js" +import { type Component, type JSX, For, Show, createEffect, createMemo, createSignal, on, onCleanup } from "solid-js" import { Icon } from "@kilocode/kilo-ui/icon" import { Spinner } from "@kilocode/kilo-ui/spinner" -import { useDialog } from "@kilocode/kilo-ui/context/dialog" import { createAutoScroll } from "@kilocode/kilo-ui/hooks" import { useSession } from "../../context/session" import { useServer } from "../../context/server" import { useLanguage } from "../../context/language" -import { recentSessions } from "../../context/session-utils" -import { formatRelativeDate } from "../../utils/date" -import { FeedbackDialog } from "./FeedbackDialog" +import { WelcomeEmptyState } from "./WelcomeEmptyState" import { TranscriptRowView } from "./TranscriptRow" import { RevertBanner } from "./RevertBanner" import { AccountSwitcher } from "../shared/AccountSwitcher" @@ -48,19 +45,6 @@ import { import { partitionRows, transcriptRows, type TranscriptRow } from "../../context/transcript-rows" import type { QuestionRequest, SuggestionRequest } from "../../types/messages" -const KiloLogo = (): JSX.Element => { - const iconsBaseUri = (window as { ICONS_BASE_URI?: string }).ICONS_BASE_URI || "" - const isLight = - document.body.classList.contains("vscode-light") || document.body.classList.contains("vscode-high-contrast-light") - const iconFile = isLight ? "kilo-light.svg" : "kilo-dark.svg" - - return ( - - ) -} - interface MessageListProps { onSelectSession?: (id: string) => void onShowHistory?: () => void @@ -71,13 +55,14 @@ interface MessageListProps { suggestions?: () => SuggestionRequest[] /** When true (subagent viewer), replace the welcome screen with an initializing indicator */ readonly?: boolean + /** Optionally replace the standard welcome content while the conversation is empty. */ + emptyState?: () => JSX.Element } export const MessageList: Component = (props) => { const session = useSession() const server = useServer() const language = useLanguage() - const dialog = useDialog() const autoScroll = createAutoScroll({ working: () => session.status() !== "idle", @@ -109,8 +94,6 @@ export const MessageList: Component = (props) => { ) const isEmpty = () => turns().length === 0 && !session.loading() && !boundary() - const recent = createMemo(() => recentSessions(session.sessions())) - const activeUserID = createMemo(() => getActiveUserMessageID(session.messages(), session.statusInfo(), (msg) => session.getParts(msg.id)), ) @@ -298,33 +281,11 @@ export const MessageList: Component = (props) => { -
- -

{language.t("session.messages.welcome")}

- 0 && props.onSelectSession}> -
- {language.t("session.recent")} - - {(s) => ( - - )} - - - - -
-
- -
+ {props.emptyState ? ( + props.emptyState() + ) : ( + + )}
diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/SidebarEmptyState.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/SidebarEmptyState.tsx new file mode 100644 index 00000000000..ea264e3dc1c --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/components/chat/SidebarEmptyState.tsx @@ -0,0 +1,39 @@ +import { type Component, Show } from "solid-js" +import { Spinner } from "@kilocode/kilo-ui/spinner" +import { useWorkStyle } from "../../context/work-style" +import { useLanguage } from "../../context/language" +import { WorkStylePicker } from "../shared/WorkStylePicker" +import { KiloLogo, WelcomeEmptyState } from "./WelcomeEmptyState" + +interface SidebarEmptyStateProps { + onSelectSession?: (id: string) => void + onShowHistory?: () => void +} + +export const SidebarEmptyState: Component = (props) => { + const work = useWorkStyle() + const language = useLanguage() + + return ( + + + {language.t("session.messages.initializing")} + + } + > + } + > +
+ +

{language.t("workStyle.onboarding.welcome")}

+ +
+
+
+ ) +} diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/WelcomeEmptyState.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/WelcomeEmptyState.tsx new file mode 100644 index 00000000000..a5bed638192 --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/components/chat/WelcomeEmptyState.tsx @@ -0,0 +1,63 @@ +import { type Component, For, Show } from "solid-js" +import { Icon } from "@kilocode/kilo-ui/icon" +import { useDialog } from "@kilocode/kilo-ui/context/dialog" +import { useSession } from "../../context/session" +import { useLanguage } from "../../context/language" +import { recentSessions } from "../../context/session-utils" +import { formatRelativeDate } from "../../utils/date" +import { FeedbackDialog } from "./FeedbackDialog" + +interface WelcomeEmptyStateProps { + onSelectSession?: (id: string) => void + onShowHistory?: () => void +} + +export const KiloLogo = () => { + const icons = (window as { ICONS_BASE_URI?: string }).ICONS_BASE_URI || "" + const light = + document.body.classList.contains("vscode-light") || document.body.classList.contains("vscode-high-contrast-light") + const file = light ? "kilo-light.svg" : "kilo-dark.svg" + + return ( + + ) +} + +export const WelcomeEmptyState: Component = (props) => { + const session = useSession() + const language = useLanguage() + const dialog = useDialog() + const recent = () => recentSessions(session.sessions()) + + return ( +
+ +

{language.t("session.messages.welcome")}

+ 0 && props.onSelectSession}> +
+ {language.t("session.recent")} + + {(item) => ( + + )} + + + + +
+
+ +
+ ) +} diff --git a/packages/kilo-vscode/webview-ui/src/components/shared/WorkStylePicker.tsx b/packages/kilo-vscode/webview-ui/src/components/shared/WorkStylePicker.tsx new file mode 100644 index 00000000000..92506e74762 --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/components/shared/WorkStylePicker.tsx @@ -0,0 +1,56 @@ +import { For } from "solid-js" +import type { Component } from "solid-js" +import { Button } from "@kilocode/kilo-ui/button" +import { Card } from "@kilocode/kilo-ui/card" +import { Icon } from "@kilocode/kilo-ui/icon" +import { useLanguage } from "../../context/language" +import { useVSCode } from "../../context/vscode" +import { useWorkStyle } from "../../context/work-style" +import { WORK_STYLE_CHOICES } from "../../../../src/shared/work-style-presets" + +const details = ["permissions", "visibility"] as const + +export const WorkStylePicker: Component = () => { + const language = useLanguage() + const vscode = useVSCode() + const work = useWorkStyle() + const open = (event: MouseEvent) => { + event.preventDefault() + vscode.postMessage({ type: "openSettingsPanel", tab: "autoApprove" }) + } + + return ( + +

{language.t("workStyle.onboarding.title")}

+ +
+ + {(choice) => ( + + )} + +
+ +

+ {language.t("workStyle.onboarding.settingsNote")} + + + {language.t("workStyle.onboarding.settings")} + +

+
+ ) +} diff --git a/packages/kilo-vscode/webview-ui/src/context/onboarding/work-style-toasts.ts b/packages/kilo-vscode/webview-ui/src/context/onboarding/work-style-toasts.ts new file mode 100644 index 00000000000..60e2f0b190e --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/context/onboarding/work-style-toasts.ts @@ -0,0 +1,23 @@ +import { showToast } from "@kilocode/kilo-ui/toast" +import type { LanguageContextValue } from "../language" + +export function createWorkStyleToasts(t: LanguageContextValue["t"]) { + return { + saved() { + showToast({ + variant: "success", + icon: "circle-check", + title: t("workStyle.toast.saved.title"), + duration: 2000, + }) + }, + failed(message: string, persistent: boolean) { + showToast({ + variant: "error", + title: t("common.requestFailed"), + description: message, + persistent, + }) + }, + } +} diff --git a/packages/kilo-vscode/webview-ui/src/context/work-style-state.ts b/packages/kilo-vscode/webview-ui/src/context/work-style-state.ts new file mode 100644 index 00000000000..dcd60ac856e --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/context/work-style-state.ts @@ -0,0 +1,7 @@ +import type { WorkStyleState } from "../../../src/shared/work-style-presets" + +export function resolveWorkStyleOnboarding(current: boolean, style: WorkStyleState): boolean { + if (style === "unset") return true + if (style === "skipped") return current + return false +} diff --git a/packages/kilo-vscode/webview-ui/src/context/work-style.tsx b/packages/kilo-vscode/webview-ui/src/context/work-style.tsx new file mode 100644 index 00000000000..df219d4661d --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/context/work-style.tsx @@ -0,0 +1,117 @@ +import { createContext, useContext, createEffect, createMemo, createSignal, onCleanup } from "solid-js" +import type { Accessor, ParentComponent } from "solid-js" +import { useVSCode } from "./vscode" +import { useLanguage } from "./language" +import { resolveWorkStyleOnboarding } from "./work-style-state" +import { createWorkStyleToasts } from "./onboarding/work-style-toasts" +import type { ExtensionMessage } from "../types/messages" +import { TelemetryEventName } from "../../../src/services/telemetry/types" +import type { WorkStyle, WorkStyleState } from "../../../src/shared/work-style-presets" + +export interface WorkStyleContextValue { + style: Accessor + loading: Accessor + applying: Accessor + shouldShowOnboarding: Accessor + apply: (style: WorkStyle) => void +} + +export const WorkStyleContext = createContext() + +export const WorkStyleProvider: ParentComponent = (props) => { + const vscode = useVSCode() + const language = useLanguage() + const [style, setStyle] = createSignal("unset") + const [loading, setLoading] = createSignal(true) + const [applying, setApplying] = createSignal(false) + const [display, setDisplay] = createSignal(false) + const toast = createWorkStyleToasts(language.t) + + const unsubscribe = vscode.onMessage((message: ExtensionMessage) => { + if (message.type === "workStyleLoaded") { + if (applying()) return + setStyle(message.style) + setDisplay((current) => resolveWorkStyleOnboarding(current, message.style)) + setLoading(false) + return + } + if (message.type === "workStyleApplied") { + setApplying(false) + setStyle(message.style) + setDisplay(false) + toast.saved() + return + } + if (message.type !== "workStyleApplyFailed") return + setApplying(false) + toast.failed(message.message, message.rollbackFailed) + }) + + const request = () => vscode.postMessage({ type: "requestWorkStyle" }) + + request() + + const unsubReady = vscode.onMessage((message: ExtensionMessage) => { + if (message.type !== "extensionDataReady") return + unsubReady() + if (loading()) request() + }) + + const onNewTaskRequest = () => { + if (applying() || !display()) return + setDisplay(false) + setStyle("skipped") + vscode.postMessage({ type: "setWorkStyle", style: "skipped" }) + } + window.addEventListener("newTaskRequest", onNewTaskRequest) + + onCleanup(() => { + unsubscribe() + unsubReady() + window.removeEventListener("newTaskRequest", onNewTaskRequest) + }) + + function apply(style: WorkStyle) { + if (applying()) return + setApplying(true) + vscode.postMessage({ + type: "telemetry", + event: TelemetryEventName.WORK_STYLE_SELECTED, + properties: { style }, + }) + vscode.postMessage({ type: "applyWorkStyle", style }) + } + + const ready = createMemo(() => !loading()) + const onboarding = createMemo(() => ready() && display()) + let acknowledged = false + + createEffect(() => { + if (!onboarding()) { + acknowledged = false + return + } + if (acknowledged) return + acknowledged = true + vscode.postMessage({ + type: "telemetry", + event: TelemetryEventName.WORK_STYLE_ONBOARDING_SHOWN, + }) + }) + + const value: WorkStyleContextValue = { + style, + loading: () => !ready(), + applying, + shouldShowOnboarding: onboarding, + apply, + } + + return {props.children} +} + +export function useWorkStyle(): WorkStyleContextValue { + const context = useContext(WorkStyleContext) + if (!context) throw new Error("useWorkStyle must be used within a WorkStyleProvider") + return context +} diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index f3d9b0bb23b..b0084e40d41 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -998,6 +998,31 @@ export const dict = { "feedback.dialog.github": "الإبلاغ عن مشكلة على GitHub", "feedback.dialog.discord": "الانضمام إلى مجتمع Discord", "feedback.dialog.support": "دعم العملاء", + "workStyle.onboarding.welcome": "مرحبًا بك في Kilo", + "workStyle.onboarding.title": "اختر كيف تريد العمل", + "workStyle.onboarding.settingsNote": "يمكنك تغيير هذه الخيارات في أي وقت من", + "workStyle.onboarding.settings": "الإعدادات.", + "workStyle.onboarding.description": + "يحدد هذا الإعداد القيم الافتراضية الأولية للأذونات وكتل الاستدلال ومخرجات المحطة الطرفية والمخطط الزمني للسياق. يُطبّق مرة واحدة فقط ويتجاوز الإعدادات التي خصصتها مسبقًا.", + "workStyle.onboarding.skip": "تخطي الآن", + "workStyle.toast.saved.title": "تم حفظ الوضع بنجاح", + "workStyle.toast.saved.description": "يمكنك تحديث تفضيلاتك في أي وقت من الإعدادات.", + "workStyle.toast.saved.action": "الانتقال إلى الإعدادات", + "workStyle.choice.permissions": "الأذونات", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "العرض", + "workStyle.choice.human-in-the-loop.eyebrow": "الإنسان ضمن سير العمل", + "workStyle.choice.human-in-the-loop.title": "راجع أولًا", + "workStyle.choice.human-in-the-loop.description": "يتوقف Kilo مؤقتًا ويعرض لك خطته أثناء العمل.", + "workStyle.choice.human-in-the-loop.permissions": "يطلب الإذن قبل تعديل الملفات أو تشغيل الأوامر.", + "workStyle.choice.human-in-the-loop.bash": "يطلب الإذن لتشغيل أي أمر في المحطة الطرفية.", + "workStyle.choice.human-in-the-loop.visibility": "يعرض تفاصيل المحادثة كاملة، بما في ذلك الاستدلال.", + "workStyle.choice.autonomous.eyebrow": "مقاطعات أقل", + "workStyle.choice.autonomous.title": "استقلالية عالية", + "workStyle.choice.autonomous.description": "مقاطعات أقل وواجهة أكثر انسيابية.", + "workStyle.choice.autonomous.permissions": "يعدّل الملفات ويشغّل الأوامر في مساحة العمل دون طلب الإذن.", + "workStyle.choice.autonomous.bash": "يمكنه تشغيل أوامر المحطة الطرفية في مساحة العمل دون موافقة.", + "workStyle.choice.autonomous.visibility": "تظل التفاصيل مطوية حتى توسّعها.", "session.cloud.import.title": "استيراد من السحابة", "session.cloud.import.placeholder": "معرّف الجلسة أو الرابط أو أمر kilo import", "session.cloud.import.button": "استيراد", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 4666963e8a5..ae04ef3315f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1014,6 +1014,32 @@ export const dict = { "feedback.dialog.github": "Reportar um problema no GitHub", "feedback.dialog.discord": "Entrar na nossa comunidade Discord", "feedback.dialog.support": "Suporte ao cliente", + "workStyle.onboarding.welcome": "Boas-vindas ao Kilo", + "workStyle.onboarding.title": "Escolha como você quer trabalhar", + "workStyle.onboarding.settingsNote": "Você pode alterar essas opções a qualquer momento em", + "workStyle.onboarding.settings": "Configurações.", + "workStyle.onboarding.description": + "Define os padrões iniciais de permissões, blocos de raciocínio, saída do terminal e linha do tempo do contexto. É aplicado apenas uma vez e ignora configurações que você já personalizou.", + "workStyle.onboarding.skip": "Pular por enquanto", + "workStyle.toast.saved.title": "Modo salvo com sucesso", + "workStyle.toast.saved.description": "Atualize suas preferências a qualquer momento nas Configurações.", + "workStyle.toast.saved.action": "Ir para Configurações", + "workStyle.choice.permissions": "Permissões", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Visibilidade", + "workStyle.choice.human-in-the-loop.eyebrow": "Supervisão humana", + "workStyle.choice.human-in-the-loop.title": "Revisar primeiro", + "workStyle.choice.human-in-the-loop.description": "O Kilo pausa e mostra o plano enquanto trabalha.", + "workStyle.choice.human-in-the-loop.permissions": "Pede permissão antes de editar arquivos ou executar comandos.", + "workStyle.choice.human-in-the-loop.bash": "Pede permissão para executar qualquer comando no terminal.", + "workStyle.choice.human-in-the-loop.visibility": "Exibe todos os detalhes da conversa, incluindo o raciocínio.", + "workStyle.choice.autonomous.eyebrow": "Menos interrupções", + "workStyle.choice.autonomous.title": "Alta autonomia", + "workStyle.choice.autonomous.description": "Menos interrupções e uma interface simplificada.", + "workStyle.choice.autonomous.permissions": + "Edita arquivos e executa comandos no espaço de trabalho sem pedir permissão.", + "workStyle.choice.autonomous.bash": "Pode executar comandos do terminal no espaço de trabalho sem aprovação.", + "workStyle.choice.autonomous.visibility": "Os detalhes permanecem recolhidos até você expandi-los.", "session.cloud.import.title": "Importar da nuvem", "session.cloud.import.placeholder": "ID da sessão, URL ou comando kilo import", "session.cloud.import.button": "Importar", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 05fbb5566c5..b6e5725db7a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1055,6 +1055,31 @@ export const dict = { "feedback.dialog.github": "Prijavite problem na GitHubu", "feedback.dialog.discord": "Pridružite se našoj Discord zajednici", "feedback.dialog.support": "Korisnička podrška", + "workStyle.onboarding.welcome": "Dobro došli u Kilo", + "workStyle.onboarding.title": "Odaberite kako želite raditi", + "workStyle.onboarding.settingsNote": "Ove opcije možete promijeniti bilo kada u", + "workStyle.onboarding.settings": "Postavkama.", + "workStyle.onboarding.description": + "Postavlja početne zadane vrijednosti za dozvole, blokove zaključivanja, izlaz terminala i vremensku liniju konteksta. Primjenjuje se samo jednom i preskače postavke koje ste već prilagodili.", + "workStyle.onboarding.skip": "Preskoči za sada", + "workStyle.toast.saved.title": "Režim je uspješno sačuvan", + "workStyle.toast.saved.description": "Svoje postavke možete ažurirati bilo kada u Postavkama.", + "workStyle.toast.saved.action": "Idi na Postavke", + "workStyle.choice.permissions": "Dozvole", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Vidljivost", + "workStyle.choice.human-in-the-loop.eyebrow": "Čovjek nadzire proces", + "workStyle.choice.human-in-the-loop.title": "Prvo pregledajte", + "workStyle.choice.human-in-the-loop.description": "Kilo zastaje i prikazuje vam svoj plan tokom rada.", + "workStyle.choice.human-in-the-loop.permissions": "Traži dozvolu prije uređivanja datoteka ili pokretanja komandi.", + "workStyle.choice.human-in-the-loop.bash": "Traži dozvolu za svaku terminalsku komandu.", + "workStyle.choice.human-in-the-loop.visibility": "Prikazuje sve detalje razgovora, uključujući zaključivanje.", + "workStyle.choice.autonomous.eyebrow": "Manje prekida", + "workStyle.choice.autonomous.title": "Visoka autonomija", + "workStyle.choice.autonomous.description": "Manje prekida i pojednostavljen interfejs.", + "workStyle.choice.autonomous.permissions": "Uređuje datoteke i pokreće komande u radnom prostoru bez pitanja.", + "workStyle.choice.autonomous.bash": "Može pokretati terminalske komande u radnom prostoru bez odobrenja.", + "workStyle.choice.autonomous.visibility": "Detalji ostaju sažeti dok ih ne proširite.", "session.cloud.import.title": "Uvezi iz oblaka", "session.cloud.import.placeholder": "ID sesije, URL ili kilo import naredba", "session.cloud.import.button": "Uvezi", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 1c76e00b89e..241e3c45116 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1047,6 +1047,32 @@ export const dict = { "feedback.dialog.github": "Rapportér et problem på GitHub", "feedback.dialog.discord": "Deltag i vores Discord-fællesskab", "feedback.dialog.support": "Kundesupport", + "workStyle.onboarding.welcome": "Velkommen til Kilo", + "workStyle.onboarding.title": "Vælg, hvordan du vil arbejde", + "workStyle.onboarding.settingsNote": "Du kan til enhver tid ændre disse valg under", + "workStyle.onboarding.settings": "Indstillinger.", + "workStyle.onboarding.description": + "Dette angiver startindstillingerne for tilladelser, ræsonneringsblokke, terminaloutput og konteksttidslinjen. Det anvendes kun én gang og springer indstillinger over, som du allerede har tilpasset.", + "workStyle.onboarding.skip": "Spring over indtil videre", + "workStyle.toast.saved.title": "Tilstanden blev gemt", + "workStyle.toast.saved.description": "Opdater dine præferencer når som helst under Indstillinger.", + "workStyle.toast.saved.action": "Gå til Indstillinger", + "workStyle.choice.permissions": "Tilladelser", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Synlighed", + "workStyle.choice.human-in-the-loop.eyebrow": "Menneskelig kontrol", + "workStyle.choice.human-in-the-loop.title": "Gennemgå først", + "workStyle.choice.human-in-the-loop.description": "Kilo holder pause og viser dig sin plan undervejs.", + "workStyle.choice.human-in-the-loop.permissions": + "Spørger om tilladelse, før filer redigeres eller kommandoer køres.", + "workStyle.choice.human-in-the-loop.bash": "Spørger om tilladelse til alle terminalkommandoer.", + "workStyle.choice.human-in-the-loop.visibility": "Viser alle samtaledetaljer, herunder ræsonnement.", + "workStyle.choice.autonomous.eyebrow": "Færre afbrydelser", + "workStyle.choice.autonomous.title": "Høj autonomi", + "workStyle.choice.autonomous.description": "Færre afbrydelser og en strømlinet brugerflade.", + "workStyle.choice.autonomous.permissions": "Redigerer filer og kører kommandoer i arbejdsområdet uden at spørge.", + "workStyle.choice.autonomous.bash": "Kan køre terminalkommandoer i arbejdsområdet uden godkendelse.", + "workStyle.choice.autonomous.visibility": "Detaljerne forbliver foldet sammen, indtil du folder dem ud.", "session.cloud.import.title": "Importér fra skyen", "session.cloud.import.placeholder": "Sessions-ID, URL eller kilo import-kommando", "session.cloud.import.button": "Importér", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index af2b5d740f6..04ffc2f2c13 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1062,6 +1062,33 @@ export const dict = { "feedback.dialog.github": "Ein Problem auf GitHub melden", "feedback.dialog.discord": "Unserer Discord-Community beitreten", "feedback.dialog.support": "Kundensupport", + "workStyle.onboarding.welcome": "Willkommen bei Kilo", + "workStyle.onboarding.title": "Wähle, wie du arbeiten möchtest", + "workStyle.onboarding.settingsNote": "Du kannst diese Optionen jederzeit ändern unter", + "workStyle.onboarding.settings": "Einstellungen.", + "workStyle.onboarding.description": + "Hiermit werden die anfänglichen Standardeinstellungen für Berechtigungen, Denkblöcke, Terminalausgabe und Kontextzeitleiste festgelegt. Dies gilt nur einmal und überspringt Einstellungen, die Sie bereits angepasst haben.", + "workStyle.onboarding.skip": "Vorerst überspringen", + "workStyle.toast.saved.title": "Modus erfolgreich gespeichert", + "workStyle.toast.saved.description": "Du kannst deine Einstellungen jederzeit in den Einstellungen ändern.", + "workStyle.toast.saved.action": "Zu den Einstellungen", + "workStyle.choice.permissions": "Berechtigungen", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Sichtbarkeit", + "workStyle.choice.human-in-the-loop.eyebrow": "Menschliche Kontrolle", + "workStyle.choice.human-in-the-loop.title": "Zuerst überprüfen", + "workStyle.choice.human-in-the-loop.description": "Kilo pausiert und zeigt dir während der Arbeit seinen Plan.", + "workStyle.choice.human-in-the-loop.permissions": + "Fragt vor dem Bearbeiten von Dateien oder Ausführen von Befehlen nach.", + "workStyle.choice.human-in-the-loop.bash": "Der Agent fragt bei allen Terminalbefehlen um Erlaubnis.", + "workStyle.choice.human-in-the-loop.visibility": "Zeigt alle Gesprächsdetails einschließlich der Überlegungen.", + "workStyle.choice.autonomous.eyebrow": "Weniger Unterbrechungen", + "workStyle.choice.autonomous.title": "Hohe Autonomie", + "workStyle.choice.autonomous.description": "Weniger Unterbrechungen und eine optimierte Benutzeroberfläche.", + "workStyle.choice.autonomous.permissions": + "Bearbeitet Dateien und führt Befehle im Arbeitsbereich ohne Nachfrage aus.", + "workStyle.choice.autonomous.bash": "Kann Terminalbefehle im Arbeitsbereich ohne Genehmigung ausführen.", + "workStyle.choice.autonomous.visibility": "Details bleiben eingeklappt, bis du sie aufklappst.", "session.cloud.import.title": "Aus der Cloud importieren", "session.cloud.import.placeholder": "Sitzungs-ID, URL oder kilo import-Befehl", "session.cloud.import.button": "Importieren", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index bb53b6e4bb7..affab854d31 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -973,6 +973,31 @@ export const dict = { "feedback.dialog.github": "Report an issue on GitHub", "feedback.dialog.discord": "Join our Discord community", "feedback.dialog.support": "Customer Support", + "workStyle.onboarding.welcome": "Welcome to Kilo", + "workStyle.onboarding.title": "Choose how you want to work", + "workStyle.onboarding.description": + "This sets the starting defaults for permissions, reasoning blocks, terminal output, and the context timeline. It only applies once and skips settings you already customized.", + "workStyle.onboarding.skip": "Skip for now", + "workStyle.onboarding.settingsNote": "You can change these options anytime in", + "workStyle.onboarding.settings": "Settings.", + "workStyle.toast.saved.title": "Mode saved successfully", + "workStyle.toast.saved.description": "Update your preferences anytime in Settings.", + "workStyle.toast.saved.action": "Go to Settings", + "workStyle.choice.permissions": "Permissions", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Visibility", + "workStyle.choice.human-in-the-loop.eyebrow": "Human in the Loop", + "workStyle.choice.human-in-the-loop.title": "Review first", + "workStyle.choice.human-in-the-loop.description": "Kilo pauses and shows you its plan as it works.", + "workStyle.choice.human-in-the-loop.permissions": "Asks before editing files or running commands.", + "workStyle.choice.human-in-the-loop.bash": "Asks for permission when running all terminal commands.", + "workStyle.choice.human-in-the-loop.visibility": "Shows full conversation details, including reasoning.", + "workStyle.choice.autonomous.eyebrow": "Fewer interruptions", + "workStyle.choice.autonomous.title": "High autonomy", + "workStyle.choice.autonomous.description": "Fewer interruptions, streamlined interface.", + "workStyle.choice.autonomous.permissions": "Edits files and runs commands in the workspace without asking.", + "workStyle.choice.autonomous.bash": "Can run terminal commands in the workspace without approval.", + "workStyle.choice.autonomous.visibility": "Details stay collapsed until you expand them.", "session.cloud.import.title": "Import session", "session.cloud.import.placeholder": "Session ID, URL, or kilo import command", "session.cloud.import.button": "Import", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 06a52faaae0..68d58c4c587 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1058,6 +1058,33 @@ export const dict = { "feedback.dialog.github": "Reportar un problema en GitHub", "feedback.dialog.discord": "Unirse a nuestra comunidad de Discord", "feedback.dialog.support": "Atención al cliente", + "workStyle.onboarding.welcome": "Te damos la bienvenida a Kilo", + "workStyle.onboarding.title": "Elige cómo quieres trabajar", + "workStyle.onboarding.settingsNote": "Puedes cambiar estas opciones en cualquier momento en", + "workStyle.onboarding.settings": "Configuración.", + "workStyle.onboarding.description": + "Esto establece los valores iniciales de permisos, bloques de razonamiento, salida del terminal y cronología de contexto. Solo se aplica una vez y omite los ajustes que ya hayas personalizado.", + "workStyle.onboarding.skip": "Omitir por ahora", + "workStyle.toast.saved.title": "Modo guardado correctamente", + "workStyle.toast.saved.description": "Actualiza tus preferencias cuando quieras en Configuración.", + "workStyle.toast.saved.action": "Ir a Configuración", + "workStyle.choice.permissions": "Permisos", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Visibilidad", + "workStyle.choice.human-in-the-loop.eyebrow": "Supervisión humana", + "workStyle.choice.human-in-the-loop.title": "Revisar primero", + "workStyle.choice.human-in-the-loop.description": "Kilo se detiene y te muestra su plan mientras trabaja.", + "workStyle.choice.human-in-the-loop.permissions": "Pide permiso antes de editar archivos o ejecutar comandos.", + "workStyle.choice.human-in-the-loop.bash": "Pide permiso para ejecutar todos los comandos del terminal.", + "workStyle.choice.human-in-the-loop.visibility": + "Muestra todos los detalles de la conversación, incluido el razonamiento.", + "workStyle.choice.autonomous.eyebrow": "Menos interrupciones", + "workStyle.choice.autonomous.title": "Alta autonomía", + "workStyle.choice.autonomous.description": "Menos interrupciones y una interfaz optimizada.", + "workStyle.choice.autonomous.permissions": + "Edita archivos y ejecuta comandos en el espacio de trabajo sin preguntar.", + "workStyle.choice.autonomous.bash": "Puede ejecutar comandos en el terminal del espacio de trabajo sin aprobación.", + "workStyle.choice.autonomous.visibility": "Los detalles permanecen contraídos hasta que los despliegues.", "session.cloud.import.title": "Importar desde la nube", "session.cloud.import.placeholder": "ID de sesión, URL o comando kilo import", "session.cloud.import.button": "Importar", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 0bd546a3660..382d972c4d7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1066,6 +1066,36 @@ export const dict = { "feedback.dialog.github": "Signaler un problème sur GitHub", "feedback.dialog.discord": "Rejoindre notre communauté Discord", "feedback.dialog.support": "Service client", + "workStyle.onboarding.welcome": "Bienvenue dans Kilo", + "workStyle.onboarding.title": "Choisissez votre façon de travailler", + "workStyle.onboarding.settingsNote": "Vous pouvez modifier ces options à tout moment dans les", + "workStyle.onboarding.settings": "Paramètres.", + "workStyle.onboarding.description": + "Ceci définit les paramètres initiaux pour les autorisations, les blocs de raisonnement, la sortie du terminal et la chronologie du contexte. Ce réglage ne s'applique qu'une fois et ignore les paramètres que vous avez déjà personnalisés.", + "workStyle.onboarding.skip": "Ignorer pour l'instant", + "workStyle.toast.saved.title": "Mode enregistré avec succès", + "workStyle.toast.saved.description": "Modifiez vos préférences à tout moment dans les paramètres.", + "workStyle.toast.saved.action": "Accéder aux paramètres", + "workStyle.choice.permissions": "Autorisations", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Visibilité", + "workStyle.choice.human-in-the-loop.eyebrow": "Contrôle humain", + "workStyle.choice.human-in-the-loop.title": "Vérifier d'abord", + "workStyle.choice.human-in-the-loop.description": + "Kilo s'interrompt et vous présente son plan au fil de son travail.", + "workStyle.choice.human-in-the-loop.permissions": + "Demande avant de modifier des fichiers ou d'exécuter des commandes.", + "workStyle.choice.human-in-the-loop.bash": "L'agent demande l'autorisation pour chaque commande du terminal.", + "workStyle.choice.human-in-the-loop.visibility": + "Affiche tous les détails de la conversation, y compris le raisonnement.", + "workStyle.choice.autonomous.eyebrow": "Moins d'interruptions", + "workStyle.choice.autonomous.title": "Autonomie élevée", + "workStyle.choice.autonomous.description": "Moins d'interruptions et une interface simplifiée.", + "workStyle.choice.autonomous.permissions": + "Modifie les fichiers et exécute les commandes dans l'espace de travail sans demander.", + "workStyle.choice.autonomous.bash": + "Peut exécuter des commandes dans le terminal de l'espace de travail sans autorisation.", + "workStyle.choice.autonomous.visibility": "Les détails restent repliés jusqu'à ce que vous les développiez.", "session.cloud.import.title": "Importer depuis le cloud", "session.cloud.import.placeholder": "ID de session, URL ou commande kilo import", "session.cloud.import.button": "Importer", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/it.ts b/packages/kilo-vscode/webview-ui/src/i18n/it.ts index 604935e8736..4656f1e8950 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/it.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/it.ts @@ -866,6 +866,32 @@ export const dict = { "feedback.dialog.github": "Segnala un problema su GitHub", "feedback.dialog.discord": "Entra nella community Discord", "feedback.dialog.support": "Supporto clienti", + "workStyle.onboarding.welcome": "Ti diamo il benvenuto in Kilo", + "workStyle.onboarding.title": "Scegli come vuoi lavorare", + "workStyle.onboarding.description": + "Imposta i valori iniziali per autorizzazioni, blocchi di ragionamento, output del terminale e timeline del contesto. Viene applicato una sola volta e ignora le impostazioni già personalizzate.", + "workStyle.onboarding.settingsNote": "Puoi modificare queste opzioni in qualsiasi momento in", + "workStyle.onboarding.settings": "Impostazioni.", + "workStyle.onboarding.skip": "Ignora per ora", + "workStyle.toast.saved.title": "Modalità salvata correttamente", + "workStyle.toast.saved.description": "Aggiorna le tue preferenze in qualsiasi momento nelle Impostazioni.", + "workStyle.toast.saved.action": "Vai alle Impostazioni", + "workStyle.choice.permissions": "Autorizzazioni", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Visibilità", + "workStyle.choice.human-in-the-loop.eyebrow": "Supervisione umana", + "workStyle.choice.human-in-the-loop.title": "Prima la revisione", + "workStyle.choice.human-in-the-loop.description": "Kilo si mette in pausa e ti mostra il suo piano mentre lavora.", + "workStyle.choice.human-in-the-loop.permissions": "Chiede conferma prima di modificare file o eseguire comandi.", + "workStyle.choice.human-in-the-loop.bash": "Chiede l'autorizzazione per ogni comando del terminale.", + "workStyle.choice.human-in-the-loop.visibility": + "Mostra tutti i dettagli della conversazione, incluso il ragionamento.", + "workStyle.choice.autonomous.eyebrow": "Meno interruzioni", + "workStyle.choice.autonomous.title": "Autonomia elevata", + "workStyle.choice.autonomous.description": "Meno interruzioni e un'interfaccia semplificata.", + "workStyle.choice.autonomous.permissions": "Modifica file ed esegue comandi nel workspace senza chiedere conferma.", + "workStyle.choice.autonomous.bash": "Può eseguire comandi nel terminale del workspace senza approvazione.", + "workStyle.choice.autonomous.visibility": "I dettagli restano compressi finché non li espandi.", "session.cloud.import.title": "Importa sessione", "session.cloud.import.placeholder": "ID sessione, URL o comando kilo import", "session.cloud.import.button": "Importa", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 9ce44191137..277ea1a10bc 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1041,6 +1041,31 @@ export const dict = { "feedback.dialog.github": "GitHubで問題を報告する", "feedback.dialog.discord": "Discordコミュニティに参加する", "feedback.dialog.support": "カスタマーサポート", + "workStyle.onboarding.welcome": "Kiloへようこそ", + "workStyle.onboarding.title": "希望する作業スタイルを選択", + "workStyle.onboarding.description": + "権限、推論ブロック、ターミナル出力、コンテキストタイムラインの初期設定を行います。適用されるのは一度だけで、すでにカスタマイズした設定は変更されません。", + "workStyle.onboarding.settingsNote": "これらのオプションはいつでも変更できます:", + "workStyle.onboarding.settings": "設定。", + "workStyle.onboarding.skip": "今はスキップ", + "workStyle.toast.saved.title": "モードを保存しました", + "workStyle.toast.saved.description": "設定画面でいつでも変更できます。", + "workStyle.toast.saved.action": "設定を開く", + "workStyle.choice.permissions": "権限", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "表示", + "workStyle.choice.human-in-the-loop.eyebrow": "人間による確認", + "workStyle.choice.human-in-the-loop.title": "まず確認", + "workStyle.choice.human-in-the-loop.description": "Kiloは作業中に一時停止し、計画を表示します。", + "workStyle.choice.human-in-the-loop.permissions": "ファイルの編集やコマンドの実行前に許可を求めます。", + "workStyle.choice.human-in-the-loop.bash": "すべてのターミナルコマンド実行時に許可を求める", + "workStyle.choice.human-in-the-loop.visibility": "推論を含む会話の詳細をすべて表示します。", + "workStyle.choice.autonomous.eyebrow": "中断を少なく", + "workStyle.choice.autonomous.title": "高い自律性", + "workStyle.choice.autonomous.description": "中断を減らし、インターフェースを簡素化します。", + "workStyle.choice.autonomous.permissions": "確認なしでワークスペース内のファイルを編集し、コマンドを実行します。", + "workStyle.choice.autonomous.bash": "ワークスペース内で承認なしにターミナルコマンドを実行できます。", + "workStyle.choice.autonomous.visibility": "詳細は展開するまで折りたたまれたままです。", "session.cloud.import.title": "クラウドからインポート", "session.cloud.import.placeholder": "セッションID、URL、またはkilo importコマンド", "session.cloud.import.button": "インポート", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 7273ae5f6ab..fdaf39d51d6 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1003,6 +1003,31 @@ export const dict = { "feedback.dialog.github": "GitHub에 이슈 보고하기", "feedback.dialog.discord": "Discord 커뮤니티 참여하기", "feedback.dialog.support": "고객 지원", + "workStyle.onboarding.welcome": "Kilo에 오신 것을 환영합니다", + "workStyle.onboarding.title": "원하는 작업 방식을 선택하세요", + "workStyle.onboarding.description": + "권한, 추론 블록, 터미널 출력 및 컨텍스트 타임라인의 초기 기본값을 설정합니다. 한 번만 적용되며 이미 사용자 지정한 설정은 건너뜁니다.", + "workStyle.onboarding.settingsNote": "이 옵션은 언제든지 다음에서 변경할 수 있습니다:", + "workStyle.onboarding.settings": "설정.", + "workStyle.onboarding.skip": "지금은 건너뛰기", + "workStyle.toast.saved.title": "모드가 저장되었습니다", + "workStyle.toast.saved.description": "설정에서 언제든지 환경설정을 변경할 수 있습니다.", + "workStyle.toast.saved.action": "설정으로 이동", + "workStyle.choice.permissions": "권한", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "표시", + "workStyle.choice.human-in-the-loop.eyebrow": "사용자 검토 포함", + "workStyle.choice.human-in-the-loop.title": "먼저 검토", + "workStyle.choice.human-in-the-loop.description": "Kilo가 작업 중에 잠시 멈추고 계획을 보여줍니다.", + "workStyle.choice.human-in-the-loop.permissions": "파일을 편집하거나 명령을 실행하기 전에 권한을 요청합니다.", + "workStyle.choice.human-in-the-loop.bash": "모든 터미널 명령 실행 시 권한 요청", + "workStyle.choice.human-in-the-loop.visibility": "추론을 포함한 전체 대화 세부 정보를 표시합니다.", + "workStyle.choice.autonomous.eyebrow": "중단 최소화", + "workStyle.choice.autonomous.title": "높은 자율성", + "workStyle.choice.autonomous.description": "중단을 줄이고 인터페이스를 간소화합니다.", + "workStyle.choice.autonomous.permissions": "묻지 않고 작업 공간의 파일을 편집하고 명령을 실행합니다.", + "workStyle.choice.autonomous.bash": "승인 없이 작업 공간에서 터미널 명령을 실행할 수 있습니다.", + "workStyle.choice.autonomous.visibility": "세부 정보는 펼칠 때까지 접힌 상태로 유지됩니다.", "session.cloud.import.title": "클라우드에서 가져오기", "session.cloud.import.placeholder": "세션 ID, URL 또는 kilo import 명령어", "session.cloud.import.button": "가져오기", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index d7e8de9b4e5..42f413e7f75 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1010,6 +1010,33 @@ export const dict = { "feedback.dialog.github": "Meld een probleem op GitHub", "feedback.dialog.discord": "Word lid van onze Discord community", "feedback.dialog.support": "Klantenservice", + "workStyle.onboarding.welcome": "Welkom bij Kilo", + "workStyle.onboarding.title": "Kies hoe je wilt werken", + "workStyle.onboarding.description": + "Hiermee stel je de beginwaarden in voor machtigingen, redeneerblokken, terminaluitvoer en de contexttijdlijn. Dit wordt slechts één keer toegepast en slaat instellingen over die je al hebt aangepast.", + "workStyle.onboarding.settingsNote": "Je kunt deze opties op elk moment wijzigen in", + "workStyle.onboarding.settings": "Instellingen.", + "workStyle.onboarding.skip": "Voorlopig overslaan", + "workStyle.toast.saved.title": "Modus succesvol opgeslagen", + "workStyle.toast.saved.description": "Werk je voorkeuren op elk moment bij in Instellingen.", + "workStyle.toast.saved.action": "Naar Instellingen", + "workStyle.choice.permissions": "Machtigingen", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Zichtbaarheid", + "workStyle.choice.human-in-the-loop.eyebrow": "Menselijke controle", + "workStyle.choice.human-in-the-loop.title": "Eerst controleren", + "workStyle.choice.human-in-the-loop.description": "Kilo pauzeert en toont tijdens het werk zijn plan.", + "workStyle.choice.human-in-the-loop.permissions": + "Vraagt toestemming voordat bestanden worden bewerkt of opdrachten worden uitgevoerd.", + "workStyle.choice.human-in-the-loop.bash": "Vraagt toestemming voor elke terminalopdracht.", + "workStyle.choice.human-in-the-loop.visibility": "Toont alle gespreksdetails, inclusief de redenering.", + "workStyle.choice.autonomous.eyebrow": "Minder onderbrekingen", + "workStyle.choice.autonomous.title": "Hoge autonomie", + "workStyle.choice.autonomous.description": "Minder onderbrekingen, gestroomlijnde interface.", + "workStyle.choice.autonomous.permissions": + "Bewerkt bestanden en voert opdrachten in de werkruimte uit zonder toestemming te vragen.", + "workStyle.choice.autonomous.bash": "Kan terminalopdrachten in de werkruimte zonder goedkeuring uitvoeren.", + "workStyle.choice.autonomous.visibility": "Details blijven ingeklapt totdat je ze uitvouwt.", "session.cloud.import.title": "Importeer uit de cloud", "session.cloud.import.placeholder": "Sessie-ID, URL, of kilo import commando", "session.cloud.import.button": "Importeren", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 07e0fad3d27..8c5db2c95c9 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1014,6 +1014,31 @@ export const dict = { "feedback.dialog.github": "Rapporter et problem på GitHub", "feedback.dialog.discord": "Bli med i Discord-fellesskapet vårt", "feedback.dialog.support": "Kundestøtte", + "workStyle.onboarding.welcome": "Velkommen til Kilo", + "workStyle.onboarding.title": "Velg hvordan du vil arbeide", + "workStyle.onboarding.description": + "Dette angir startinnstillingene for tillatelser, resonneringsblokker, terminalutdata og konteksttidslinjen. Det brukes bare én gang og hopper over innstillinger du allerede har tilpasset.", + "workStyle.onboarding.settingsNote": "Du kan endre disse alternativene når som helst under", + "workStyle.onboarding.settings": "Innstillinger.", + "workStyle.onboarding.skip": "Hopp over inntil videre", + "workStyle.toast.saved.title": "Modusen er lagret", + "workStyle.toast.saved.description": "Oppdater innstillingene når som helst under Innstillinger.", + "workStyle.toast.saved.action": "Gå til Innstillinger", + "workStyle.choice.permissions": "Tillatelser", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Synlighet", + "workStyle.choice.human-in-the-loop.eyebrow": "Menneskelig kontroll", + "workStyle.choice.human-in-the-loop.title": "Gjennomgå først", + "workStyle.choice.human-in-the-loop.description": "Kilo tar pause og viser deg planen sin mens den arbeider.", + "workStyle.choice.human-in-the-loop.permissions": "Ber om tillatelse før filer redigeres eller kommandoer kjøres.", + "workStyle.choice.human-in-the-loop.bash": "Ber om tillatelse til alle terminalkommandoer.", + "workStyle.choice.human-in-the-loop.visibility": "Viser alle samtaledetaljer, inkludert resonnering.", + "workStyle.choice.autonomous.eyebrow": "Færre avbrudd", + "workStyle.choice.autonomous.title": "Høy autonomi", + "workStyle.choice.autonomous.description": "Færre avbrudd og et strømlinjeformet grensesnitt.", + "workStyle.choice.autonomous.permissions": "Redigerer filer og kjører kommandoer i arbeidsområdet uten å spørre.", + "workStyle.choice.autonomous.bash": "Kan kjøre terminalkommandoer i arbeidsområdet uten godkjenning.", + "workStyle.choice.autonomous.visibility": "Detaljene forblir skjult til du utvider dem.", "session.cloud.import.title": "Importer fra skyen", "session.cloud.import.placeholder": "Økt-ID, URL eller kilo import-kommando", "session.cloud.import.button": "Importer", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index e13ecf15289..367b7e5dbd2 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1013,6 +1013,32 @@ export const dict = { "feedback.dialog.github": "Zgłoś problem na GitHubie", "feedback.dialog.discord": "Dołącz do naszej społeczności Discord", "feedback.dialog.support": "Wsparcie klienta", + "workStyle.onboarding.welcome": "Witamy w Kilo", + "workStyle.onboarding.title": "Wybierz sposób pracy", + "workStyle.onboarding.description": + "Ustawia początkowe wartości domyślne uprawnień, bloków rozumowania, danych wyjściowych terminala i osi czasu kontekstu. Jest stosowane tylko raz i pomija ustawienia, które zostały już przez Ciebie zmienione.", + "workStyle.onboarding.settingsNote": "Te opcje możesz zmienić w dowolnym momencie w", + "workStyle.onboarding.settings": "Ustawieniach.", + "workStyle.onboarding.skip": "Pomiń na razie", + "workStyle.toast.saved.title": "Tryb został pomyślnie zapisany", + "workStyle.toast.saved.description": "Możesz je zmienić w dowolnym momencie w Ustawieniach.", + "workStyle.toast.saved.action": "Przejdź do Ustawień", + "workStyle.choice.permissions": "Uprawnienia", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Widoczność", + "workStyle.choice.human-in-the-loop.eyebrow": "Człowiek w pętli", + "workStyle.choice.human-in-the-loop.title": "Najpierw przejrzyj", + "workStyle.choice.human-in-the-loop.description": "Kilo wstrzymuje pracę i pokazuje swój plan w trakcie działania.", + "workStyle.choice.human-in-the-loop.permissions": "Prosi o zgodę przed edycją plików lub uruchomieniem poleceń.", + "workStyle.choice.human-in-the-loop.bash": "Prosi o pozwolenie na każde polecenie terminala.", + "workStyle.choice.human-in-the-loop.visibility": "Wyświetla wszystkie szczegóły rozmowy, w tym tok rozumowania.", + "workStyle.choice.autonomous.eyebrow": "Mniej przerw", + "workStyle.choice.autonomous.title": "Wysoka autonomia", + "workStyle.choice.autonomous.description": "Mniej przerw i uproszczony interfejs.", + "workStyle.choice.autonomous.permissions": + "Edytuje pliki i uruchamia polecenia w przestrzeni roboczej bez pytania o zgodę.", + "workStyle.choice.autonomous.bash": "Może uruchamiać polecenia terminala w przestrzeni roboczej bez zatwierdzenia.", + "workStyle.choice.autonomous.visibility": "Szczegóły pozostają zwinięte, dopóki ich nie rozwiniesz.", "session.cloud.import.title": "Importuj z chmury", "session.cloud.import.placeholder": "ID sesji, URL lub polecenie kilo import", "session.cloud.import.button": "Importuj", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index ada39ffa53f..c84a94b0783 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1052,6 +1052,33 @@ export const dict = { "feedback.dialog.github": "Сообщить о проблеме на GitHub", "feedback.dialog.discord": "Присоединиться к нашему Discord", "feedback.dialog.support": "Служба поддержки", + "workStyle.onboarding.welcome": "Добро пожаловать в Kilo", + "workStyle.onboarding.title": "Выберите, как вы хотите работать", + "workStyle.onboarding.description": + "Задаёт начальные значения разрешений, блоков рассуждений, вывода терминала и временной шкалы контекста. Применяется только один раз и не затрагивает уже изменённые вами настройки.", + "workStyle.onboarding.skip": "Пока пропустить", + "workStyle.onboarding.settingsNote": "Эти параметры можно изменить в любое время в разделе", + "workStyle.onboarding.settings": "«Настройки».", + "workStyle.toast.saved.title": "Режим успешно сохранён", + "workStyle.toast.saved.description": "Изменить их можно в любое время в настройках.", + "workStyle.toast.saved.action": "Перейти в настройки", + "workStyle.choice.permissions": "Разрешения", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Видимость", + "workStyle.choice.human-in-the-loop.eyebrow": "Человек контролирует процесс", + "workStyle.choice.human-in-the-loop.title": "Сначала проверка", + "workStyle.choice.human-in-the-loop.description": "Kilo приостанавливается и показывает свой план по ходу работы.", + "workStyle.choice.human-in-the-loop.permissions": + "Запрашивает разрешение перед редактированием файлов или выполнением команд.", + "workStyle.choice.human-in-the-loop.bash": "Запрашивает разрешение на каждую команду терминала.", + "workStyle.choice.human-in-the-loop.visibility": "Показывает все детали разговора, включая ход рассуждений.", + "workStyle.choice.autonomous.eyebrow": "Меньше прерываний", + "workStyle.choice.autonomous.title": "Высокая автономность", + "workStyle.choice.autonomous.description": "Меньше прерываний, упрощённый интерфейс.", + "workStyle.choice.autonomous.permissions": + "Редактирует файлы и выполняет команды в рабочем пространстве без разрешения.", + "workStyle.choice.autonomous.bash": "Может выполнять команды терминала в рабочем пространстве без подтверждения.", + "workStyle.choice.autonomous.visibility": "Детали остаются свёрнутыми, пока вы их не развернёте.", "session.cloud.import.title": "Импорт из облака", "session.cloud.import.placeholder": "ID сессии, URL или команда kilo import", "session.cloud.import.button": "Импортировать", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 8736c4eac61..2646e88a69a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1038,6 +1038,31 @@ export const dict = { "feedback.dialog.github": "รายงานปัญหาบน GitHub", "feedback.dialog.discord": "เข้าร่วมชุมชน Discord ของเรา", "feedback.dialog.support": "ฝ่ายสนับสนุนลูกค้า", + "workStyle.onboarding.welcome": "ยินดีต้อนรับสู่ Kilo", + "workStyle.onboarding.title": "เลือกวิธีที่คุณต้องการทำงาน", + "workStyle.onboarding.description": + "ตั้งค่าเริ่มต้นสำหรับสิทธิ์ บล็อกการให้เหตุผล เอาต์พุตเทอร์มินัล และไทม์ไลน์บริบท การตั้งค่านี้ใช้เพียงครั้งเดียวและจะข้ามรายการที่คุณปรับแต่งไว้แล้ว", + "workStyle.onboarding.skip": "ข้ามไปก่อน", + "workStyle.onboarding.settingsNote": "คุณสามารถเปลี่ยนตัวเลือกเหล่านี้ได้ทุกเมื่อใน", + "workStyle.onboarding.settings": "การตั้งค่า", + "workStyle.toast.saved.title": "บันทึกโหมดเรียบร้อยแล้ว", + "workStyle.toast.saved.description": "อัปเดตการตั้งค่าของคุณได้ทุกเมื่อในการตั้งค่า", + "workStyle.toast.saved.action": "ไปที่การตั้งค่า", + "workStyle.choice.permissions": "สิทธิ์", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "การแสดงผล", + "workStyle.choice.human-in-the-loop.eyebrow": "มีผู้ใช้ร่วมตรวจสอบ", + "workStyle.choice.human-in-the-loop.title": "ตรวจสอบก่อน", + "workStyle.choice.human-in-the-loop.description": "Kilo จะหยุดและแสดงแผนให้คุณเห็นระหว่างการทำงาน", + "workStyle.choice.human-in-the-loop.permissions": "ขออนุญาตก่อนแก้ไขไฟล์หรือเรียกใช้คำสั่ง", + "workStyle.choice.human-in-the-loop.bash": "ขออนุญาตเมื่อเรียกใช้คำสั่งเทอร์มินัลทุกคำสั่ง", + "workStyle.choice.human-in-the-loop.visibility": "แสดงรายละเอียดการสนทนาทั้งหมด รวมถึงกระบวนการให้เหตุผล", + "workStyle.choice.autonomous.eyebrow": "รบกวนน้อยลง", + "workStyle.choice.autonomous.title": "ทำงานอัตโนมัติสูง", + "workStyle.choice.autonomous.description": "ขัดจังหวะน้อยลง พร้อมอินเทอร์เฟซที่กระชับขึ้น", + "workStyle.choice.autonomous.permissions": "แก้ไขไฟล์และเรียกใช้คำสั่งในพื้นที่ทำงานโดยไม่ต้องขออนุญาต", + "workStyle.choice.autonomous.bash": "เรียกใช้คำสั่งเทอร์มินัลในพื้นที่ทำงานได้โดยไม่ต้องขออนุมัติ", + "workStyle.choice.autonomous.visibility": "รายละเอียดจะถูกย่อไว้จนกว่าคุณจะขยายดู", "session.cloud.import.title": "นำเข้าจากคลาวด์", "session.cloud.import.placeholder": "ID เซสชัน, URL หรือคำสั่ง kilo import", "session.cloud.import.button": "นำเข้า", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 96502bfb070..b4331e0522d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1009,6 +1009,33 @@ export const dict = { "feedback.dialog.github": "GitHub'da sorun bildirin", "feedback.dialog.discord": "Discord topluluğumuza katılın", "feedback.dialog.support": "Müşteri Desteği", + "workStyle.onboarding.welcome": "Kilo'ya hoş geldiniz", + "workStyle.onboarding.title": "Nasıl çalışmak istediğinizi seçin", + "workStyle.onboarding.description": + "İzinler, akıl yürütme blokları, terminal çıktısı ve bağlam zaman çizelgesi için başlangıç varsayılanlarını belirler. Yalnızca bir kez uygulanır ve daha önce özelleştirdiğiniz ayarları atlar.", + "workStyle.onboarding.skip": "Şimdilik atla", + "workStyle.onboarding.settingsNote": "Bu seçenekleri istediğiniz zaman şuradan değiştirebilirsiniz:", + "workStyle.onboarding.settings": "Ayarlar.", + "workStyle.toast.saved.title": "Mod başarıyla kaydedildi", + "workStyle.toast.saved.description": "Tercihlerinizi istediğiniz zaman Ayarlar'dan güncelleyebilirsiniz.", + "workStyle.toast.saved.action": "Ayarlara git", + "workStyle.choice.permissions": "İzinler", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Görünürlük", + "workStyle.choice.human-in-the-loop.eyebrow": "İnsan denetimli", + "workStyle.choice.human-in-the-loop.title": "Önce inceleyin", + "workStyle.choice.human-in-the-loop.description": "Kilo çalışırken duraklar ve planını size gösterir.", + "workStyle.choice.human-in-the-loop.permissions": + "Dosyaları düzenlemeden veya komutları çalıştırmadan önce izin ister.", + "workStyle.choice.human-in-the-loop.bash": "Her terminal komutunu çalıştırmadan önce izin ister.", + "workStyle.choice.human-in-the-loop.visibility": "Akıl yürütme dahil tüm konuşma ayrıntılarını gösterir.", + "workStyle.choice.autonomous.eyebrow": "Daha az kesinti", + "workStyle.choice.autonomous.title": "Yüksek özerklik", + "workStyle.choice.autonomous.description": "Daha az kesinti, daha sade bir arayüz.", + "workStyle.choice.autonomous.permissions": + "Çalışma alanındaki dosyaları izin istemeden düzenler ve komutları çalıştırır.", + "workStyle.choice.autonomous.bash": "Çalışma alanında terminal komutlarını onay almadan çalıştırabilir.", + "workStyle.choice.autonomous.visibility": "Ayrıntılar siz genişletene kadar daraltılmış olarak kalır.", "session.cloud.import.title": "Buluttan içe aktar", "session.cloud.import.placeholder": "Oturum kimliği, URL veya kilo import komutu", "session.cloud.import.button": "İçe Aktar", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts index bab4276376e..31bd1c5a611 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts @@ -1009,6 +1009,31 @@ export const dict = { "feedback.dialog.github": "Повідомити про проблему на GitHub", "feedback.dialog.discord": "Приєднатися до нашої спільноти Discord", "feedback.dialog.support": "Служба підтримки клієнтів", + "workStyle.onboarding.welcome": "Ласкаво просимо до Kilo", + "workStyle.onboarding.title": "Виберіть, як ви хочете працювати", + "workStyle.onboarding.description": + "Встановлює початкові значення дозволів, блоків міркувань, виводу термінала та часової шкали контексту. Застосовується лише один раз і не змінює вже налаштовані вами параметри.", + "workStyle.onboarding.skip": "Поки пропустити", + "workStyle.onboarding.settingsNote": "Ці параметри можна будь-коли змінити в розділі", + "workStyle.onboarding.settings": "«Налаштування».", + "workStyle.toast.saved.title": "Режим успішно збережено", + "workStyle.toast.saved.description": "Змінити їх можна будь-коли в налаштуваннях.", + "workStyle.toast.saved.action": "Перейти до налаштувань", + "workStyle.choice.permissions": "Дозволи", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "Видимість", + "workStyle.choice.human-in-the-loop.eyebrow": "Людина контролює процес", + "workStyle.choice.human-in-the-loop.title": "Спочатку перевірка", + "workStyle.choice.human-in-the-loop.description": "Kilo призупиняється та показує свій план у процесі роботи.", + "workStyle.choice.human-in-the-loop.permissions": "Запитує дозвіл перед редагуванням файлів або виконанням команд.", + "workStyle.choice.human-in-the-loop.bash": "Запитує дозвіл на кожну команду термінала.", + "workStyle.choice.human-in-the-loop.visibility": "Показує всі деталі розмови, зокрема хід міркувань.", + "workStyle.choice.autonomous.eyebrow": "Менше переривань", + "workStyle.choice.autonomous.title": "Висока автономність", + "workStyle.choice.autonomous.description": "Менше переривань, спрощений інтерфейс.", + "workStyle.choice.autonomous.permissions": "Редагує файли та виконує команди в робочому просторі без дозволу.", + "workStyle.choice.autonomous.bash": "Може виконувати команди термінала в робочому просторі без схвалення.", + "workStyle.choice.autonomous.visibility": "Деталі залишаються згорнутими, доки ви їх не розгорнете.", "session.cloud.import.title": "Імпортувати з хмари", "session.cloud.import.placeholder": "Ідентифікатор сесії, URL або команда kilo import", "session.cloud.import.button": "Імпортувати", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index f84aa0cb646..c186582fd05 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1022,6 +1022,31 @@ export const dict = { "feedback.dialog.github": "在 GitHub 上报告问题", "feedback.dialog.discord": "加入我们的 Discord 社区", "feedback.dialog.support": "客户支持", + "workStyle.onboarding.welcome": "欢迎使用 Kilo", + "workStyle.onboarding.title": "选择你想要的工作方式", + "workStyle.onboarding.description": + "这将设置权限、推理块、终端输出和上下文时间线的初始默认值。此设置仅应用一次,并会跳过你已自定义的设置。", + "workStyle.onboarding.skip": "暂时跳过", + "workStyle.onboarding.settingsNote": "你可以随时在以下位置更改这些选项:", + "workStyle.onboarding.settings": "设置。", + "workStyle.toast.saved.title": "模式已成功保存", + "workStyle.toast.saved.description": "可随时在“设置”中更新偏好设置。", + "workStyle.toast.saved.action": "前往设置", + "workStyle.choice.permissions": "权限", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "可见性", + "workStyle.choice.human-in-the-loop.eyebrow": "人工参与", + "workStyle.choice.human-in-the-loop.title": "先审查", + "workStyle.choice.human-in-the-loop.description": "Kilo 会在工作过程中暂停并向你展示其计划。", + "workStyle.choice.human-in-the-loop.permissions": "编辑文件或运行命令前会征求你的许可。", + "workStyle.choice.human-in-the-loop.bash": "运行所有终端命令时请求权限", + "workStyle.choice.human-in-the-loop.visibility": "显示完整的对话详情,包括推理过程。", + "workStyle.choice.autonomous.eyebrow": "减少打扰", + "workStyle.choice.autonomous.title": "高度自主", + "workStyle.choice.autonomous.description": "减少打扰,界面更简洁。", + "workStyle.choice.autonomous.permissions": "无需询问即可在工作区中编辑文件和运行命令。", + "workStyle.choice.autonomous.bash": "可以在工作区中无需批准即可运行终端命令。", + "workStyle.choice.autonomous.visibility": "详情会保持折叠,直到你将其展开。", "session.cloud.import.title": "从云端导入", "session.cloud.import.placeholder": "会话 ID、URL 或 kilo import 命令", "session.cloud.import.button": "导入", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 00a0b0af725..e9d977f7c0c 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -990,6 +990,31 @@ export const dict = { "feedback.dialog.github": "在 GitHub 上回報問題", "feedback.dialog.discord": "加入我們的 Discord 社群", "feedback.dialog.support": "客戶支援", + "workStyle.onboarding.welcome": "歡迎使用 Kilo", + "workStyle.onboarding.title": "選擇你想要的工作方式", + "workStyle.onboarding.description": + "這會設定權限、推理區塊、終端機輸出和上下文時間軸的初始預設值。此設定只會套用一次,並會略過你已自訂的設定。", + "workStyle.onboarding.skip": "暫時略過", + "workStyle.onboarding.settingsNote": "你可以隨時在以下位置變更這些選項:", + "workStyle.onboarding.settings": "設定。", + "workStyle.toast.saved.title": "模式已成功儲存", + "workStyle.toast.saved.description": "您可以隨時在「設定」中更新偏好設定。", + "workStyle.toast.saved.action": "前往設定", + "workStyle.choice.permissions": "權限", + "workStyle.choice.bash": "Bash", + "workStyle.choice.visibility": "可見性", + "workStyle.choice.human-in-the-loop.eyebrow": "人工參與", + "workStyle.choice.human-in-the-loop.title": "先審查", + "workStyle.choice.human-in-the-loop.description": "Kilo 會在工作過程中暫停並向你顯示其計畫。", + "workStyle.choice.human-in-the-loop.permissions": "編輯檔案或執行指令前會徵求你的許可。", + "workStyle.choice.human-in-the-loop.bash": "執行所有終端機指令時要求權限", + "workStyle.choice.human-in-the-loop.visibility": "顯示完整的對話詳細資訊,包括推理過程。", + "workStyle.choice.autonomous.eyebrow": "減少中斷", + "workStyle.choice.autonomous.title": "高度自主", + "workStyle.choice.autonomous.description": "減少中斷,介面更精簡。", + "workStyle.choice.autonomous.permissions": "無需詢問即可在工作區中編輯檔案和執行指令。", + "workStyle.choice.autonomous.bash": "可以在工作區中不經核准執行終端機指令。", + "workStyle.choice.autonomous.visibility": "詳細資訊會保持收合,直到你將其展開。", "session.cloud.import.title": "從雲端匯入", "session.cloud.import.placeholder": "工作階段 ID、URL 或 kilo import 指令", "session.cloud.import.button": "匯入", diff --git a/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx b/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx index 1e2ac6841b0..3f960e7fa23 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx @@ -16,6 +16,8 @@ import ModeEditView from "../components/settings/ModeEditView" import McpEditView from "../components/settings/McpEditView" import type { AgentConfig, CommandConfig, Config } from "../types/messages" import IndexingTab from "../components/settings/IndexingTab" +import { SidebarEmptyState } from "../components/chat/SidebarEmptyState" +import { WorkStyleContext, type WorkStyleContextValue } from "../context/work-style" const meta: Meta = { title: "Settings", @@ -96,6 +98,36 @@ function OpenModelPicker(props: { children: any }) { ) } +const work: WorkStyleContextValue = { + style: () => "unset", + loading: () => false, + applying: () => false, + shouldShowOnboarding: () => true, + apply: noop, +} + +function WorkStyleOnboarding() { + return ( + + +
+ +
+
+
+ ) +} + +export const WorkStyleOnboardingDefault: Story = { + name: "Work style onboarding — default width", + render: () => , +} + +export const WorkStyleOnboarding200: Story = { + name: "Work style onboarding — narrow width", + render: () => , +} + export const AgentBehaviourAgents: Story = { name: "AgentBehaviourTab — available agents list", render: () => { diff --git a/packages/kilo-vscode/webview-ui/src/styles/welcome.css b/packages/kilo-vscode/webview-ui/src/styles/welcome.css index cd595d1ba39..cdcc79caea9 100644 --- a/packages/kilo-vscode/webview-ui/src/styles/welcome.css +++ b/packages/kilo-vscode/webview-ui/src/styles/welcome.css @@ -20,6 +20,180 @@ line-height: 1.4; } +/* ============================================ + Work Style Picker + ============================================ */ + +.message-list-empty.work-style-empty { + height: auto; + min-height: 100%; + box-sizing: border-box; + gap: 12px; + animation: work-style-enter 420ms ease-out 120ms both; +} + +@keyframes work-style-enter { + from { + opacity: 0; + transform: translateY(12px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@media (prefers-reduced-motion: reduce) { + .message-list-empty.work-style-empty { + animation: none; + } +} + +.work-style-welcome { + margin: 0 0 4px; + color: var(--vscode-foreground); + font-size: var(--kilo-font-size-20); + font-weight: 650; + line-height: 1.2; +} + +[data-component="card"].work-style-picker { + display: flex; + flex-direction: column; + gap: 20px; + width: 100%; + max-width: 420px; + padding: 18px; + border: 1px solid var(--border-weak-base, var(--vscode-panel-border)); + border-radius: 10px; + background: var(--vscode-editorWidget-background); + color: var(--vscode-foreground); + text-align: left; + box-shadow: 0 12px 32px rgb(0 0 0 / 22%); +} + +[data-slot="work-style-title"] { + margin: 0; + font-size: var(--kilo-font-size-14); + font-weight: 650; + line-height: 1.35; +} + +[data-slot="work-style-options"] { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); + gap: 20px; + min-width: 0; +} + +[data-component="button"].work-style-mode { + display: flex; + flex-direction: column; + align-items: stretch; + gap: 12px; + width: 100%; + height: auto; + min-width: 0; + min-height: 0; + padding: 14px; + border: 1px solid var(--border-weak-base, var(--vscode-panel-border)); + border-radius: 8px; + background: color-mix(in srgb, var(--vscode-editor-background) 94%, var(--vscode-button-secondaryBackground)); + color: var(--vscode-foreground); + text-align: left; + white-space: normal; +} + +[data-component="button"].work-style-mode:hover { + border-color: var(--vscode-focusBorder, var(--vscode-textLink-foreground)); + background: color-mix(in srgb, var(--vscode-list-hoverBackground) 70%, var(--vscode-editor-background)); +} + +[data-slot="work-style-mode-copy"] { + display: flex; + flex-direction: column; + gap: 6px; +} + +[data-slot="work-style-mode-title"] { + margin: 0; + color: var(--vscode-textLink-foreground); + font-size: var(--kilo-font-size-11); + font-weight: 650; + line-height: 1.25; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +[data-slot="work-style-mode-description"] { + margin: 0; + color: var(--text-weak-base, var(--vscode-descriptionForeground)); + font-size: var(--kilo-font-size-12); + line-height: 1.45; +} + +[data-slot="work-style-mode-details"] { + display: flex; + flex-direction: column; + gap: 6px; + margin: 0; + padding-left: 18px; + color: var(--vscode-foreground); + list-style: disc; + font-size: var(--kilo-font-size-11); + line-height: 1.4; +} + +[data-slot="work-style-settings-note"] { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: flex-start; + gap: 4px; + margin: 0; + color: var(--text-weak-base, var(--vscode-descriptionForeground)); + font-size: var(--kilo-font-size-11); + line-height: 1.4; + text-align: left; +} + +[data-slot="work-style-settings-note"] a { + display: inline-flex; + align-items: center; + gap: 3px; + color: var(--vscode-textLink-foreground); + text-decoration: none; +} + +[data-slot="work-style-settings-note"] a:hover { + color: var(--vscode-textLink-activeForeground); + text-decoration: underline; +} + +@media (max-width: 320px) { + .message-list-empty.work-style-empty { + padding-inline: 8px; + } + + .work-style-welcome { + font-size: var(--kilo-font-size-16); + } + + [data-component="card"].work-style-picker { + gap: 16px; + padding: 12px; + } + + [data-slot="work-style-options"] { + gap: 16px; + } + + [data-component="button"].work-style-mode { + padding: 12px; + } +} + /* ============================================ Feedback Button (empty state) ============================================ */ diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts index d0d74bd4d92..5af9547dd03 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts @@ -18,6 +18,7 @@ import type { QuestionRequest, SuggestionRequest, TodoItem } from "./questions" import type { ModelSelection, Provider, ProviderAuthState } from "./providers" import type { AgentInfo, SkillInfo, SlashCommandInfo } from "./agents" import type { BrowserSettings, Config, FeatureFlags, IndexingStatus, KiloEmbeddingModelCatalog } from "./config" +import type { WorkStyle, WorkStyleState } from "../../../../src/shared/work-style-presets" import type { KilocodeNotification, ProfileData } from "./profile" import type { AgentManagerApplyWorktreeDiffConflict, @@ -503,6 +504,22 @@ export interface TimelineSettingLoadedMessage { visible: boolean } +export interface WorkStyleLoadedMessage { + type: "workStyleLoaded" + style: WorkStyleState +} + +export interface WorkStyleAppliedMessage { + type: "workStyleApplied" + style: WorkStyle +} + +export interface WorkStyleApplyFailedMessage { + type: "workStyleApplyFailed" + message: string + rollbackFailed: boolean +} + export interface NotificationsLoadedMessage { type: "notificationsLoaded" notifications: KilocodeNotification[] @@ -1004,6 +1021,9 @@ export type ExtensionMessage = | GlobalConfigLoadedMessage | NotificationSettingsLoadedMessage | TimelineSettingLoadedMessage + | WorkStyleLoadedMessage + | WorkStyleAppliedMessage + | WorkStyleApplyFailedMessage | NotificationsLoadedMessage | AgentManagerSessionMetaMessage | AgentManagerRepoInfoMessage diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts index de99aab4c71..680cc412f1b 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts @@ -5,6 +5,7 @@ import type { PermissionFileDiff } from "./permissions" import type { ModelSelection, ProviderConfig } from "./providers" import type { Config } from "./config" import type { ModelAllocation, ReviewComment } from "./agent-manager" +import type { WorkStyle, WorkStyleState } from "../../../../src/shared/work-style-presets" import type { ClearLegacyDataMessage, FinalizeLegacyMigrationMessage, @@ -386,6 +387,20 @@ export interface RequestTimelineSettingMessage { type: "requestTimelineSetting" } +export interface RequestWorkStyleMessage { + type: "requestWorkStyle" +} + +export interface SetWorkStyleMessage { + type: "setWorkStyle" + style: WorkStyleState +} + +export interface ApplyWorkStyleMessage { + type: "applyWorkStyle" + style: WorkStyle +} + export interface StreamSessionVisibleMessage { type: "streamSessionVisible" sessionID: string @@ -1125,6 +1140,9 @@ export type WebviewMessage = | ChatCompletionAcceptedMessage | UpdateSettingRequest | RequestTimelineSettingMessage + | RequestWorkStyleMessage + | SetWorkStyleMessage + | ApplyWorkStyleMessage | StreamSessionVisibleMessage | RequestBrowserSettingsMessage | RequestClaudeCompatSettingMessage