From 25d9448d63dad21da61dc0c6100f3b1b56be5617 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Mon, 31 Aug 2026 12:54:55 +0200 Subject: [PATCH 1/4] fix(vscode): remove unsupported legacy migration --- .changeset/roo-import-only.md | 5 + packages/kilo-docs/source-links.md | 4 - packages/kilo-vscode/package.json | 5 - packages/kilo-vscode/src/KiloProvider.ts | 61 +- packages/kilo-vscode/src/extension.ts | 5 - .../src/kilo-provider/handlers/migration.ts | 196 +-- .../src/legacy-migration/legacy-types.ts | 337 ----- .../src/legacy-migration/migration-service.ts | 1273 ----------------- .../migration-session-progress.ts | 2 +- .../src/legacy-migration/migration-types.ts | 2 +- .../legacy-migration/native-mode-defaults.ts | 91 -- .../src/legacy-migration/provider-mapping.ts | 308 ---- .../cli-backend/connection-service.ts | 22 - .../tests/unit/kilo-provider-followup.test.ts | 1 - .../unit/kilo-provider-load-messages.test.ts | 1 - .../kilo-provider-route-integration.test.ts | 1 - .../kilo-provider-session-refresh.test.ts | 39 +- .../legacy-migration/migration-cache.test.ts | 73 +- .../legacy-migration/native-modes.test.ts | 322 ----- .../tests/unit/roo-migration-ui.fixture.tsx | 260 ++++ .../tests/unit/roo-migration-ui.test.ts | 63 + packages/kilo-vscode/webview-ui/src/App.tsx | 28 +- .../components/migration/MigrationWizard.tsx | 859 ++--------- .../src/components/migration/index.ts | 4 - .../src/components/migration/migration.css | 104 -- .../components/settings/AboutKiloCodeTab.tsx | 26 +- .../src/components/settings/Settings.tsx | 2 +- .../kilo-vscode/webview-ui/src/i18n/en.ts | 2 + .../src/stories/migration.stories.tsx | 3 - .../src/types/messages/extension-messages.ts | 4 - .../src/types/messages/migration.ts | 88 +- .../src/types/messages/webview-messages.ts | 13 +- 32 files changed, 551 insertions(+), 3653 deletions(-) create mode 100644 .changeset/roo-import-only.md delete mode 100644 packages/kilo-vscode/src/legacy-migration/migration-service.ts delete mode 100644 packages/kilo-vscode/src/legacy-migration/native-mode-defaults.ts delete mode 100644 packages/kilo-vscode/src/legacy-migration/provider-mapping.ts delete mode 100644 packages/kilo-vscode/tests/unit/legacy-migration/native-modes.test.ts create mode 100644 packages/kilo-vscode/tests/unit/roo-migration-ui.fixture.tsx create mode 100644 packages/kilo-vscode/tests/unit/roo-migration-ui.test.ts diff --git a/.changeset/roo-import-only.md b/.changeset/roo-import-only.md new file mode 100644 index 00000000000..4da96b70f69 --- /dev/null +++ b/.changeset/roo-import-only.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Stop checking for unsupported legacy Kilo migrations at startup while keeping Roo Code session import available. diff --git a/packages/kilo-docs/source-links.md b/packages/kilo-docs/source-links.md index 4b8efaca49e..8ad9a90309a 100644 --- a/packages/kilo-docs/source-links.md +++ b/packages/kilo-docs/source-links.md @@ -42,8 +42,6 @@ - -- - - - @@ -138,8 +136,6 @@ - -- - - diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 90931c7ebda..34aa3d93983 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -196,11 +196,6 @@ "title": "Show Changes", "category": "Kilo Code" }, - { - "command": "kilo-code.new.openMigrationWizard", - "title": "Migrate Settings from Legacy Version", - "category": "Kilo Code" - }, { "command": "kilo-code.new.showMemory", "title": "Show Project Memory", diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index e854d119c87..112ced8f90a 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -104,19 +104,13 @@ import { import * as McpOAuth from "./kilo-provider/mcp-oauth" import { retryable, backoff, MAX_RETRIES } from "./util/retry" import { hasGit } from "./kilo-provider/git-status" -// legacy-migration start import { - checkAndShowMigrationWizard, handleRequestMigrationData, handleStartMigration, - handleFinalizeLegacyMigration, - handleSkipLegacyMigration, - handleClearLegacyData, type MigrationContext, type MigrationSource, } from "./kilo-provider/handlers/migration" import type { MigrationSelections } from "./legacy-migration/legacy-types" -// legacy-migration end import { handleLogin, handleLogout, @@ -445,16 +439,12 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper }) private unsubscribeEvent: (() => void) | null = null private unsubscribeState: (() => void) | null = null - /** Cached migration data so migration doesn't re-read from disk/SecretStorage. */ // legacy-migration private migrationCache: MigrationContext["migrationCache"] = new Map() - /** Guard to prevent checkAndShowMigrationWizard running concurrently. */ // legacy-migration - private migrationCheckInFlight = false // legacy-migration private unsubscribeNotificationDismiss: (() => void) | null = null private unsubscribeLanguageChange: (() => void) | null = null private unsubscribeProfileChange: (() => void) | null = null private unsubscribeFavoritesChange: (() => void) | null = null private unsubscribeModelSelectorExpanded: (() => void) | null = null - private unsubscribeMigrationComplete: (() => void) | null = null // legacy-migration private unsubscribeClearPendingPrompts: (() => void) | null = null private unsubscribeDirectoryProvider: (() => void) | null = null private unsubscribeSandboxPreference: (() => void) | null = null @@ -760,18 +750,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.sendRemoteStatus() } - - // legacy-migration start - // Show the migration wizard once the CLI connection is established. - // Three triggers cover all timing scenarios: - // "webviewReady" + connected — webview loaded after SSE was already up - // "sse-connected" — SSE connected after webview was ready - // "initializeConnection" — sidebar path where connect() resolves before - // onStateChange is subscribed, so sse-connected never fires - if (this.connectionState === "connected") { - void checkAndShowMigrationWizard(this.migrationCtx) - } - // legacy-migration end } public resolveWebviewView( @@ -1126,7 +1104,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper if (this.handleChildSyncMessage(message)) return if (await this.handleMemoryMessage(message)) return if (await this.handleProfileDataMessage(message)) return - if (this.handleLegacyMigrationMessage(message)) return + if (this.handleMigrationMessage(message)) return switch (message.type) { case "webviewReady": console.log("[Kilo New] KiloProvider: ✅ webviewReady received") @@ -1708,8 +1686,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper return false } - // legacy-migration start - private handleLegacyMigrationMessage(message: { type: string }): boolean { + private handleMigrationMessage(message: { type: string }): boolean { switch (message.type) { case "requestMigrationData": { const msg = message as unknown as { source: MigrationSource; operationId: string } @@ -1725,21 +1702,11 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper void handleStartMigration(this.migrationCtx, msg.source, msg.operationId, msg.selections) break } - case "skipLegacyMigration": - void handleSkipLegacyMigration(this.migrationCtx) - break - case "clearLegacyData": - void handleClearLegacyData(this.migrationCtx) - break - case "finalizeLegacyMigration": - void handleFinalizeLegacyMigration(this.migrationCtx) - break default: return false } return true } - // legacy-migration end private async toggleFavorite(message: { action: "add" | "remove" @@ -1904,13 +1871,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.postMessage({ type: "modelSelectorExpandedLoaded", value }) }) - // legacy-migration start - // Subscribe to migration-complete broadcast from any KiloProvider instance - this.unsubscribeMigrationComplete = this.connectionService.onMigrationComplete(() => { - this.postMessage({ type: "migrationState", needed: false, source: "legacy" }) - }) - // legacy-migration end - // Subscribe to clear-pending-prompts broadcast (fired after config save drains prompts) this.unsubscribeClearPendingPrompts = this.connectionService.onClearPendingPrompts(() => { this.postMessage({ type: "clearPendingPrompts" }) @@ -5427,30 +5387,16 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper }) } - // legacy-migration start ------------------------------------------------------- - // Migration handlers extracted to kilo-provider/handlers/migration.ts - private get migrationCtx(): MigrationContext { - const self = this return { client: this.client, extensionContext: this.extensionContext, postMessage: (msg) => this.postMessage(msg), - migrationCache: self.migrationCache, - get migrationCheckInFlight() { - return self.migrationCheckInFlight - }, - set migrationCheckInFlight(val) { - self.migrationCheckInFlight = val - }, + migrationCache: this.migrationCache, refreshSessions: () => this.refreshSessions(), - disposeGlobal: () => this.disposeGlobal(), - broadcastComplete: () => this.connectionService.notifyMigrationComplete(), } } - // legacy-migration end --------------------------------------------------------- - // ── Worktree stats polling (sidebar diff badge) ────────────────── private startStatsPolling(): void { if (this.opts.disableStatsPolling) return @@ -5502,7 +5448,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.unsubscribeProfileChange?.() this.unsubscribeFavoritesChange?.() this.unsubscribeModelSelectorExpanded?.() - this.unsubscribeMigrationComplete?.() this.unsubscribeClearPendingPrompts?.() this.unsubscribeDirectoryProvider?.() this.unsubscribeSandboxPreference?.() diff --git a/packages/kilo-vscode/src/extension.ts b/packages/kilo-vscode/src/extension.ts index 7e7bfff1625..45a8d5295ce 100644 --- a/packages/kilo-vscode/src/extension.ts +++ b/packages/kilo-vscode/src/extension.ts @@ -472,11 +472,6 @@ export async function activate(context: vscode.ExtensionContext) { await target.waitForReady() await target.toggleMemory() }), - // legacy-migration start - vscode.commands.registerCommand("kilo-code.new.openMigrationWizard", () => { - provider.postMessage({ type: "migrationState", needed: true, source: "legacy" }) - }), - // legacy-migration end vscode.commands.registerCommand("kilo-code.new.generateTerminalCommand", async () => { const input = await vscode.window.showInputBox({ prompt: "Describe the terminal command you want to generate", diff --git a/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts b/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts index 70c0f9c76cd..0aa2efc5d98 100644 --- a/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts +++ b/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts @@ -1,54 +1,27 @@ -/** - * Legacy migration handlers — extracted from KiloProvider. - * - * Manages the migration wizard for users upgrading from Kilo Code v5.x. - * VS Code access is limited to migration service helpers and injected context. - */ - import type { KiloClient } from "@kilocode/sdk/v2/client" import type { - LegacyMigrationData, MigrationSelections, MigrationSessionProgress, MigrationSessionSelection, } from "../../legacy-migration/legacy-types" -import * as MigrationService from "../../legacy-migration/migration-service" import { runSessionBatch } from "../../legacy-migration/session-batch" import { migrate as migrateSession } from "../../legacy-migration/sessions/migrate" import { resolveSession } from "../../legacy-migration/task-store" import { detectRooCodeSessions, type RooImportSource } from "../../roo-import/service" -/** Subset of vscode.ExtensionContext needed by migration handlers. */ interface MigrationExtensionContext { globalState: { get(key: string): T | undefined get(key: string, defaultValue: T): T update(key: string, value: unknown): PromiseLike } - secrets: { - get(key: string): PromiseLike - store(key: string, value: string): PromiseLike - delete(key: string): PromiseLike - } globalStorageUri: { fsPath: string } } -export type MigrationSource = "legacy" | "roo" -export type MigrationCacheEntry = - | { operationId: string; source: "legacy"; data: LegacyMigrationData } - | { operationId: string; source: "roo"; data: RooImportSource | null } +export type MigrationSource = "roo" +export type MigrationCacheEntry = { operationId: string; source: "roo"; data: RooImportSource | null } export type MigrationCache = Map -export function getMigrationCache( - cache: MigrationCache, - source: "legacy", - operationId: string, -): Extract | undefined -export function getMigrationCache( - cache: MigrationCache, - source: "roo", - operationId: string, -): Extract | undefined export function getMigrationCache(cache: MigrationCache, source: MigrationSource, operationId: string) { const entry = cache.get(operationId) return entry?.source === source ? entry : undefined @@ -60,31 +33,12 @@ export interface MigrationContext { postMessage(msg: unknown): void refreshSessions(): void migrationCache: MigrationCache - migrationCheckInFlight: boolean - lastMigrationHadErrors?: boolean - disposeGlobal(): Promise - broadcastComplete(): void } -function emptyData(sessions: LegacyMigrationData["sessions"] = []): LegacyMigrationData { - return { - hasData: sessions.length > 0, - providers: [], - mcpServers: [], - customModes: [], - sessions, - } -} - -function postSessionProgress( - ctx: MigrationContext, - source: MigrationSource, - operationId: string, - progress: MigrationSessionProgress, -): void { +function postSessionProgress(ctx: MigrationContext, operationId: string, progress: MigrationSessionProgress): void { ctx.postMessage({ type: "migrationSessionProgress", - source, + source: "roo", operationId, session: progress.session, index: progress.index, @@ -94,74 +48,22 @@ function postSessionProgress( }) } -/** - * Check for legacy data on first run and send migration state to the webview - * if the user has not yet been prompted. - * - * Uses a state-based approach (migrationState message) instead of navigate - * to avoid race conditions with SettingsEditorProvider's view navigation. - */ -export async function checkAndShowMigrationWizard(ctx: MigrationContext): Promise { - if (!ctx.extensionContext) return - if (ctx.migrationCheckInFlight) return - // MigrationService.getMigrationStatus accepts the full ExtensionContext shape - const status = MigrationService.getMigrationStatus( - ctx.extensionContext as Parameters[0], - ) - if (status) return // already prompted (skipped or completed) - - ctx.migrationCheckInFlight = true - const data = await MigrationService.detectLegacyData( - ctx.extensionContext as Parameters[0], - ) - ctx.migrationCheckInFlight = false - - if (!data.hasData) return - - console.log("[Kilo New] KiloProvider: 🔄 Legacy data detected, showing migration wizard") - // The wizard re-requests the data via requestMigrationData on mount, so only the flag is sent here. - ctx.postMessage({ - type: "migrationState", - needed: true, - source: "legacy", - }) -} - -/** Send migration data for the requested source to the webview. */ export async function handleRequestMigrationData( ctx: MigrationContext, source: MigrationSource, operationId: string, ): Promise { - if (!ctx.extensionContext) return - // A new request means a new wizard session; drop any entry from an abandoned one. + if (source !== "roo" || !ctx.extensionContext) return for (const key of ctx.migrationCache.keys()) { if (key !== operationId) ctx.migrationCache.delete(key) } - const data = await (async () => { - if (source === "roo") { - const roo = await detectRooCodeSessions(ctx.extensionContext as Parameters[0]) - ctx.migrationCache.set(operationId, { operationId, source, data: roo }) - return emptyData(roo?.sessions ?? []) - } - const legacy = await MigrationService.detectLegacyData( - ctx.extensionContext as Parameters[0], - ) - ctx.migrationCache.set(operationId, { operationId, source, data: legacy }) - return legacy - })() + const roo = await detectRooCodeSessions(ctx.extensionContext as Parameters[0]) + ctx.migrationCache.set(operationId, { operationId, source, data: roo }) ctx.postMessage({ type: "migrationData", source, operationId, - data: { - providers: data.providers, - mcpServers: data.mcpServers, - customModes: data.customModes, - sessions: data.sessions, - defaultModel: data.defaultModel, - settings: data.settings, - }, + data: { sessions: roo?.sessions ?? [] }, }) } @@ -203,98 +105,22 @@ async function startRooMigration( onProgress: (item, status, message) => { ctx.postMessage({ type: "migrationProgress", source: "roo", operationId, item, status, message }) }, - onSessionProgress: (progress) => postSessionProgress(ctx, "roo", operationId, progress), + onSessionProgress: (progress) => postSessionProgress(ctx, operationId, progress), }) - ctx.lastMigrationHadErrors = results.some((item) => item.status === "error") ctx.postMessage({ type: "migrationComplete", source: "roo", operationId, results }) } -/** Run the migration for the selected items. */ -async function startLegacyMigration( - ctx: MigrationContext, - operationId: string, - selections: MigrationSelections, -): Promise { - if (!ctx.extensionContext || !ctx.client) return - try { - const cached = getMigrationCache(ctx.migrationCache, "legacy", operationId) - const results = await MigrationService.migrate( - ctx.extensionContext as Parameters[0], - ctx.client, - selections, - (item, status, message) => { - ctx.postMessage({ type: "migrationProgress", source: "legacy", operationId, item, status, message }) - }, - (progress: MigrationSessionProgress) => { - postSessionProgress(ctx, "legacy", operationId, progress) - }, - cached?.data.settings, - cached?.data.sessions, - ) - - ctx.lastMigrationHadErrors = results.some((item) => item.status === "error") - ctx.postMessage({ type: "migrationComplete", source: "legacy", operationId, results }) - } catch (error) { - ctx.lastMigrationHadErrors = true - console.error("[Kilo New] KiloProvider: ❌ Migration failed", error) - ctx.postMessage({ - type: "migrationComplete", - source: "legacy", - operationId, - results: [ - { - item: "Migration", - category: "settings", - status: "error", - message: error instanceof Error ? error.message : String(error), - }, - ], - }) - } -} - export async function handleStartMigration( ctx: MigrationContext, source: MigrationSource, operationId: string, selections: MigrationSelections, ): Promise { + if (source !== "roo") return try { - if (source === "roo") { - await startRooMigration(ctx, operationId, selections) - return - } - await startLegacyMigration(ctx, operationId, selections) + await startRooMigration(ctx, operationId, selections) } finally { - // The operation has finished (or thrown); its cached discovery is no longer needed. ctx.migrationCache.delete(operationId) } } - -export async function handleFinalizeLegacyMigration(ctx: MigrationContext): Promise { - if (!ctx.extensionContext) return - await ctx.disposeGlobal() - await MigrationService.setMigrationStatus( - ctx.extensionContext as Parameters[0], - ctx.lastMigrationHadErrors ? "completed_with_errors" : "completed", - ) - ctx.broadcastComplete() - ctx.refreshSessions() -} - -/** Record that the user skipped migration and broadcast to all instances. */ -export async function handleSkipLegacyMigration(ctx: MigrationContext): Promise { - if (!ctx.extensionContext) return - await MigrationService.setMigrationStatus( - ctx.extensionContext as Parameters[0], - "skipped", - ) - ctx.broadcastComplete() -} - -/** Clear legacy data from SecretStorage and globalState after user opts in. */ -export async function handleClearLegacyData(ctx: MigrationContext): Promise { - if (!ctx.extensionContext) return - await MigrationService.clearLegacyData(ctx.extensionContext as Parameters[0]) -} diff --git a/packages/kilo-vscode/src/legacy-migration/legacy-types.ts b/packages/kilo-vscode/src/legacy-migration/legacy-types.ts index 489bf0abab7..33f982d80c9 100644 --- a/packages/kilo-vscode/src/legacy-migration/legacy-types.ts +++ b/packages/kilo-vscode/src/legacy-migration/legacy-types.ts @@ -1,304 +1,3 @@ -/** - * legacy-migration - Types for legacy Kilo Code extension (v5.x) data structures. - * - * These types represent the shapes stored in VS Code SecretStorage and on disk - * by the legacy extension (kilocode.kilo-code v5.x, a Roo Code fork). - * They are intentionally loose (allowing [key: string]: unknown) to tolerate - * schema drift between legacy versions. - */ - -// --------------------------------------------------------------------------- -// Provider profiles (stored in SecretStorage under "roo_cline_config_api_config") -// --------------------------------------------------------------------------- - -export interface LegacyProviderProfiles { - currentApiConfigName: string - apiConfigs: Record - modeApiConfigs?: Record -} - -/** - * Flat union of every provider-specific field from the legacy extension. - * Only the fields we actually need for migration are explicitly typed; - * the rest are captured by the index signature. - */ -export interface LegacyProviderSettings { - id?: string - apiProvider?: string - apiModelId?: string - - // Anthropic - apiKey?: string - anthropicBaseUrl?: string - - // OpenRouter - openRouterApiKey?: string - openRouterModelId?: string - openRouterBaseUrl?: string - - // OpenAI (custom/compatible) - openAiApiKey?: string - openAiModelId?: string - openAiBaseUrl?: string - - // OpenAI Native - openAiNativeApiKey?: string - openAiNativeBaseUrl?: string - - // Gemini - geminiApiKey?: string - googleGeminiBaseUrl?: string - - // Vertex AI - vertexJsonCredentials?: string - vertexProjectId?: string - vertexRegion?: string - - // AWS Bedrock - awsAccessKey?: string - awsSecretKey?: string - awsSessionToken?: string - awsRegion?: string - awsApiKey?: string - - // DeepSeek - deepSeekApiKey?: string - deepSeekBaseUrl?: string - - // Mistral - mistralApiKey?: string - - // Groq - groqApiKey?: string - - // xAI - xaiApiKey?: string - - // Fireworks - fireworksApiKey?: string - - // Featherless - featherlessApiKey?: string - - // Cerebras - cerebrasApiKey?: string - - // SambaNova - sambaNovaApiKey?: string - - // Ollama - ollamaApiKey?: string - ollamaBaseUrl?: string - ollamaModelId?: string - - // LM Studio - lmStudioBaseUrl?: string - lmStudioModelId?: string - - // Kilocode - kilocodeToken?: string - kilocodeModel?: string - kilocodeOrganizationId?: string - - // LiteLLM - litellmApiKey?: string - litellmBaseUrl?: string - litellmModelId?: string - - // DeepInfra - deepInfraApiKey?: string - deepInfraBaseUrl?: string - deepInfraModelId?: string - - // Chutes - chutesApiKey?: string - - // Baseten - basetenApiKey?: string - - // Corethink - corethinkApiKey?: string - - // Unbound - unboundApiKey?: string - unboundModelId?: string - - // Requesty - requestyApiKey?: string - requestyBaseUrl?: string - requestyModelId?: string - - // Hugging Face - huggingFaceApiKey?: string - huggingFaceModelId?: string - - // IO Intelligence - ioIntelligenceApiKey?: string - ioIntelligenceModelId?: string - - // Vercel AI Gateway - vercelAiGatewayApiKey?: string - vercelAiGatewayModelId?: string - - // Z.ai - zaiApiKey?: string - - // Moonshot - moonshotApiKey?: string - moonshotBaseUrl?: string - - // Doubao - doubaoApiKey?: string - doubaoBaseUrl?: string - - // MiniMax - minimaxApiKey?: string - minimaxBaseUrl?: string - - // OVHcloud - ovhCloudAiEndpointsApiKey?: string - ovhCloudAiEndpointsBaseUrl?: string - ovhCloudAiEndpointsModelId?: string - - // Inception Labs - inceptionLabsApiKey?: string - inceptionLabsBaseUrl?: string - inceptionLabsModelId?: string - - // SAP AI Core - sapAiCoreServiceKey?: string - - // Synthetic - syntheticApiKey?: string - - // NanoGPT - nanoGptApiKey?: string - nanoGptModelId?: string - - // Poe - poeApiKey?: string - poeModelId?: string - - // AiHubMix - aihubmixApiKey?: string - aihubmixModelId?: string - aihubmixBaseUrl?: string - - // ZenMux - zenmuxApiKey?: string - zenmuxModelId?: string - zenmuxBaseUrl?: string - - // Allow dynamic property access for provider-mapping lookups - [key: string]: unknown -} - -// --------------------------------------------------------------------------- -// MCP settings (stored on disk at /settings/mcp_settings.json) -// --------------------------------------------------------------------------- - -export interface LegacyMcpSettings { - mcpServers: Record -} - -export interface LegacyMcpServer { - type?: "stdio" | "sse" | "streamable-http" - command?: string - args?: string[] - cwd?: string - url?: string - env?: Record - headers?: Record - disabled?: boolean - timeout?: number -} - -// --------------------------------------------------------------------------- -// Autocomplete settings (stored in globalState under "ghostServiceSettings") -// --------------------------------------------------------------------------- - -export interface LegacyAutocompleteSettings { - enableAutoTrigger?: boolean - enableSmartInlineTaskKeybinding?: boolean - enableChatAutocomplete?: boolean -} - -// --------------------------------------------------------------------------- -// Settings (stored in VS Code globalState under "kilo-code.*" keys) -// --------------------------------------------------------------------------- - -export interface LegacySettings { - autoApprovalEnabled?: boolean - allowedCommands?: string[] - deniedCommands?: string[] - // Fine-grained auto-approval (legacy globalState keys — no prefix) - alwaysAllowReadOnly?: boolean - alwaysAllowReadOnlyOutsideWorkspace?: boolean - alwaysAllowWrite?: boolean - alwaysAllowExecute?: boolean - alwaysAllowMcp?: boolean - alwaysAllowModeSwitch?: boolean - alwaysAllowSubtasks?: boolean - language?: string - autocomplete?: LegacyAutocompleteSettings -} - -// --------------------------------------------------------------------------- -// Custom modes (stored on disk at /settings/custom_modes.yaml) -// --------------------------------------------------------------------------- - -interface LegacyCustomModesFile { - customModes: LegacyCustomMode[] -} - -export interface LegacyCustomMode { - slug: string - name: string - roleDefinition: string - customInstructions?: string - whenToUse?: string - description?: string - groups: Array]> -} - -// --------------------------------------------------------------------------- -// Custom mode prompts (stored in VS Code globalState under "customModePrompts") -// --------------------------------------------------------------------------- - -/** Partial prompt overrides the legacy extension stored per-mode in globalState */ -export interface LegacyPromptComponent { - roleDefinition?: string - customInstructions?: string - whenToUse?: string - description?: string -} - -// --------------------------------------------------------------------------- -// Migration data shapes -// --------------------------------------------------------------------------- - -export interface MigrationProviderInfo { - profileName: string - provider: string - model?: string - hasApiKey: boolean - supported: boolean - newProviderName?: string -} - -export interface MigrationMcpServerInfo { - name: string - type: string - disabled?: boolean -} - -export interface MigrationCustomModeInfo { - name: string - slug: string - /** Original slug when migrating a modified native mode under a new slug */ - nativeSlug?: string -} - export interface MigrationSessionInfo { id: string title: string @@ -306,49 +5,13 @@ export interface MigrationSessionInfo { time: number } -export interface LegacyMigrationData { - providers: MigrationProviderInfo[] - mcpServers: MigrationMcpServerInfo[] - customModes: MigrationCustomModeInfo[] - sessions?: MigrationSessionInfo[] - defaultModel?: { provider: string; model: string } - settings?: LegacySettings - hasData: boolean -} - -export interface MigrationAutoApprovalSelections { - /** Master toggle + command allowlist/denylist */ - commandRules: boolean - /** Read permission (alwaysAllowReadOnly / alwaysAllowReadOnlyOutsideWorkspace) */ - readPermission: boolean - /** Write permission (alwaysAllowWrite) */ - writePermission: boolean - /** Execute permission (alwaysAllowExecute) */ - executePermission: boolean - /** MCP tool permission (alwaysAllowMcp) */ - mcpPermission: boolean - /** Task/subtask permission (alwaysAllowModeSwitch / alwaysAllowSubtasks) */ - taskPermission: boolean -} - -export interface MigrationSettingsSelections { - autoApproval: MigrationAutoApprovalSelections - language: boolean - autocomplete: boolean -} - export interface MigrationSessionSelection { id: string force?: boolean } export interface MigrationSelections { - providers: string[] - mcpServers: string[] - customModes: string[] sessions?: MigrationSessionSelection[] - defaultModel: boolean - settings: MigrationSettingsSelections } export type MigrationSessionPhase = "preparing" | "storing" | "skipped" | "done" | "summary" | "error" diff --git a/packages/kilo-vscode/src/legacy-migration/migration-service.ts b/packages/kilo-vscode/src/legacy-migration/migration-service.ts deleted file mode 100644 index 9ac01ab8f4c..00000000000 --- a/packages/kilo-vscode/src/legacy-migration/migration-service.ts +++ /dev/null @@ -1,1273 +0,0 @@ -/** - * legacy-migration - Core migration service. - * - * Reads legacy Kilo Code v5.x data from VS Code SecretStorage and the extension's - * global storage directory, then writes it to the new CLI backend via the SDK. - */ - -import * as vscode from "vscode" -import type { KiloClient } from "@kilocode/sdk/v2/client" -import type { - McpLocalConfig, - McpRemoteConfig, - AgentConfig, - PermissionConfig, - PermissionObjectConfig, -} from "@kilocode/sdk/v2/client" -import { PROVIDER_MAP, UNSUPPORTED_PROVIDERS, DEFAULT_MODE_SLUGS } from "./provider-mapping" -import type { ProviderMapping } from "./provider-mapping" -import { NATIVE_MODE_DEFAULTS } from "./native-mode-defaults" -import { getMigrationErrorMessage } from "./errors/migration-error" -import type { - LegacyProviderProfiles, - LegacyProviderSettings, - LegacyMcpSettings, - LegacyCustomMode, - LegacyMcpServer, - LegacySettings, - LegacyAutocompleteSettings, - LegacyPromptComponent, - LegacyMigrationData, - MigrationSelections, - MigrationAutoApprovalSelections, - MigrationProviderInfo, - MigrationMcpServerInfo, - MigrationCustomModeInfo, - MigrationSessionInfo, - MigrationSessionProgress, -} from "./legacy-types" -import type { MigrationResultItem } from "./migration-types" -import { runSessionBatch } from "./session-batch" -import { listSessions, resolveSession, scanTaskStore } from "./task-store" -import { createSessionID } from "./sessions/lib/ids" -import type { LegacyHistoryItem } from "./sessions/lib/legacy-types" -import { migrate as migrateSession } from "./sessions/migrate" - -// --------------------------------------------------------------------------- -// Constants -// --------------------------------------------------------------------------- - -const SECRET_KEY = "roo_cline_config_api_config" -const CODEX_OAUTH_SECRET_KEY = "openai-codex-oauth-credentials" -const MIGRATION_STATUS_KEY = "kilo.legacyMigrationStatus" - -type MigrationStatus = "completed" | "completed_with_errors" | "skipped" - -// --------------------------------------------------------------------------- -// Status helpers -// --------------------------------------------------------------------------- - -export function getMigrationStatus(context: vscode.ExtensionContext): MigrationStatus | undefined { - return context.globalState.get(MIGRATION_STATUS_KEY) -} - -export async function setMigrationStatus(context: vscode.ExtensionContext, status: MigrationStatus): Promise { - await context.globalState.update(MIGRATION_STATUS_KEY, status) -} - -// --------------------------------------------------------------------------- -// Detection -// --------------------------------------------------------------------------- - -/** - * Reads legacy data from SecretStorage and global storage files. - * Returns a structured summary for display in the migration wizard. - */ -export async function detectLegacyData(context: vscode.ExtensionContext): Promise { - const profiles = await readLegacyProviderProfiles(context) - const mcpSettings = await readLegacyMcpSettings(context) - const customModes = await readLegacyCustomModes(context) - const prompts = readLegacyCustomModePrompts(context) - const settings = readLegacySettings(context) - const sessions = listSessions(await readSessionCatalog(context)) - - const oauthProviders = new Set() - const codexRaw = await context.secrets.get(CODEX_OAUTH_SECRET_KEY) - if (codexRaw) oauthProviders.add("openai-codex") - - const providers = buildProviderList(profiles, oauthProviders) - const mcpServers = buildMcpServerList(mcpSettings) - const modes = buildCustomModeList(customModes, prompts) - const defaultModel = resolveDefaultModel(profiles, oauthProviders) - - const hasSettings = - settings.autoApprovalEnabled !== undefined || - (settings.allowedCommands?.length ?? 0) > 0 || - (settings.deniedCommands?.length ?? 0) > 0 || - settings.alwaysAllowReadOnly !== undefined || - settings.alwaysAllowReadOnlyOutsideWorkspace !== undefined || - settings.alwaysAllowWrite !== undefined || - settings.alwaysAllowExecute !== undefined || - settings.alwaysAllowMcp !== undefined || - settings.alwaysAllowModeSwitch !== undefined || - settings.alwaysAllowSubtasks !== undefined || - Boolean(settings.language) || - Boolean(settings.autocomplete) - - const hasData = - providers.length > 0 || mcpServers.length > 0 || modes.length > 0 || hasSettings || sessions.length > 0 - - return { - providers, - mcpServers, - customModes: modes, - sessions: sessions.length > 0 ? sessions : undefined, - defaultModel, - settings: hasSettings ? settings : undefined, - hasData, - } -} - -async function readSessionCatalog(context: vscode.ExtensionContext) { - const items = context.globalState.get("taskHistory", []) - const dir = vscode.Uri.joinPath(context.globalStorageUri, "tasks").fsPath - return (await scanTaskStore(dir, items, { mode: "history" })).catalog -} - -// --------------------------------------------------------------------------- -// Migration -// --------------------------------------------------------------------------- - -export type ProgressCallback = ( - item: string, - status: "migrating" | "success" | "warning" | "error", - message?: string, -) => void - -export type SessionProgressCallback = (progress: MigrationSessionProgress) => void - -/** - * Executes migration for the selected items. - * Calls onProgress for each item with real-time status updates. - * Pass `cachedSettings` (from a prior detectLegacyData call) to avoid re-reading - * globalState. Provider profiles, MCP servers, and custom modes are always re-read - * from SecretStorage/disk to ensure the data is current at migration time. - */ -export async function migrate( - context: vscode.ExtensionContext, - client: KiloClient, - selections: MigrationSelections, - onProgress: ProgressCallback, - onSessionProgress?: SessionProgressCallback, - cachedSettings?: LegacySettings, - cachedSessions?: MigrationSessionInfo[], -): Promise { - const profiles = await readLegacyProviderProfiles(context) - const mcpSettings = await readLegacyMcpSettings(context) - const customModes = await readLegacyCustomModes(context) - const prompts = readLegacyCustomModePrompts(context) - const legacySettings = cachedSettings ?? readLegacySettings(context) - const catalog = await readSessionCatalog(context) - const sessions = cachedSessions ?? listSessions(catalog) - - const results: MigrationResultItem[] = [] - - // Migrate provider API keys - for (const profileName of selections.providers) { - const settings = profiles?.apiConfigs[profileName] - if (!settings) { - results.push({ item: profileName, category: "provider", status: "error", message: "Profile not found" }) - continue - } - onProgress(profileName, "migrating") - const result = await migrateProvider(context, profileName, settings, client) - results.push(result) - onProgress(profileName, result.status, result.message) - } - - // Migrate MCP servers - if (selections.mcpServers.length > 0 && mcpSettings) { - const mcpConfig: Record = {} - for (const name of selections.mcpServers) { - const server = mcpSettings.mcpServers[name] - if (!server) { - results.push({ item: name, category: "mcpServer", status: "error", message: "Server not found" }) - continue - } - onProgress(name, "migrating") - const converted = convertMcpServer(server) - if (converted) { - mcpConfig[name] = converted - results.push({ item: name, category: "mcpServer", status: "success" }) - onProgress(name, "success") - } else { - results.push({ - item: name, - category: "mcpServer", - status: "warning", - message: "Could not convert server config", - }) - onProgress(name, "warning", "Could not convert server config") - } - } - if (Object.keys(mcpConfig).length > 0) { - await client.global.config.update({ config: { mcp: mcpConfig } }) - } - } - - // Migrate custom modes as agents - if (selections.customModes.length > 0) { - const agentConfig: Record = {} - // Build a lookup of detected modes by slug so we can resolve nativeSlug - const detected = buildCustomModeList(customModes, prompts) - for (const slug of selections.customModes) { - const info = detected.find((m) => m.slug === slug) - if (!info) { - results.push({ item: slug, category: "customMode", status: "error", message: "Mode not found" }) - continue - } - - if (info.nativeSlug) { - // Modified native mode — merge YAML custom mode + customModePrompts - const merged = buildMergedNativeMode( - customModes?.find((m) => m.slug === info.nativeSlug), - prompts?.[info.nativeSlug], - info.nativeSlug, - ) - if (merged) { - onProgress(info.name, "migrating") - const agent = convertCustomMode(merged) - // Set explicit name so the UI shows "(Custom)" instead of title-casing the slug - agent.name = info.name - agentConfig[slug] = agent - results.push({ item: info.name, category: "customMode", status: "success" }) - onProgress(info.name, "success") - } else { - results.push({ - item: info.name, - category: "customMode", - status: "error", - message: "Failed to build merged mode", - }) - } - } else { - // Regular custom mode (existing behavior) - const mode = customModes?.find((m) => m.slug === slug) - if (!mode) { - results.push({ item: slug, category: "customMode", status: "error", message: "Mode not found" }) - continue - } - onProgress(mode.name, "migrating") - agentConfig[slug] = convertCustomMode(mode) - results.push({ item: mode.name, category: "customMode", status: "success" }) - onProgress(mode.name, "success") - } - } - if (Object.keys(agentConfig).length > 0) { - await client.global.config.update({ config: { agent: agentConfig } }) - } - } - - if (selections.sessions?.length) { - results.push( - ...(await runSessionBatch({ - selections: selections.sessions, - sessions, - resolve: (id) => resolveSession(catalog, id), - migrate: (selection, source, progress) => migrateSession(selection, context, client, progress, source), - onProgress, - onSessionProgress, - })), - ) - } - - // Migrate default model - if (selections.defaultModel && profiles) { - const activeName = profiles.currentApiConfigName - const active = profiles.apiConfigs[activeName] - if (active) { - onProgress("Default model", "migrating") - const result = await migrateDefaultModel(active, client) - results.push(result) - onProgress("Default model", result.status, result.message) - } - } - - // Migrate auto-approval settings (granular, each selected item is independent) - const apSel = selections.settings.autoApproval - if ( - apSel.commandRules || - apSel.readPermission || - apSel.writePermission || - apSel.executePermission || - apSel.mcpPermission || - apSel.taskPermission - ) { - const apItems = await migrateAutoApproval(legacySettings, apSel, client, onProgress) - results.push(...apItems) - } - - // Migrate language setting - if (selections.settings.language && legacySettings.language) { - onProgress("Language preference", "migrating") - const result = await migrateLanguage(legacySettings.language) - results.push(result) - onProgress("Language preference", result.status, result.message) - } - - // Migrate autocomplete settings - if (selections.settings.autocomplete && legacySettings.autocomplete) { - onProgress("Autocomplete settings", "migrating") - const result = await migrateAutocomplete(legacySettings.autocomplete) - results.push(result) - onProgress("Autocomplete settings", result.status, result.message) - } - - return results -} - -// --------------------------------------------------------------------------- -// Cleanup -// --------------------------------------------------------------------------- - -/** - * Removes legacy data from SecretStorage, globalState, and VS Code settings. - */ -export async function clearLegacyData(context: vscode.ExtensionContext): Promise { - await context.secrets.delete(SECRET_KEY) - await context.secrets.delete(CODEX_OAUTH_SECRET_KEY) - - const legacyStateKeys = [ - "kilo-code.allowedCommands", - "kilo-code.deniedCommands", - "kilo-code.autoApprovalEnabled", - "kilo-code.fuzzyMatchThreshold", - "kilo-code.diffEnabled", - "kilo-code.language", - "kilo-code.customModes", - "kilo-code.firstInstallCompleted", - "kilo-code.telemetrySetting", - "ghostServiceSettings", - // Fine-grained auto-approval keys (no prefix in legacy globalState) - "alwaysAllowReadOnly", - "alwaysAllowReadOnlyOutsideWorkspace", - "alwaysAllowWrite", - "alwaysAllowWriteOutsideWorkspace", - "alwaysAllowWriteProtected", - "alwaysAllowDelete", - "alwaysAllowExecute", - "alwaysAllowBrowser", - "alwaysAllowMcp", - "alwaysAllowModeSwitch", - "alwaysAllowSubtasks", - "alwaysAllowFollowupQuestions", - "followupAutoApproveTimeoutMs", - ] - for (const key of legacyStateKeys) { - await context.globalState.update(key, undefined) - } - - // Clear legacy VS Code settings registered under the "kilo-code" configuration scope. - // These are set via the old extension's contributes.configuration and persist in the - // user's settings.json even after the extension is uninstalled. - const legacyVscodeSettings = [ - "allowedCommands", - "deniedCommands", - "commandExecutionTimeout", - "commandTimeoutAllowlist", - "preventCompletionWithOpenTodos", - "vsCodeLmModelSelector", - "customStoragePath", - "enableCodeActions", - "autoImportSettingsPath", - "maximumIndexedFilesForFileSearch", - "useAgentRules", - "apiRequestTimeout", - "newTaskRequireTodos", - "enableSettingsSync", - "toolProtocol", - "debug", - ] - const cfg = vscode.workspace.getConfiguration("kilo-code") - for (const key of legacyVscodeSettings) { - await cfg.update(key, undefined, vscode.ConfigurationTarget.Global) - } -} - -// --------------------------------------------------------------------------- -// Internal — provider migration -// --------------------------------------------------------------------------- - -async function migrateProvider( - context: vscode.ExtensionContext, - profileName: string, - settings: LegacyProviderSettings, - client: KiloClient, -): Promise { - const provider = settings.apiProvider - if (!provider) { - return { item: profileName, category: "provider", status: "error", message: "No provider type found" } - } - - if (UNSUPPORTED_PROVIDERS.has(provider)) { - return { - item: profileName, - category: "provider", - status: "warning", - message: `Provider "${provider}" is not supported in the new version`, - } - } - - const mapping = PROVIDER_MAP[provider] - if (!mapping) { - return { - item: profileName, - category: "provider", - status: "warning", - message: `Unknown provider "${provider}"`, - } - } - - // OAuth providers store credentials in a separate VS Code secret - if (mapping.oauthSecretKey) { - const creds = await readOAuthCredentials(context, mapping.oauthSecretKey) - if (!creds) { - return { item: profileName, category: "provider", status: "warning", message: "No OAuth credentials found" } - } - await client.auth.set({ providerID: mapping.id, auth: { type: "oauth" as const, ...creds } }) - return { item: profileName, category: "provider", status: "success" } - } - - // Providers that use env/ADC-based auth (e.g. Vertex AI) — skip auth.set, only migrate config options - if (mapping.skipAuth) { - await migrateConfigFields(mapping, settings, client) - // Warn users who had inline service account credentials — the CLI uses ADC only - const hadCredentials = Boolean(settings.vertexJsonCredentials ?? settings.vertexKeyFile) - return { - item: profileName, - category: "provider", - status: hadCredentials ? "warning" : "success", - message: hadCredentials - ? "Project and location migrated. The new CLI uses Application Default Credentials — set GOOGLE_APPLICATION_CREDENTIALS or run 'gcloud auth application-default login'" - : undefined, - } - } - - const apiKey = settings[mapping.key] as string | undefined - if (!apiKey) { - return { item: profileName, category: "provider", status: "warning", message: "No API key found in profile" } - } - - // The profile endpoint requires type:"oauth". The legacy extension stored the same Kilo - // API token — write it in the OAuth format the new extension expects (matching device-auth: - // access + refresh + 1-year expiry). - if (mapping.id === "kilo") { - const org = mapping.organizationIdField ? (settings[mapping.organizationIdField] as string | undefined) : undefined - await client.auth.set({ - providerID: "kilo", - auth: { - type: "oauth" as const, - access: apiKey, - refresh: apiKey, - expires: Date.now() + 365 * 24 * 60 * 60 * 1000, - accountId: org, - }, - }) - return { item: profileName, category: "provider", status: "success" } - } - - // For providers that support an organization ID (e.g. Kilo Gateway), migrate using OAuth - // auth so the CLI can read accountId for org-scoped API requests. - const organizationId = mapping.organizationIdField - ? (settings[mapping.organizationIdField] as string | undefined) - : undefined - - const auth = organizationId - ? { type: "oauth" as const, access: apiKey, refresh: "", expires: 0, accountId: organizationId } - : { type: "api" as const, key: apiKey } - - await client.auth.set({ providerID: mapping.id, auth }) - - // If a custom base URL is configured, also persist it to the backend config - if (mapping.urlField) { - const url = settings[mapping.urlField] as string | undefined - if (url) { - await client.global.config.update({ - config: { provider: { [mapping.id]: { options: { apiKey, baseURL: url } } } }, - }) - } - } - - await migrateConfigFields(mapping, settings, client) - - return { item: profileName, category: "provider", status: "success" } -} - -async function migrateConfigFields( - mapping: ProviderMapping, - settings: LegacyProviderSettings, - client: KiloClient, -): Promise { - if (!mapping.configFields?.length) return - const opts: Record = {} - for (const { from, option } of mapping.configFields) { - const val = settings[from] as string | undefined - if (val) opts[option] = val - } - if (Object.keys(opts).length > 0) { - await client.global.config.update({ - config: { provider: { [mapping.id]: { options: opts } } }, - }) - } -} - -async function migrateDefaultModel(settings: LegacyProviderSettings, client: KiloClient): Promise { - const provider = settings.apiProvider - if (!provider) { - return { item: "Default model", category: "defaultModel", status: "error", message: "No provider type found" } - } - - const mapping = PROVIDER_MAP[provider] - if (!mapping) { - return { - item: "Default model", - category: "defaultModel", - status: "warning", - message: `Provider "${provider}" is not supported in the new version`, - } - } - - const modelField = mapping.modelField ?? "apiModelId" - const modelId = settings[modelField] as string | undefined - if (!modelId) { - return { item: "Default model", category: "defaultModel", status: "warning", message: "No model ID found" } - } - - await client.global.config.update({ config: { model: `${mapping.id}/${modelId}` } }) - return { item: "Default model", category: "defaultModel", status: "success" } -} - -// --------------------------------------------------------------------------- -// Internal — settings migration (auto-approval, language) -// --------------------------------------------------------------------------- - -async function migrateAutoApproval( - settings: LegacySettings, - sel: MigrationAutoApprovalSelections, - client: KiloClient, - onProgress: ProgressCallback, -): Promise { - const { - autoApprovalEnabled, - allowedCommands, - deniedCommands, - alwaysAllowReadOnly, - alwaysAllowReadOnlyOutsideWorkspace, - alwaysAllowWrite, - alwaysAllowExecute, - alwaysAllowMcp, - alwaysAllowModeSwitch, - alwaysAllowSubtasks, - } = settings - - // The master toggle acts as a global fallback for unspecified tools. - const fallback: "allow" | "ask" = autoApprovalEnabled === true ? "allow" : "ask" - - const results: MigrationResultItem[] = [] - // We collect all permission updates and apply them in one call at the end. - const permission: PermissionConfig = {} - // Track if global "allow" was already written so we skip the per-tool object update - // that would otherwise overwrite it with a narrower permission set. - let globalAllowApplied = false - - // Command rules: master toggle + allowedCommands + deniedCommands - if (sel.commandRules) { - const label = "Command rules" - onProgress(label, "migrating") - const hasCommandLists = Boolean(allowedCommands?.length || deniedCommands?.length) - if (autoApprovalEnabled === true && !hasCommandLists) { - // Global allow with no specific command rules — apply immediately using the scalar form. - // PermissionConfig is "allow" | "ask" | "deny" | { read?: ..., ... }, so a global allow - // must be the scalar string, not an object with a "*" key. - await client.global.config.update({ config: { permission: "allow" } }) - globalAllowApplied = true - } else if (hasCommandLists) { - const bashRules: PermissionObjectConfig = {} - // The legacy system matched commands as longest prefix (e.g. "npm run" matched "npm run dev"). - // The new CLI uses Wildcard.match with full command text anchored to ^ and $, so "npm run" - // would only match the literal string "npm run". Appending " *" approximates prefix semantics: - // Wildcard.match treats trailing " *" as "( .*)?", matching with or without arguments. - for (const cmd of allowedCommands ?? []) { - bashRules[cmd.trimEnd() + " *"] = "allow" - } - for (const cmd of deniedCommands ?? []) { - bashRules[cmd.trimEnd() + " *"] = "deny" - } - // alwaysAllowExecute=false must override the master toggle - bashRules["*"] = alwaysAllowExecute === true ? "allow" : alwaysAllowExecute === false ? "ask" : fallback - permission.bash = bashRules - } - results.push({ item: label, category: "settings", status: "success" }) - onProgress(label, "success") - } - - // Read permissions - if (sel.readPermission) { - const label = "Read permission" - onProgress(label, "migrating") - if (alwaysAllowReadOnly === true) { - permission.read = "allow" - permission.glob = "allow" - permission.grep = "allow" - permission.list = "allow" - } else if (alwaysAllowReadOnly === false) { - permission.read = "ask" - } - if (alwaysAllowReadOnlyOutsideWorkspace === true) { - permission.external_directory = "allow" - } else if (alwaysAllowReadOnlyOutsideWorkspace === false) { - permission.external_directory = "ask" - } - results.push({ item: label, category: "settings", status: "success" }) - onProgress(label, "success") - } - - // Write permissions - if (sel.writePermission) { - const label = "Write permission" - onProgress(label, "migrating") - if (alwaysAllowWrite === true) { - permission.edit = "allow" - } else if (alwaysAllowWrite === false) { - permission.edit = "ask" - } - results.push({ item: label, category: "settings", status: "success" }) - onProgress(label, "success") - } - - // Execute permissions (bash only — command lists handled above in commandRules) - if (sel.executePermission && !sel.commandRules) { - const label = "Execute permission" - onProgress(label, "migrating") - if (alwaysAllowExecute === true) { - permission.bash = "allow" - } else if (alwaysAllowExecute === false) { - permission.bash = "ask" - } - results.push({ item: label, category: "settings", status: "success" }) - onProgress(label, "success") - } else if (sel.executePermission) { - // executePermission selected together with commandRules — bash rules already built above, - // just record the result item - results.push({ item: "Execute permission", category: "settings", status: "success" }) - } - - // MCP / skill permissions - if (sel.mcpPermission) { - const label = "MCP permission" - onProgress(label, "migrating") - if (alwaysAllowMcp === true) { - permission.skill = "allow" - } else if (alwaysAllowMcp === false) { - permission.skill = "ask" - } - results.push({ item: label, category: "settings", status: "success" }) - onProgress(label, "success") - } - - // Task / subtask permissions - if (sel.taskPermission) { - const label = "Task permission" - onProgress(label, "migrating") - if (alwaysAllowModeSwitch === true || alwaysAllowSubtasks === true) { - permission.task = "allow" - } else if (alwaysAllowModeSwitch === false && alwaysAllowSubtasks === false) { - permission.task = "ask" - } - results.push({ item: label, category: "settings", status: "success" }) - onProgress(label, "success") - } - - // Only write the per-tool object form if global allow wasn't already applied — - // writing an object after "allow" would narrow permissions to only the listed tools. - if (!globalAllowApplied && Object.keys(permission).length > 0) { - await client.global.config.update({ config: { permission } }) - } - - return results -} - -async function migrateAutocomplete(settings: LegacyAutocompleteSettings): Promise { - try { - const config = vscode.workspace.getConfiguration("kilo-code.new.autocomplete") - if (settings.enableAutoTrigger !== undefined) { - await config.update("enableAutoTrigger", settings.enableAutoTrigger, vscode.ConfigurationTarget.Global) - } - if (settings.enableSmartInlineTaskKeybinding !== undefined) { - await config.update( - "enableSmartInlineTaskKeybinding", - settings.enableSmartInlineTaskKeybinding, - vscode.ConfigurationTarget.Global, - ) - } - if (settings.enableChatAutocomplete !== undefined) { - await config.update("enableChatAutocomplete", settings.enableChatAutocomplete, vscode.ConfigurationTarget.Global) - } - return { item: "Autocomplete settings", category: "settings", status: "success" } - } catch (err) { - return { - item: "Autocomplete settings", - category: "settings", - status: "error", - message: getMigrationErrorMessage(err), - } - } -} - -// Maps legacy locale codes to their new-extension equivalents. -// Legacy used IETF BCP-47 tags (zh-CN, pt-BR) while the new extension uses short codes. -// Entries absent from this map have no equivalent in the new extension. -const LEGACY_LOCALE_MAP: Record = { - // Direct matches - en: "en", - de: "de", - es: "es", - fr: "fr", - ja: "ja", - ko: "ko", - pl: "pl", - ru: "ru", - ar: "ar", - th: "th", - da: "da", - no: "no", - bs: "bs", - // Format changes - "zh-CN": "zh", - "zh-TW": "zht", - "pt-BR": "br", -} - -async function migrateLanguage(language: string): Promise { - const mapped = LEGACY_LOCALE_MAP[language] - if (!mapped) { - return { - item: "Language preference", - category: "settings", - status: "warning", - message: `Language "${language}" is not supported in the new version`, - } - } - try { - const config = vscode.workspace.getConfiguration("kilo-code.new") - await config.update("language", mapped, vscode.ConfigurationTarget.Global) - return { item: "Language preference", category: "settings", status: "success" } - } catch (err) { - return { - item: "Language preference", - category: "settings", - status: "error", - message: getMigrationErrorMessage(err), - } - } -} - -// --------------------------------------------------------------------------- -// Internal — MCP conversion (legacy → McpServerConfig) -// --------------------------------------------------------------------------- - -function convertMcpServer(server: LegacyMcpServer): McpLocalConfig | McpRemoteConfig | null { - const enabled = server.disabled ? { enabled: false as const } : {} - // Legacy stores timeout in seconds, the new config expects milliseconds - const timeout = server.timeout !== undefined ? server.timeout * 1000 : undefined - if (server.type === "sse" || server.type === "streamable-http") { - if (!server.url) return null - return { - type: "remote", - url: server.url, - headers: server.headers, - ...(timeout !== undefined && { timeout }), - ...enabled, - } - } - // Default: stdio - if (!server.command) return null - const command = server.args ? [server.command, ...server.args] : [server.command] - return { - type: "local", - command, - environment: server.env, - ...(timeout !== undefined && { timeout }), - ...enabled, - } -} - -// --------------------------------------------------------------------------- -// Internal — custom mode conversion (legacy → AgentConfig) -// --------------------------------------------------------------------------- - -// Group name → CLI permission key (mirrors ModesMigrator.convertPermissions in the CLI) -const GROUP_TO_PERMISSION: Record = { - read: "read", - edit: "edit", - browser: "bash", - command: "bash", - mcp: "skill", -} -const ALL_MODE_PERMISSIONS = ["read", "edit", "bash", "skill"] - -function convertCustomModePermissions(groups: LegacyCustomMode["groups"]): PermissionConfig { - const permission: Record = {} - const allowed = new Set() - - for (const group of groups) { - const groupName = typeof group === "string" ? group : group[0] - const groupConfig = typeof group === "string" ? undefined : group[1] - const permKey = GROUP_TO_PERMISSION[groupName] ?? groupName - allowed.add(permKey) - - const newValue = groupConfig?.fileRegex ? { [groupConfig.fileRegex]: "allow", "*": "deny" } : "allow" - - // Multiple legacy groups can map to the same permission key (browser + command → bash). - // Merge rules so neither overwrites the other: - // - if either side is "allow", the key is fully allowed - // - if both sides are objects, merge their pattern maps - const existing = permission[permKey] - if (existing === undefined) { - permission[permKey] = newValue - } else if (existing === "allow" || newValue === "allow") { - permission[permKey] = "allow" - } else if (typeof existing === "object" && typeof newValue === "object") { - permission[permKey] = { ...existing, ...newValue } - } else { - permission[permKey] = newValue - } - } - - // Explicitly deny permissions not in the groups (CLI defaults to "ask" for missing ones) - for (const perm of ALL_MODE_PERMISSIONS) { - if (!allowed.has(perm)) { - permission[perm] = "deny" - } - } - - return permission as PermissionConfig -} - -function convertCustomMode(mode: LegacyCustomMode): AgentConfig { - const parts = [mode.roleDefinition] - if (mode.customInstructions?.trim()) { - parts.push( - [ - "USER'S CUSTOM INSTRUCTIONS", - "", - "The following additional instructions are provided by the user, and should be followed to the best of your ability.", - "", - `Mode-specific Instructions:\n${mode.customInstructions.trim()}`, - ].join("\n"), - ) - } - return { - mode: "primary", - description: mode.description ?? mode.whenToUse ?? mode.roleDefinition?.slice(0, 120), - prompt: parts.filter(Boolean).join("\n\n"), - permission: convertCustomModePermissions(mode.groups), - } -} - -// --------------------------------------------------------------------------- -// Internal — OAuth credential helpers -// --------------------------------------------------------------------------- - -/** - * Reads OAuth credentials stored in a separate VS Code secret (e.g. openai-codex-oauth-credentials). - * Returns the fields needed by the CLI's Auth.Oauth type, or null if absent/malformed. - */ -async function readOAuthCredentials( - context: vscode.ExtensionContext, - secretKey: string, -): Promise<{ access: string; refresh: string; expires: number; accountId?: string } | null> { - const raw = await context.secrets.get(secretKey) - if (!raw) return null - const parsed = (() => { - try { - return JSON.parse(raw) as Record - } catch { - return null - } - })() - if (!parsed) return null - const access = parsed.access_token as string | undefined - const refresh = parsed.refresh_token as string | undefined - const expires = parsed.expires as number | undefined - if (!access || !refresh || expires === undefined) return null - return { access, refresh, expires, accountId: parsed.accountId as string | undefined } -} - -// --------------------------------------------------------------------------- -// Internal — reading legacy data from storage -// --------------------------------------------------------------------------- - -async function readLegacyProviderProfiles(context: vscode.ExtensionContext): Promise { - const raw = await context.secrets.get(SECRET_KEY) - if (!raw) return null - try { - const parsed = JSON.parse(raw) as Record - if (!parsed.apiConfigs || typeof parsed.apiConfigs !== "object") return null - return parsed as unknown as LegacyProviderProfiles - } catch { - return null - } -} - -async function readLegacyMcpSettings(context: vscode.ExtensionContext): Promise { - const filePath = vscode.Uri.joinPath(context.globalStorageUri, "settings", "mcp_settings.json") - const bytes = await vscode.workspace.fs.readFile(filePath).then( - (b) => b, - () => null, - ) - if (!bytes) return null - try { - const parsed = JSON.parse(Buffer.from(bytes).toString("utf8")) as Record - if (!parsed.mcpServers || typeof parsed.mcpServers !== "object") return null - return parsed as unknown as LegacyMcpSettings - } catch { - return null - } -} - -async function readLegacyCustomModes(context: vscode.ExtensionContext): Promise { - const filePath = vscode.Uri.joinPath(context.globalStorageUri, "settings", "custom_modes.yaml") - const bytes = await vscode.workspace.fs.readFile(filePath).then( - (b) => b, - () => null, - ) - if (!bytes) return null - const text = Buffer.from(bytes).toString("utf8") - return parseCustomModesYaml(text) -} - -function readLegacyCustomModePrompts(context: vscode.ExtensionContext): Record | null { - return context.globalState.get>("customModePrompts") ?? null -} - -function readLegacySettings(context: vscode.ExtensionContext): LegacySettings { - const raw = context.globalState.get>("ghostServiceSettings") - const autocomplete: LegacyAutocompleteSettings | undefined = - raw && typeof raw === "object" - ? { - enableAutoTrigger: raw.enableAutoTrigger as boolean | undefined, - enableSmartInlineTaskKeybinding: raw.enableSmartInlineTaskKeybinding as boolean | undefined, - enableChatAutocomplete: raw.enableChatAutocomplete as boolean | undefined, - } - : undefined - - return { - autoApprovalEnabled: context.globalState.get("kilo-code.autoApprovalEnabled"), - allowedCommands: context.globalState.get("kilo-code.allowedCommands"), - deniedCommands: context.globalState.get("kilo-code.deniedCommands"), - // Fine-grained auto-approval — stored without prefix in legacy globalState - alwaysAllowReadOnly: context.globalState.get("alwaysAllowReadOnly"), - alwaysAllowReadOnlyOutsideWorkspace: context.globalState.get("alwaysAllowReadOnlyOutsideWorkspace"), - alwaysAllowWrite: context.globalState.get("alwaysAllowWrite"), - alwaysAllowExecute: context.globalState.get("alwaysAllowExecute"), - alwaysAllowMcp: context.globalState.get("alwaysAllowMcp"), - alwaysAllowModeSwitch: context.globalState.get("alwaysAllowModeSwitch"), - alwaysAllowSubtasks: context.globalState.get("alwaysAllowSubtasks"), - language: context.globalState.get("kilo-code.language"), - autocomplete: hasAutocompleteData(autocomplete) ? autocomplete : undefined, - } -} - -function hasAutocompleteData(s: LegacyAutocompleteSettings | undefined): s is LegacyAutocompleteSettings { - if (!s) return false - return ( - s.enableAutoTrigger !== undefined || - s.enableSmartInlineTaskKeybinding !== undefined || - s.enableChatAutocomplete !== undefined - ) -} - -/** - * Minimal YAML parser for the custom_modes.yaml format. - * Tries JSON first (some legacy versions stored JSON), then parses the simple - * YAML structure manually to avoid a runtime dependency on a YAML library. - */ -// Strip surrounding single or double quotes from a YAML scalar value -function stripYamlQuotes(value: string): string { - return value.replace(/^(['"])(.*)\1$/, "$2") -} - -function parseCustomModesYaml(text: string): LegacyCustomMode[] | null { - // Try JSON first - const jsonResult = (() => { - try { - const parsed = JSON.parse(text) as { customModes?: LegacyCustomMode[] } - return parsed.customModes ?? null - } catch { - return null - } - })() - if (jsonResult) return jsonResult - - // Parse the simple YAML shape: - // customModes: - // - slug: xxx - // name: xxx - // roleDefinition: | - // ... - // groups: - // - read - const modes: LegacyCustomMode[] = [] - const lines = text.split("\n") - let inModes = false - let current: Partial | null = null - // Track which block scalar field is currently being collected - let blockField: "roleDefinition" | "customInstructions" | null = null - let inGroups = false - let blockLines: string[] = [] - - const flush = () => { - if (current?.slug && current?.name) { - if (blockField && blockLines.length > 0) { - current[blockField] = blockLines.join("\n").trim() - } - modes.push({ groups: [], ...current } as LegacyCustomMode) - } - current = null - blockField = null - inGroups = false - blockLines = [] - } - - for (const rawLine of lines) { - if (!inModes) { - if (rawLine.trim() === "customModes:") inModes = true - continue - } - - if (/^ - slug: /.test(rawLine)) { - flush() - current = { slug: stripYamlQuotes(rawLine.replace(/^ - slug: /, "").trim()), groups: [] } - continue - } - - if (!current) continue - - if (/^ name: /.test(rawLine)) { - current.name = stripYamlQuotes(rawLine.replace(/^ name: /, "").trim()) - continue - } - - // Block scalar fields (roleDefinition, customInstructions) with | or > - const blockMatch = rawLine.match(/^ (roleDefinition|customInstructions): [|>]/) - if (blockMatch) { - // Flush any previously open block - if (blockField && blockLines.length > 0) { - current[blockField] = blockLines.join("\n").trim() - } - blockField = blockMatch[1] as "roleDefinition" | "customInstructions" - inGroups = false - blockLines = [] - continue - } - - // Single-line scalar fields - if (/^ roleDefinition: /.test(rawLine) && !blockField) { - current.roleDefinition = stripYamlQuotes(rawLine.replace(/^ roleDefinition: /, "").trim()) - continue - } - - if (/^ customInstructions: /.test(rawLine) && !blockField) { - current.customInstructions = stripYamlQuotes(rawLine.replace(/^ customInstructions: /, "").trim()) - continue - } - - if (/^ whenToUse: /.test(rawLine) && !blockField) { - current.whenToUse = stripYamlQuotes(rawLine.replace(/^ whenToUse: /, "").trim()) - continue - } - - if (/^ description: /.test(rawLine) && !blockField) { - current.description = stripYamlQuotes(rawLine.replace(/^ description: /, "").trim()) - continue - } - - // Continuation lines of an open block scalar - if (blockField) { - if (/^ /.test(rawLine)) { - blockLines.push(rawLine.replace(/^ /, "")) - continue - } - // Block ended — flush and fall through to process this line - current[blockField] = blockLines.join("\n").trim() - blockField = null - blockLines = [] - } - - if (/^ groups:/.test(rawLine)) { - inGroups = true - current.groups = [] - continue - } - - if (inGroups && /^ - /.test(rawLine)) { - const group = stripYamlQuotes(rawLine.replace(/^ - /, "").trim()) - current.groups = [...(current.groups ?? []), group] - continue - } - - if (inGroups && !/^ /.test(rawLine)) { - inGroups = false - } - } - - flush() - return modes.length > 0 ? modes : null -} - -// --------------------------------------------------------------------------- -// Internal — building display lists for the wizard -// --------------------------------------------------------------------------- - -function buildProviderList( - profiles: LegacyProviderProfiles | null, - oauthProviders: Set, -): MigrationProviderInfo[] { - if (!profiles?.apiConfigs) return [] - - return Object.entries(profiles.apiConfigs).map(([profileName, settings]) => { - const provider = settings.apiProvider ?? "unknown" - const mapping = PROVIDER_MAP[provider] - const unsupported = UNSUPPORTED_PROVIDERS.has(provider) - - const modelField = mapping?.modelField ?? "apiModelId" - const model = settings[modelField] as string | undefined - - const hasApiKey = mapping?.oauthSecretKey - ? oauthProviders.has(provider) - : mapping?.skipAuth - ? (mapping.configFields?.some((f) => Boolean(settings[f.from])) ?? false) - : mapping - ? Boolean(settings[mapping.key]) - : false - - return { - profileName, - provider, - model, - hasApiKey, - supported: Boolean(mapping) && !unsupported, - newProviderName: mapping?.name, - } - }) -} - -function buildMcpServerList(settings: LegacyMcpSettings | null): MigrationMcpServerInfo[] { - if (!settings?.mcpServers) return [] - return Object.entries(settings.mcpServers).map(([name, server]) => ({ - name, - type: server.type ?? "stdio", - disabled: server.disabled, - })) -} - -/** @internal — exported for testing only */ -export function buildCustomModeList( - modes: LegacyCustomMode[] | null, - prompts: Record | null, -): MigrationCustomModeInfo[] { - const result: MigrationCustomModeInfo[] = [] - - // Non-native custom modes (existing behavior) - if (modes) { - for (const m of modes) { - if (!DEFAULT_MODE_SLUGS.has(m.slug)) { - result.push({ name: m.name, slug: m.slug }) - } - } - } - - // Modified native modes — detect user modifications and offer migration under a new slug - for (const slug of DEFAULT_MODE_SLUGS) { - const defaults = NATIVE_MODE_DEFAULTS[slug] - if (!defaults) continue // "build" has no legacy defaults - - const yaml = modes?.find((m) => m.slug === slug) - const prompt = prompts?.[slug] - - if (!isNativeModeModified(yaml, prompt, defaults)) continue - - const name = yaml?.name ?? defaults.name - result.push({ name: `${name} (Custom)`, slug: `${slug}-custom`, nativeSlug: slug }) - } - - return result -} - -/** - * Checks whether a native mode has been meaningfully modified from its defaults. - * A full YAML override always counts as modified. For customModePrompts, we compare - * each field against the known default and only count it if it actually differs. - * @internal — exported for testing only - */ -export function isNativeModeModified( - yaml: LegacyCustomMode | undefined, - prompt: LegacyPromptComponent | undefined, - defaults: { roleDefinition: string; customInstructions?: string; whenToUse?: string; description?: string }, -): boolean { - if (yaml) return true - if (!prompt) return false - - if (prompt.roleDefinition && prompt.roleDefinition !== defaults.roleDefinition) return true - if (prompt.customInstructions && prompt.customInstructions !== (defaults.customInstructions ?? "")) return true - if (prompt.whenToUse && prompt.whenToUse !== (defaults.whenToUse ?? "")) return true - if (prompt.description && prompt.description !== (defaults.description ?? "")) return true - - return false -} - -/** - * Builds a merged LegacyCustomMode for a modified native mode by combining the YAML - * custom mode (if any) with customModePrompts overrides. When only prompts exist, the - * native defaults provide the base structure (name, groups). - * @internal — exported for testing only - */ -export function buildMergedNativeMode( - yaml: LegacyCustomMode | undefined, - prompt: LegacyPromptComponent | undefined, - slug: string, -): LegacyCustomMode | null { - const defaults = NATIVE_MODE_DEFAULTS[slug] - if (!defaults) return null - - const base: LegacyCustomMode = yaml - ? { ...yaml } - : { - slug, - name: defaults.name, - roleDefinition: defaults.roleDefinition, - customInstructions: defaults.customInstructions, - whenToUse: defaults.whenToUse, - description: defaults.description, - groups: [...defaults.groups], - } - - // Overlay customModePrompts on top (matching legacy runtime behavior) - if (prompt) { - if (prompt.roleDefinition) base.roleDefinition = prompt.roleDefinition - if (prompt.customInstructions) base.customInstructions = prompt.customInstructions - if (prompt.whenToUse) base.whenToUse = prompt.whenToUse - if (prompt.description) base.description = prompt.description - } - - return base -} - -function resolveDefaultModel( - profiles: LegacyProviderProfiles | null, - oauthProviders: Set, -): { provider: string; model: string } | undefined { - if (!profiles?.currentApiConfigName) return undefined - const active = profiles.apiConfigs[profiles.currentApiConfigName] - if (!active?.apiProvider) return undefined - const mapping = PROVIDER_MAP[active.apiProvider] - if (!mapping) return undefined - // If the active profile requires OAuth credentials (e.g. openai-codex) but they are - // unavailable, do not offer default-model migration — it would write a broken reference. - if (mapping.oauthSecretKey && !oauthProviders.has(active.apiProvider)) return undefined - const modelField = mapping.modelField ?? "apiModelId" - const model = active[modelField] as string | undefined - if (!model) return undefined - return { provider: mapping.name, model } -} diff --git a/packages/kilo-vscode/src/legacy-migration/migration-session-progress.ts b/packages/kilo-vscode/src/legacy-migration/migration-session-progress.ts index 128cefa10a2..ecb898299be 100644 --- a/packages/kilo-vscode/src/legacy-migration/migration-session-progress.ts +++ b/packages/kilo-vscode/src/legacy-migration/migration-session-progress.ts @@ -1,5 +1,5 @@ import type { MigrationSessionInfo, MigrationSessionProgress } from "./legacy-types" -import type { SessionProgressCallback } from "./migration-service" +type SessionProgressCallback = (progress: MigrationSessionProgress) => void export interface MigrationSessionMeta { session: MigrationSessionInfo diff --git a/packages/kilo-vscode/src/legacy-migration/migration-types.ts b/packages/kilo-vscode/src/legacy-migration/migration-types.ts index bd32d39ffd5..02b4a012d62 100644 --- a/packages/kilo-vscode/src/legacy-migration/migration-types.ts +++ b/packages/kilo-vscode/src/legacy-migration/migration-types.ts @@ -1,6 +1,6 @@ export interface MigrationResultItem { item: string - category: "provider" | "mcpServer" | "customMode" | "defaultModel" | "settings" | "session" + category: "session" status: "success" | "warning" | "error" message?: string } diff --git a/packages/kilo-vscode/src/legacy-migration/native-mode-defaults.ts b/packages/kilo-vscode/src/legacy-migration/native-mode-defaults.ts deleted file mode 100644 index e8f52c0d6b6..00000000000 --- a/packages/kilo-vscode/src/legacy-migration/native-mode-defaults.ts +++ /dev/null @@ -1,91 +0,0 @@ -/** - * legacy-migration - Default values for native modes from the legacy Kilo Code v5.x extension. - * - * These are the exact built-in mode definitions shipped with the legacy extension. - * They are frozen references used to detect whether a user has actually modified a - * native mode's prompts before migrating it as a custom agent. - */ - -import type { LegacyCustomMode } from "./legacy-types" - -/** Prompt-level fields we compare against to detect modifications */ -export interface NativeModeDefaults { - name: string - roleDefinition: string - customInstructions?: string - whenToUse?: string - /** Short description shown in the UI (e.g., "Write, modify, and refactor code") */ - description?: string - groups: LegacyCustomMode["groups"] -} - -/** - * Built-in default values for each native mode slug from legacy Kilo Code v5.x. - * "build" is excluded because it does not exist as a legacy built-in mode. - */ -export const NATIVE_MODE_DEFAULTS: Record = { - architect: { - name: "Architect", - roleDefinition: - "You are Kilo Code, an experienced technical leader who is inquisitive and an excellent planner. Your goal is to gather information and get context to create a detailed plan for accomplishing the user's task, which the user will review and approve before they switch into another mode to implement the solution.", - whenToUse: - "Use this mode when you need to plan, design, or strategize before implementation. Perfect for breaking down complex problems, creating technical specifications, designing system architecture, or brainstorming solutions before coding.", - description: "Plan and design before implementation", - customInstructions: - "1. Do some information gathering (using provided tools) to get more context about the task.\n\n2. You should also ask the user clarifying questions to get a better understanding of the task.\n\n3. Once you've gained more context about the user's request, break down the task into clear, actionable steps and create a todo list using the `update_todo_list` tool. Each todo item should be:\n - Specific and actionable\n - Listed in logical execution order\n - Focused on a single, well-defined outcome\n - Clear enough that another mode could execute it independently\n\n **Note:** If the `update_todo_list` tool is not available, write the plan to a markdown file (e.g., `plan.md` or `todo.md`) instead.\n\n4. As you gather more information or discover new requirements, update the todo list to reflect the current understanding of what needs to be accomplished.\n\n5. Ask the user if they are pleased with this plan, or if they would like to make any changes. Think of this as a brainstorming session where you can discuss the task and refine the todo list.\n\n6. Include Mermaid diagrams if they help clarify complex workflows or system architecture. Please avoid using double quotes (\"\") and parentheses () inside square brackets ([]) in Mermaid diagrams, as this can cause parsing errors.\n\n7. Use the switch_mode tool to request switching to another mode when you need to edit non-markdown files (like source code files: .ts, .js, .py, .java, etc.) or execute commands. You CAN directly create and edit markdown files (.md) without switching modes.\n\n**IMPORTANT: Focus on creating clear, actionable todo lists rather than lengthy markdown documents. Use the todo list as your primary planning tool to track and organize the work that needs to be done.**\n\n**CRITICAL: Never provide level of effort time estimates (e.g., hours, days, weeks) for tasks. Focus solely on breaking down the work into clear, actionable steps without estimating how long they will take.**\n\nUnless told otherwise, if you want to save a plan file, put it in the /plans directory", - groups: ["read", ["edit", { fileRegex: "\\.md$", description: "Markdown files only" }], "browser", "mcp"], - }, - code: { - name: "Code", - roleDefinition: - "You are Kilo Code, a highly skilled software engineer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.", - whenToUse: - "Use this mode when you need to write, modify, or refactor code. Ideal for implementing features, fixing bugs, creating new files, or making code improvements across any programming language or framework.", - description: "Write, modify, and refactor code", - groups: ["read", "edit", "browser", "command", "mcp"], - }, - ask: { - name: "Ask", - roleDefinition: - "You are Kilo Code, a knowledgeable technical assistant focused on answering questions and providing information about software development, technology, and related topics.", - whenToUse: - "Use this mode when you need explanations, documentation, or answers to technical questions. Best for understanding concepts, analyzing existing code, getting recommendations, or learning about technologies without making changes.", - description: "Get answers and explanations", - customInstructions: - "You can analyze code, explain concepts, and access external resources. Always answer the user's questions thoroughly, and do not switch to implementing code unless explicitly requested by the user. Include Mermaid diagrams when they clarify your response.", - groups: ["read", "browser", "mcp"], - }, - debug: { - name: "Debug", - roleDefinition: - "You are Kilo Code, an expert software debugger specializing in systematic problem diagnosis and resolution.", - whenToUse: - "Use this mode when you're troubleshooting issues, investigating errors, or diagnosing problems. Specialized in systematic debugging, adding logging, analyzing stack traces, and identifying root causes before applying fixes.", - description: "Diagnose and fix software issues", - customInstructions: - "Reflect on 5-7 different possible sources of the problem, distill those down to 1-2 most likely sources, and then add logs to validate your assumptions. Explicitly ask the user to confirm the diagnosis before fixing the problem.", - groups: ["read", "edit", "browser", "command", "mcp"], - }, - orchestrator: { - name: "Orchestrator", - roleDefinition: - "You are Kilo Code, a strategic workflow orchestrator who coordinates complex tasks by delegating them to appropriate specialized modes. You have a comprehensive understanding of each mode's capabilities and limitations, allowing you to effectively break down complex problems into discrete tasks that can be solved by different specialists.", - whenToUse: - "Use this mode for complex, multi-step projects that require coordination across different specialties. Ideal when you need to break down large tasks into subtasks, manage workflows, or coordinate work that spans multiple domains or expertise areas.", - description: "Coordinate tasks across multiple modes", - customInstructions: - "Your role is to coordinate complex workflows by delegating tasks to specialized modes. As an orchestrator, you should:\n\n1. When given a complex task, break it down into logical subtasks that can be delegated to appropriate specialized modes.\n\n2. For each subtask, use the `new_task` tool to delegate. Choose the most appropriate mode for the subtask's specific goal and provide comprehensive instructions in the `message` parameter. These instructions must include:\n * All necessary context from the parent task or previous subtasks required to complete the work.\n * A clearly defined scope, specifying exactly what the subtask should accomplish.\n * An explicit statement that the subtask should *only* perform the work outlined in these instructions and not deviate.\n * An instruction for the subtask to signal completion by using the `attempt_completion` tool, providing a concise yet thorough summary of the outcome in the `result` parameter, keeping in mind that this summary will be the source of truth used to keep track of what was completed on this project.\n * A statement that these specific instructions supersede any conflicting general instructions the subtask's mode might have.\n\n3. Track and manage the progress of all subtasks. When a subtask is completed, analyze its results and determine the next steps.\n\n4. Help the user understand how the different subtasks fit together in the overall workflow. Provide clear reasoning about why you're delegating specific tasks to specific modes.\n\n5. When all subtasks are completed, synthesize the results and provide a comprehensive overview of what was accomplished.\n\n6. Ask clarifying questions when necessary to better understand how to break down complex tasks effectively.\n\n7. Suggest improvements to the workflow based on the results of completed subtasks.\n\nUse subtasks to maintain clarity. If a request significantly shifts focus or requires a different expertise (mode), consider creating a subtask rather than overloading the current one.", - groups: [], - }, - review: { - name: "Review", - roleDefinition: - "You are Kilo Code, an expert code reviewer with deep expertise in software engineering best practices, security vulnerabilities, performance optimization, and code quality. Your role is advisory - provide clear, actionable feedback on code quality and potential issues.", - whenToUse: - "Use this mode when you need to review code changes. Ideal for reviewing uncommitted work before committing, comparing your branch against main/develop, or analyzing changes before merging.", - description: "Review code changes locally", - customInstructions: - 'When you enter Review mode, you will receive a list of changed files. Use tools to explore the changes dynamically.\n\n## How to Review\n\n1. **Start with git diff**: Use `execute_command` to run `git diff` (for uncommitted) or `git diff ..HEAD` (for branch) to see the actual changes.\n\n2. **Examine specific files**: For complex changes, use `read_file` to see the full file context, not just the diff.\n\n3. **Gather history context**: Use `git log`, `git blame`, or `git show` when you need to understand why code was written a certain way.\n\n4. **Be confident**: Only flag issues where you have high confidence. Use these thresholds:\n - **CRITICAL (95%+)**: Security vulnerabilities, data loss risks, crashes, authentication bypasses\n - **WARNING (85%+)**: Bugs, logic errors, performance issues, unhandled errors\n - **SUGGESTION (75%+)**: Code quality improvements, best practices, maintainability\n - **Below 75%**: Don\'t comment - gather more context first\n\n5. **Focus on what matters**:\n - Security: Injection, auth issues, data exposure\n - Bugs: Logic errors, null handling, race conditions\n - Performance: Inefficient algorithms, memory leaks\n - Error handling: Missing try-catch, unhandled promises\n\n6. **Don\'t flag**:\n - Style preferences that don\'t affect functionality\n - Minor naming suggestions\n - Patterns that match existing codebase conventions\n\n## Output Format\n\n### Summary\n2-3 sentences describing what this change does and your overall assessment.\n\n### Issues Found\n| Severity | File:Line | Issue |\n|----------|-----------|-------|\n| CRITICAL | path/file.ts:42 | Brief description |\n| WARNING | path/file.ts:78 | Brief description |\n\nIf no issues: "No issues found."\n\n### Detailed Findings\nFor each issue:\n- **File:** `path/to/file.ts:line`\n- **Confidence:** X%\n- **Problem:** What\'s wrong and why it matters\n- **Suggestion:** Recommended fix with code snippet\n\n### Recommendation\nOne of: **APPROVE** | **APPROVE WITH SUGGESTIONS** | **NEEDS CHANGES**\n\n## Presenting Your Review\n\nAfter completing your review analysis and formatting your findings:\n\n- If your recommendation is **APPROVE** with no issues found, use `attempt_completion` to present your clean review.\n- If your recommendation is **APPROVE WITH SUGGESTIONS** or **NEEDS CHANGES**, use `ask_followup_question` instead of `attempt_completion`. Present your full review as the question text and include fix suggestions with mode switching so the user can apply fixes with one click.\n\nWhen using `ask_followup_question`, always provide exactly 1-3 suggestions in the `follow_up` array (never more than 3). Tailor them based on what you found. Choose the appropriate mode for each suggestion:\n- `mode="code"` for direct code fixes (bugs, missing error handling, clear improvements)\n- `mode="debug"` for issues needing investigation before fixing (race conditions, unclear root causes, intermittent failures)\n- `mode="orchestrator"` when there are many issues (3+) spanning different categories that need coordinated, planned fixes\n\nSuggestion patterns based on review findings:\n- **Few clear fixes (1-4 issues, same category):** offer mode="code" fixes\n- **Many issues across categories (3+, mixed security/performance/quality):** offer mode="orchestrator" to plan fixes and mode="code" for quick wins\n- **Issues needing investigation:** include a mode="debug" option to investigate root causes\n- **Suggestions only:** offer mode="code" to apply improvements\n\nExample with complex findings across multiple categories:\nUse `ask_followup_question` with:\n- question: Your full review (Summary, Issues Found table, Detailed Findings, and Recommendation)\n- follow_up:\n - { text: "Plan and coordinate fixes across all issue categories", mode: "orchestrator" }\n - { text: "Fix critical and warning issues only", mode: "code" }\n\nExample with straightforward fixes:\nUse `ask_followup_question` with:\n- question: Your full review (Summary, Issues Found table, Detailed Findings, and Recommendation)\n- follow_up:\n - { text: "Fix all issues found in this review", mode: "code" }\n - { text: "Fix critical issues only", mode: "code" }', - groups: ["read", "browser", "mcp", "command"], - }, -} diff --git a/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts b/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts deleted file mode 100644 index 02c67a2357b..00000000000 --- a/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts +++ /dev/null @@ -1,308 +0,0 @@ -/** - * legacy-migration - Maps legacy apiProvider values to new provider IDs and key fields. - * - * The legacy extension used flat per-provider key names (e.g. apiKey, openRouterApiKey). - * The new CLI backend uses a per-provider auth endpoint (PUT /auth/:providerId). - */ - -export interface ProviderMapping { - /** New provider ID for the auth endpoint (PUT /auth/:id) */ - id: string - /** Field name in LegacyProviderSettings holding the primary API key */ - key: string - /** Display name for the provider in the wizard UI */ - name: string - /** Field holding model ID (defaults to "apiModelId") */ - modelField?: string - /** Field holding custom base URL (to also store in config) */ - urlField?: string - /** Field holding an organization/account ID (used for OAuth-style auth) */ - organizationIdField?: string - /** VS Code secret key holding OAuth credentials stored separately from the provider profile */ - oauthSecretKey?: string - /** If true, skip auth.set entirely — provider uses env/ADC-based auth (e.g. Vertex AI) */ - skipAuth?: boolean - /** Legacy settings fields to write as provider config options (e.g. project/location for Vertex) */ - configFields?: Array<{ from: string; option: string }> -} - -/** - * Maps legacy `apiProvider` values → new provider info. - * Providers absent from this map are flagged as unsupported. - */ -export const PROVIDER_MAP: Record = { - anthropic: { - id: "anthropic", - key: "apiKey", - name: "Anthropic", - }, - openrouter: { - id: "openrouter", - key: "openRouterApiKey", - name: "OpenRouter", - modelField: "openRouterModelId", - }, - openai: { - id: "openai-compatible", - key: "openAiApiKey", - name: "OpenAI (Compatible)", - modelField: "openAiModelId", - urlField: "openAiBaseUrl", - }, - "openai-native": { - id: "openai", - key: "openAiNativeApiKey", - name: "OpenAI", - urlField: "openAiNativeBaseUrl", - }, - "openai-responses": { - id: "openai", - key: "openAiApiKey", - name: "OpenAI", - modelField: "openAiModelId", - }, - gemini: { - id: "google", - key: "geminiApiKey", - name: "Google Gemini", - urlField: "googleGeminiBaseUrl", - }, - vertex: { - id: "google-vertex", - key: "vertexJsonCredentials", - name: "Google Vertex AI", - skipAuth: true, - configFields: [ - { from: "vertexProjectId", option: "project" }, - { from: "vertexRegion", option: "location" }, - ], - }, - bedrock: { - id: "amazon-bedrock", - key: "awsAccessKey", - name: "AWS Bedrock", - }, - deepseek: { - id: "deepseek", - key: "deepSeekApiKey", - name: "DeepSeek", - urlField: "deepSeekBaseUrl", - }, - mistral: { - id: "mistral", - key: "mistralApiKey", - name: "Mistral", - }, - groq: { - id: "groq", - key: "groqApiKey", - name: "Groq", - }, - xai: { - id: "xai", - key: "xaiApiKey", - name: "xAI", - }, - fireworks: { - id: "fireworks", - key: "fireworksApiKey", - name: "Fireworks", - }, - featherless: { - id: "featherless", - key: "featherlessApiKey", - name: "Featherless", - }, - cerebras: { - id: "cerebras", - key: "cerebrasApiKey", - name: "Cerebras", - }, - sambanova: { - id: "sambanova", - key: "sambaNovaApiKey", - name: "SambaNova", - }, - ollama: { - id: "ollama", - key: "ollamaApiKey", - name: "Ollama", - modelField: "ollamaModelId", - urlField: "ollamaBaseUrl", - }, - lmstudio: { - id: "lmstudio", - key: "lmStudioBaseUrl", - name: "LM Studio", - modelField: "lmStudioModelId", - urlField: "lmStudioBaseUrl", - }, - kilocode: { - id: "kilo", - key: "kilocodeToken", - name: "Kilo (Gateway)", - modelField: "kilocodeModel", - organizationIdField: "kilocodeOrganizationId", - }, - litellm: { - id: "litellm", - key: "litellmApiKey", - name: "LiteLLM", - modelField: "litellmModelId", - urlField: "litellmBaseUrl", - }, - deepinfra: { - id: "deepinfra", - key: "deepInfraApiKey", - name: "DeepInfra", - modelField: "deepInfraModelId", - urlField: "deepInfraBaseUrl", - }, - chutes: { - id: "chutes", - key: "chutesApiKey", - name: "Chutes", - }, - baseten: { - id: "baseten", - key: "basetenApiKey", - name: "Baseten", - }, - corethink: { - id: "corethink", - key: "corethinkApiKey", - name: "Corethink", - }, - unbound: { - id: "unbound", - key: "unboundApiKey", - name: "Unbound", - modelField: "unboundModelId", - }, - requesty: { - id: "requesty", - key: "requestyApiKey", - name: "Requesty", - modelField: "requestyModelId", - urlField: "requestyBaseUrl", - }, - huggingface: { - id: "huggingface", - key: "huggingFaceApiKey", - name: "Hugging Face", - modelField: "huggingFaceModelId", - }, - "io-intelligence": { - id: "io-intelligence", - key: "ioIntelligenceApiKey", - name: "IO Intelligence", - modelField: "ioIntelligenceModelId", - }, - "vercel-ai-gateway": { - id: "vercel-ai-gateway", - key: "vercelAiGatewayApiKey", - name: "Vercel AI Gateway", - modelField: "vercelAiGatewayModelId", - }, - zai: { - id: "zai", - key: "zaiApiKey", - name: "Z.ai", - }, - moonshot: { - id: "moonshot", - key: "moonshotApiKey", - name: "Moonshot", - urlField: "moonshotBaseUrl", - }, - doubao: { - id: "doubao", - key: "doubaoApiKey", - name: "Doubao", - urlField: "doubaoBaseUrl", - }, - minimax: { - id: "minimax", - key: "minimaxApiKey", - name: "MiniMax", - urlField: "minimaxBaseUrl", - }, - ovhcloud: { - id: "ovhcloud", - key: "ovhCloudAiEndpointsApiKey", - name: "OVHcloud AI Endpoints", - modelField: "ovhCloudAiEndpointsModelId", - urlField: "ovhCloudAiEndpointsBaseUrl", - }, - inception: { - id: "inception", - key: "inceptionLabsApiKey", - name: "Inception Labs", - modelField: "inceptionLabsModelId", - urlField: "inceptionLabsBaseUrl", - }, - "sap-ai-core": { - id: "sap-ai-core", - key: "sapAiCoreServiceKey", - name: "SAP AI Core", - }, - synthetic: { - id: "synthetic", - key: "syntheticApiKey", - name: "Synthetic", - }, - apertis: { - id: "apertis", - key: "apertisApiKey", - name: "Apertis", - modelField: "apertisModelId", - urlField: "apertisBaseUrl", - }, - "openai-codex": { - id: "openai", - key: "", - name: "OpenAI (ChatGPT Plus/Pro)", - oauthSecretKey: "openai-codex-oauth-credentials", - }, - "nano-gpt": { - id: "nano-gpt", - key: "nanoGptApiKey", - name: "NanoGPT", - modelField: "nanoGptModelId", - }, - poe: { - id: "poe", - key: "poeApiKey", - name: "Poe", - modelField: "poeModelId", - }, - aihubmix: { - id: "aihubmix", - key: "aihubmixApiKey", - name: "AiHubMix", - modelField: "aihubmixModelId", - urlField: "aihubmixBaseUrl", - }, - zenmux: { - id: "zenmux", - key: "zenmuxApiKey", - name: "ZenMux", - modelField: "zenmuxModelId", - urlField: "zenmuxBaseUrl", - }, -} - -/** Providers that have no equivalent in the new CLI backend */ -export const UNSUPPORTED_PROVIDERS = new Set([ - "fake-ai", - "human-relay", - "vscode-lm", - "claude-code", - "qwen-code", - "virtual-quota-fallback", - "glama", - "roo", -]) - -/** Built-in default mode slugs that should not be migrated */ -export const DEFAULT_MODE_SLUGS = new Set(["code", "build", "architect", "ask", "debug", "orchestrator", "review"]) diff --git a/packages/kilo-vscode/src/services/cli-backend/connection-service.ts b/packages/kilo-vscode/src/services/cli-backend/connection-service.ts index 32988bbe256..4f8b506d6cb 100644 --- a/packages/kilo-vscode/src/services/cli-backend/connection-service.ts +++ b/packages/kilo-vscode/src/services/cli-backend/connection-service.ts @@ -14,7 +14,6 @@ type SSEEventFilter = (event: SSEPayload, directory?: string) => boolean type NotificationDismissListener = (notificationId: string) => void type LanguageChangeListener = (locale: string) => void type ProfileChangeListener = (data: unknown) => void -type MigrationCompleteListener = () => void type FavoritesChangeListener = (favorites: Array<{ providerID: string; modelID: string }>) => void type ModelSelectorExpandedListener = (value: boolean) => void type ClearPendingPromptsListener = () => void @@ -103,7 +102,6 @@ export class KiloConnectionService { private readonly notificationDismissListeners: Set = new Set() private readonly languageChangeListeners: Set = new Set() private readonly profileChangeListeners: Set = new Set() - private readonly migrationCompleteListeners: Set = new Set() private readonly favoritesChangeListeners: Set = new Set() private readonly modelSelectorExpandedListeners: Set = new Set() private readonly clearPendingPromptsListeners: Set = new Set() @@ -465,25 +463,6 @@ export class KiloConnectionService { } } - /** - * Subscribe to migration-complete events broadcast from any KiloProvider. Returns unsubscribe function. - */ - onMigrationComplete(listener: MigrationCompleteListener): () => void { - this.migrationCompleteListeners.add(listener) - return () => { - this.migrationCompleteListeners.delete(listener) - } - } - - /** - * Broadcast a migration-complete event to all subscribed KiloProvider instances. - */ - notifyMigrationComplete(): void { - for (const listener of this.migrationCompleteListeners) { - listener() - } - } - /** * Subscribe to favorites change events broadcast from any KiloProvider. Returns unsubscribe function. */ @@ -705,7 +684,6 @@ export class KiloConnectionService { this.stateListeners.clear() this.notificationDismissListeners.clear() this.profileChangeListeners.clear() - this.migrationCompleteListeners.clear() this.favoritesChangeListeners.clear() this.clearPendingPromptsListeners.clear() this.directoryProviders.clear() diff --git a/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts b/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts index c75c2054218..2a43e5faa25 100644 --- a/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts +++ b/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts @@ -84,7 +84,6 @@ function connection() { onClearPendingPrompts: () => () => undefined, onLanguageChanged: () => () => undefined, onProfileChanged: () => () => undefined, - onMigrationComplete: () => () => undefined, onFavoritesChanged: () => () => undefined, onModelSelectorExpandedChanged: () => () => undefined, registerDirectoryProvider: () => () => undefined, diff --git a/packages/kilo-vscode/tests/unit/kilo-provider-load-messages.test.ts b/packages/kilo-vscode/tests/unit/kilo-provider-load-messages.test.ts index f08ab19c084..7be81090581 100644 --- a/packages/kilo-vscode/tests/unit/kilo-provider-load-messages.test.ts +++ b/packages/kilo-vscode/tests/unit/kilo-provider-load-messages.test.ts @@ -213,7 +213,6 @@ function createConnection(client: ReturnType | null) { onNotificationDismissed: () => () => undefined, onLanguageChanged: () => () => undefined, onProfileChanged: () => () => undefined, - onMigrationComplete: () => () => undefined, onFavoritesChanged: () => () => undefined, onModelSelectorExpandedChanged: () => () => undefined, onClearPendingPrompts: () => () => undefined, diff --git a/packages/kilo-vscode/tests/unit/kilo-provider-route-integration.test.ts b/packages/kilo-vscode/tests/unit/kilo-provider-route-integration.test.ts index 3c3d70b7d8b..0948e5debe0 100644 --- a/packages/kilo-vscode/tests/unit/kilo-provider-route-integration.test.ts +++ b/packages/kilo-vscode/tests/unit/kilo-provider-route-integration.test.ts @@ -73,7 +73,6 @@ function mockConnection(getImpl?: (p: SessionGetParams) => Promise, vcs onNotificationDismissed: () => () => undefined, onLanguageChanged: () => () => undefined, onProfileChanged: () => () => undefined, - onMigrationComplete: () => () => undefined, onFavoritesChanged: () => () => undefined, onModelSelectorExpandedChanged: () => () => undefined, onClearPendingPrompts: () => () => undefined, diff --git a/packages/kilo-vscode/tests/unit/kilo-provider-session-refresh.test.ts b/packages/kilo-vscode/tests/unit/kilo-provider-session-refresh.test.ts index e96a67d6b71..03a010a3b65 100644 --- a/packages/kilo-vscode/tests/unit/kilo-provider-session-refresh.test.ts +++ b/packages/kilo-vscode/tests/unit/kilo-provider-session-refresh.test.ts @@ -13,6 +13,9 @@ type ProviderInternals = { webview: { postMessage: (message: unknown) => Promise } | null initializeConnection: () => Promise handleLoadSessions: () => Promise + isWebviewReady: boolean + syncWebviewState: (reason: string) => Promise + handleMigrationMessage: (message: { type: string }) => boolean } function deferred() { @@ -51,6 +54,7 @@ function createClient() { return { calls, session: { + status: async () => ({ data: {} }), list: async (params: { directory: string }) => { calls.push(params.directory) return { data: [] } @@ -93,7 +97,6 @@ function createConnection(client: ReturnType) { onNotificationDismissed: () => () => undefined, onLanguageChanged: () => () => undefined, onProfileChanged: () => () => undefined, - onMigrationComplete: () => () => undefined, onFavoritesChanged: () => () => undefined, onModelSelectorExpandedChanged: () => () => undefined, onClearPendingPrompts: () => () => undefined, @@ -109,6 +112,40 @@ function createConnection(client: ReturnType) { } describe("KiloProvider pending session refresh", () => { + it("syncs startup state without reading legacy credentials or exposing legacy actions", async () => { + const client = createClient() + const connection = createConnection(client) + await connection.connect() + const reads: string[] = [] + const ctx = { + globalStorageUri: { fsPath: "/storage/kilocode.kilo-code" }, + globalState: { get: (_key: string, fallback?: unknown) => fallback }, + secrets: { + get: async (key: string) => { + reads.push(key) + return undefined + }, + }, + } + const provider = new KiloProvider({} as never, connection as never, ctx as never) + const internal = provider as unknown as ProviderInternals + const sent: unknown[] = [] + internal.connectionState = "connected" + internal.isWebviewReady = true + internal.webview = { postMessage: async (message) => sent.push(message) } + + for (const reason of ["initializeConnection", "sse-connected", "webviewReady"]) { + await internal.syncWebviewState(reason) + } + + expect(reads).toEqual([]) + expect(sent).toContainEqual(expect.objectContaining({ type: "ready" })) + expect(sent).not.toContainEqual(expect.objectContaining({ type: "migrationState" })) + for (const type of ["skipLegacyMigration", "clearLegacyData", "finalizeLegacyMigration"]) { + expect(internal.handleMigrationMessage({ type })).toBe(false) + } + }) + it("does not let a late listing restore the previous project's identity", async () => { const client = createClient() const pending = new Map>>() diff --git a/packages/kilo-vscode/tests/unit/legacy-migration/migration-cache.test.ts b/packages/kilo-vscode/tests/unit/legacy-migration/migration-cache.test.ts index a2e4cdd4018..feab070444f 100644 --- a/packages/kilo-vscode/tests/unit/legacy-migration/migration-cache.test.ts +++ b/packages/kilo-vscode/tests/unit/legacy-migration/migration-cache.test.ts @@ -8,35 +8,29 @@ import { type MigrationContext, } from "../../../src/kilo-provider/handlers/migration" -const legacy = { - hasData: false, - providers: [], - mcpServers: [], - customModes: [], -} - -function makeContext(cache: MigrationCache): MigrationContext { +function makeContext(cache: MigrationCache, sent: unknown[] = []): MigrationContext { return { client: null, - extensionContext: { globalStorageUri: { fsPath: "/storage/kilocode.kilo-code" } }, - postMessage: () => {}, + extensionContext: { + globalStorageUri: { fsPath: "/storage/kilocode.kilo-code" }, + get secrets() { + throw new Error("Roo import must not access SecretStorage") + }, + }, + postMessage: (message) => sent.push(message), refreshSessions: () => {}, migrationCache: cache, - migrationCheckInFlight: false, - disposeGlobal: async () => {}, - broadcastComplete: () => {}, } as unknown as MigrationContext } describe("migration cache", () => { - it("isolates entries by operation and source", () => { + it("isolates Roo entries by operation", () => { const cache: MigrationCache = new Map() - const entry: MigrationCacheEntry = { operationId: "new", source: "legacy", data: legacy } + const entry: MigrationCacheEntry = { operationId: "new", source: "roo", data: null } cache.set("new", entry) - expect(getMigrationCache(cache, "legacy", "new")).toBe(entry) - expect(getMigrationCache(cache, "roo", "new")).toBeUndefined() - expect(getMigrationCache(cache, "legacy", "stale")).toBeUndefined() + expect(getMigrationCache(cache, "roo", "new")).toBe(entry) + expect(getMigrationCache(cache, "roo", "stale")).toBeUndefined() }) it("retains an empty Roo discovery for its operation", () => { @@ -48,39 +42,40 @@ describe("migration cache", () => { expect(getMigrationCache(cache, "roo", "empty")?.data).toBeNull() }) - it("drops entries from abandoned operations when a new request arrives", async () => { + it("discovers Roo sessions without accessing secrets and drops abandoned operations", async () => { const cache: MigrationCache = new Map() + const sent: unknown[] = [] cache.set("abandoned", { operationId: "abandoned", source: "roo", data: null }) - await handleRequestMigrationData(makeContext(cache), "roo", "fresh") + await handleRequestMigrationData(makeContext(cache, sent), "roo", "fresh") expect(cache.has("abandoned")).toBe(false) expect(getMigrationCache(cache, "roo", "fresh")).toBeDefined() + expect(sent).toEqual([{ type: "migrationData", source: "roo", operationId: "fresh", data: { sessions: [] } }]) + }) + + it("ignores obsolete migration requests without accessing extension storage", async () => { + const cache: MigrationCache = new Map() + const sent: unknown[] = [] + const ctx = makeContext(cache, sent) + Object.defineProperty(ctx, "extensionContext", { + get() { + throw new Error("Unsupported migrations must not access extension storage") + }, + }) + + await handleRequestMigrationData(ctx, "legacy" as never, "old") + await handleStartMigration(ctx, "legacy" as never, "old", { sessions: [] }) + + expect(cache.size).toBe(0) + expect(sent).toEqual([]) }) it("evicts an operation's entry once the migration completes", async () => { const cache: MigrationCache = new Map() cache.set("op", { operationId: "op", source: "roo", data: null }) - await handleStartMigration(makeContext(cache), "roo", "op", { - providers: [], - mcpServers: [], - customModes: [], - sessions: [], - defaultModel: false, - settings: { - autoApproval: { - commandRules: false, - readPermission: false, - writePermission: false, - executePermission: false, - mcpPermission: false, - taskPermission: false, - }, - language: false, - autocomplete: false, - }, - }) + await handleStartMigration(makeContext(cache), "roo", "op", { sessions: [] }) expect(cache.has("op")).toBe(false) }) diff --git a/packages/kilo-vscode/tests/unit/legacy-migration/native-modes.test.ts b/packages/kilo-vscode/tests/unit/legacy-migration/native-modes.test.ts deleted file mode 100644 index 980f4842bf4..00000000000 --- a/packages/kilo-vscode/tests/unit/legacy-migration/native-modes.test.ts +++ /dev/null @@ -1,322 +0,0 @@ -import { describe, expect, it } from "bun:test" -import { - buildCustomModeList, - isNativeModeModified, - buildMergedNativeMode, -} from "../../../src/legacy-migration/migration-service" -import { NATIVE_MODE_DEFAULTS } from "../../../src/legacy-migration/native-mode-defaults" -import type { LegacyCustomMode, LegacyPromptComponent } from "../../../src/legacy-migration/legacy-types" - -// --------------------------------------------------------------------------- -// isNativeModeModified -// --------------------------------------------------------------------------- - -describe("isNativeModeModified", () => { - const defaults = NATIVE_MODE_DEFAULTS["code"]! - - it("returns true when a YAML override exists", () => { - const yaml: LegacyCustomMode = { - slug: "code", - name: "My Code", - roleDefinition: "custom role", - groups: ["read"], - } - expect(isNativeModeModified(yaml, undefined, defaults)).toBe(true) - }) - - it("returns false when no YAML and no prompts exist", () => { - expect(isNativeModeModified(undefined, undefined, defaults)).toBe(false) - }) - - it("returns false when prompts match the defaults exactly", () => { - const prompt: LegacyPromptComponent = { - roleDefinition: defaults.roleDefinition, - } - expect(isNativeModeModified(undefined, prompt, defaults)).toBe(false) - }) - - it("returns true when roleDefinition differs from default", () => { - const prompt: LegacyPromptComponent = { - roleDefinition: "You are a Python specialist.", - } - expect(isNativeModeModified(undefined, prompt, defaults)).toBe(true) - }) - - it("returns true when customInstructions differs from default", () => { - const prompt: LegacyPromptComponent = { - customInstructions: "Always use type hints.", - } - // code mode has no default customInstructions, so any non-empty value is different - expect(isNativeModeModified(undefined, prompt, defaults)).toBe(true) - }) - - it("returns true when whenToUse differs from default", () => { - const prompt: LegacyPromptComponent = { - whenToUse: "Use for Python only.", - } - expect(isNativeModeModified(undefined, prompt, defaults)).toBe(true) - }) - - it("returns false when prompts have empty strings", () => { - const prompt: LegacyPromptComponent = { - roleDefinition: "", - customInstructions: "", - whenToUse: "", - } - expect(isNativeModeModified(undefined, prompt, defaults)).toBe(false) - }) - - it("returns false when customInstructions matches default (ask mode)", () => { - const ask = NATIVE_MODE_DEFAULTS["ask"]! - const prompt: LegacyPromptComponent = { - customInstructions: ask.customInstructions, - } - expect(isNativeModeModified(undefined, prompt, ask)).toBe(false) - }) - - it("returns true when customInstructions differs from default (ask mode)", () => { - const ask = NATIVE_MODE_DEFAULTS["ask"]! - const prompt: LegacyPromptComponent = { - customInstructions: "Different instructions.", - } - expect(isNativeModeModified(undefined, prompt, ask)).toBe(true) - }) - - it("returns true when description differs from default", () => { - const prompt: LegacyPromptComponent = { - description: "My custom short description", - } - expect(isNativeModeModified(undefined, prompt, defaults)).toBe(true) - }) - - it("returns false when description matches default", () => { - const prompt: LegacyPromptComponent = { - description: defaults.description, - } - expect(isNativeModeModified(undefined, prompt, defaults)).toBe(false) - }) -}) - -// --------------------------------------------------------------------------- -// buildCustomModeList -// --------------------------------------------------------------------------- - -describe("buildCustomModeList", () => { - it("returns non-native custom modes as before", () => { - const modes: LegacyCustomMode[] = [ - { slug: "translate", name: "Translate", roleDefinition: "translator", groups: ["read"] }, - ] - const result = buildCustomModeList(modes, null) - expect(result).toEqual([{ name: "Translate", slug: "translate" }]) - }) - - it("still filters out unmodified native modes from YAML", () => { - // A mode list with only non-native entries + an exact-slug match that is not a YAML - // override (just a non-matching slug that happens to be native) — this shouldn't happen - // in practice because custom_modes.yaml would only have a native slug if the user put it there - const result = buildCustomModeList(null, null) - expect(result).toEqual([]) - }) - - it("includes a modified native mode from YAML with -custom slug", () => { - const modes: LegacyCustomMode[] = [ - { - slug: "code", - name: "My Code Mode", - roleDefinition: "You are a specialized engineer.", - groups: ["read", "edit"], - }, - ] - const result = buildCustomModeList(modes, null) - expect(result).toEqual([{ name: "My Code Mode (Custom)", slug: "code-custom", nativeSlug: "code" }]) - }) - - it("includes a modified native mode from customModePrompts with -custom slug", () => { - const prompts: Record = { - code: { roleDefinition: "You are a Python expert." }, - } - const result = buildCustomModeList(null, prompts) - expect(result).toEqual([{ name: "Code (Custom)", slug: "code-custom", nativeSlug: "code" }]) - }) - - it("does not include a native mode when prompts match defaults", () => { - const defaults = NATIVE_MODE_DEFAULTS["code"]! - const prompts: Record = { - code: { roleDefinition: defaults.roleDefinition }, - } - const result = buildCustomModeList(null, prompts) - expect(result).toEqual([]) - }) - - it("combines non-native custom modes and modified native modes", () => { - const modes: LegacyCustomMode[] = [ - { slug: "translate", name: "Translate", roleDefinition: "translator", groups: ["read"] }, - { slug: "code", name: "Custom Code", roleDefinition: "specialized", groups: ["read", "edit"] }, - ] - const result = buildCustomModeList(modes, null) - expect(result).toHaveLength(2) - expect(result[0]).toEqual({ name: "Translate", slug: "translate" }) - expect(result[1]).toEqual({ name: "Custom Code (Custom)", slug: "code-custom", nativeSlug: "code" }) - }) - - it("produces only one entry when both YAML and prompts exist for same native slug", () => { - const modes: LegacyCustomMode[] = [ - { slug: "code", name: "Custom Code", roleDefinition: "from yaml", groups: ["read"] }, - ] - const prompts: Record = { - code: { roleDefinition: "from prompts" }, - } - const result = buildCustomModeList(modes, prompts) - const native = result.filter((m) => m.nativeSlug === "code") - expect(native).toHaveLength(1) - expect(native[0]!.slug).toBe("code-custom") - }) - - it("excludes 'build' since it is a native slug with no legacy defaults", () => { - const modes: LegacyCustomMode[] = [{ slug: "build", name: "Build", roleDefinition: "builder", groups: ["read"] }] - // "build" is in DEFAULT_MODE_SLUGS (so filtered from non-native pass) but has no - // entry in NATIVE_MODE_DEFAULTS (so skipped in the native-modification pass) - const result = buildCustomModeList(modes, null) - expect(result).toEqual([]) - }) - - it("detects multiple modified native modes", () => { - const prompts: Record = { - code: { roleDefinition: "Custom code role" }, - debug: { roleDefinition: "Custom debug role" }, - } - const result = buildCustomModeList(null, prompts) - const slugs = result.map((m) => m.slug) - expect(slugs).toContain("code-custom") - expect(slugs).toContain("debug-custom") - }) -}) - -// --------------------------------------------------------------------------- -// buildMergedNativeMode -// --------------------------------------------------------------------------- - -describe("buildMergedNativeMode", () => { - it("returns null for unknown slugs", () => { - expect(buildMergedNativeMode(undefined, undefined, "nonexistent")).toBeNull() - }) - - it("uses YAML mode as base when present", () => { - const yaml: LegacyCustomMode = { - slug: "code", - name: "My Code", - roleDefinition: "custom role from yaml", - groups: ["read"], - } - const result = buildMergedNativeMode(yaml, undefined, "code") - expect(result).not.toBeNull() - expect(result!.roleDefinition).toBe("custom role from yaml") - expect(result!.groups).toEqual(["read"]) - }) - - it("uses native defaults as base when no YAML", () => { - const prompt: LegacyPromptComponent = { - roleDefinition: "custom role from prompts", - } - const result = buildMergedNativeMode(undefined, prompt, "code") - expect(result).not.toBeNull() - expect(result!.roleDefinition).toBe("custom role from prompts") - expect(result!.name).toBe("Code") - expect(result!.groups).toEqual(NATIVE_MODE_DEFAULTS["code"]!.groups) - }) - - it("overlays prompts on top of YAML", () => { - const yaml: LegacyCustomMode = { - slug: "code", - name: "My Code", - roleDefinition: "yaml role", - customInstructions: "yaml instructions", - groups: ["read"], - } - const prompt: LegacyPromptComponent = { - roleDefinition: "prompt role", - } - const result = buildMergedNativeMode(yaml, prompt, "code") - expect(result).not.toBeNull() - expect(result!.roleDefinition).toBe("prompt role") - expect(result!.customInstructions).toBe("yaml instructions") - }) - - it("preserves default groups when only prompts are present", () => { - const prompt: LegacyPromptComponent = { - customInstructions: "extra instructions", - } - const result = buildMergedNativeMode(undefined, prompt, "architect") - expect(result).not.toBeNull() - expect(result!.groups).toEqual(NATIVE_MODE_DEFAULTS["architect"]!.groups) - }) - - it("does not mutate the YAML input", () => { - const yaml: LegacyCustomMode = { - slug: "code", - name: "My Code", - roleDefinition: "original", - groups: ["read"], - } - const prompt: LegacyPromptComponent = { - roleDefinition: "overridden", - } - buildMergedNativeMode(yaml, prompt, "code") - expect(yaml.roleDefinition).toBe("original") - }) - - it("does not overlay empty prompt strings", () => { - const yaml: LegacyCustomMode = { - slug: "code", - name: "My Code", - roleDefinition: "yaml role", - groups: ["read"], - } - const prompt: LegacyPromptComponent = { - roleDefinition: "", - customInstructions: "", - } - const result = buildMergedNativeMode(yaml, prompt, "code") - expect(result!.roleDefinition).toBe("yaml role") - expect(result!.customInstructions).toBeUndefined() - }) - - it("includes whenToUse from prompts", () => { - const prompt: LegacyPromptComponent = { - whenToUse: "Use for special tasks", - } - const result = buildMergedNativeMode(undefined, prompt, "code") - expect(result!.whenToUse).toBe("Use for special tasks") - }) - - it("overlays description from prompts", () => { - const prompt: LegacyPromptComponent = { - description: "My custom description", - } - const result = buildMergedNativeMode(undefined, prompt, "code") - expect(result!.description).toBe("My custom description") - }) - - it("preserves default description when prompt description is empty", () => { - const prompt: LegacyPromptComponent = { - description: "", - } - const result = buildMergedNativeMode(undefined, prompt, "code") - expect(result!.description).toBe(NATIVE_MODE_DEFAULTS["code"]!.description) - }) - - it("overlays description from prompts on top of YAML", () => { - const yaml: LegacyCustomMode = { - slug: "code", - name: "My Code", - roleDefinition: "yaml role", - description: "yaml description", - groups: ["read"], - } - const prompt: LegacyPromptComponent = { - description: "prompt description", - } - const result = buildMergedNativeMode(yaml, prompt, "code") - expect(result!.description).toBe("prompt description") - }) -}) diff --git a/packages/kilo-vscode/tests/unit/roo-migration-ui.fixture.tsx b/packages/kilo-vscode/tests/unit/roo-migration-ui.fixture.tsx new file mode 100644 index 00000000000..99d7327c9cc --- /dev/null +++ b/packages/kilo-vscode/tests/unit/roo-migration-ui.fixture.tsx @@ -0,0 +1,260 @@ +import assert from "node:assert/strict" +import { Window } from "happy-dom" +import type { MigrationSessionInfo, WebviewMessage } from "../../webview-ui/src/types/messages" + +const window = new Window({ url: "http://localhost" }) +const style = window.getComputedStyle.bind(window) +const sent: WebviewMessage[] = [] +Object.assign(globalThis, { + window, + document: window.document, + navigator: window.navigator, + Node: window.Node, + NodeFilter: window.NodeFilter, + Element: window.Element, + HTMLElement: window.HTMLElement, + HTMLHeadElement: window.HTMLHeadElement, + HTMLInputElement: window.HTMLInputElement, + SVGElement: window.SVGElement, + MutationObserver: window.MutationObserver, + ResizeObserver: window.ResizeObserver, + CustomEvent: window.CustomEvent, + Event: window.Event, + MouseEvent: window.MouseEvent, + MessageEvent: window.MessageEvent, + getComputedStyle: (node: Element) => { + const value = style(node) + Object.defineProperty(value, "animationName", { configurable: true, value: "none" }) + return value + }, + requestAnimationFrame: window.requestAnimationFrame.bind(window), + cancelAnimationFrame: window.cancelAnimationFrame.bind(window), + acquireVsCodeApi: () => ({ + postMessage: (message: WebviewMessage) => sent.push(message), + getState: () => undefined, + setState: () => {}, + }), +}) + +const { Show, createSignal } = await import("solid-js") +const { render } = await import("solid-js/web") +const { DialogProvider } = await import("@kilocode/kilo-ui/context/dialog") +const { VSCodeProvider } = await import("../../webview-ui/src/context/vscode") +const { LanguageProvider } = await import("../../webview-ui/src/context/language") +const { ConfigProvider } = await import("../../webview-ui/src/context/config") +const { default: AboutKiloCodeTab } = await import("../../webview-ui/src/components/settings/AboutKiloCodeTab") +const { default: MigrationWizard } = await import("../../webview-ui/src/components/migration/MigrationWizard") + +const root = document.createElement("div") +document.body.append(root) +const [open, setOpen] = createSignal(false) +const closed: string[] = [] +const close = (reason: string) => { + closed.push(reason) + setOpen(false) +} +const dispose = render( + () => ( + + "en"}> + + + { + assert.equal(source, "roo") + setOpen(true) + }} + /> + } + > + close("back")} onComplete={() => close("complete")} /> + + + + + + ), + root, +) + +const button = (text: string) => { + const node = [...document.querySelectorAll("button")].find( + (item) => item.textContent?.trim() === text, + ) + assert(node, `Missing button: ${text}`) + return node +} +const query = (selector: string) => { + const node = document.querySelector(selector) + assert(node, `Missing element: ${selector}`) + return node +} +const { post: emit } = await import("../../webview-ui/src/utils/webview-message") +const settle = async () => { + await Promise.resolve() + await window.happyDOM.waitUntilComplete() +} +const requests = () => sent.filter((item) => item.type === "requestMigrationData") +const starts = () => sent.filter((item) => item.type === "startMigration") +const sessions: MigrationSessionInfo[] = [ + { id: "roo-a", title: "First Roo session", directory: "/workspace/test", time: 1 }, + { id: "roo-b", title: "Skipped Roo session", directory: "/workspace/test", time: 2 }, + { id: "roo-c", title: "Failed Roo session", directory: "/workspace/test", time: 3 }, +] +const catalog = { + sessions, + providers: [{ profileName: "Unsupported provider", supported: true, hasApiKey: true }], + mcpServers: [{ name: "Unsupported server", type: "stdio" }], + customModes: [{ name: "Unsupported mode", slug: "unsupported" }], + defaultModel: { provider: "unsupported", model: "unsupported" }, + settings: { language: "de", autoApprovalEnabled: true, autocomplete: { enableAutoTrigger: true } }, +} + +assert.equal(requests().length, 0) +assert.doesNotMatch(root.textContent ?? "", /Legacy Migration|Migrate from Legacy Version/) +button("Import Sessions from Roo Code").click() +const first = requests().at(-1)! +assert.equal(first.source, "roo") +assert(first.operationId) +assert.equal(button("Import Sessions").disabled, true) +assert.match(root.textContent ?? "", /No Roo Code sessions found/) +button("Back").click() +assert.deepEqual(closed, ["back"]) +assert.equal(starts().length, 0) +button("Import Sessions from Roo Code").click() +const request = requests().at(-1)! +assert.notEqual(request.operationId, first.operationId) +const scope = { source: "roo", operationId: request.operationId } +for (const stale of [ + { ...scope, source: "legacy" }, + { ...scope, operationId: first.operationId }, +]) { + emit({ ...stale, type: "migrationData", data: catalog }) +} +assert.equal(button("Import Sessions").disabled, true) +emit({ ...scope, type: "migrationData", data: catalog }) +assert.equal(root.querySelectorAll('input[type="checkbox"]').length, 1) +assert.doesNotMatch( + root.textContent ?? "", + /Migrate Your Settings|Provider API Keys|MCP Servers|Custom Modes|UI Language/, +) +assert.match(root.textContent ?? "", /3 sessions detected/) +const checkbox = query('input[aria-label="Chat Sessions & History"]') as HTMLInputElement +checkbox.click() +assert.equal(button("Import Sessions").disabled, true) +checkbox.click() +button("Import Sessions").click() +const started = starts().at(-1)! +assert.equal(started.source, "roo") +assert.equal(started.operationId, request.operationId) +assert.deepEqual(started.selections, { + sessions: sessions.map((session) => ({ id: session.id })), +}) + +const update = (index: number, phase: string, error?: string) => + emit({ + ...scope, + type: "migrationSessionProgress", + session: sessions.at(index), + index: index + 1, + total: 3, + phase, + error, + }) +update(0, "preparing") +assert.match(query(".migration-session-progress__header").textContent ?? "", /Migrating 1 of 3/) +update(0, "storing") +assert.equal(root.querySelectorAll(".migration-session-progress__dot--active").length, 1) +for (const stale of [ + { ...scope, source: "legacy" }, + { ...scope, operationId: first.operationId }, +]) { + emit({ ...stale, type: "migrationProgress", item: "roo-a", status: "error", message: "Stale error" }) + emit({ + ...stale, + type: "migrationSessionProgress", + session: sessions.at(0), + index: 1, + total: 3, + phase: "error", + error: "Stale error", + }) + emit({ ...stale, type: "migrationComplete", results: [{ item: "roo-a", category: "session", status: "error" }] }) +} +assert.equal(button("Import Sessions").disabled, true) +assert.doesNotMatch(root.textContent ?? "", /Stale error/) +button("Back").click() +await settle() +assert.match(query('[data-component="dialog"]').textContent ?? "", /Migration in Progress/) +button("Stay").click() +await settle() +assert.deepEqual(closed, ["back"]) +assert.equal(button("Import Sessions").disabled, true) + +update(0, "done") +update(1, "skipped") +update(2, "error", "Could not import test session") +update(2, "summary") +emit({ + ...scope, + type: "migrationComplete", + results: [ + { item: "roo-a", category: "session", status: "success" }, + { item: "roo-b", category: "session", status: "warning" }, + { item: "roo-c", category: "session", status: "error" }, + ], +}) +assert.match(query(".migration-session-summary__list--success").textContent ?? "", /First Roo session/) +assert.match(query(".migration-session-summary__list--skipped").textContent ?? "", /Skipped Roo session/) +assert.match(query(".migration-session-summary__list--errored").textContent ?? "", /Could not import test session/) +button("Continue").click() +assert.match(query(".migration-wizard__summary").textContent ?? "", /1 of 3 items migrated successfully/) +;(query(".migration-session-summary__pick input") as HTMLInputElement).click() +button("Force Re-import").click() +await settle() +assert.match(query('[data-component="dialog"]').textContent ?? "", /overwrite them and delete any new messages/) +button("Cancel").click() +await settle() +assert.equal(starts().length, 1) +button("Force Re-import").click() +await settle() +button("Proceed").click() +await settle() +const forced = starts().at(-1)! +assert.equal(forced.operationId, request.operationId) +assert.equal(forced.source, "roo") +assert.deepEqual(forced.selections.sessions, [{ id: "roo-b", force: true }]) +assert.deepEqual({ ...forced.selections, sessions: started.selections.sessions }, started.selections) +emit({ ...scope, type: "migrationProgress", item: "roo-b", status: "success" }) +update(1, "done") +update(1, "summary") +emit({ ...scope, type: "migrationComplete", results: [{ item: "roo-b", category: "session", status: "success" }] }) +assert.match(query(".migration-session-summary__list--success").textContent ?? "", /First Roo session/) +assert.match(query(".migration-session-summary__list--success").textContent ?? "", /Skipped Roo session/) +assert.equal(root.querySelector(".migration-session-summary__list--skipped"), null) +assert(root.querySelector(".migration-wizard__status-icon--success")) +button("Done").click() +assert.deepEqual(closed, ["back", "complete"]) +assert.equal(sent.at(-1)?.type, "loadSessions") + +button("Import Sessions from Roo Code").click() +const latest = requests().at(-1)! +emit({ source: "roo", operationId: latest.operationId, type: "migrationData", data: { sessions } }) +button("Import Sessions").click() +button("Back").click() +await settle() +button("Proceed").click() +await settle() +assert.deepEqual(closed, ["back", "complete", "back"]) +assert.equal(root.querySelector(".migration-wizard"), null) +assert.equal( + sent.some((item) => /Legacy/.test(item.type)), + false, +) +dispose() +await window.happyDOM.close() diff --git a/packages/kilo-vscode/tests/unit/roo-migration-ui.test.ts b/packages/kilo-vscode/tests/unit/roo-migration-ui.test.ts new file mode 100644 index 00000000000..a23a3ef0d08 --- /dev/null +++ b/packages/kilo-vscode/tests/unit/roo-migration-ui.test.ts @@ -0,0 +1,63 @@ +import { describe, expect, it } from "bun:test" +import path from "node:path" +import { build } from "esbuild" +import { solidPlugin } from "esbuild-plugin-solid" + +const root = path.resolve(import.meta.dir, "../..") +const webview = path.join(root, "webview-ui") + +describe("Roo migration UI", () => { + it("does not handle startup migration state or expose legacy actions", async () => { + const files = [ + "src/App.tsx", + "src/types/messages/migration.ts", + "src/types/messages/extension-messages.ts", + "src/types/messages/webview-messages.ts", + ] + for (const file of files) { + const text = await Bun.file(path.join(webview, file)).text() + for (const action of ["migrationState", "clearLegacyData", "skipLegacyMigration", "finalizeLegacyMigration"]) { + expect(text).not.toContain(action) + } + } + }) + + it("imports only Roo sessions with scoped progress, results, and confirmation dialogs", async () => { + const solid = path.dirname(Bun.resolveSync("solid-js/package.json", webview)) + const aliases: Record = { + "solid-js": path.join(solid, "dist/solid.js"), + "solid-js/web": path.join(solid, "web/dist/web.js"), + "solid-js/store": path.join(solid, "store/dist/store.js"), + } + const result = await build({ + entryPoints: [path.join(import.meta.dir, "roo-migration-ui.fixture.tsx")], + bundle: true, + conditions: ["browser"], + external: ["happy-dom"], + format: "esm", + logLevel: "silent", + loader: { ".css": "empty" }, + platform: "node", + plugins: [ + { + name: "solid-dedupe", + setup(ctx) { + ctx.onResolve({ filter: /^solid-js(\/web|\/store)?$/ }, (args) => ({ path: aliases[args.path] })) + }, + }, + solidPlugin(), + ], + target: "es2022", + write: false, + }) + const file = path.join(import.meta.dir, `.roo-migration-ui-${crypto.randomUUID()}.mjs`) + await Bun.write(file, result.outputFiles.at(0)!.contents) + try { + const child = Bun.spawnSync(["bun", file], { cwd: webview, stdout: "pipe", stderr: "pipe" }) + const output = child.stdout.toString() + child.stderr.toString() + expect(child.exitCode, output).toBe(0) + } finally { + await Bun.file(file).delete() + } + }) +}) diff --git a/packages/kilo-vscode/webview-ui/src/App.tsx b/packages/kilo-vscode/webview-ui/src/App.tsx index a46b6ae510f..4e718880d57 100644 --- a/packages/kilo-vscode/webview-ui/src/App.tsx +++ b/packages/kilo-vscode/webview-ui/src/App.tsx @@ -26,7 +26,7 @@ registerExpandedTaskTool() // Apply VS Code sidebar preferences to other tools (e.g. bash expanded by default). registerVscodeToolOverrides() import HistoryView from "./components/history/HistoryView" -import { MigrationWizard } from "./components/migration" // legacy-migration +import { MigrationWizard } from "./components/migration" import type { Message as SDKMessage, Part as SDKPart } from "@kilocode/sdk/v2" import { cycleAgent as cycle } from "./context/session-agent" import "./styles/chat.css" @@ -222,10 +222,7 @@ const AppContent: Component = () => { const [currentView, setCurrentView] = createSignal("newTask") const [settingsTab, setSettingsTab] = createSignal() const [agentManagerProjectId, setAgentManagerProjectId] = createSignal() - // legacy-migration: state-driven flag independent of currentView to avoid - // race conditions with SettingsEditorProvider's navigate messages. - const [migrationNeeded, setMigrationNeeded] = createSignal(false) - const [migrationSource, setMigrationSource] = createSignal<"legacy" | "roo">("legacy") + const [migration, setMigration] = createSignal(false) const session = useSession() const tabs = useLocalTabs() const server = useServer() @@ -316,12 +313,6 @@ const AppContent: Component = () => { session.setCurrentSessionID(message.sessionID) setCurrentView("subAgentViewer") } - // legacy-migration: state-driven migration wizard - if (message?.type === "migrationState") { - console.log("[Kilo New] App: 🔄 migrationState:", message.needed) - setMigrationSource(message.source) - setMigrationNeeded(message.needed) - } } window.addEventListener("message", handler) onCleanup(() => window.removeEventListener("message", handler)) @@ -365,9 +356,8 @@ const AppContent: Component = () => { surface={topBarSurface} /> - {/* legacy-migration start — state-driven overlay, independent of currentView */} { agentManagerProjectId={agentManagerProjectId()} agentManagerSettings={host.KILO_AGENT_MANAGER_SETTINGS === true} onTabChange={setSettingsTab} - onMigrationClick={(source) => { - setMigrationSource(source) - setMigrationNeeded(true) - }} + onMigrationClick={() => setMigration(true)} /> @@ -422,13 +409,8 @@ const AppContent: Component = () => { } > - setMigrationNeeded(false)} - onComplete={() => setMigrationNeeded(false)} - /> + setMigration(false)} onComplete={() => setMigration(false)} /> - {/* legacy-migration end */} ) } diff --git a/packages/kilo-vscode/webview-ui/src/components/migration/MigrationWizard.tsx b/packages/kilo-vscode/webview-ui/src/components/migration/MigrationWizard.tsx index fb749c34d98..cb15150b62c 100644 --- a/packages/kilo-vscode/webview-ui/src/components/migration/MigrationWizard.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/migration/MigrationWizard.tsx @@ -1,11 +1,3 @@ -/** - * legacy-migration - Multi-step migration wizard UI component. - * - * Screens: - * 1. What's New — feature showcase for the new extension - * 2. Migrate — grouped selection, live in-place progress, cleanup - */ - import { Show, createSignal, onMount, onCleanup } from "solid-js" import type { Component, JSX } from "solid-js" import { useDialog } from "@kilocode/kilo-ui/context/dialog" @@ -23,13 +15,9 @@ import { type SessionSummaryState, } from "./session-migration-summary-state" import type { - MigrationProviderInfo, - MigrationMcpServerInfo, - MigrationCustomModeInfo, MigrationSessionInfo, + MigrationSessionSelection, MigrationResultItem, - MigrationAutoApprovalSelections, - LegacySettings, MigrationDataMessage, MigrationProgressMessage, MigrationSessionProgressMessage, @@ -38,10 +26,6 @@ import type { } from "../../types/messages" import "./migration.css" -// --------------------------------------------------------------------------- -// KiloLogo — replicates the pattern from MessageList.tsx -// --------------------------------------------------------------------------- - const KiloLogo = (): JSX.Element => { const iconsBaseUri = (window as { ICONS_BASE_URI?: string }).ICONS_BASE_URI || "" const isLight = @@ -54,69 +38,6 @@ const KiloLogo = (): JSX.Element => { ) } -// --------------------------------------------------------------------------- -// Inline SVG icons for feature cards -// --------------------------------------------------------------------------- - -const BoltIcon = (): JSX.Element => ( - - - -) - -const MonitorIcon = (): JSX.Element => ( - - - - - -) - -const UsersIcon = (): JSX.Element => ( - - - - - - -) - -const ServerIcon = (): JSX.Element => ( - - - - - -) - const CheckmarkSvg = (): JSX.Element => ( @@ -164,24 +85,14 @@ const WarningSvg = (): JSX.Element => ( ) -// --------------------------------------------------------------------------- -// Types -// --------------------------------------------------------------------------- - -type Screen = "whats-new" | "migrate" type MigratePhase = "selecting" | "migrating" | "error" | "done" interface ProgressEntry { item: string - group: string status: "pending" | "migrating" | "success" | "warning" | "error" message?: string } -// --------------------------------------------------------------------------- -// Component -// --------------------------------------------------------------------------- - export interface MigrationWizardProps { source?: MigrationSource operationId?: string @@ -189,125 +100,45 @@ export interface MigrationWizardProps { onComplete: () => void } -const capabilities = { - legacy: { - intro: true, - persist: true, - cleanup: true, - categories: new Set(["providers", "mcpServers", "customModes", "sessions", "defaultModel", "settings"]), - }, - roo: { - intro: false, - persist: false, - cleanup: false, - categories: new Set(["sessions"]), - }, -} satisfies Record }> - const MigrationWizard: Component = (props) => { const vscode = useVSCode() const dialog = useDialog() const language = useLanguage() - const source = props.source ?? "legacy" - const config = capabilities[source] + const source = props.source ?? "roo" const operationId = props.operationId ?? crypto.randomUUID() - - const [screen, setScreen] = createSignal(config.intro ? "whats-new" : "migrate") const [phase, setPhase] = createSignal("selecting") - - // Data from extension - const [providers, setProviders] = createSignal([]) - const [mcpServers, setMcpServers] = createSignal([]) - const [customModes, setCustomModes] = createSignal([]) const [sessions, setSessions] = createSignal([]) - const [defaultModel, setDefaultModel] = createSignal<{ provider: string; model: string } | undefined>(undefined) - const [legacySettings, setLegacySettings] = createSignal(undefined) - - // Group-level selections - const [migrateProviders, setMigrateProviders] = createSignal(true) - const [migrateMcpServers, setMigrateMcpServers] = createSignal(true) - const [migrateModes, setMigrateModes] = createSignal(true) - const [migrateSessions, setMigrateSessions] = createSignal(true) - const [migrateDefaultModel, setMigrateDefaultModel] = createSignal(true) - const [migrateAutoApproval, setMigrateAutoApproval] = createSignal(true) - const [migrateLanguage, setMigrateLanguage] = createSignal(true) - const [migrateAutocomplete, setMigrateAutocomplete] = createSignal(true) - - // Progress tracking - const [progressEntries, setProgressEntries] = createSignal([]) + const [selected, setSelected] = createSignal(false) + const [entries, setEntries] = createSignal([]) const [results, setResults] = createSignal([]) - const [sessionProgress, setSessionProgress] = createSignal(undefined) - const [sessionSummary, setSessionSummary] = createSignal(createSessionSummary()) - const [running, setRunning] = createSignal(false) - - // Cleanup preference - const [clearLegacyData, setClearLegacyData] = createSignal(false) - - // --------------------------------------------------------------------------- - // Message handling - // --------------------------------------------------------------------------- - - const applyData = (data: MigrationDataMessage["data"]) => { - setProviders(config.categories.has("providers") ? data.providers : []) - setMcpServers(config.categories.has("mcpServers") ? data.mcpServers : []) - setCustomModes(config.categories.has("customModes") ? data.customModes : []) - setSessions(config.categories.has("sessions") ? (data.sessions ?? []) : []) - setDefaultModel(config.categories.has("defaultModel") ? data.defaultModel : undefined) - setLegacySettings(config.categories.has("settings") ? data.settings : undefined) - setMigrateProviders( - config.categories.has("providers") && data.providers.some((item) => item.supported && item.hasApiKey), - ) - setMigrateMcpServers(config.categories.has("mcpServers") && data.mcpServers.length > 0) - setMigrateModes(config.categories.has("customModes") && data.customModes.length > 0) - setMigrateSessions(config.categories.has("sessions") && (data.sessions?.length ?? 0) > 0) - setMigrateDefaultModel(config.categories.has("defaultModel") && Boolean(data.defaultModel)) - - const settings = config.categories.has("settings") ? data.settings : undefined - if (!settings) return - setMigrateAutoApproval( - settings.autoApprovalEnabled !== undefined || - Boolean(settings.allowedCommands?.length) || - Boolean(settings.deniedCommands?.length) || - settings.alwaysAllowReadOnly !== undefined || - settings.alwaysAllowReadOnlyOutsideWorkspace !== undefined || - settings.alwaysAllowWrite !== undefined || - settings.alwaysAllowExecute !== undefined || - settings.alwaysAllowMcp !== undefined || - settings.alwaysAllowModeSwitch !== undefined || - settings.alwaysAllowSubtasks !== undefined, - ) - setMigrateLanguage(Boolean(settings.language)) - setMigrateAutocomplete(Boolean(settings.autocomplete)) - } + const [progress, setProgress] = createSignal(undefined) + const [summary, setSummary] = createSignal(createSessionSummary()) + const running = () => phase() === "migrating" onMount(() => { const handler = (event: MessageEvent) => { const msg = event.data if (msg?.source !== source || msg?.operationId !== operationId) return if (msg.type === "migrationData") { - applyData((msg as MigrationDataMessage).data) + const data = (msg as MigrationDataMessage).data + setSessions(data.sessions ?? []) + setSelected((data.sessions?.length ?? 0) > 0) } if (msg.type === "migrationProgress") { const update = msg as MigrationProgressMessage - setProgressEntries((prev) => { - const existing = prev.findIndex((e) => e.item === update.item) - const entry: ProgressEntry = { - item: update.item, - group: existing >= 0 ? prev[existing]?.group || update.item : update.item, - status: update.status, - message: update.message, - } - return existing >= 0 ? prev.map((e, i) => (i === existing ? entry : e)) : [...prev, entry] + setEntries((prev) => { + const entry = { item: update.item, status: update.status, message: update.message } + return prev.some((item) => item.item === update.item) + ? prev.map((item) => (item.item === update.item ? entry : item)) + : [...prev, entry] }) } if (msg.type === "migrationSessionProgress") { const update = msg as MigrationSessionProgressMessage - setSessionSummary((prev) => - updateSessionSummary(prev, createSessionItem(update.session, update.error), update.phase), - ) - setSessionProgress({ + setSummary((prev) => updateSessionSummary(prev, createSessionItem(update.session, update.error), update.phase)) + setProgress({ session: update.session, index: update.index, total: update.total, @@ -318,13 +149,10 @@ const MigrationWizard: Component = (props) => { if (msg.type === "migrationComplete") { const complete = msg as MigrationCompleteMessage - setResults(complete.results) - setRunning(false) - const hasErrors = complete.results.some((r) => r.status === "error") - setPhase(hasErrors ? "error" : "done") - if (!hasErrors) { - vscode.postMessage({ type: "loadSessions" }) - } + setResults(complete.results.filter((item) => item.category === "session")) + const errors = results().some((item) => item.status === "error") + setPhase(errors ? "error" : "done") + if (!errors) vscode.postMessage({ type: "loadSessions" }) } } @@ -333,618 +161,165 @@ const MigrationWizard: Component = (props) => { onCleanup(() => window.removeEventListener("message", handler)) }) - // --------------------------------------------------------------------------- - // Actions - // --------------------------------------------------------------------------- - - const handleSkip = () => { - if (!config.persist) { - props.onBack() - return - } - vscode.postMessage({ type: "skipLegacyMigration" }) - props.onBack() - } - - const emptyAutoApproval = (): MigrationAutoApprovalSelections => ({ - commandRules: false, - readPermission: false, - writePermission: false, - executePermission: false, - mcpPermission: false, - taskPermission: false, - }) - - const autoApprovalSelections = (): MigrationAutoApprovalSelections => { - if (!migrateAutoApproval()) return emptyAutoApproval() - const settings = legacySettings() - return { - commandRules: - settings?.autoApprovalEnabled !== undefined || - Boolean(settings?.allowedCommands?.length) || - Boolean(settings?.deniedCommands?.length), - readPermission: - settings?.alwaysAllowReadOnly !== undefined || settings?.alwaysAllowReadOnlyOutsideWorkspace !== undefined, - writePermission: settings?.alwaysAllowWrite !== undefined, - executePermission: settings?.alwaysAllowExecute !== undefined, - mcpPermission: settings?.alwaysAllowMcp !== undefined, - taskPermission: settings?.alwaysAllowModeSwitch !== undefined || settings?.alwaysAllowSubtasks !== undefined, - } - } - - const selections = (sessions: { id: string; force?: boolean }[] = []) => ({ - providers: migrateProviders() - ? providers() - .filter((provider) => provider.supported && provider.hasApiKey) - .map((provider) => provider.profileName) - : [], - mcpServers: migrateMcpServers() ? mcpServers().map((server) => server.name) : [], - customModes: migrateModes() ? customModes().map((mode) => mode.slug) : [], - sessions, - defaultModel: migrateDefaultModel(), - settings: { - autoApproval: autoApprovalSelections(), - language: migrateLanguage(), - autocomplete: migrateAutocomplete(), - }, - }) - - const handleStartMigration = () => { - const selected = selections(migrateSessions() ? sessions().map((session) => ({ id: session.id })) : []) - const approval = selected.settings.autoApproval - const entries: ProgressEntry[] = [ - ...selected.providers.map((item) => ({ item, group: "providers", status: "pending" as const })), - ...selected.mcpServers.map((item) => ({ item, group: "mcpServers", status: "pending" as const })), - ...selected.customModes.map((item) => ({ item, group: "customModes", status: "pending" as const })), - ...selected.sessions.map((session) => ({ item: session.id, group: "sessions", status: "pending" as const })), - ...(selected.defaultModel && defaultModel() - ? [{ item: "Default model", group: "defaultModel", status: "pending" as const }] - : []), - ...( - [ - [approval.commandRules, "Command rules"], - [approval.readPermission, "Read permission"], - [approval.writePermission, "Write permission"], - [approval.executePermission, "Execute permission"], - [approval.mcpPermission, "MCP permission"], - [approval.taskPermission, "Task permission"], - ] as const - ).flatMap(([enabled, item]) => (enabled ? [{ item, group: "autoApproval", status: "pending" as const }] : [])), - ...(selected.settings.language && legacySettings()?.language - ? [{ item: "Language preference", group: "language", status: "pending" as const }] - : []), - ...(selected.settings.autocomplete && legacySettings()?.autocomplete - ? [{ item: "Autocomplete settings", group: "autocomplete", status: "pending" as const }] - : []), - ] - setProgressEntries(entries) - setSessionSummary(createSessionSummary()) - setSessionProgress(undefined) - setRunning(true) + const start = (sessions: MigrationSessionSelection[]) => { + setEntries(sessions.map((session) => ({ item: session.id, status: "pending" }))) + setResults([]) + setProgress(undefined) setPhase("migrating") - vscode.postMessage({ type: "startMigration", source, operationId, selections: selected }) + vscode.postMessage({ + type: "startMigration", + source, + operationId, + selections: { sessions }, + }) } - const handleForceReimport = (ids: string[]) => { + const migrate = () => { + if (!selected() || sessions().length === 0 || running()) return + setSummary(createSessionSummary()) + start(sessions().map((session) => ({ id: session.id }))) + } + + const force = (ids: string[]) => { + if (running() || ids.length === 0) return dialog.show(() => ( { - setRunning(true) - setPhase("migrating") - setSessionProgress(undefined) - setResults((prev) => prev.filter((item) => item.category !== "session")) - setProgressEntries((prev) => [ - ...prev.filter((item) => item.group !== "sessions"), - ...ids.map((item) => ({ item, group: "sessions", status: "pending" as const })), - ]) - vscode.postMessage({ - type: "startMigration", - source, - operationId, - selections: { - providers: [], - mcpServers: [], - customModes: [], - sessions: ids.map((id) => ({ id, force: true })), - defaultModel: false, - settings: { - autoApproval: emptyAutoApproval(), - language: false, - autocomplete: false, - }, - }, - }) + start(ids.map((id) => ({ id, force: true }))) showToast({ variant: "success", title: language.t("migration.forceReimport.toast.started") }) }} /> )) } - const handleDone = () => { - if (!config.persist) { - vscode.postMessage({ type: "loadSessions" }) - props.onComplete() + const back = () => { + if (!running()) { + props.onBack() return } + dialog.show(() => props.onBack()} />) + } - if (running()) { - dialog.show(() => ( - { - vscode.postMessage({ type: "finalizeLegacyMigration" }) - if (config.cleanup && clearLegacyData()) { - vscode.postMessage({ type: "clearLegacyData" }) - } - props.onComplete() - }} - /> - )) - return - } - vscode.postMessage({ type: "finalizeLegacyMigration" }) - if (config.cleanup && clearLegacyData()) { - vscode.postMessage({ type: "clearLegacyData" }) - } + const done = () => { + vscode.postMessage({ type: "loadSessions" }) props.onComplete() } - // --------------------------------------------------------------------------- - // Data helpers - // --------------------------------------------------------------------------- - - const supportedProviderCount = () => providers().filter((p) => p.supported && p.hasApiKey).length - - const hasAnyAutoApprovalData = () => { - const s = legacySettings() - return ( - s !== undefined && - (s.autoApprovalEnabled !== undefined || - Boolean(s.allowedCommands?.length) || - Boolean(s.deniedCommands?.length) || - s.alwaysAllowReadOnly !== undefined || - s.alwaysAllowReadOnlyOutsideWorkspace !== undefined || - s.alwaysAllowWrite !== undefined || - s.alwaysAllowExecute !== undefined || - s.alwaysAllowMcp !== undefined || - s.alwaysAllowModeSwitch !== undefined || - s.alwaysAllowSubtasks !== undefined) - ) - } - - const hasLanguageData = () => Boolean(legacySettings()?.language) - const hasAutocompleteData = () => Boolean(legacySettings()?.autocomplete) - const hasSessions = () => sessions().length > 0 - - const hasAnySelection = () => - (migrateProviders() && supportedProviderCount() > 0) || - (migrateMcpServers() && mcpServers().length > 0) || - (migrateModes() && customModes().length > 0) || - (migrateSessions() && hasSessions()) || - (migrateDefaultModel() && Boolean(defaultModel())) || - (migrateAutoApproval() && hasAnyAutoApprovalData()) || - (migrateLanguage() && hasLanguageData()) || - (migrateAutocomplete() && hasAutocompleteData()) - - const hasNothingToShow = () => - supportedProviderCount() === 0 && - mcpServers().length === 0 && - customModes().length === 0 && - !hasSessions() && - !defaultModel() && - !hasAnyAutoApprovalData() && - !hasLanguageData() && - !hasAutocompleteData() - - // Group-level status for progress display - const groupStatus = (group: string): ProgressEntry["status"] => { - const entries = progressEntries().filter((entry) => entry.group === group) - if (entries.length === 0) return "pending" - if (group === "sessions" && running()) { - if (entries.some((entry) => entry.status === "migrating" || entry.status === "pending")) return "migrating" - } - if (entries.some((entry) => entry.status === "error")) return "error" - if (entries.some((entry) => entry.status === "warning")) return "warning" - if (entries.every((entry) => entry.status === "success")) return "success" - if (entries.some((entry) => entry.status === "migrating")) return "migrating" + const status = (): ProgressEntry["status"] => { + const list = entries() + if (list.length === 0) return "pending" + if (running() && list.some((item) => item.status === "migrating" || item.status === "pending")) return "migrating" + if (list.some((item) => item.status === "error")) return "error" + if (list.some((item) => item.status === "warning")) return "warning" + if (list.every((item) => item.status === "success")) return "success" + if (list.some((item) => item.status === "migrating")) return "migrating" return "pending" } - const successCount = () => results().filter((result) => result.status === "success").length - const totalCount = () => results().length - const groupMessage = (group: string) => - progressEntries().find((entry) => entry.group === group && entry.status === "error")?.message - const sessionIconSpinning = () => phase() === "migrating" && migrateSessions() && hasSessions() + const success = () => results().filter((item) => item.status === "success").length - // --------------------------------------------------------------------------- - // Status icon renderer - // --------------------------------------------------------------------------- - - const StatusIcon = (gProps: { group: string }): JSX.Element => { - const status = () => groupStatus(gProps.group) - const spinning = () => (gProps.group === "sessions" ? sessionIconSpinning() : status() === "migrating") - return ( - <> - -
- - -
-
-
- - -
- -
-
- -
- -
-
- -
- -
-
- - ) - } - - // --------------------------------------------------------------------------- - // JSX - // --------------------------------------------------------------------------- + const StatusIcon = (): JSX.Element => ( + <> + +
+ + +
+
+
+ + +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ + ) return (
- {/* ---- Screen 1: What's New ---- */} -
+
-

{language.t("migration.whatsNew.title")}

-

{language.t("migration.whatsNew.subtitle")}

+

{language.t("settings.aboutKiloCode.rooImport.button")}

+

{language.t("settings.aboutKiloCode.rooImport.description")}

-
-
-
- -
-
-
{language.t("migration.whatsNew.features.performance.title")}
-
{language.t("migration.whatsNew.features.performance.detail")}
-
-
- -
-
- -
-
-
{language.t("migration.whatsNew.features.interface.title")}
-
{language.t("migration.whatsNew.features.interface.detail")}
-
-
- -
-
- -
-
-
{language.t("migration.whatsNew.features.agentManager.title")}
-
{language.t("migration.whatsNew.features.agentManager.detail")}
-
-
- -
-
- -
-
-
{language.t("migration.whatsNew.features.foundation.title")}
-
{language.t("migration.whatsNew.features.foundation.detail")}
-
-
-
- - - - -
- - {/* ---- Screen 2: Migrate Settings ---- */} -
-
- -

{language.t("migration.migrate.title")}

-

{language.t("migration.migrate.subtitle")}

-
- - +
-
{language.t("migration.migrate.nothingToMigrate")}
+
{language.t("migration.roo.empty")}
- + 0}>
- {/* Summary after migration */} -
0 ? " migration-wizard__summary--success" : ""}`} - > +
0 ? " migration-wizard__summary--success" : ""}`}> {language.t("migration.complete.summary", { - success: String(successCount()), - total: String(totalCount()), + success: String(success()), + total: String(results().length), })}
- - {/* Provider API Keys */} - 0}> -
- }> - - -
-
{language.t("migration.select.providers")}
-
- {language.t("migration.migrate.keysDetected", { - count: String(supportedProviderCount()), - })} -
-
-
-
- - {/* MCP Servers */} - 0}> -
- }> - - -
-
{language.t("migration.select.mcpServers")}
-
- {language.t("migration.migrate.serversConfigured", { - count: String(mcpServers().length), - })} -
-
-
-
- - {/* Custom Modes */} - 0}> -
- }> - - -
-
{language.t("migration.select.customModes")}
-
- {language.t("migration.migrate.modesFound", { - count: String(customModes().length), - })} -
-
-
-
- - -
- }> - - -
-
{language.t("migration.migrate.chatHistory")}
-
- {language.t("migration.migrate.sessionsDetected", { count: String(sessions().length) })} -
- - } - > - - - -
-
-
- - {/* Default Model */} - -
- }> - - -
-
{language.t("migration.select.defaultModel")}
-
-
-
- - {/* Auto-Approval */} - -
- }> - - -
-
{language.t("migration.select.autoApproval")}
-
-
-
- - {/* Language */} - -
- }> - - -
-
{language.t("migration.select.language")}
-
-
-
- - {/* Autocomplete */} - -
- }> - - -
-
{language.t("migration.select.autocomplete")}
-
-
-
- - {/* Cleanup option after done */} - {/* - -
-
+
+ }> -
setClearLegacyData((v) => !v)}> -
{language.t("migration.complete.cleanup")}
-
{language.t("migration.complete.cleanupDescription")}
+ +
+
{language.t("migration.migrate.chatHistory")}
+
+ {language.t("migration.migrate.sessionsDetected", { count: String(sessions().length) })}
+ + } + > + + +
- - */} +
- {/* Footer */} - {/* legacy-migration start */} -
-

{language.t("settings.aboutKiloCode.legacyMigration.title")}

+
+

{language.t("settings.aboutKiloCode.rooImport.button")}

= (props) => { "line-height": "1.5", }} > - {language.t("settings.aboutKiloCode.legacyMigration.description")} + {language.t("settings.aboutKiloCode.rooImport.description")}

-
- - -
+
- {/* legacy-migration end */} {/* Reset Settings */}
diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/Settings.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/Settings.tsx index 22ff8dadc0a..dace3609b1d 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/Settings.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/Settings.tsx @@ -47,7 +47,7 @@ export interface SettingsProps { agentManagerProjectId?: string agentManagerSettings?: boolean onTabChange?: (tab: string) => void - onMigrationClick?: (source: MigrationSource) => void // legacy-migration + onMigrationClick?: (source: MigrationSource) => void } const AgentManagerTab: Component<{ projectId?: string }> = (props) => { diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index ef5153f788d..340fcef6031 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1162,6 +1162,8 @@ export const dict = { "Migrate settings from a previous installation of Kilo Code, including provider API keys and default model.", "settings.aboutKiloCode.rooImport.description": "Import conversation history from a Roo Code installation.", "settings.aboutKiloCode.rooImport.button": "Import Sessions from Roo Code", + "migration.roo.button": "Import Sessions", + "migration.roo.empty": "No Roo Code sessions found.", // Screen 1 — What's New "migration.whatsNew.title": "What's New in Kilo Code", diff --git a/packages/kilo-vscode/webview-ui/src/stories/migration.stories.tsx b/packages/kilo-vscode/webview-ui/src/stories/migration.stories.tsx index 086bce8ea88..0ae3c44d414 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/migration.stories.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/migration.stories.tsx @@ -26,9 +26,6 @@ const RooWizard: Component = () => { source: "roo", operationId, data: { - providers: [], - mcpServers: [], - customModes: [], sessions: [ { id: "roo-1", 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 6ed1bee92ac..cc28f510509 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 @@ -82,7 +82,6 @@ import type { MigrationDataMessage, MigrationProgressMessage, MigrationSessionProgressMessage, - MigrationStateMessage, } from "./migration" import type { MemoryEventMessage, MemoryLoadedMessage, MemoryOperationResultMessage } from "./memory" @@ -1636,13 +1635,10 @@ export type ExtensionMessage = | AgentManagerTerminalErrorMessage | AgentManagerTerminalDestinationChangedMessage | AgentManagerScriptTerminalsMessage - // legacy-migration start - | MigrationStateMessage | MigrationDataMessage | MigrationProgressMessage | MigrationSessionProgressMessage | MigrationCompleteMessage - // legacy-migration end | EnhancePromptResultMessage | EnhancePromptErrorMessage | ViewSubAgentSessionMessage diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/migration.ts b/packages/kilo-vscode/webview-ui/src/types/messages/migration.ts index c7f7bebc75f..b80b5c13d50 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/migration.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/migration.ts @@ -1,45 +1,3 @@ -// legacy-migration start -export interface MigrationProviderInfo { - profileName: string - provider: string - model?: string - hasApiKey: boolean - supported: boolean - newProviderName?: string -} - -export interface MigrationMcpServerInfo { - name: string - type: string -} - -export interface MigrationCustomModeInfo { - name: string - slug: string -} - -export interface LegacyAutocompleteSettings { - enableAutoTrigger?: boolean - enableSmartInlineTaskKeybinding?: boolean - enableChatAutocomplete?: boolean -} - -export interface LegacySettings { - autoApprovalEnabled?: boolean - allowedCommands?: string[] - deniedCommands?: string[] - // Fine-grained auto-approval (legacy globalState keys — no prefix) - alwaysAllowReadOnly?: boolean - alwaysAllowReadOnlyOutsideWorkspace?: boolean - alwaysAllowWrite?: boolean - alwaysAllowExecute?: boolean - alwaysAllowMcp?: boolean - alwaysAllowModeSwitch?: boolean - alwaysAllowSubtasks?: boolean - language?: string - autocomplete?: LegacyAutocompleteSettings -} - export interface MigrationSessionInfo { id: string title: string @@ -49,30 +7,19 @@ export interface MigrationSessionInfo { export interface MigrationResultItem { item: string - category: "provider" | "mcpServer" | "customMode" | "session" | "defaultModel" | "settings" + category: "session" status: "success" | "warning" | "error" message?: string } -export type MigrationSource = "legacy" | "roo" - -export interface MigrationStateMessage { - type: "migrationState" - needed: boolean - source: "legacy" -} +export type MigrationSource = "roo" export interface MigrationDataMessage { type: "migrationData" source: MigrationSource operationId: string data: { - providers: MigrationProviderInfo[] - mcpServers: MigrationMcpServerInfo[] - customModes: MigrationCustomModeInfo[] sessions?: MigrationSessionInfo[] - defaultModel?: { provider: string; model: string } - settings?: LegacySettings } } @@ -111,15 +58,6 @@ export interface RequestMigrationDataMessage { operationId: string } -export interface MigrationAutoApprovalSelections { - commandRules: boolean - readPermission: boolean - writePermission: boolean - executePermission: boolean - mcpPermission: boolean - taskPermission: boolean -} - export interface MigrationSessionSelection { id: string force?: boolean @@ -130,28 +68,6 @@ export interface StartMigrationMessage { source: MigrationSource operationId: string selections: { - providers: string[] - mcpServers: string[] - customModes: string[] sessions?: MigrationSessionSelection[] - defaultModel: boolean - settings: { - autoApproval: MigrationAutoApprovalSelections - language: boolean - autocomplete: boolean - } } } - -export interface SkipLegacyMigrationMessage { - type: "skipLegacyMigration" -} - -export interface ClearLegacyDataMessage { - type: "clearLegacyData" -} - -export interface FinalizeLegacyMigrationMessage { - type: "finalizeLegacyMigration" -} -// legacy-migration end 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 ae08673e9f8..2fa459701b5 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 @@ -10,13 +10,7 @@ import type { BrowserFeedbackData } from "../../../../src/shared/browser-feedbac import type { WorkStyle, WorkStyleState } from "../../../../src/shared/work-style-presets" import type { RefreshProviderUsageMessage, RequestProviderUsageMessage } from "./provider-usage" import type { AnacondaDesktopWebviewMessage } from "../../../../src/shared/anaconda-desktop-messages" -import type { - ClearLegacyDataMessage, - FinalizeLegacyMigrationMessage, - RequestMigrationDataMessage, - SkipLegacyMigrationMessage, - StartMigrationMessage, -} from "./migration" +import type { RequestMigrationDataMessage, StartMigrationMessage } from "./migration" import type { MemoryShowMessage, MemoryOperationMessage, RequestMemoryMessage } from "./memory" import type { Activity } from "../../utils/session-activity" @@ -1694,13 +1688,8 @@ export type WebviewMessage = | RefreshPRMessage | OpenPRMessage | CommentActionMessage - // legacy-migration start | RequestMigrationDataMessage | StartMigrationMessage - | SkipLegacyMigrationMessage - | ClearLegacyDataMessage - | FinalizeLegacyMigrationMessage - // legacy-migration end | ApplyWorktreeDiffMessage | RevertWorktreeFileMessage | EnhancePromptRequest From 18fd9ab378a6bd6baf146ca86e9d12ec636ef019 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Mon, 31 Aug 2026 13:16:50 +0200 Subject: [PATCH 2/4] fix(i18n): clean up retired migration translations --- .../kilo-vscode/webview-ui/src/i18n/ar.ts | 47 +----------------- .../kilo-vscode/webview-ui/src/i18n/br.ts | 47 +----------------- .../kilo-vscode/webview-ui/src/i18n/bs.ts | 47 +----------------- .../kilo-vscode/webview-ui/src/i18n/da.ts | 48 +----------------- .../kilo-vscode/webview-ui/src/i18n/de.ts | 49 +------------------ .../kilo-vscode/webview-ui/src/i18n/en.ts | 48 ------------------ .../kilo-vscode/webview-ui/src/i18n/es.ts | 48 +----------------- .../kilo-vscode/webview-ui/src/i18n/fa.ts | 47 +----------------- .../kilo-vscode/webview-ui/src/i18n/fr.ts | 48 +----------------- .../kilo-vscode/webview-ui/src/i18n/it.ts | 41 +--------------- .../kilo-vscode/webview-ui/src/i18n/ja.ts | 47 +----------------- .../kilo-vscode/webview-ui/src/i18n/ko.ts | 47 +----------------- .../kilo-vscode/webview-ui/src/i18n/nl.ts | 48 +----------------- .../kilo-vscode/webview-ui/src/i18n/no.ts | 47 +----------------- .../kilo-vscode/webview-ui/src/i18n/pl.ts | 47 +----------------- .../kilo-vscode/webview-ui/src/i18n/ru.ts | 47 +----------------- .../kilo-vscode/webview-ui/src/i18n/th.ts | 47 +----------------- .../kilo-vscode/webview-ui/src/i18n/tr.ts | 48 +----------------- .../kilo-vscode/webview-ui/src/i18n/uk.ts | 48 +----------------- .../kilo-vscode/webview-ui/src/i18n/zh.ts | 46 +---------------- .../kilo-vscode/webview-ui/src/i18n/zht.ts | 46 +---------------- 21 files changed, 40 insertions(+), 948 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index e9dcf909fa5..a779460520f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1141,58 +1141,16 @@ export const dict = { "question.summary": "{{n}} من {{total}} أسئلة", "common.review": "مراجعة", - // legacy-migration start - "settings.legacyMigration.link": "الترحيل من الإصدار القديم", - "settings.aboutKiloCode.legacyMigration.title": "ترحيل الإصدار القديم", - "settings.aboutKiloCode.legacyMigration.description": - "ترحيل الإعدادات من تثبيت سابق لـ Kilo Code، بما في ذلك مفاتيح API لمقدمي الخدمة والنموذج الافتراضي.", "settings.aboutKiloCode.rooImport.description": "استيراد سجل المحادثات من تثبيت Roo Code.", "settings.aboutKiloCode.rooImport.button": "استيراد الجلسات من Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "ما الجديد في Kilo Code", - "migration.whatsNew.subtitle": "لقد أعدنا بناء الإضافة على أساس أسرع وأكثر كفاءة.", - "migration.whatsNew.features.performance.title": "أداء أسرع للوكيل", - "migration.whatsNew.features.performance.detail": - "استدعاءات الأدوات المتوازية والوكلاء الفرعيون يتيحون لوكيلك إنجاز المزيد في وقت واحد — فتقضي وقتًا أقل في الانتظار ووقتًا أكثر في الإنجاز.", - "migration.whatsNew.features.interface.title": "واجهة مبسّطة", - "migration.whatsNew.features.interface.detail": "أقل تشتيتًا، أسهل وأسرع في القراءة.", - "migration.whatsNew.features.agentManager.title": "مدير الوكلاء", - "migration.whatsNew.features.agentManager.detail": - "واجهة موحدة لتشغيل عدة وكلاء بالتوازي، كل منهم في شجرة عمل خاصة — راقب التقدم، وبدّل السياق، وراجع التغييرات في مكان واحد.", - "migration.whatsNew.features.foundation.title": "أساس مشترك", - "migration.whatsNew.features.foundation.detail": - "نواة صغيرة وفعالة واحدة عبر كل منتجات Kilo. تجربة مألوفة بغض النظر عن طريقة عملك.", - "migration.whatsNew.blogLink": "اقرأ الإعلان الكامل", - "migration.whatsNew.docsLink": "الجديد والأسئلة الشائعة", - "migration.whatsNew.continue": "متابعة", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "ترحيل إعداداتك", - "migration.migrate.subtitle": "لقد وجدنا إعدادات من تثبيتك السابق. إليك ما يمكننا نقله.", + "migration.roo.button": "استيراد الجلسات", + "migration.roo.empty": "لم يتم العثور على جلسات Roo Code.", "migration.migrate.selectLabel": "اختر ما تريد ترحيله", "migration.migrate.chatHistory": "جلسات الدردشة والسجل", - "migration.migrate.button": "ترحيل الإعدادات", - "migration.migrate.skip": "تخطي", - "migration.migrate.keysDetected": "تم اكتشاف {{count}} مفاتيح", - "migration.migrate.serversConfigured": "تم تكوين {{count}} خادم(خوادم)", - "migration.migrate.modesFound": "تم العثور على {{count}} وضع(أوضاع)", - "migration.migrate.nothingToMigrate": "لم يتم العثور على أي شيء لترحيله في الإعدادات القديمة.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "مفاتيح API لمقدمي الخدمة", - "migration.select.mcpServers": "خوادم MCP", - "migration.select.customModes": "الأوضاع المخصصة / الوكلاء", - "migration.select.defaultModel": "النموذج الافتراضي", - "migration.select.autoApproval": "الموافقة التلقائية", - "migration.select.language": "لغة واجهة المستخدم", - "migration.select.autocomplete": "إعدادات الإكمال التلقائي", // Migrate — completion "migration.complete.summary": "تم ترحيل {{success}} من {{total}} عناصر بنجاح.", - "migration.complete.cleanup": "إزالة بيانات الإعدادات القديمة", - "migration.complete.cleanupDescription": - "هذا يزيل الإعدادات القديمة من مساحة تخزين VS Code. لن تتمكن من إعادة تشغيل هذا الترحيل.", "migration.complete.done": "تم", "migration.migrate.sessionsDetected": "تم اكتشاف {{count}} جلسة", "migration.error.continue": "متابعة", @@ -1226,7 +1184,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "تاريخ غير معروف", "migration.sessionFormat.unknown": "غير معروف", "migration.sessionFormat.unknownError": "خطأ غير معروف", - // legacy-migration end "error.details.show": "التفاصيل", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 26120823bf9..260b064febd 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1184,58 +1184,16 @@ export const dict = { "question.summary": "{{n}} de {{total}} perguntas", "common.review": "Revisar", - // legacy-migration start - "settings.legacyMigration.link": "Migrar da Versão Legada", - "settings.aboutKiloCode.legacyMigration.title": "Migração Legada", - "settings.aboutKiloCode.legacyMigration.description": - "Migre as configurações de uma instalação anterior do Kilo Code, incluindo chaves de API de provedor e modelo padrão.", "settings.aboutKiloCode.rooImport.description": "Importe o histórico de conversas de uma instalação do Roo Code.", "settings.aboutKiloCode.rooImport.button": "Importar sessões do Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "O Que Há de Novo no Kilo Code", - "migration.whatsNew.subtitle": "Reconstruímos a extensão sobre uma base mais rápida e eficiente.", - "migration.whatsNew.features.performance.title": "Desempenho de Agente Mais Rápido", - "migration.whatsNew.features.performance.detail": - "Chamadas de ferramentas paralelas e subagentes permitem que seu agente faça mais de uma vez — assim você gasta menos tempo esperando e mais tempo entregando.", - "migration.whatsNew.features.interface.title": "Interface Simplificada", - "migration.whatsNew.features.interface.detail": "Menos distrações, mais fácil e rápido de ler.", - "migration.whatsNew.features.agentManager.title": "Gerenciador de Agentes", - "migration.whatsNew.features.agentManager.detail": - "Uma interface unificada para executar múltiplos agentes em paralelo, cada um em sua própria worktree — monitore o progresso, troque de contexto e revise alterações em um só lugar.", - "migration.whatsNew.features.foundation.title": "Base Compartilhada", - "migration.whatsNew.features.foundation.detail": - "Um núcleo pequeno e eficiente em todos os produtos Kilo. Uma experiência familiar independentemente de como você escolha trabalhar.", - "migration.whatsNew.blogLink": "Leia o anúncio completo", - "migration.whatsNew.docsLink": "Novidades e perguntas frequentes", - "migration.whatsNew.continue": "Continuar", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Migre Suas Configurações", - "migration.migrate.subtitle": "Encontramos configurações da sua instalação anterior. Veja o que podemos trazer.", + "migration.roo.button": "Importar sessões", + "migration.roo.empty": "Nenhuma sessão do Roo Code encontrada.", "migration.migrate.selectLabel": "Selecione o que migrar", "migration.migrate.chatHistory": "Sessões de Chat e Histórico", - "migration.migrate.button": "Migrar Configurações", - "migration.migrate.skip": "Pular", - "migration.migrate.keysDetected": "{{count}} chaves detectadas", - "migration.migrate.serversConfigured": "{{count}} servidor(es) configurado(s)", - "migration.migrate.modesFound": "{{count}} modo(s) encontrado(s)", - "migration.migrate.nothingToMigrate": "Nada para migrar foi encontrado nas configurações legadas.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "Chaves de API de Provedor", - "migration.select.mcpServers": "Servidores MCP", - "migration.select.customModes": "Modos Personalizados / Agentes", - "migration.select.defaultModel": "Modelo Padrão", - "migration.select.autoApproval": "Aprovação Automática", - "migration.select.language": "Idioma da Interface", - "migration.select.autocomplete": "Configurações de Autocomplete", // Migrate — completion "migration.complete.summary": "{{success}} de {{total}} itens migrados com sucesso.", - "migration.complete.cleanup": "Remover dados de configurações legadas", - "migration.complete.cleanupDescription": - "Isso remove as configurações antigas do armazenamento do VS Code. Você não poderá executar esta migração novamente.", "migration.complete.done": "Concluído", "migration.migrate.sessionsDetected": "{{count}} sessões detectadas", "migration.error.continue": "Continuar", @@ -1269,7 +1227,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Data desconhecida", "migration.sessionFormat.unknown": "Desconhecido", "migration.sessionFormat.unknownError": "Erro desconhecido", - // legacy-migration end "error.details.show": "Detalhes", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 97dff4307df..1254b3a39be 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1175,58 +1175,16 @@ export const dict = { "question.summary": "{{n}} od {{total}} pitanja", "common.review": "Pregled", - // legacy-migration start - "settings.legacyMigration.link": "Migriraj sa prethodne verzije", - "settings.aboutKiloCode.legacyMigration.title": "Migracija sa prethodne verzije", - "settings.aboutKiloCode.legacyMigration.description": - "Migrirajte postavke iz prethodne instalacije Kilo Code, uključujući API ključeve provajdera i podrazumijevani model.", "settings.aboutKiloCode.rooImport.description": "Uvezite historiju razgovora iz instalacije Roo Code.", "settings.aboutKiloCode.rooImport.button": "Uvezi sesije iz Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "Šta je novo u Kilo Code", - "migration.whatsNew.subtitle": "Ponovo smo izgradili ekstenziju na bržem i efikasnijem temelju.", - "migration.whatsNew.features.performance.title": "Brže performanse agenta", - "migration.whatsNew.features.performance.detail": - "Paralelni pozivi alata i podagenti omogućavaju vašem agentu da radi više odjednom — tako trošite manje vremena čekajući, a više isporučujući.", - "migration.whatsNew.features.interface.title": "Pojednostavljeni interfejs", - "migration.whatsNew.features.interface.detail": "Manje distrakcija, lakše i brže za čitanje.", - "migration.whatsNew.features.agentManager.title": "Upravljač agentima", - "migration.whatsNew.features.agentManager.detail": - "Jedinstveni interfejs za pokretanje više agenata paralelno, svaki na svom worktree-u — pratite napredak, mijenjajte kontekst i pregledajte promjene na jednom mjestu.", - "migration.whatsNew.features.foundation.title": "Zajednički temelj", - "migration.whatsNew.features.foundation.detail": - "Jedno malo, efikasno jezgro kroz sve Kilo proizvode. Poznato iskustvo bez obzira na to kako odaberete raditi.", - "migration.whatsNew.blogLink": "Pročitajte cijeli oglas", - "migration.whatsNew.docsLink": "Novosti i često postavljana pitanja", - "migration.whatsNew.continue": "Nastavi", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Migrirajte svoje postavke", - "migration.migrate.subtitle": "Pronašli smo postavke iz vaše prethodne instalacije. Evo šta možemo prenijeti.", + "migration.roo.button": "Uvezi sesije", + "migration.roo.empty": "Nisu pronađene sesije iz Roo Code.", "migration.migrate.selectLabel": "Odaberite šta želite migrirati", "migration.migrate.chatHistory": "Sesije razgovora i historija", - "migration.migrate.button": "Migriraj postavke", - "migration.migrate.skip": "Preskoči", - "migration.migrate.keysDetected": "{{count}} ključeva otkriveno", - "migration.migrate.serversConfigured": "{{count}} server(a) konfigurisano", - "migration.migrate.modesFound": "{{count}} režim(a) pronađeno", - "migration.migrate.nothingToMigrate": "U starim postavkama nije pronađeno ništa za migraciju.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "API ključevi provajdera", - "migration.select.mcpServers": "MCP serveri", - "migration.select.customModes": "Prilagođeni režimi / Agenti", - "migration.select.defaultModel": "Podrazumijevani model", - "migration.select.autoApproval": "Automatsko odobravanje", - "migration.select.language": "Jezik korisničkog interfejsa", - "migration.select.autocomplete": "Postavke automatskog dovršavanja", // Migrate — completion "migration.complete.summary": "Uspješno migrirano {{success}} od {{total}} stavki.", - "migration.complete.cleanup": "Ukloni stare podatke postavki", - "migration.complete.cleanupDescription": - "Ovo uklanja stare postavke iz VS Code pohrane. Nećete moći ponovo pokrenuti ovu migraciju.", "migration.complete.done": "Završeno", "migration.migrate.sessionsDetected": "Otkrivene {{count}} sesije", "migration.error.continue": "Nastavi", @@ -1260,7 +1218,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Nepoznat datum", "migration.sessionFormat.unknown": "Nepoznato", "migration.sessionFormat.unknownError": "Nepoznata greška", - // legacy-migration end "error.details.show": "Detalji", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 320bbb267c9..21baf665f4d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1169,59 +1169,16 @@ export const dict = { "question.summary": "{{n}} af {{total}} spørgsmål", "common.review": "Gennemgå", - // legacy-migration start - "settings.legacyMigration.link": "Migrer fra legacy-version", - "settings.aboutKiloCode.legacyMigration.title": "Legacy-migrering", - "settings.aboutKiloCode.legacyMigration.description": - "Migrer indstillinger fra en tidligere installation af Kilo Code, herunder udbyder API-nøgler og standardmodel.", "settings.aboutKiloCode.rooImport.description": "Importer samtalehistorik fra en installation af Roo Code.", "settings.aboutKiloCode.rooImport.button": "Importer sessioner fra Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "Nyheder i Kilo Code", - "migration.whatsNew.subtitle": "Vi har genopbygget udvidelsen på et hurtigere og mere effektivt fundament.", - "migration.whatsNew.features.performance.title": "Hurtigere agentydelse", - "migration.whatsNew.features.performance.detail": - "Parallelle værktøjskald og underagenter lader din agent tackle mere på én gang — så du bruger mindre tid på at vente og mere tid på at levere.", - "migration.whatsNew.features.interface.title": "Strømlinet brugerflade", - "migration.whatsNew.features.interface.detail": "Færre distraktioner, nemmere og hurtigere at læse.", - "migration.whatsNew.features.agentManager.title": "Agentstyring", - "migration.whatsNew.features.agentManager.detail": - "En samlet brugerflade til at køre flere agenter parallelt, hver på sit eget worktree — overvåg fremskridt, skift kontekst og gennemgå ændringer ét sted.", - "migration.whatsNew.features.foundation.title": "Fælles fundament", - "migration.whatsNew.features.foundation.detail": - "Én lille, effektiv kerne på tværs af alle Kilo-produkter. En velkendt oplevelse uanset hvordan du vælger at arbejde.", - "migration.whatsNew.blogLink": "Læs den fulde meddelelse", - "migration.whatsNew.docsLink": "Nyheder og ofte stillede spørgsmål", - "migration.whatsNew.continue": "Fortsæt", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Migrer dine indstillinger", - "migration.migrate.subtitle": - "Vi har fundet indstillinger fra din tidligere installation. Her er, hvad vi kan overføre.", + "migration.roo.button": "Importér sessioner", + "migration.roo.empty": "Ingen Roo Code-sessioner fundet.", "migration.migrate.selectLabel": "Vælg hvad der skal migreres", "migration.migrate.chatHistory": "Chatsessioner og historik", - "migration.migrate.button": "Migrer indstillinger", - "migration.migrate.skip": "Spring over", - "migration.migrate.keysDetected": "{{count}} nøgler fundet", - "migration.migrate.serversConfigured": "{{count}} server(e) konfigureret", - "migration.migrate.modesFound": "{{count}} tilstand(e) fundet", - "migration.migrate.nothingToMigrate": "Der blev ikke fundet noget at migrere i legacy-indstillingerne.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "Udbyder API-nøgler", - "migration.select.mcpServers": "MCP-servere", - "migration.select.customModes": "Brugerdefinerede tilstande / Agenter", - "migration.select.defaultModel": "Standardmodel", - "migration.select.autoApproval": "Automatisk godkendelse", - "migration.select.language": "UI-sprog", - "migration.select.autocomplete": "Indstillinger for autofuldførelse", // Migrate — completion "migration.complete.summary": "{{success}} af {{total}} elementer blev migreret med succes.", - "migration.complete.cleanup": "Fjern legacy-indstillingsdata", - "migration.complete.cleanupDescription": - "Dette fjerner de gamle indstillinger fra VS Code-lageret. Du vil ikke kunne køre denne migrering igen.", "migration.complete.done": "Færdig", "migration.migrate.sessionsDetected": "{{count}} sessioner fundet", "migration.error.continue": "Fortsæt", @@ -1255,7 +1212,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Ukendt dato", "migration.sessionFormat.unknown": "Ukendt", "migration.sessionFormat.unknownError": "Ukendt fejl", - // legacy-migration end "error.details.show": "Detaljer", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 8f9e3a8fe01..d9a00ea6b58 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1196,61 +1196,17 @@ export const dict = { "question.summary": "{{n}} von {{total}} Fragen", "common.review": "Überprüfen", - // legacy-migration start - "settings.legacyMigration.link": "Von der Legacy-Version migrieren", - "settings.aboutKiloCode.legacyMigration.title": "Legacy-Migration", - "settings.aboutKiloCode.legacyMigration.description": - "Migrieren Sie Einstellungen von einer früheren Installation von Kilo Code, einschließlich Anbieter-API-Schlüsseln und dem Standardmodell.", "settings.aboutKiloCode.rooImport.description": "Importieren Sie den Konversationsverlauf von einer Installation von Roo Code.", "settings.aboutKiloCode.rooImport.button": "Sitzungen aus Roo Code importieren", - // Screen 1 — What's New - "migration.whatsNew.title": "Neuigkeiten in Kilo Code", - "migration.whatsNew.subtitle": - "Wir haben die Erweiterung auf einer schnelleren, effizienteren Grundlage neu aufgebaut.", - "migration.whatsNew.features.performance.title": "Schnellere Agentenleistung", - "migration.whatsNew.features.performance.detail": - "Parallele Werkzeugaufrufe und Unteragenten lassen Ihren Agenten mehr gleichzeitig erledigen — so verbringen Sie weniger Zeit mit Warten und mehr Zeit mit Ergebnissen.", - "migration.whatsNew.features.interface.title": "Optimierte Oberfläche", - "migration.whatsNew.features.interface.detail": "Weniger Ablenkungen, einfacher und schneller zu lesen.", - "migration.whatsNew.features.agentManager.title": "Agentenverwaltung", - "migration.whatsNew.features.agentManager.detail": - "Eine einheitliche Oberfläche zum parallelen Ausführen mehrerer Agenten, jeweils in einem eigenen Worktree — Fortschritt überwachen, Kontext wechseln und Änderungen an einem Ort überprüfen.", - "migration.whatsNew.features.foundation.title": "Gemeinsame Grundlage", - "migration.whatsNew.features.foundation.detail": - "Ein kleiner, effizienter Kern über alle Kilo-Produkte hinweg. Ein vertrautes Erlebnis, egal wie Sie arbeiten.", - "migration.whatsNew.blogLink": "Die vollständige Ankündigung lesen", - "migration.whatsNew.docsLink": "Neuigkeiten & häufige Fragen", - "migration.whatsNew.continue": "Weiter", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Ihre Einstellungen migrieren", - "migration.migrate.subtitle": - "Wir haben Einstellungen aus Ihrer vorherigen Installation gefunden. Hier ist, was wir übernehmen können.", + "migration.roo.button": "Sitzungen importieren", + "migration.roo.empty": "Keine Roo Code-Sitzungen gefunden.", "migration.migrate.selectLabel": "Auswählen, was migriert werden soll", "migration.migrate.chatHistory": "Chat-Sitzungen & Verlauf", - "migration.migrate.button": "Einstellungen migrieren", - "migration.migrate.skip": "Überspringen", - "migration.migrate.keysDetected": "{{count}} Schlüssel erkannt", - "migration.migrate.serversConfigured": "{{count}} Server konfiguriert", - "migration.migrate.modesFound": "{{count}} Modus/Modi gefunden", - "migration.migrate.nothingToMigrate": "In den Legacy-Einstellungen wurde nichts zum Migrieren gefunden.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "Anbieter-API-Schlüssel", - "migration.select.mcpServers": "MCP-Server", - "migration.select.customModes": "Benutzerdefinierte Modi / Agenten", - "migration.select.defaultModel": "Standardmodell", - "migration.select.autoApproval": "Automatische Genehmigung", - "migration.select.language": "UI-Sprache", - "migration.select.autocomplete": "Einstellungen für Autovervollständigung", // Migrate — completion "migration.complete.summary": "{{success}} von {{total}} Elementen erfolgreich migriert.", - "migration.complete.cleanup": "Legacy-Einstellungsdaten entfernen", - "migration.complete.cleanupDescription": - "Dadurch werden die alten Einstellungen aus dem VS Code-Speicher entfernt. Sie können diese Migration danach nicht erneut ausführen.", "migration.complete.done": "Fertig", "migration.migrate.sessionsDetected": "{{count}} Sitzungen erkannt", "migration.error.continue": "Weiter", @@ -1284,7 +1240,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Unbekanntes Datum", "migration.sessionFormat.unknown": "Unbekannt", "migration.sessionFormat.unknownError": "Unbekannter Fehler", - // legacy-migration end "error.details.show": "Details", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 340fcef6031..3e596d07f55 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1155,61 +1155,14 @@ export const dict = { "question.summary": "{{n}} of {{total}} questions", "common.review": "Review", - // legacy-migration start - "settings.legacyMigration.link": "Migrate from Legacy Version", - "settings.aboutKiloCode.legacyMigration.title": "Legacy Migration", - "settings.aboutKiloCode.legacyMigration.description": - "Migrate settings from a previous installation of Kilo Code, including provider API keys and default model.", "settings.aboutKiloCode.rooImport.description": "Import conversation history from a Roo Code installation.", "settings.aboutKiloCode.rooImport.button": "Import Sessions from Roo Code", "migration.roo.button": "Import Sessions", "migration.roo.empty": "No Roo Code sessions found.", - - // Screen 1 — What's New - "migration.whatsNew.title": "What's New in Kilo Code", - "migration.whatsNew.subtitle": "We've rebuilt the extension on a faster, more efficient foundation.", - "migration.whatsNew.features.performance.title": "Faster Agent Performance", - "migration.whatsNew.features.performance.detail": - "Parallel tool calls and subagents let your agent tackle more at once — so you spend less time watching and more time shipping.", - "migration.whatsNew.features.interface.title": "Streamlined Interface", - "migration.whatsNew.features.interface.detail": "Fewer distractions, easier and quicker to read.", - "migration.whatsNew.features.agentManager.title": "Agent Manager", - "migration.whatsNew.features.agentManager.detail": - "A unified interface for running multiple agents in parallel, each on its own worktree — monitor progress, switch context, and review changes in one place.", - "migration.whatsNew.features.foundation.title": "Shared Foundation", - "migration.whatsNew.features.foundation.detail": - "One small, efficient core across every Kilo product. A familiar experience however you choose to work.", - "migration.whatsNew.blogLink": "Read the full announcement", - "migration.whatsNew.docsLink": "What's new & FAQ", - "migration.whatsNew.continue": "Continue", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Migrate Your Settings", - "migration.migrate.subtitle": "We found settings from your previous installation. Here's what we can bring over.", "migration.migrate.selectLabel": "Select what to migrate", "migration.migrate.chatHistory": "Chat Sessions & History", - "migration.migrate.button": "Migrate Settings", - "migration.migrate.skip": "Skip", - "migration.migrate.keysDetected": "{{count}} keys detected", - "migration.migrate.serversConfigured": "{{count}} server(s) configured", - "migration.migrate.modesFound": "{{count}} mode(s) found", "migration.migrate.sessionsDetected": "{{count}} sessions detected", - "migration.migrate.nothingToMigrate": "Nothing to migrate was found in the legacy settings.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "Provider API Keys", - "migration.select.mcpServers": "MCP Servers", - "migration.select.customModes": "Custom Modes / Agents", - "migration.select.defaultModel": "Default Model", - "migration.select.autoApproval": "Auto-Approval", - "migration.select.language": "UI Language", - "migration.select.autocomplete": "Autocomplete Settings", - - // Migrate — completion "migration.complete.summary": "{{success}} of {{total}} items migrated successfully.", - "migration.complete.cleanup": "Remove legacy settings data", - "migration.complete.cleanupDescription": - "This removes the old settings from VS Code storage. You will not be able to re-run this migration.", "migration.complete.done": "Done", "migration.error.continue": "Continue", "migration.sessionSummary.title": "Summary:", @@ -1241,7 +1194,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Unknown date", "migration.sessionFormat.unknown": "Unknown", "migration.sessionFormat.unknownError": "Unknown error", - // legacy-migration end "error.details.show": "Details", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 2ed27849091..d9778fa4fb2 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1185,61 +1185,18 @@ export const dict = { "question.summary": "{{n}} de {{total}} preguntas", "common.review": "Revisar", - // legacy-migration start - "settings.legacyMigration.link": "Migrar desde la versión heredada", - "settings.aboutKiloCode.legacyMigration.title": "Migración heredada", - "settings.aboutKiloCode.legacyMigration.description": - "Migra la configuración de una instalación anterior de Kilo Code, incluyendo las claves API de proveedores y el modelo predeterminado.", "settings.aboutKiloCode.rooImport.description": "Importa el historial de conversaciones de una instalación de Roo Code.", "settings.aboutKiloCode.rooImport.button": "Importar sesiones desde Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "Novedades en Kilo Code", - "migration.whatsNew.subtitle": "Hemos reconstruido la extensión sobre una base más rápida y eficiente.", - "migration.whatsNew.features.performance.title": "Rendimiento de agente más rápido", - "migration.whatsNew.features.performance.detail": - "Las llamadas a herramientas en paralelo y los subagentes permiten que tu agente aborde más a la vez — así pasas menos tiempo esperando y más tiempo entregando.", - "migration.whatsNew.features.interface.title": "Interfaz optimizada", - "migration.whatsNew.features.interface.detail": "Menos distracciones, más fácil y rápido de leer.", - "migration.whatsNew.features.agentManager.title": "Administrador de agentes", - "migration.whatsNew.features.agentManager.detail": - "Una interfaz unificada para ejecutar múltiples agentes en paralelo, cada uno en su propio worktree — supervisa el progreso, cambia de contexto y revisa cambios en un solo lugar.", - "migration.whatsNew.features.foundation.title": "Base compartida", - "migration.whatsNew.features.foundation.detail": - "Un núcleo pequeño y eficiente en todos los productos Kilo. Una experiencia familiar sin importar cómo elijas trabajar.", - "migration.whatsNew.blogLink": "Leer el anuncio completo", - "migration.whatsNew.docsLink": "Novedades y preguntas frecuentes", - "migration.whatsNew.continue": "Continuar", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Migra tu configuración", - "migration.migrate.subtitle": - "Encontramos configuraciones de tu instalación anterior. Esto es lo que podemos transferir.", + "migration.roo.button": "Importar sesiones", + "migration.roo.empty": "No se encontraron sesiones de Roo Code.", "migration.migrate.selectLabel": "Selecciona qué migrar", "migration.migrate.chatHistory": "Sesiones de chat e historial", - "migration.migrate.button": "Migrar configuración", - "migration.migrate.skip": "Omitir", - "migration.migrate.keysDetected": "{{count}} claves detectadas", - "migration.migrate.serversConfigured": "{{count}} servidor(es) configurado(s)", - "migration.migrate.modesFound": "{{count}} modo(s) encontrado(s)", "migration.migrate.sessionsDetected": "{{count}} sesiones detectadas", - "migration.migrate.nothingToMigrate": "No se encontró nada para migrar en la configuración heredada.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "Claves API de proveedores", - "migration.select.mcpServers": "Servidores MCP", - "migration.select.customModes": "Modos personalizados / Agentes", - "migration.select.defaultModel": "Modelo predeterminado", - "migration.select.autoApproval": "Aprobación automática", - "migration.select.language": "Idioma de la interfaz", - "migration.select.autocomplete": "Configuración de autocompletado", // Migrate — completion "migration.complete.summary": "{{success}} de {{total}} elementos migrados con éxito.", - "migration.complete.cleanup": "Eliminar datos de la configuración heredada", - "migration.complete.cleanupDescription": - "Esto elimina la configuración antigua del almacenamiento de VS Code. No podrás volver a ejecutar esta migración.", "migration.complete.done": "Hecho", "migration.error.continue": "Continuar", "migration.sessionSummary.title": "Resumen:", @@ -1271,7 +1228,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Fecha desconocida", "migration.sessionFormat.unknown": "Desconocido", "migration.sessionFormat.unknownError": "Error desconocido", - // legacy-migration end "error.details.show": "Detalles", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fa.ts b/packages/kilo-vscode/webview-ui/src/i18n/fa.ts index e8caa79979f..6d57f6dc6fe 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fa.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fa.ts @@ -1167,59 +1167,17 @@ export const dict = { "question.summary": "{{n}} از {{total}} سؤال", "common.review": "بررسی", - // legacy-migration start - "settings.legacyMigration.link": "انتقال از نسخه قدیمی", - "settings.aboutKiloCode.legacyMigration.title": "انتقال از نسخه قدیمی", - "settings.aboutKiloCode.legacyMigration.description": - "تنظیمات را از نصب قبلی Kilo Code منتقل کنید، از جمله کلیدهای API ارائه‌دهنده و مدل پیش‌فرض.", "settings.aboutKiloCode.rooImport.description": "تاریخچه مکالمات را از یک نصب Roo Code وارد کنید.", "settings.aboutKiloCode.rooImport.button": "وارد کردن جلسات از Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "تازه‌های Kilo Code", - "migration.whatsNew.subtitle": "افزونه را بر پایه‌ای سریع‌تر و کارآمدتر بازسازی کرده‌ایم.", - "migration.whatsNew.features.performance.title": "عملکرد سریع‌تر عامل", - "migration.whatsNew.features.performance.detail": - "فراخوانی ابزارهای موازی و زیرعامل‌ها به عامل شما امکان می‌دهند کارهای بیشتری را همزمان انجام دهد — تا زمان کمتری صرف نظارت کنید و زمان بیشتری برای ارسال داشته باشید.", - "migration.whatsNew.features.interface.title": "رابط کاربری ساده‌تر", - "migration.whatsNew.features.interface.detail": "حواس‌پرتی کمتر، خواندن آسان‌تر و سریع‌تر.", - "migration.whatsNew.features.agentManager.title": "Agent Manager", - "migration.whatsNew.features.agentManager.detail": - "یک رابط یکپارچه برای اجرای چندین عامل به‌صورت موازی، هر کدام در worktree مخصوص خود — پیشرفت را رصد کنید، بین زمینه‌ها جابه‌جا شوید و تغییرات را در یک مکان بررسی کنید.", - "migration.whatsNew.features.foundation.title": "پایه مشترک", - "migration.whatsNew.features.foundation.detail": - "یک هسته کوچک و کارآمد در تمام محصولات Kilo. تجربه‌ای آشنا، هر طور که انتخاب کنید کار کنید.", - "migration.whatsNew.blogLink": "خواندن اعلامیه کامل", - "migration.whatsNew.docsLink": "چه چیزی جدید است و سؤالات متداول", - "migration.whatsNew.continue": "ادامه", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "تنظیمات خود را منتقل کنید", - "migration.migrate.subtitle": "تنظیماتی از نصب قبلی شما یافتیم. این‌ها چیزهایی هستند که می‌توانیم منتقل کنیم.", + "migration.roo.button": "وارد کردن جلسات", + "migration.roo.empty": "هیچ جلسه‌ای از Roo Code یافت نشد.", "migration.migrate.selectLabel": "انتخاب موارد برای انتقال", "migration.migrate.chatHistory": "جلسات و تاریخچه چت", - "migration.migrate.button": "انتقال تنظیمات", - "migration.migrate.skip": "رد کردن", - "migration.migrate.keysDetected": "{{count}} کلید شناسایی شد", - "migration.migrate.serversConfigured": "{{count}} سرور پیکربندی شده", - "migration.migrate.modesFound": "{{count}} حالت یافت شد", "migration.migrate.sessionsDetected": "{{count}} نشست شناسایی شد", - "migration.migrate.nothingToMigrate": "هیچ موردی برای انتقال در تنظیمات قدیمی یافت نشد.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "کلیدهای API ارائه‌دهنده", - "migration.select.mcpServers": "سرورهای MCP", - "migration.select.customModes": "حالت‌ها / عوامل سفارشی", - "migration.select.defaultModel": "مدل پیش‌فرض", - "migration.select.autoApproval": "تأیید خودکار", - "migration.select.language": "زبان رابط کاربری", - "migration.select.autocomplete": "تنظیمات تکمیل خودکار", // Migrate — completion "migration.complete.summary": "{{success}} از {{total}} مورد با موفقیت منتقل شد.", - "migration.complete.cleanup": "حذف داده‌های تنظیمات قدیمی", - "migration.complete.cleanupDescription": - "این گزینه تنظیمات قدیمی را از حافظه VS Code حذف می‌کند. پس از این کار، امکان اجرای مجدد این انتقال وجود نخواهد داشت.", "migration.complete.done": "انجام شد", "migration.error.continue": "ادامه", "migration.sessionSummary.title": "خلاصه:", @@ -1251,7 +1209,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "تاریخ نامشخص", "migration.sessionFormat.unknown": "نامشخص", "migration.sessionFormat.unknownError": "خطای نامشخص", - // legacy-migration end "error.details.show": "جزئیات", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 9bd82535124..c4a08dd308b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1203,60 +1203,17 @@ export const dict = { "question.summary": "{{n}} sur {{total}} questions", "common.review": "Réviser", - // legacy-migration start - "settings.legacyMigration.link": "Migrer depuis l'ancienne version", - "settings.aboutKiloCode.legacyMigration.title": "Migration de l'ancienne version", - "settings.aboutKiloCode.legacyMigration.description": - "Migrer les paramètres d'une précédente installation de Kilo Code, y compris les clés d'API des fournisseurs et le modèle par défaut.", "settings.aboutKiloCode.rooImport.description": "Importer l'historique des conversations depuis une installation de Roo Code.", "settings.aboutKiloCode.rooImport.button": "Importer les sessions depuis Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "Nouveautés de Kilo Code", - "migration.whatsNew.subtitle": "Nous avons reconstruit l'extension sur une base plus rapide et plus efficace.", - "migration.whatsNew.features.performance.title": "Performance accélérée de l'agent", - "migration.whatsNew.features.performance.detail": - "Les appels d'outils en parallèle et les sous-agents permettent à votre agent de traiter plus de tâches simultanément — vous passez moins de temps à attendre et plus de temps à livrer.", - "migration.whatsNew.features.interface.title": "Interface simplifiée", - "migration.whatsNew.features.interface.detail": "Moins de distractions, plus facile et plus rapide à lire.", - "migration.whatsNew.features.agentManager.title": "Gestionnaire d'agents", - "migration.whatsNew.features.agentManager.detail": - "Une interface unifiée pour exécuter plusieurs agents en parallèle, chacun sur son propre arbre de travail — surveillez la progression, changez de contexte et examinez les modifications depuis un seul endroit.", - "migration.whatsNew.features.foundation.title": "Base partagée", - "migration.whatsNew.features.foundation.detail": - "Un noyau petit et efficace partagé par tous les produits Kilo. Une expérience familière quelle que soit votre façon de travailler.", - "migration.whatsNew.blogLink": "Lire l'annonce complète", - "migration.whatsNew.docsLink": "Nouveautés & questions fréquentes", - "migration.whatsNew.continue": "Continuer", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Migrer vos paramètres", - "migration.migrate.subtitle": - "Nous avons trouvé des paramètres de votre précédente installation. Voici ce que nous pouvons récupérer.", + "migration.roo.button": "Importer les sessions", + "migration.roo.empty": "Aucune session Roo Code trouvée.", "migration.migrate.selectLabel": "Sélectionnez ce que vous souhaitez migrer", "migration.migrate.chatHistory": "Sessions de discussion et historique", - "migration.migrate.button": "Migrer les paramètres", - "migration.migrate.skip": "Ignorer", - "migration.migrate.keysDetected": "{{count}} clés détectées", - "migration.migrate.serversConfigured": "{{count}} serveur(s) configuré(s)", - "migration.migrate.modesFound": "{{count}} mode(s) trouvé(s)", - "migration.migrate.nothingToMigrate": "Rien à migrer n'a été trouvé dans les anciens paramètres.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "Clés d'API des fournisseurs", - "migration.select.mcpServers": "Serveurs MCP", - "migration.select.customModes": "Modes personnalisés / Agents", - "migration.select.defaultModel": "Modèle par défaut", - "migration.select.autoApproval": "Approbation automatique", - "migration.select.language": "Langue de l'interface", - "migration.select.autocomplete": "Paramètres de saisie semi-automatique", // Migrate — completion "migration.complete.summary": "{{success}} éléments sur {{total}} migrés avec succès.", - "migration.complete.cleanup": "Supprimer les données des anciens paramètres", - "migration.complete.cleanupDescription": - "Cela supprime les anciens paramètres du stockage de VS Code. Vous ne pourrez pas réexécuter cette migration.", "migration.complete.done": "Terminé", "migration.migrate.sessionsDetected": "{{count}} sessions détectées", "migration.error.continue": "Continuer", @@ -1292,7 +1249,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Date inconnue", "migration.sessionFormat.unknown": "Inconnu", "migration.sessionFormat.unknownError": "Erreur inconnue", - // legacy-migration end "error.details.show": "Détails", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/it.ts b/packages/kilo-vscode/webview-ui/src/i18n/it.ts index 8c4a01eab3c..1675f505e86 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/it.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/it.ts @@ -1052,52 +1052,15 @@ export const dict = { "profile.switchingAccount": "Cambio account...", "question.summary": "{{n}} di {{total}} domande", "common.review": "Revisione", - "settings.legacyMigration.link": "Migra dalla versione legacy", - "settings.aboutKiloCode.legacyMigration.title": "Migrazione legacy", - "settings.aboutKiloCode.legacyMigration.description": - "Migra le impostazioni da una precedente installazione di Kilo Code, incluse API key dei provider e modello predefinito.", "settings.aboutKiloCode.rooImport.description": "Importa la cronologia delle conversazioni da una installazione di Roo Code.", "settings.aboutKiloCode.rooImport.button": "Importa sessioni da Roo Code", - "migration.whatsNew.title": "Novità in Kilo Code", - "migration.whatsNew.subtitle": "Abbiamo ricostruito l'estensione su fondamenta più veloci ed efficienti.", - "migration.whatsNew.features.performance.title": "Prestazioni agente più rapide", - "migration.whatsNew.features.performance.detail": - "Chiamate tool parallele e sub-agent permettono all'agente di gestire più cose insieme, così passi meno tempo ad aspettare e più tempo a lavorare.", - "migration.whatsNew.features.interface.title": "Interfaccia semplificata", - "migration.whatsNew.features.interface.detail": "Meno distrazioni, lettura più semplice e rapida.", - "migration.whatsNew.features.agentManager.title": "Agent Manager", - "migration.whatsNew.features.agentManager.detail": - "Un'interfaccia unificata per eseguire più agenti in parallelo, ognuno nel proprio worktree: monitora avanzamento, cambia contesto e rivedi modifiche in un unico posto.", - "migration.whatsNew.features.foundation.title": "Fondamenta condivise", - "migration.whatsNew.features.foundation.detail": - "Un core piccolo ed efficiente per ogni prodotto Kilo. Un'esperienza familiare comunque tu scelga di lavorare.", - "migration.whatsNew.blogLink": "Leggi l'annuncio completo", - "migration.whatsNew.docsLink": "Novità e FAQ", - "migration.whatsNew.continue": "Continua", - "migration.migrate.title": "Migra le impostazioni", - "migration.migrate.subtitle": - "Abbiamo trovato impostazioni dalla precedente installazione. Ecco cosa possiamo importare.", + "migration.roo.button": "Importa sessioni", + "migration.roo.empty": "Nessuna sessione di Roo Code trovata.", "migration.migrate.selectLabel": "Seleziona cosa migrare", "migration.migrate.chatHistory": "Sessioni chat e cronologia", - "migration.migrate.button": "Migra impostazioni", - "migration.migrate.skip": "Salta", - "migration.migrate.keysDetected": "{{count}} chiavi rilevate", - "migration.migrate.serversConfigured": "{{count}} server configurati", - "migration.migrate.modesFound": "{{count}} modalità trovate", "migration.migrate.sessionsDetected": "{{count}} sessioni rilevate", - "migration.migrate.nothingToMigrate": "Non è stato trovato nulla da migrare nelle impostazioni legacy.", - "migration.select.providers": "API key provider", - "migration.select.mcpServers": "Server MCP", - "migration.select.customModes": "Modalità / agenti personalizzati", - "migration.select.defaultModel": "Modello predefinito", - "migration.select.autoApproval": "Approvazione automatica", - "migration.select.language": "Lingua UI", - "migration.select.autocomplete": "Impostazioni autocompletamento", "migration.complete.summary": "{{success}} di {{total}} elementi migrati correttamente.", - "migration.complete.cleanup": "Rimuovi dati impostazioni legacy", - "migration.complete.cleanupDescription": - "Rimuove le vecchie impostazioni dallo storage di VS Code. Non potrai rieseguire questa migrazione.", "migration.complete.done": "Fine", "migration.error.continue": "Continua", "migration.sessionSummary.title": "Riepilogo:", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index b374d7c80ea..6f7af01df44 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1162,58 +1162,16 @@ export const dict = { "question.summary": "{{total}} 問中 {{n}} 問目", "common.review": "確認", - // legacy-migration start - "settings.legacyMigration.link": "レガシーバージョンからの移行", - "settings.aboutKiloCode.legacyMigration.title": "レガシー移行", - "settings.aboutKiloCode.legacyMigration.description": - "プロバイダーのAPIキーやデフォルトモデルなど、以前にインストールしたKilo Codeから設定を移行します。", "settings.aboutKiloCode.rooImport.description": "インストールしたRoo Codeから会話履歴を移行します。", "settings.aboutKiloCode.rooImport.button": "Roo Codeからセッションをインポート", - // Screen 1 — What's New - "migration.whatsNew.title": "Kilo Codeの新機能", - "migration.whatsNew.subtitle": "より高速で効率的な基盤上に拡張機能を再構築しました。", - "migration.whatsNew.features.performance.title": "高速なエージェントパフォーマンス", - "migration.whatsNew.features.performance.detail": - "並列ツール呼び出しとサブエージェントにより、エージェントがより多くのタスクを同時に処理できます — 待ち時間が減り、作業効率が向上します。", - "migration.whatsNew.features.interface.title": "洗練されたインターフェース", - "migration.whatsNew.features.interface.detail": "不要な要素を排除し、より読みやすく素早く操作できます。", - "migration.whatsNew.features.agentManager.title": "エージェントマネージャー", - "migration.whatsNew.features.agentManager.detail": - "複数のエージェントを並列実行するための統合インターフェース。それぞれ独自のワークツリー上で動作し、進捗の確認、コンテキストの切り替え、変更のレビューを一箇所で行えます。", - "migration.whatsNew.features.foundation.title": "共通基盤", - "migration.whatsNew.features.foundation.detail": - "すべてのKilo製品で共有される小さく効率的なコア。どのような作業スタイルでも馴染みのある体験を提供します。", - "migration.whatsNew.blogLink": "完全なアナウンスを読む", - "migration.whatsNew.docsLink": "新機能とよくある質問", - "migration.whatsNew.continue": "続行", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "設定の移行", - "migration.migrate.subtitle": "以前のインストールから設定が見つかりました。移行可能な項目は以下の通りです。", + "migration.roo.button": "セッションをインポート", + "migration.roo.empty": "Roo Codeのセッションが見つかりませんでした。", "migration.migrate.selectLabel": "移行する項目を選択", "migration.migrate.chatHistory": "チャットセッションと履歴", - "migration.migrate.button": "設定を移行", - "migration.migrate.skip": "スキップ", - "migration.migrate.keysDetected": "{{count}}個のキーを検出", - "migration.migrate.serversConfigured": "{{count}}個のサーバーが設定済み", - "migration.migrate.modesFound": "{{count}}個のモードが見つかりました", - "migration.migrate.nothingToMigrate": "レガシー設定に移行する項目が見つかりませんでした。", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "プロバイダーのAPIキー", - "migration.select.mcpServers": "MCPサーバー", - "migration.select.customModes": "カスタムモード / エージェント", - "migration.select.defaultModel": "デフォルトモデル", - "migration.select.autoApproval": "自動承認", - "migration.select.language": "UI言語", - "migration.select.autocomplete": "オートコンプリート設定", // Migrate — completion "migration.complete.summary": "{{total}}個中{{success}}個の項目が正常に移行されました。", - "migration.complete.cleanup": "レガシー設定データを削除する", - "migration.complete.cleanupDescription": - "VS Codeのストレージから古い設定を削除します。この移行を再度実行することはできなくなります。", "migration.complete.done": "完了", "migration.migrate.sessionsDetected": "{{count}} 件のセッションが見つかりました", "migration.error.continue": "続行", @@ -1247,7 +1205,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "不明な日付", "migration.sessionFormat.unknown": "不明", "migration.sessionFormat.unknownError": "不明なエラー", - // legacy-migration end "error.details.show": "詳細", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index ccb7892444c..582e5565944 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1149,58 +1149,16 @@ export const dict = { "question.summary": "{{total}}개 질문 중 {{n}}번째", "common.review": "검토", - // legacy-migration start - "settings.legacyMigration.link": "레거시 버전에서 마이그레이션", - "settings.aboutKiloCode.legacyMigration.title": "레거시 마이그레이션", - "settings.aboutKiloCode.legacyMigration.description": - "공급자 API 키 및 기본 모델을 포함하여 이전 Kilo Code 설치에서 설정을 마이그레이션합니다.", "settings.aboutKiloCode.rooImport.description": "Roo Code 설치에서 대화 기록을 가져옵니다.", "settings.aboutKiloCode.rooImport.button": "Roo Code에서 세션 가져오기", - // Screen 1 — What's New - "migration.whatsNew.title": "Kilo Code의 새로운 기능", - "migration.whatsNew.subtitle": "더 빠르고 효율적인 기반 위에 확장 프로그램을 재구축했습니다.", - "migration.whatsNew.features.performance.title": "더 빠른 에이전트 성능", - "migration.whatsNew.features.performance.detail": - "병렬 도구 호출과 하위 에이전트를 통해 에이전트가 더 많은 작업을 동시에 처리할 수 있습니다 — 대기 시간은 줄이고 작업 효율은 높입니다.", - "migration.whatsNew.features.interface.title": "간소화된 인터페이스", - "migration.whatsNew.features.interface.detail": "불필요한 요소를 줄여 더 쉽고 빠르게 읽을 수 있습니다.", - "migration.whatsNew.features.agentManager.title": "에이전트 관리자", - "migration.whatsNew.features.agentManager.detail": - "여러 에이전트를 각자의 작업 트리에서 병렬로 실행할 수 있는 통합 인터페이스 — 진행 상황 모니터링, 컨텍스트 전환, 변경 사항 검토를 한 곳에서 수행합니다.", - "migration.whatsNew.features.foundation.title": "공유 기반", - "migration.whatsNew.features.foundation.detail": - "모든 Kilo 제품에 걸쳐 하나의 작고 효율적인 코어. 어떤 방식으로 작업하든 익숙한 경험을 제공합니다.", - "migration.whatsNew.blogLink": "전체 공지 읽기", - "migration.whatsNew.docsLink": "새로운 기능 및 자주 묻는 질문", - "migration.whatsNew.continue": "계속", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "설정 마이그레이션", - "migration.migrate.subtitle": "이전 설치에서 설정을 찾았습니다. 가져올 수 있는 항목은 다음과 같습니다.", + "migration.roo.button": "세션 가져오기", + "migration.roo.empty": "Roo Code 세션을 찾을 수 없습니다.", "migration.migrate.selectLabel": "마이그레이션할 항목 선택", "migration.migrate.chatHistory": "채팅 세션 및 기록", - "migration.migrate.button": "설정 마이그레이션", - "migration.migrate.skip": "건너뛰기", - "migration.migrate.keysDetected": "{{count}}개의 키 감지됨", - "migration.migrate.serversConfigured": "{{count}}개의 서버 구성됨", - "migration.migrate.modesFound": "{{count}}개의 모드 발견됨", - "migration.migrate.nothingToMigrate": "레거시 설정에서 마이그레이션할 항목을 찾지 못했습니다.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "공급자 API 키", - "migration.select.mcpServers": "MCP 서버", - "migration.select.customModes": "사용자 지정 모드 / 에이전트", - "migration.select.defaultModel": "기본 모델", - "migration.select.autoApproval": "자동 승인", - "migration.select.language": "UI 언어", - "migration.select.autocomplete": "자동 완성 설정", // Migrate — completion "migration.complete.summary": "{{total}}개 중 {{success}}개 항목이 성공적으로 마이그레이션되었습니다.", - "migration.complete.cleanup": "레거시 설정 데이터 제거", - "migration.complete.cleanupDescription": - "이 작업은 VS Code 저장소에서 이전 설정을 제거합니다. 이 마이그레이션을 다시 실행할 수 없게 됩니다.", "migration.complete.done": "완료", "migration.migrate.sessionsDetected": "{{count}}개의 세션이 감지되었습니다", "migration.error.continue": "계속", @@ -1234,7 +1192,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "알 수 없는 날짜", "migration.sessionFormat.unknown": "알 수 없음", "migration.sessionFormat.unknownError": "알 수 없는 오류", - // legacy-migration end "error.details.show": "상세 정보", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index d83698258b8..6ecd7ed07a7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1155,59 +1155,16 @@ export const dict = { "question.summary": "{{n}} van de {{total}} vragen", "common.review": "Beoordelen", - // legacy-migration start - "settings.legacyMigration.link": "Migreer van Legacy Versie", - "settings.aboutKiloCode.legacyMigration.title": "Legacy Migratie", - "settings.aboutKiloCode.legacyMigration.description": - "Migreer instellingen van een eerdere installatie van Kilo Code, inclusief provider API-sleutels en standaard model.", "settings.aboutKiloCode.rooImport.description": "Importeer gespreksgeschiedenis van een Roo Code installatie.", "settings.aboutKiloCode.rooImport.button": "Sessies importeren uit Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "Wat is er Nieuw in Kilo Code", - "migration.whatsNew.subtitle": "We hebben de extensie opnieuw opgebouwd op een snellere, efficiëntere basis.", - "migration.whatsNew.features.performance.title": "Snellere Agent Prestaties", - "migration.whatsNew.features.performance.detail": - "Parallelle tool calls en subagents laten je agent meer tegelijk aanpakken — zodat je minder tijd besteedt aan wachten en meer tijd aan releasen.", - "migration.whatsNew.features.interface.title": "Gestroomlijnde Interface", - "migration.whatsNew.features.interface.detail": "Minder afleiding, makkelijker en sneller te lezen.", - "migration.whatsNew.features.agentManager.title": "Agentenbeheer", - "migration.whatsNew.features.agentManager.detail": - "Een uniforme interface voor het parallel uitvoeren van meerdere agents, elk op zijn eigen worktree — monitor de voortgang, wissel van context en bekijk wijzigingen op één plek.", - "migration.whatsNew.features.foundation.title": "Gedeelde Basis", - "migration.whatsNew.features.foundation.detail": - "Één kleine, efficiënte kern voor elk Kilo-product. Een vertrouwde ervaring, hoe je ook wilt werken.", - "migration.whatsNew.blogLink": "Lees de volledige aankondiging", - "migration.whatsNew.docsLink": "Wat is er nieuw & veelgestelde vragen", - "migration.whatsNew.continue": "Doorgaan", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Migreer Je Instellingen", - "migration.migrate.subtitle": - "We hebben instellingen gevonden van je vorige installatie. Hier is wat we kunnen overzetten.", + "migration.roo.button": "Sessies importeren", + "migration.roo.empty": "Geen Roo Code-sessies gevonden.", "migration.migrate.selectLabel": "Selecteer wat je wilt migreren", "migration.migrate.chatHistory": "Chatsessies & Geschiedenis", - "migration.migrate.button": "Migreer Instellingen", - "migration.migrate.skip": "Overslaan", - "migration.migrate.keysDetected": "{{count}} sleutels gedetecteerd", - "migration.migrate.serversConfigured": "{{count}} server(s) geconfigureerd", - "migration.migrate.modesFound": "{{count}} modus(sen) gevonden", - "migration.migrate.nothingToMigrate": "Er is niets om te migreren gevonden in de oude instellingen.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "Provider API-sleutels", - "migration.select.mcpServers": "MCP Servers", - "migration.select.customModes": "Aangepaste Modi / Agents", - "migration.select.defaultModel": "Standaard Model", - "migration.select.autoApproval": "Automatische Goedkeuring", - "migration.select.language": "UI Taal", - "migration.select.autocomplete": "Automatisch Aanvullen Instellingen", // Migrate — completion "migration.complete.summary": "{{success}} van de {{total}} items succesvol gemigreerd.", - "migration.complete.cleanup": "Verwijder oude instellingendata", - "migration.complete.cleanupDescription": - "Dit verwijdert de oude instellingen uit de VS Code-opslag. U zult deze migratie niet opnieuw kunnen uitvoeren.", "migration.complete.done": "Klaar", "migration.migrate.sessionsDetected": "{{count}} sessies gedetecteerd", "migration.error.continue": "Doorgaan", @@ -1241,7 +1198,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Onbekende datum", "migration.sessionFormat.unknown": "Onbekend", "migration.sessionFormat.unknownError": "Onbekende fout", - // legacy-migration end "error.details.show": "Details", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index bef6e357a03..8b8aebf39c4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1168,58 +1168,16 @@ export const dict = { "question.summary": "{{n}} av {{total}} spørsmål", "common.review": "Gjennomgå", - // legacy-migration start - "settings.legacyMigration.link": "Migrer fra eldre versjon", - "settings.aboutKiloCode.legacyMigration.title": "Migrering fra eldre versjon", - "settings.aboutKiloCode.legacyMigration.description": - "Migrer innstillinger fra en tidligere installasjon av Kilo Code, inkludert API-nøkler for leverandører og standardmodell.", "settings.aboutKiloCode.rooImport.description": "Importer samtalehistorikk fra en installasjon av Roo Code.", "settings.aboutKiloCode.rooImport.button": "Importer økter fra Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "Hva er nytt i Kilo Code", - "migration.whatsNew.subtitle": "Vi har bygget utvidelsen på nytt med et raskere og mer effektivt grunnlag.", - "migration.whatsNew.features.performance.title": "Raskere agentytelse", - "migration.whatsNew.features.performance.detail": - "Parallelle verktøykall og underagenter lar agenten din håndtere mer samtidig — slik at du bruker mindre tid på å vente og mer tid på å levere.", - "migration.whatsNew.features.interface.title": "Strømlinjeformet grensesnitt", - "migration.whatsNew.features.interface.detail": "Færre forstyrrelser, enklere og raskere å lese.", - "migration.whatsNew.features.agentManager.title": "Agentbehandling", - "migration.whatsNew.features.agentManager.detail": - "Et samlet grensesnitt for å kjøre flere agenter parallelt, hver på sitt eget worktree — overvåk fremdrift, bytt kontekst og gjennomgå endringer på ett sted.", - "migration.whatsNew.features.foundation.title": "Delt grunnlag", - "migration.whatsNew.features.foundation.detail": - "Én liten, effektiv kjerne på tvers av alle Kilo-produkter. En kjent opplevelse uansett hvordan du velger å jobbe.", - "migration.whatsNew.blogLink": "Les hele kunngjøringen", - "migration.whatsNew.docsLink": "Nyheter og ofte stilte spørsmål", - "migration.whatsNew.continue": "Fortsett", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Migrer innstillingene dine", - "migration.migrate.subtitle": "Vi fant innstillinger fra din tidligere installasjon. Her er hva vi kan ta med over.", + "migration.roo.button": "Importer økter", + "migration.roo.empty": "Ingen Roo Code-økter funnet.", "migration.migrate.selectLabel": "Velg hva som skal migreres", "migration.migrate.chatHistory": "Chatøkter og historikk", - "migration.migrate.button": "Migrer innstillinger", - "migration.migrate.skip": "Hopp over", - "migration.migrate.keysDetected": "{{count}} nøkler oppdaget", - "migration.migrate.serversConfigured": "{{count}} server(e) konfigurert", - "migration.migrate.modesFound": "{{count}} modus(er) funnet", - "migration.migrate.nothingToMigrate": "Ingenting å migrere ble funnet i de eldre innstillingene.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "API-nøkler for leverandører", - "migration.select.mcpServers": "MCP-servere", - "migration.select.customModes": "Egendefinerte moduser / Agenter", - "migration.select.defaultModel": "Standardmodell", - "migration.select.autoApproval": "Automatisk godkjenning", - "migration.select.language": "UI-språk", - "migration.select.autocomplete": "Innstillinger for autofullføring", // Migrate — completion "migration.complete.summary": "{{success}} av {{total}} elementer ble migrert.", - "migration.complete.cleanup": "Fjern eldre innstillingsdata", - "migration.complete.cleanupDescription": - "Dette fjerner de gamle innstillingene fra VS Code-lagringen. Du vil ikke kunne kjøre denne migreringen på nytt.", "migration.complete.done": "Ferdig", "migration.migrate.sessionsDetected": "{{count}} økter oppdaget", "migration.error.continue": "Fortsett", @@ -1253,7 +1211,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Ukjent dato", "migration.sessionFormat.unknown": "Ukjent", "migration.sessionFormat.unknownError": "Ukjent feil", - // legacy-migration end "task.todos.progress": "{{done}}/{{total}} oppgaver fullført", "task.todos.allDone": "{{count}} oppgaver fullført", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index fffec121333..115bc27b4dd 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1175,58 +1175,16 @@ export const dict = { "question.summary": "{{n}} z {{total}} pytań", "common.review": "Przejrzyj", - // legacy-migration start - "settings.legacyMigration.link": "Migracja ze starszej wersji", - "settings.aboutKiloCode.legacyMigration.title": "Migracja starszej wersji", - "settings.aboutKiloCode.legacyMigration.description": - "Migruj ustawienia z poprzedniej instalacji Kilo Code, w tym klucze API dostawców i domyślny model.", "settings.aboutKiloCode.rooImport.description": "Importuj historię rozmów z instalacji Roo Code.", "settings.aboutKiloCode.rooImport.button": "Importuj sesje z Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "Co nowego w Kilo Code", - "migration.whatsNew.subtitle": "Przebudowaliśmy rozszerzenie na szybszym i wydajniejszym fundamencie.", - "migration.whatsNew.features.performance.title": "Szybsza wydajność agenta", - "migration.whatsNew.features.performance.detail": - "Równoległe wywołania narzędzi i podagenci pozwalają agentowi robić więcej naraz — mniej czekania, więcej działania.", - "migration.whatsNew.features.interface.title": "Uproszczony interfejs", - "migration.whatsNew.features.interface.detail": "Mniej rozpraszaczy, łatwiejszy i szybszy do czytania.", - "migration.whatsNew.features.agentManager.title": "Menedżer agentów", - "migration.whatsNew.features.agentManager.detail": - "Zunifikowany interfejs do uruchamiania wielu agentów równolegle, każdy na własnym drzewie roboczym — monitoruj postęp, przełączaj kontekst i przeglądaj zmiany w jednym miejscu.", - "migration.whatsNew.features.foundation.title": "Wspólny fundament", - "migration.whatsNew.features.foundation.detail": - "Jedno małe, wydajne jądro we wszystkich produktach Kilo. Znajome doświadczenie niezależnie od sposobu pracy.", - "migration.whatsNew.blogLink": "Przeczytaj pełne ogłoszenie", - "migration.whatsNew.docsLink": "Nowości i często zadawane pytania", - "migration.whatsNew.continue": "Kontynuuj", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Migruj swoje ustawienia", - "migration.migrate.subtitle": "Znaleźliśmy ustawienia z poprzedniej instalacji. Oto co możemy przenieść.", + "migration.roo.button": "Importuj sesje", + "migration.roo.empty": "Nie znaleziono sesji Roo Code.", "migration.migrate.selectLabel": "Wybierz, co zmigrować", "migration.migrate.chatHistory": "Sesje czatu i historia", - "migration.migrate.button": "Migruj ustawienia", - "migration.migrate.skip": "Pomiń", - "migration.migrate.keysDetected": "Wykryto {{count}} kluczy", - "migration.migrate.serversConfigured": "Skonfigurowano {{count}} serwer(ów)", - "migration.migrate.modesFound": "Znaleziono {{count}} tryb(ów)", - "migration.migrate.nothingToMigrate": "W starszych ustawieniach nie znaleziono niczego do zmigrowania.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "Klucze API dostawców", - "migration.select.mcpServers": "Serwery MCP", - "migration.select.customModes": "Niestandardowe tryby / Agenci", - "migration.select.defaultModel": "Domyślny model", - "migration.select.autoApproval": "Automatyczne zatwierdzanie", - "migration.select.language": "Język interfejsu", - "migration.select.autocomplete": "Ustawienia autouzupełniania", // Migrate — completion "migration.complete.summary": "Pomyślnie zmigrowano {{success}} z {{total}} elementów.", - "migration.complete.cleanup": "Usuń dane starszych ustawień", - "migration.complete.cleanupDescription": - "Spowoduje to usunięcie starych ustawień z magazynu VS Code. Nie będzie można ponownie uruchomić tej migracji.", "migration.complete.done": "Gotowe", "migration.migrate.sessionsDetected": "Wykryto {{count}} sesji", "migration.error.continue": "Kontynuuj", @@ -1260,7 +1218,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Nieznana data", "migration.sessionFormat.unknown": "Nieznane", "migration.sessionFormat.unknownError": "Nieznany błąd", - // legacy-migration end "error.details.show": "Szczegóły", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 041510f7572..032af0555b1 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1169,58 +1169,16 @@ export const dict = { "question.summary": "{{n}} из {{total}} вопросов", "common.review": "Просмотр", - // legacy-migration start - "settings.legacyMigration.link": "Миграция с устаревшей версии", - "settings.aboutKiloCode.legacyMigration.title": "Миграция с устаревшей версии", - "settings.aboutKiloCode.legacyMigration.description": - "Перенос настроек из предыдущей установки Kilo Code, включая API-ключи провайдеров и модель по умолчанию.", "settings.aboutKiloCode.rooImport.description": "Импорт истории переписки из установки Roo Code.", "settings.aboutKiloCode.rooImport.button": "Импортировать сеансы из Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "Что нового в Kilo Code", - "migration.whatsNew.subtitle": "Мы перестроили расширение на более быстрой и эффективной основе.", - "migration.whatsNew.features.performance.title": "Более быстрая работа агента", - "migration.whatsNew.features.performance.detail": - "Параллельные вызовы инструментов и подагенты позволяют вашему агенту делать больше одновременно — меньше ожидания, больше результатов.", - "migration.whatsNew.features.interface.title": "Упрощённый интерфейс", - "migration.whatsNew.features.interface.detail": "Меньше отвлекающих факторов, проще и быстрее для чтения.", - "migration.whatsNew.features.agentManager.title": "Менеджер агентов", - "migration.whatsNew.features.agentManager.detail": - "Единый интерфейс для запуска нескольких агентов параллельно, каждый в своём worktree — отслеживайте прогресс, переключайте контекст и просматривайте изменения в одном месте.", - "migration.whatsNew.features.foundation.title": "Общая основа", - "migration.whatsNew.features.foundation.detail": - "Одно компактное и эффективное ядро для всех продуктов Kilo. Знакомый опыт независимо от выбранного способа работы.", - "migration.whatsNew.blogLink": "Читать полный анонс", - "migration.whatsNew.docsLink": "Что нового и часто задаваемые вопросы", - "migration.whatsNew.continue": "Продолжить", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Перенос ваших настроек", - "migration.migrate.subtitle": "Мы нашли настройки от вашей предыдущей установки. Вот что можно перенести.", + "migration.roo.button": "Импортировать сеансы", + "migration.roo.empty": "Сеансы Roo Code не найдены.", "migration.migrate.selectLabel": "Выберите, что перенести", "migration.migrate.chatHistory": "Сессии чата и история", - "migration.migrate.button": "Перенести настройки", - "migration.migrate.skip": "Пропустить", - "migration.migrate.keysDetected": "Обнаружено ключей: {{count}}", - "migration.migrate.serversConfigured": "Настроено серверов: {{count}}", - "migration.migrate.modesFound": "Найдено режимов: {{count}}", - "migration.migrate.nothingToMigrate": "В старых настройках не найдено данных для переноса.", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "API-ключи провайдеров", - "migration.select.mcpServers": "Серверы MCP", - "migration.select.customModes": "Пользовательские режимы / Агенты", - "migration.select.defaultModel": "Модель по умолчанию", - "migration.select.autoApproval": "Автоматическое подтверждение", - "migration.select.language": "Язык интерфейса", - "migration.select.autocomplete": "Настройки автодополнения", // Migrate — completion "migration.complete.summary": "Успешно перенесено: {{success}} из {{total}} элементов.", - "migration.complete.cleanup": "Удалить данные старых настроек", - "migration.complete.cleanupDescription": - "Это удалит старые настройки из хранилища VS Code. Вы не сможете запустить эту миграцию повторно.", "migration.complete.done": "Готово", "migration.migrate.sessionsDetected": "Обнаружено {{count}} сеансов", "migration.error.continue": "Продолжить", @@ -1254,7 +1212,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Неизвестная дата", "migration.sessionFormat.unknown": "Неизвестно", "migration.sessionFormat.unknownError": "Неизвестная ошибка", - // legacy-migration end "error.details.show": "Подробности", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index bf955791e2e..9e29f8250ce 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1146,58 +1146,16 @@ export const dict = { "question.summary": "{{n}} จาก {{total}} คำถาม", "common.review": "ตรวจสอบ", - // legacy-migration start - "settings.legacyMigration.link": "ย้ายข้อมูลจากเวอร์ชันดั้งเดิม", - "settings.aboutKiloCode.legacyMigration.title": "การย้ายข้อมูลจากเวอร์ชันดั้งเดิม", - "settings.aboutKiloCode.legacyMigration.description": - "ย้ายการตั้งค่าจากการติดตั้ง Kilo Code ก่อนหน้านี้ รวมถึงคีย์ API ของผู้ให้บริการและโมเดลเริ่มต้น", "settings.aboutKiloCode.rooImport.description": "นำเข้าประวัติการสนทนาจากการติดตั้ง Roo Code", "settings.aboutKiloCode.rooImport.button": "นำเข้าเซสชันจาก Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "มีอะไรใหม่ใน Kilo Code", - "migration.whatsNew.subtitle": "เราได้สร้างส่วนขยายใหม่บนรากฐานที่เร็วและมีประสิทธิภาพมากขึ้น", - "migration.whatsNew.features.performance.title": "ประสิทธิภาพเอเจนต์ที่เร็วขึ้น", - "migration.whatsNew.features.performance.detail": - "การเรียกเครื่องมือแบบขนานและเอเจนต์ย่อยช่วยให้เอเจนต์ของคุณจัดการได้มากขึ้นในครั้งเดียว — คุณจึงใช้เวลารอน้อยลงและส่งงานได้มากขึ้น", - "migration.whatsNew.features.interface.title": "อินเทอร์เฟซที่กระชับ", - "migration.whatsNew.features.interface.detail": "สิ่งรบกวนน้อยลง อ่านง่ายและรวดเร็วขึ้น", - "migration.whatsNew.features.agentManager.title": "ตัวจัดการตัวแทน", - "migration.whatsNew.features.agentManager.detail": - "อินเทอร์เฟซรวมสำหรับการเรียกใช้เอเจนต์หลายตัวพร้อมกัน แต่ละตัวบน worktree ของตัวเอง — ติดตามความคืบหน้า สลับบริบท และตรวจสอบการเปลี่ยนแปลงได้ในที่เดียว", - "migration.whatsNew.features.foundation.title": "รากฐานที่ใช้ร่วมกัน", - "migration.whatsNew.features.foundation.detail": - "แกนหลักขนาดเล็กและมีประสิทธิภาพเดียวกันในทุกผลิตภัณฑ์ Kilo ประสบการณ์ที่คุ้นเคยไม่ว่าคุณจะเลือกทำงานอย่างไร", - "migration.whatsNew.blogLink": "อ่านประกาศฉบับเต็ม", - "migration.whatsNew.docsLink": "มีอะไรใหม่และคำถามที่พบบ่อย", - "migration.whatsNew.continue": "ดำเนินการต่อ", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "ย้ายการตั้งค่าของคุณ", - "migration.migrate.subtitle": "เราพบการตั้งค่าจากการติดตั้งก่อนหน้านี้ของคุณ นี่คือสิ่งที่เราสามารถนำมาได้", + "migration.roo.button": "นำเข้าเซสชัน", + "migration.roo.empty": "ไม่พบเซสชัน Roo Code", "migration.migrate.selectLabel": "เลือกสิ่งที่จะย้าย", "migration.migrate.chatHistory": "เซสชันแชทและประวัติ", - "migration.migrate.button": "ย้ายการตั้งค่า", - "migration.migrate.skip": "ข้าม", - "migration.migrate.keysDetected": "ตรวจพบ {{count}} คีย์", - "migration.migrate.serversConfigured": "กำหนดค่า {{count}} เซิร์ฟเวอร์", - "migration.migrate.modesFound": "พบ {{count}} โหมด", - "migration.migrate.nothingToMigrate": "ไม่พบสิ่งที่จะย้ายในการตั้งค่าดั้งเดิม", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "คีย์ API ของผู้ให้บริการ", - "migration.select.mcpServers": "เซิร์ฟเวอร์ MCP", - "migration.select.customModes": "โหมดที่กำหนดเอง / เอเจนต์", - "migration.select.defaultModel": "โมเดลเริ่มต้น", - "migration.select.autoApproval": "การอนุมัติอัตโนมัติ", - "migration.select.language": "ภาษาของ UI", - "migration.select.autocomplete": "การตั้งค่าการเติมข้อความอัตโนมัติ", // Migrate — completion "migration.complete.summary": "ย้ายข้อมูลสำเร็จ {{success}} จาก {{total}} รายการ", - "migration.complete.cleanup": "ลบข้อมูลการตั้งค่าเดิม", - "migration.complete.cleanupDescription": - "การดำเนินการนี้จะลบการตั้งค่าเดิมจากที่เก็บข้อมูล VS Code คุณจะไม่สามารถเรียกใช้การย้ายข้อมูลนี้ได้อีก", "migration.complete.done": "เสร็จสิ้น", "migration.migrate.sessionsDetected": "ตรวจพบ {{count}} เซสชัน", "migration.error.continue": "ดำเนินการต่อ", @@ -1231,7 +1189,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "ไม่ทราบวันที่", "migration.sessionFormat.unknown": "ไม่ทราบ", "migration.sessionFormat.unknownError": "ข้อผิดพลาดที่ไม่ทราบสาเหตุ", - // legacy-migration end "error.details.show": "รายละเอียด", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 321d6d59476..567d69dfaea 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1142,59 +1142,16 @@ export const dict = { "question.summary": "{{total}} sorudan {{n}} tanesi", "common.review": "İncele", - // legacy-migration start - "settings.legacyMigration.link": "Eski Sürümden Taşı", - "settings.aboutKiloCode.legacyMigration.title": "Eski Sürüm Taşıma", - "settings.aboutKiloCode.legacyMigration.description": - "Sağlayıcı API anahtarları ve varsayılan model dahil olmak üzere Kilo Code'un önceki yüklemesinden ayarları taşıyın.", "settings.aboutKiloCode.rooImport.description": "Bir Roo Code yüklemesinden konuşma geçmişini içe aktarın.", "settings.aboutKiloCode.rooImport.button": "Roo Code'dan Oturumları İçe Aktar", - // Screen 1 — What's New - "migration.whatsNew.title": "Kilo Code'daki Yenilikler", - "migration.whatsNew.badge": "Beta", - "migration.whatsNew.subtitle": "Uzantıyı daha hızlı ve daha verimli bir temel üzerine yeniden inşa ettik.", - "migration.whatsNew.features.performance.title": "Daha Hızlı Ajan Performansı", - "migration.whatsNew.features.performance.detail": - "Paralel araç çağrıları ve alt ajanlar, ajanınızın aynı anda daha fazlasını yapmasını sağlar — böylece izlemek yerine daha fazla üretirsiniz.", - "migration.whatsNew.features.interface.title": "Basitleştirilmiş Arayüz", - "migration.whatsNew.features.interface.detail": "Daha az dikkat dağıtıcı, daha kolay ve hızlı okuma.", - "migration.whatsNew.features.agentManager.title": "Ajan Yöneticisi", - "migration.whatsNew.features.agentManager.detail": - "Birden fazla ajanı paralel olarak çalıştırmak için birleşik bir arayüz, her biri kendi worktree'sinde — ilerlemeyi izleyin, bağlam değiştirin ve değişiklikleri tek bir yerden inceleyin.", - "migration.whatsNew.features.foundation.title": "Paylaşılan Temel", - "migration.whatsNew.features.foundation.detail": - "Her Kilo ürününde küçük ve verimli bir çekirdek. Nasıl çalışmayı tercih ederseniz edin, tanıdık bir deneyim.", - "migration.whatsNew.blogLink": "Tam duyuruyu oku", - "migration.whatsNew.docsLink": "Yenilikler ve sık sorulan sorular", - "migration.whatsNew.continue": "Devam", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Ayarlarınızı Taşıyın", - "migration.migrate.subtitle": "Önceki yüklemenizden ayarlar bulduk. İşte taşıyabileceğimiz ayarlar.", + "migration.roo.button": "Oturumları İçe Aktar", + "migration.roo.empty": "Roo Code oturumu bulunamadı.", "migration.migrate.selectLabel": "Taşınacakları seçin", "migration.migrate.chatHistory": "Sohbet Oturumları ve Geçmiş", - "migration.migrate.button": "Ayarları Taşı", - "migration.migrate.skip": "Atla", - "migration.migrate.keysDetected": "{{count}} anahtar algılandı", - "migration.migrate.serversConfigured": "{{count}} sunucu yapılandırıldı", - "migration.migrate.modesFound": "{{count}} mod bulundu", - "migration.migrate.nothingToMigrate": "Eski ayarlarda taşınacak bir şey bulunamadı.", - - // Migrate — item labels - "migration.select.providers": "Sağlayıcı API Anahtarları", - "migration.select.mcpServers": "MCP Sunucuları", - "migration.select.customModes": "Özel Modlar / Ajanlar", - "migration.select.defaultModel": "Varsayılan Model", - "migration.select.autoApproval": "Otomatik Onay", - "migration.select.language": "Arayüz Dili", - "migration.select.autocomplete": "Otomatik Tamamlama Ayarları", // Migrate — completion "migration.complete.summary": "{{total}} öğeden {{success}} tanesi başarıyla taşındı.", - "migration.complete.cleanup": "Eski ayar verilerini kaldır", - "migration.complete.cleanupDescription": - "Bu, VS Code depolamasından eski ayarları kaldırır. Bu taşımayı yeniden çalıştıramazsınız.", "migration.complete.done": "Bitti", "migration.migrate.sessionsDetected": "{{count}} oturum bulundu", "migration.error.continue": "Devam et", @@ -1228,7 +1185,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Bilinmeyen tarih", "migration.sessionFormat.unknown": "Bilinmiyor", "migration.sessionFormat.unknownError": "Bilinmeyen hata", - // legacy-migration end "error.details.show": "Ayrıntılar", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts index c94d1723ff1..f11d02a43d4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts @@ -1141,59 +1141,16 @@ export const dict = { "question.summary": "{{n}} з {{total}} питань", "common.review": "Переглянути", - // legacy-migration start - "settings.legacyMigration.link": "Перенести зі старої версії", - "settings.aboutKiloCode.legacyMigration.title": "Перенесення зі старої версії", - "settings.aboutKiloCode.legacyMigration.description": - "Перенести налаштування з попередньої версії Kilo Code, включаючи API-ключі провайдерів та стандартну модель.", "settings.aboutKiloCode.rooImport.description": "Імпортувати історію розмов з інсталяції Roo Code.", "settings.aboutKiloCode.rooImport.button": "Імпортувати сесії з Roo Code", - // Screen 1 — What's New - "migration.whatsNew.title": "Що нового в Kilo Code", - "migration.whatsNew.badge": "Бета", - "migration.whatsNew.subtitle": "Ми відбудували розширення на більш швидкій та ефективній основі.", - "migration.whatsNew.features.performance.title": "Швидша продуктивність агента", - "migration.whatsNew.features.performance.detail": - "Паралельні виклики інструментів і підагенти дозволяють агенту робити більше одночасно — щоб ви більше створювали, а менше спостерігали.", - "migration.whatsNew.features.interface.title": "Спрощений інтерфейс", - "migration.whatsNew.features.interface.detail": "Менше відволікань, легше і швидше читати.", - "migration.whatsNew.features.agentManager.title": "Менеджер агентів", - "migration.whatsNew.features.agentManager.detail": - "Єдиний інтерфейс для запуску кількох агентів паралельно, кожен у власному робочому дереві — стежте за прогресом, перемикайте контекст і переглядайте зміни з одного місця.", - "migration.whatsNew.features.foundation.title": "Спільна основа", - "migration.whatsNew.features.foundation.detail": - "Малий та ефективний ядерний модуль у кожному продукті Kilo. Знайомий досвід незалежно від того, як ви вважаєте за краще працювати.", - "migration.whatsNew.blogLink": "Читати повне оголошення", - "migration.whatsNew.docsLink": "Що нового та часті запитання", - "migration.whatsNew.continue": "Продовжити", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "Перенесіть свої налаштування", - "migration.migrate.subtitle": "Ми знайшли налаштування з попередньої версії. Ось що можна перенести.", + "migration.roo.button": "Імпортувати сесії", + "migration.roo.empty": "Сесій Roo Code не знайдено.", "migration.migrate.selectLabel": "Вибрати для перенесення", "migration.migrate.chatHistory": "Сесії чату та історія", - "migration.migrate.button": "Перенести налаштування", - "migration.migrate.skip": "Пропустити", - "migration.migrate.keysDetected": "Виявлено {{count}} ключів", - "migration.migrate.serversConfigured": "Налаштовано {{count}} серверів", - "migration.migrate.modesFound": "Знайдено {{count}} режимів", - "migration.migrate.nothingToMigrate": "У старих налаштуваннях нічого для перенесення не знайдено.", - - // Migrate — item labels - "migration.select.providers": "API-ключі провайдерів", - "migration.select.mcpServers": "MCP-сервери", - "migration.select.customModes": "Власні режими / агенти", - "migration.select.defaultModel": "Стандартна модель", - "migration.select.autoApproval": "Автоматичне схвалення", - "migration.select.language": "Мова інтерфейсу", - "migration.select.autocomplete": "Налаштування автодоповнення", // Migrate — completion "migration.complete.summary": "{{success}} з {{total}} елементів успішно перенесено.", - "migration.complete.cleanup": "Видалити старі дані налаштувань", - "migration.complete.cleanupDescription": - "Це видалить старі налаштування зі сховища VS Code. Ви не зможете повторно запустити це перенесення.", "migration.complete.done": "Готово", "migration.migrate.sessionsDetected": "Знайдено {{count}} сесій", "migration.error.continue": "Продовжити", @@ -1227,7 +1184,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "Невідома дата", "migration.sessionFormat.unknown": "Невідомо", "migration.sessionFormat.unknownError": "Невідома помилка", - // legacy-migration end "error.details.show": "Деталі", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 74540bcf976..39f75e55ccd 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1106,57 +1106,16 @@ export const dict = { "question.summary": "第 {{n}} / {{total}} 个问题", "common.review": "审查", - // legacy-migration start - "settings.legacyMigration.link": "从旧版迁移", - "settings.aboutKiloCode.legacyMigration.title": "旧版迁移", - "settings.aboutKiloCode.legacyMigration.description": - "从旧版 Kilo Code 安装迁移设置,包括提供商 API 密钥和默认模型。", "settings.aboutKiloCode.rooImport.description": "从 Roo Code 安装导入对话历史记录。", "settings.aboutKiloCode.rooImport.button": "从 Roo Code 导入会话", - // Screen 1 — What's New - "migration.whatsNew.title": "Kilo Code 新功能", - "migration.whatsNew.subtitle": "我们在更快、更高效的基础上重新构建了扩展。", - "migration.whatsNew.features.performance.title": "更快的智能体性能", - "migration.whatsNew.features.performance.detail": - "并行工具调用和子智能体让你的智能体可以同时处理更多任务——减少等待时间,更快交付成果。", - "migration.whatsNew.features.interface.title": "简洁的界面", - "migration.whatsNew.features.interface.detail": "更少干扰,更易阅读,更快上手。", - "migration.whatsNew.features.agentManager.title": "代理管理器", - "migration.whatsNew.features.agentManager.detail": - "一个统一的界面,可以并行运行多个智能体,每个智能体各自使用独立的 worktree——在同一个地方监控进度、切换上下文和审查变更。", - "migration.whatsNew.features.foundation.title": "共享基础", - "migration.whatsNew.features.foundation.detail": - "所有 Kilo 产品共享一个小巧高效的核心。无论你选择哪种方式工作,都能获得熟悉的体验。", - "migration.whatsNew.blogLink": "阅读完整公告", - "migration.whatsNew.docsLink": "新功能与常见问题", - "migration.whatsNew.continue": "继续", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "迁移你的设置", - "migration.migrate.subtitle": "我们发现了你之前安装的设置。以下是可以迁移的内容。", + "migration.roo.button": "导入会话", + "migration.roo.empty": "未找到 Roo Code 会话。", "migration.migrate.selectLabel": "选择要迁移的内容", "migration.migrate.chatHistory": "聊天会话和历史记录", - "migration.migrate.button": "迁移设置", - "migration.migrate.skip": "跳过", - "migration.migrate.keysDetected": "检测到 {{count}} 个密钥", - "migration.migrate.serversConfigured": "已配置 {{count}} 个服务器", - "migration.migrate.modesFound": "发现 {{count}} 个模式", - "migration.migrate.nothingToMigrate": "在旧版设置中未找到要迁移的内容。", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "提供商 API 密钥", - "migration.select.mcpServers": "MCP 服务器", - "migration.select.customModes": "自定义模式 / 代理", - "migration.select.defaultModel": "默认模型", - "migration.select.autoApproval": "自动审批", - "migration.select.language": "界面语言", - "migration.select.autocomplete": "自动补全设置", // Migrate — completion "migration.complete.summary": "成功迁移 {{success}}/{{total}} 项。", - "migration.complete.cleanup": "清除旧版设置数据", - "migration.complete.cleanupDescription": "此操作将从 VS Code 存储中删除旧版设置。您将无法再次运行此迁移。", "migration.complete.done": "完成", "migration.migrate.sessionsDetected": "检测到 {{count}} 个会话", "migration.error.continue": "继续", @@ -1189,7 +1148,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "未知日期", "migration.sessionFormat.unknown": "未知", "migration.sessionFormat.unknownError": "未知错误", - // legacy-migration end "error.details.show": "详细信息", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 773fcf20e95..19ba21d6465 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1110,57 +1110,16 @@ export const dict = { "question.summary": "第 {{n}} / {{total}} 個問題", "common.review": "審查", - // legacy-migration start - "settings.legacyMigration.link": "從舊版遷移", - "settings.aboutKiloCode.legacyMigration.title": "舊版遷移", - "settings.aboutKiloCode.legacyMigration.description": - "從舊版 Kilo Code 安裝遷移設定,包括供應商 API 金鑰和預設模型。", "settings.aboutKiloCode.rooImport.description": "從 Roo Code 安裝匯入對話歷史記錄。", "settings.aboutKiloCode.rooImport.button": "從 Roo Code 匯入工作階段", - // Screen 1 — What's New - "migration.whatsNew.title": "Kilo Code 新功能", - "migration.whatsNew.subtitle": "我們在更快、更高效的基礎上重新建構了擴充功能。", - "migration.whatsNew.features.performance.title": "更快的 Agent 效能", - "migration.whatsNew.features.performance.detail": - "平行工具呼叫和子 Agent 讓你的 Agent 可以同時處理更多任務——減少等待時間,更快交付成果。", - "migration.whatsNew.features.interface.title": "簡潔的介面", - "migration.whatsNew.features.interface.detail": "更少干擾,更易閱讀,更快上手。", - "migration.whatsNew.features.agentManager.title": "代理程式管理員", - "migration.whatsNew.features.agentManager.detail": - "一個統一的介面,可以平行執行多個 Agent,每個 Agent 各自使用獨立的 worktree——在同一個地方監控進度、切換上下文和審查變更。", - "migration.whatsNew.features.foundation.title": "共享基礎", - "migration.whatsNew.features.foundation.detail": - "所有 Kilo 產品共享一個小巧高效的核心。無論你選擇哪種方式工作,都能獲得熟悉的體驗。", - "migration.whatsNew.blogLink": "閱讀完整公告", - "migration.whatsNew.docsLink": "新功能與常見問題", - "migration.whatsNew.continue": "繼續", - - // Screen 2 — Migrate Settings - "migration.migrate.title": "遷移你的設定", - "migration.migrate.subtitle": "我們發現了你之前安裝的設定。以下是可以遷移的內容。", + "migration.roo.button": "匯入工作階段", + "migration.roo.empty": "找不到 Roo Code 工作階段。", "migration.migrate.selectLabel": "選擇要遷移的內容", "migration.migrate.chatHistory": "聊天工作階段與歷史紀錄", - "migration.migrate.button": "遷移設定", - "migration.migrate.skip": "略過", - "migration.migrate.keysDetected": "偵測到 {{count}} 個金鑰", - "migration.migrate.serversConfigured": "已設定 {{count}} 個伺服器", - "migration.migrate.modesFound": "發現 {{count}} 個模式", - "migration.migrate.nothingToMigrate": "在舊版設定中找不到可遷移的項目。", - - // Migrate — item labels (reused from old select keys) - "migration.select.providers": "供應商 API 金鑰", - "migration.select.mcpServers": "MCP 伺服器", - "migration.select.customModes": "自訂模式 / 代理", - "migration.select.defaultModel": "預設模型", - "migration.select.autoApproval": "自動核准", - "migration.select.language": "介面語言", - "migration.select.autocomplete": "自動補全設定", // Migrate — completion "migration.complete.summary": "成功遷移 {{success}}/{{total}} 項。", - "migration.complete.cleanup": "清除舊版設定資料", - "migration.complete.cleanupDescription": "此操作將從 VS Code 儲存中刪除舊版設定。您將無法再次執行此遷移。", "migration.complete.done": "完成", "migration.migrate.sessionsDetected": "偵測到 {{count}} 個工作階段", "migration.error.continue": "繼續", @@ -1193,7 +1152,6 @@ export const dict = { "migration.sessionFormat.unknownDate": "未知日期", "migration.sessionFormat.unknown": "未知", "migration.sessionFormat.unknownError": "未知錯誤", - // legacy-migration end "error.details.show": "詳細資訊", From 49af575158a6a0ecbcc70d3e0f3ae3fa5f614a66 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Mon, 31 Aug 2026 16:01:39 +0200 Subject: [PATCH 3/4] test(vscode): set origin for Roo migration fixture --- packages/kilo-vscode/tests/unit/roo-migration-ui.fixture.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/kilo-vscode/tests/unit/roo-migration-ui.fixture.tsx b/packages/kilo-vscode/tests/unit/roo-migration-ui.fixture.tsx index 99d7327c9cc..ba27037a073 100644 --- a/packages/kilo-vscode/tests/unit/roo-migration-ui.fixture.tsx +++ b/packages/kilo-vscode/tests/unit/roo-migration-ui.fixture.tsx @@ -3,6 +3,7 @@ import { Window } from "happy-dom" import type { MigrationSessionInfo, WebviewMessage } from "../../webview-ui/src/types/messages" const window = new Window({ url: "http://localhost" }) +Object.defineProperty(window, "origin", { value: window.location.origin }) const style = window.getComputedStyle.bind(window) const sent: WebviewMessage[] = [] Object.assign(globalThis, { From a28e5cb335baad45a29d1dee232cbe324fcbca88 Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Mon, 31 Aug 2026 14:05:20 +0000 Subject: [PATCH 4/4] chore: update kilo-vscode visual regression baselines --- .../migration/roo-wizard-selecting-chromium-linux.png | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/migration/roo-wizard-selecting-chromium-linux.png b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/migration/roo-wizard-selecting-chromium-linux.png index 5a1446777b1..f122bc09b2f 100644 --- a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/migration/roo-wizard-selecting-chromium-linux.png +++ b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/migration/roo-wizard-selecting-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06c6cd2c2c63745d3cbaec756ae852db3ef0749c005926b75fe3eb03f06b0495 -size 22169 +oid sha256:1326d61e6113da8874f9c836a4d105783a8b050a4ff9648e73120a66b371fc92 +size 21173