From 175562c34ff30f88230474b762c2b50dd47fae1f Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Sun, 15 Mar 2026 08:41:37 -0400 Subject: [PATCH 001/261] Answer some questions about KiloClaw --- packages/kilo-docs/pages/kiloclaw/dashboard.md | 4 ++++ .../kilo-docs/pages/kiloclaw/troubleshooting.md | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/packages/kilo-docs/pages/kiloclaw/dashboard.md b/packages/kilo-docs/pages/kiloclaw/dashboard.md index 9904f07bc74..246e7682778 100644 --- a/packages/kilo-docs/pages/kiloclaw/dashboard.md +++ b/packages/kilo-docs/pages/kiloclaw/dashboard.md @@ -74,6 +74,10 @@ If the gateway crashes, it's automatically restarted. The machine itself can be Gateway process info is only available when the machine is running. {% /callout %} +## Instance Specs + +The specs of your instance, including number of CPUs, memory, and storage, are visibile at the top right of the instance controls section. + ## Settings ### Changing the Model diff --git a/packages/kilo-docs/pages/kiloclaw/troubleshooting.md b/packages/kilo-docs/pages/kiloclaw/troubleshooting.md index 4d158a5b869..7129bb19652 100644 --- a/packages/kilo-docs/pages/kiloclaw/troubleshooting.md +++ b/packages/kilo-docs/pages/kiloclaw/troubleshooting.md @@ -73,6 +73,20 @@ Direct filesystem access is not available at this time. You can interact with fi For security reasons, SSH access is currently disabled for all KiloClaw instances. Our primary goal is to provide a secure environment for all users, and restricting direct SSH access is one of the many measures we take to ensure the platform remains safe and protected for everyone. +### Can I install tailscale on my KiloClaw instance? + +Not at this time. + +### Can I update the version of Node on my instance? + +Not at this time. + +### Can I upgrade the version of OpenClaw myself? + +We do not recommend upgrading the version of OpenClaw yourself. Different versions of OpenClaw may have different requirements and dependencies, and manually upgrading could potentially lead to compatibility issues or break your setup. + +If you upgrade to a version of OpenClaw that breaks your setup, you can use the version pinning dialog at the bottom of the settings tab on the [KiloClaw Dashboard](https://app.kilo.ai/claw) to revert to an earlier version of OpenClaw. + ### How can I update my OpenClaw? Do **not** click **Update Now** inside the OpenClaw Control UI — this is not supported for KiloClaw instances and may break your setup. From 876e439726585c83c02a8353b02ef0d8d6c2965c Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Sun, 15 Mar 2026 08:46:30 -0400 Subject: [PATCH 002/261] simplify upgrade answer --- packages/kilo-docs/pages/kiloclaw/troubleshooting.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/kilo-docs/pages/kiloclaw/troubleshooting.md b/packages/kilo-docs/pages/kiloclaw/troubleshooting.md index 7129bb19652..ab96736a308 100644 --- a/packages/kilo-docs/pages/kiloclaw/troubleshooting.md +++ b/packages/kilo-docs/pages/kiloclaw/troubleshooting.md @@ -81,17 +81,11 @@ Not at this time. Not at this time. -### Can I upgrade the version of OpenClaw myself? +### How do I upgrade the OpenClaw version? -We do not recommend upgrading the version of OpenClaw yourself. Different versions of OpenClaw may have different requirements and dependencies, and manually upgrading could potentially lead to compatibility issues or break your setup. +Use **Upgrade & Redeploy** from the [KiloClaw Dashboard](https://app.kilo.ai/claw). Do **not** click **Update Now** inside the OpenClaw Control UI — this is not supported for KiloClaw instances and may break your setup. -If you upgrade to a version of OpenClaw that breaks your setup, you can use the version pinning dialog at the bottom of the settings tab on the [KiloClaw Dashboard](https://app.kilo.ai/claw) to revert to an earlier version of OpenClaw. - -### How can I update my OpenClaw? - -Do **not** click **Update Now** inside the OpenClaw Control UI — this is not supported for KiloClaw instances and may break your setup. - -Updates are managed by the KiloClaw platform team to ensure stability. When a new version is available, it will be announced in the **Changelog** on your dashboard. To apply the update, click **Upgrade & Redeploy** from the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#redeploy). +When a new version is available, it will be announced in the **Changelog** on your dashboard. If you need to roll back, use the [version pinning](/docs/kiloclaw/version-pinning) dialog in the Settings tab. ## Architecture Notes From 4560c48aa32a0a325c38a504e177b32530db9206 Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Sun, 15 Mar 2026 08:50:43 -0400 Subject: [PATCH 003/261] clarify --- packages/kilo-docs/pages/kiloclaw/troubleshooting.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/kilo-docs/pages/kiloclaw/troubleshooting.md b/packages/kilo-docs/pages/kiloclaw/troubleshooting.md index ab96736a308..73f2147288c 100644 --- a/packages/kilo-docs/pages/kiloclaw/troubleshooting.md +++ b/packages/kilo-docs/pages/kiloclaw/troubleshooting.md @@ -81,11 +81,13 @@ Not at this time. Not at this time. -### How do I upgrade the OpenClaw version? +### How do I upgrade the OpenClaw version? Can I upgrade it myself? -Use **Upgrade & Redeploy** from the [KiloClaw Dashboard](https://app.kilo.ai/claw). Do **not** click **Update Now** inside the OpenClaw Control UI — this is not supported for KiloClaw instances and may break your setup. +Updates are managed by the KiloClaw platform team to ensure stability and dependency availability. When a new version is available, it will be announced in the **Changelog** on your dashboard. -When a new version is available, it will be announced in the **Changelog** on your dashboard. If you need to roll back, use the [version pinning](/docs/kiloclaw/version-pinning) dialog in the Settings tab. +To apply the update, click **Upgrade & Redeploy** from the [KiloClaw Dashboard](https://app.kilo.ai/claw). Do **not** click **Update Now** inside the OpenClaw Control UI — this is not supported for KiloClaw instances and may break your setup. + +If you need to roll back, use the [version pinning](/docs/kiloclaw/version-pinning) dialog in the Settings tab. ## Architecture Notes From ebeb463ab076ddd3259ae2cb645e1c3ea1df8cfb Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Mon, 16 Mar 2026 09:09:03 -0400 Subject: [PATCH 004/261] Update packages/kilo-docs/pages/kiloclaw/dashboard.md Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com> --- packages/kilo-docs/pages/kiloclaw/dashboard.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-docs/pages/kiloclaw/dashboard.md b/packages/kilo-docs/pages/kiloclaw/dashboard.md index 246e7682778..9e75225fdd0 100644 --- a/packages/kilo-docs/pages/kiloclaw/dashboard.md +++ b/packages/kilo-docs/pages/kiloclaw/dashboard.md @@ -76,7 +76,7 @@ Gateway process info is only available when the machine is running. ## Instance Specs -The specs of your instance, including number of CPUs, memory, and storage, are visibile at the top right of the instance controls section. +The specs of your instance, including number of CPUs, memory, and storage, are visible at the top right of the instance controls section. ## Settings From f59a274d8a5d572a9ea6d2a7720ce0df44a74eff Mon Sep 17 00:00:00 2001 From: theQuert Date: Wed, 18 Mar 2026 12:04:01 +0800 Subject: [PATCH 005/261] feat: add Apertis provider to VS Code legacy migration mapping Move Apertis from UNSUPPORTED_PROVIDERS to PROVIDER_MAP with proper field mappings (apertisApiKey, apertisModelId, apertisBaseUrl) so legacy VS Code extension settings migrate correctly to the new CLI backend. --- .../kilo-vscode/src/legacy-migration/provider-mapping.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts b/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts index 817cdeb9775..53de6773af5 100644 --- a/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts +++ b/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts @@ -240,6 +240,13 @@ export const PROVIDER_MAP: Record = { key: "syntheticApiKey", name: "Synthetic", }, + apertis: { + id: "apertis", + key: "apertisApiKey", + name: "Apertis", + modelField: "apertisModelId", + urlField: "apertisBaseUrl", + }, } /** Providers that have no equivalent in the new CLI backend */ @@ -256,7 +263,6 @@ export const UNSUPPORTED_PROVIDERS = new Set([ "nano-gpt", "poe", "aihubmix", - "apertis", "zenmux", ]) From 714e1f5acc349f4fa36cdc4f4d6997dbbd1f3b92 Mon Sep 17 00:00:00 2001 From: Christiaan Arnoldus Date: Mon, 23 Mar 2026 12:00:30 +0100 Subject: [PATCH 006/261] Fix merge --- .../kilo-vscode/src/legacy-migration/provider-mapping.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts b/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts index 21bc0fd0a62..02c67a2357b 100644 --- a/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts +++ b/packages/kilo-vscode/src/legacy-migration/provider-mapping.ts @@ -302,11 +302,6 @@ export const UNSUPPORTED_PROVIDERS = new Set([ "virtual-quota-fallback", "glama", "roo", - "nano-gpt", - "poe", - "aihubmix", - "zenmux", - "apertis", ]) /** Built-in default mode slugs that should not be migrated */ From b9fd360d925783b8124392dc0dc8d6e94183455e Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Mon, 23 Mar 2026 12:09:45 +0100 Subject: [PATCH 007/261] fix(vscode): remove beta label from welcome screen Remove the beta badge from the migration wizard's "What's New" screen, along with the associated CSS and i18n keys across all 17 locales. Closes #7182 --- .../src/components/migration/MigrationWizard.tsx | 5 +---- .../src/components/migration/migration.css | 12 ------------ packages/kilo-vscode/webview-ui/src/i18n/ar.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/br.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/bs.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/da.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/de.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/en.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/es.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/fr.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/ja.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/ko.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/nl.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/no.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/pl.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/ru.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/th.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/zh.ts | 1 - packages/kilo-vscode/webview-ui/src/i18n/zht.ts | 1 - 19 files changed, 1 insertion(+), 33 deletions(-) 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 87a27fea7fb..1358048b543 100644 --- a/packages/kilo-vscode/webview-ui/src/components/migration/MigrationWizard.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/migration/MigrationWizard.tsx @@ -477,10 +477,7 @@ const MigrationWizard: Component = (props) => {
-

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

+

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

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

diff --git a/packages/kilo-vscode/webview-ui/src/components/migration/migration.css b/packages/kilo-vscode/webview-ui/src/components/migration/migration.css index 5a18f5f1477..e4440e06796 100644 --- a/packages/kilo-vscode/webview-ui/src/components/migration/migration.css +++ b/packages/kilo-vscode/webview-ui/src/components/migration/migration.css @@ -67,18 +67,6 @@ width: 100%; } -.migration-wizard__badge { - font-size: 11px; - font-weight: 600; - letter-spacing: 0.5px; - padding: 3px 9px; - border-radius: 6px; - background: color-mix(in srgb, var(--vscode-button-background) 15%, transparent); - color: var(--vscode-button-background); - vertical-align: middle; - text-transform: uppercase; -} - .migration-wizard__header p { font-size: 13px; color: var(--vscode-descriptionForeground); diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index 243bce11b44..bd748c59563 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1127,7 +1127,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "ما الجديد في Kilo Code", - "migration.whatsNew.badge": "Beta", "migration.whatsNew.subtitle": "لقد أعدنا بناء الإضافة على أساس أسرع وأكثر كفاءة.", "migration.whatsNew.features.performance.title": "أداء أسرع للوكيل", "migration.whatsNew.features.performance.detail": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index f96f8903724..b45d6bda539 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1150,7 +1150,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "O Que Há de Novo no Kilo Code", - "migration.whatsNew.badge": "Beta", "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": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 8b42dea7a48..3b890673197 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1149,7 +1149,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Šta je novo u Kilo Code", - "migration.whatsNew.badge": "Beta", "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": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 411a5b69802..1a97d97c7fa 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1141,7 +1141,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Nyheder i Kilo Code", - "migration.whatsNew.badge": "Beta", "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": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 4cc653db9b5..fe55ba18fd0 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1162,7 +1162,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Neuigkeiten in Kilo Code", - "migration.whatsNew.badge": "Beta", "migration.whatsNew.subtitle": "Wir haben die Erweiterung auf einer schnelleren, effizienteren Grundlage neu aufgebaut.", "migration.whatsNew.features.performance.title": "Schnellere Agentenleistung", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 50f7404f527..f8f3ff5c907 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1154,7 +1154,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "What's New in Kilo Code", - "migration.whatsNew.badge": "Beta", "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": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 7e6f5e350ff..12835933b5a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1152,7 +1152,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Novedades en Kilo Code", - "migration.whatsNew.badge": "Beta", "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": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index dca7e206262..e2c33aaf51e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1164,7 +1164,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Nouveautés de Kilo Code", - "migration.whatsNew.badge": "Beta", "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": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 3a24e4cbd49..fa1364c4c1d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1139,7 +1139,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Kilo Codeの新機能", - "migration.whatsNew.badge": "Beta", "migration.whatsNew.subtitle": "より高速で効率的な基盤上に拡張機能を再構築しました。", "migration.whatsNew.features.performance.title": "高速なエージェントパフォーマンス", "migration.whatsNew.features.performance.detail": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index b8517874f0b..a662c8d9a22 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1130,7 +1130,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Kilo Code의 새로운 기능", - "migration.whatsNew.badge": "Beta", "migration.whatsNew.subtitle": "더 빠르고 효율적인 기반 위에 확장 프로그램을 재구축했습니다.", "migration.whatsNew.features.performance.title": "더 빠른 에이전트 성능", "migration.whatsNew.features.performance.detail": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 73605307b10..a214ee18010 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1170,7 +1170,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Wat is er Nieuw in Kilo Code", - "migration.whatsNew.badge": "Bèta", "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": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index aa4bbd50ed2..d359eca1d64 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1142,7 +1142,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Hva er nytt i Kilo Code", - "migration.whatsNew.badge": "Beta", "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": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index c44109ed9f3..3b7ae37a87b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1147,7 +1147,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Co nowego w Kilo Code", - "migration.whatsNew.badge": "Beta", "migration.whatsNew.subtitle": "Przebudowaliśmy rozszerzenie na szybszym i wydajniejszym fundamencie.", "migration.whatsNew.features.performance.title": "Szybsza wydajność agenta", "migration.whatsNew.features.performance.detail": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 854fdf704eb..7aae962324d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1146,7 +1146,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Что нового в Kilo Code", - "migration.whatsNew.badge": "Beta", "migration.whatsNew.subtitle": "Мы перестроили расширение на более быстрой и эффективной основе.", "migration.whatsNew.features.performance.title": "Более быстрая работа агента", "migration.whatsNew.features.performance.detail": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 4365eaffe02..a0ed2c579c4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1126,7 +1126,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "มีอะไรใหม่ใน Kilo Code", - "migration.whatsNew.badge": "Beta", "migration.whatsNew.subtitle": "เราได้สร้างส่วนขยายใหม่บนรากฐานที่เร็วและมีประสิทธิภาพมากขึ้น", "migration.whatsNew.features.performance.title": "ประสิทธิภาพเอเจนต์ที่เร็วขึ้น", "migration.whatsNew.features.performance.detail": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 9a1ec2d5b38..d8b0a452ba5 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1111,7 +1111,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Kilo Code 新功能", - "migration.whatsNew.badge": "Beta", "migration.whatsNew.subtitle": "我们在更快、更高效的基础上重新构建了扩展。", "migration.whatsNew.features.performance.title": "更快的智能体性能", "migration.whatsNew.features.performance.detail": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 2cb4d97de5f..124a0a59670 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1112,7 +1112,6 @@ export const dict = { // Screen 1 — What's New "migration.whatsNew.title": "Kilo Code 新功能", - "migration.whatsNew.badge": "Beta", "migration.whatsNew.subtitle": "我們在更快、更高效的基礎上重新建構了擴充功能。", "migration.whatsNew.features.performance.title": "更快的 Agent 效能", "migration.whatsNew.features.performance.detail": From 1a7b6f9fbcea0409ba20cafd940081234de27829 Mon Sep 17 00:00:00 2001 From: theQuert Date: Tue, 24 Mar 2026 00:23:20 +0800 Subject: [PATCH 008/261] feat: register Apertis as CLI provider with dynamic model fetching Add Apertis provider to the CLI backend so the migration mapping (id: "apertis") has a matching provider to consume the stored API key. - Inject apertis in ModelsDev.get() using @ai-sdk/openai-compatible - Add model fetching from api.apertis.ai/v1/models (OpenAI format) - Add auth resolution: Config > Auth store > APERTIS_API_KEY env var --- packages/opencode/src/provider/model-cache.ts | 90 +++++++++++++++++++ packages/opencode/src/provider/models.ts | 22 +++++ 2 files changed, 112 insertions(+) diff --git a/packages/opencode/src/provider/model-cache.ts b/packages/opencode/src/provider/model-cache.ts index 1d1a2d4e129..d902a40e881 100644 --- a/packages/opencode/src/provider/model-cache.ts +++ b/packages/opencode/src/provider/model-cache.ts @@ -164,11 +164,69 @@ export namespace ModelCache { return fetchKiloModels(options) } + // kilocode_change start + if (providerID === "apertis") { + return fetchApertisModels(options) + } + // kilocode_change end + // Other providers not implemented yet log.debug("provider not implemented", { providerID }) return {} } + // kilocode_change start + const APERTIS_BASE_URL = "https://api.apertis.ai/v1" + + async function fetchApertisModels(options: any): Promise> { + const baseURL = options.baseURL ?? APERTIS_BASE_URL + const apiKey = options.apiKey + + if (!apiKey) { + log.debug("no API key for apertis, skipping model fetch") + return {} + } + + const url = `${baseURL.replace(/\/+$/, "")}/models` + const response = await fetch(url, { + headers: { + Authorization: `Bearer ${apiKey}`, + }, + signal: AbortSignal.timeout(10_000), + }) + + if (!response.ok) { + log.error("apertis model fetch failed", { status: response.status }) + return {} + } + + const json = (await response.json()) as { data?: Array<{ id: string; owned_by?: string }> } + const models: Record = {} + + for (const model of json.data ?? []) { + models[model.id] = { + id: model.id, + name: model.id, + family: model.owned_by ?? "", + release_date: "", + attachment: false, + reasoning: false, + temperature: true, + tool_call: true, + cost: { input: 0, output: 0 }, + limit: { context: 128000, output: 4096 }, + options: {}, + modalities: { + input: ["text"], + output: ["text"], + }, + } + } + + return models + } + // kilocode_change end + /** * Get authentication options from multiple sources * Priority: Config > Auth > Env @@ -223,6 +281,38 @@ export namespace ModelCache { }) } + // kilocode_change start + if (providerID === "apertis") { + const config = await Config.get() + const providerConfig = config.provider?.[providerID] + if (providerConfig?.options?.apiKey) { + options.apiKey = providerConfig.options.apiKey + } + if (providerConfig?.options?.baseURL) { + options.baseURL = providerConfig.options.baseURL + } + + const auth = await Auth.get(providerID) + if (auth && auth.type === "api") { + options.apiKey = auth.key + } + + const env = Env.all() + if (env.APERTIS_API_KEY) { + options.apiKey = env.APERTIS_API_KEY + } + if (env.APERTIS_BASE_URL) { + options.baseURL = env.APERTIS_BASE_URL + } + + log.debug("apertis auth options resolved", { + providerID, + hasKey: !!options.apiKey, + hasBaseURL: !!options.baseURL, + }) + } + // kilocode_change end + return options } } diff --git a/packages/opencode/src/provider/models.ts b/packages/opencode/src/provider/models.ts index 2751547c675..3044d97f853 100644 --- a/packages/opencode/src/provider/models.ts +++ b/packages/opencode/src/provider/models.ts @@ -168,6 +168,28 @@ export namespace ModelsDev { } } + // Inject Apertis provider with dynamic model fetching + if (!providers["apertis"]) { + const apertisConfigObj = await Config.get() + const apertisConfig = apertisConfigObj.provider?.apertis?.options + const apertisBaseURL = apertisConfig?.baseURL ?? "https://api.apertis.ai/v1" + const apertisFetchOptions = { + ...(apertisConfig?.baseURL ? { baseURL: apertisConfig.baseURL } : {}), + } + const apertisModels = await ModelCache.fetch("apertis", apertisFetchOptions).catch(() => ({})) + providers["apertis"] = { + id: "apertis", + name: "Apertis", + env: ["APERTIS_API_KEY"], + api: apertisBaseURL, + npm: "@ai-sdk/openai-compatible", + models: apertisModels, + } + if (Object.keys(apertisModels).length === 0) { + ModelCache.refresh("apertis", apertisFetchOptions).catch(() => {}) + } + } + return providers // kilocode_change end } From 70633f5d504e07db459f66115ef4ffb05941ec82 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 08:55:57 +0000 Subject: [PATCH 009/261] fix(cli,vscode): include subagent costs in total session cost display The session cost displayed in the header/sidebar only summed costs from the root session's assistant messages, ignoring costs from subagent (child) sessions spawned via the task tool. This made the displayed cost misleading when subagents were used. Update all cost calculation sites to also aggregate costs from child sessions by filtering sessions with parentID matching the current session and summing their assistant message costs. Affected surfaces: - CLI TUI header and sidebar - VS Code extension (adds parentID to SessionInfo, aggregates in totalCost) - Web app (session-context-metrics, session-context-usage, session-context-tab) - ACP agent usage updates Closes #7495 --- .../src/components/session-context-usage.tsx | 15 +++++++++++- .../session/session-context-metrics.ts | 12 ++++++---- .../session/session-context-tab.tsx | 15 +++++++++++- .../kilo-vscode/src/kilo-provider-utils.ts | 1 + .../webview-ui/src/context/session.tsx | 8 ++++++- .../webview-ui/src/types/messages.ts | 1 + packages/opencode/src/acp/agent.ts | 20 +++++++++++++++- .../src/cli/cmd/tui/routes/session/header.tsx | 23 +++++++++++++++---- .../cli/cmd/tui/routes/session/sidebar.tsx | 13 ++++++++++- 9 files changed, 95 insertions(+), 13 deletions(-) diff --git a/packages/app/src/components/session-context-usage.tsx b/packages/app/src/components/session-context-usage.tsx index 08ae4d3194e..8a1a9ff5b12 100644 --- a/packages/app/src/components/session-context-usage.tsx +++ b/packages/app/src/components/session-context-usage.tsx @@ -45,7 +45,20 @@ export function SessionContextUsage(props: SessionContextUsageProps) { }), ) - const metrics = createMemo(() => getSessionContextMetrics(messages(), sync.data.provider.all)) + // kilocode_change start - include subagent session costs in total + const childCost = createMemo(() => { + const id = params.id + if (!id) return 0 + return sync.data.session + .filter((s) => s.parentID === id) + .reduce( + (acc, child) => + acc + (sync.data.message[child.id] ?? []).reduce((sum, m) => sum + (m.role === "assistant" ? m.cost : 0), 0), + 0, + ) + }) + // kilocode_change end + const metrics = createMemo(() => getSessionContextMetrics(messages(), sync.data.provider.all, childCost())) const context = createMemo(() => metrics().context) const cost = createMemo(() => { return usd().format(metrics().totalCost) diff --git a/packages/app/src/components/session/session-context-metrics.ts b/packages/app/src/components/session/session-context-metrics.ts index 4bdcff52ebb..78e09425f91 100644 --- a/packages/app/src/components/session/session-context-metrics.ts +++ b/packages/app/src/components/session/session-context-metrics.ts @@ -47,8 +47,10 @@ const lastAssistantWithTokens = (messages: Message[]) => { } } -const build = (messages: Message[] = [], providers: Provider[] = []): Metrics => { - const totalCost = messages.reduce((sum, msg) => sum + (msg.role === "assistant" ? msg.cost : 0), 0) +// kilocode_change start - accept optional child cost to include subagent costs +const build = (messages: Message[] = [], providers: Provider[] = [], childCost = 0): Metrics => { + const totalCost = messages.reduce((sum, msg) => sum + (msg.role === "assistant" ? msg.cost : 0), 0) + childCost + // kilocode_change end const message = lastAssistantWithTokens(messages) if (!message) return { totalCost, context: undefined } @@ -77,6 +79,8 @@ const build = (messages: Message[] = [], providers: Provider[] = []): Metrics => } } -export function getSessionContextMetrics(messages: Message[] = [], providers: Provider[] = []) { - return build(messages, providers) +// kilocode_change start - accept optional child cost to include subagent costs +export function getSessionContextMetrics(messages: Message[] = [], providers: Provider[] = [], childCost = 0) { + return build(messages, providers, childCost) } +// kilocode_change end diff --git a/packages/app/src/components/session/session-context-tab.tsx b/packages/app/src/components/session/session-context-tab.tsx index be5118c2eaf..15c5b08e474 100644 --- a/packages/app/src/components/session/session-context-tab.tsx +++ b/packages/app/src/components/session/session-context-tab.tsx @@ -134,7 +134,20 @@ export function SessionContextTab() { }), ) - const metrics = createMemo(() => getSessionContextMetrics(messages(), sync.data.provider.all)) + // kilocode_change start - include subagent session costs in total + const childCost = createMemo(() => { + const id = params.id + if (!id) return 0 + return sync.data.session + .filter((s) => s.parentID === id) + .reduce( + (acc, child) => + acc + (sync.data.message[child.id] ?? []).reduce((sum, m) => sum + (m.role === "assistant" ? m.cost : 0), 0), + 0, + ) + }) + // kilocode_change end + const metrics = createMemo(() => getSessionContextMetrics(messages(), sync.data.provider.all, childCost())) const ctx = createMemo(() => metrics().context) const formatter = createMemo(() => createSessionContextFormatter(language.intl())) diff --git a/packages/kilo-vscode/src/kilo-provider-utils.ts b/packages/kilo-vscode/src/kilo-provider-utils.ts index 6449f43f917..6eabed0d39e 100644 --- a/packages/kilo-vscode/src/kilo-provider-utils.ts +++ b/packages/kilo-vscode/src/kilo-provider-utils.ts @@ -61,6 +61,7 @@ export function getErrorMessage(error: unknown): string { export function sessionToWebview(session: Session) { return { id: session.id, + parentID: session.parentID ?? null, title: session.title, createdAt: new Date(session.time.created).toISOString(), updatedAt: new Date(session.time.updated).toISOString(), diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index ba7a6fbd862..a784c83ae04 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -1532,7 +1532,13 @@ export const SessionProvider: ParentComponent = (props) => { .sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()), ) - const totalCost = createMemo(() => calcTotalCost(messages())) + const totalCost = createMemo(() => { + const id = currentSessionID() + const cost = calcTotalCost(messages()) + if (!id) return cost + const children = Object.values(store.sessions).filter((s) => s.parentID === id) + return children.reduce((acc, child) => acc + calcTotalCost(store.messages[child.id] ?? []), cost) + }) // Status text derived from last assistant message parts const statusText = createMemo(() => { diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index 6a51ec31edf..432231f180c 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -128,6 +128,7 @@ export interface SessionFileDiff { // Session info (simplified for webview) export interface SessionInfo { id: string + parentID?: string | null title?: string createdAt: string updatedAt: string diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index 59ecfcc6dbe..7436d789dbf 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -106,7 +106,25 @@ export namespace ACP { } const used = msg.tokens.input + (msg.tokens.cache?.read ?? 0) - const totalCost = assistantMessages.reduce((sum, m) => sum + m.info.cost, 0) + // kilocode_change start - include subagent session costs in total + const children = await sdk.session + .children({ sessionID, directory }, { throwOnError: true }) + .then((x) => x.data ?? []) + .catch(() => [] as { id: string }[]) + const childCost = await Promise.all( + children.map((child) => + sdk.session + .messages({ sessionID: child.id, directory }, { throwOnError: true }) + .then((x) => + (x.data ?? []) + .filter((m): m is (typeof assistantMessages)[number] => m.info.role === "assistant") + .reduce((sum, m) => sum + m.info.cost, 0), + ) + .catch(() => 0), + ), + ).then((costs) => costs.reduce((a, b) => a + b, 0)) + const totalCost = assistantMessages.reduce((sum, m) => sum + m.info.cost, 0) + childCost + // kilocode_change end await connection .sessionUpdate({ diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx index 7999e392288..b1e9a9fb081 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx @@ -48,10 +48,25 @@ export function Header() { const messages = createMemo(() => sync.data.message[route.sessionID] ?? []) const cost = createMemo(() => { - const total = pipe( - messages(), - sumBy((x) => (x.role === "assistant" ? x.cost : 0)), - ) + // kilocode_change start - include subagent session costs in total + const sid = route.sessionID + const total = + pipe( + messages(), + sumBy((x) => (x.role === "assistant" ? x.cost : 0)), + ) + + sync.data.session + .filter((s) => s.parentID === sid) + .reduce( + (acc, child) => + acc + + pipe( + sync.data.message[child.id] ?? [], + sumBy((x) => (x.role === "assistant" ? x.cost : 0)), + ), + 0, + ) + // kilocode_change end return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx index 45824208bfe..5c71bd8af06 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx @@ -41,7 +41,18 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { ) const cost = createMemo(() => { - const total = messages().reduce((sum, x) => sum + (x.role === "assistant" ? x.cost : 0), 0) + // kilocode_change start - include subagent session costs in total + const total = + messages().reduce((sum, x) => sum + (x.role === "assistant" ? x.cost : 0), 0) + + sync.data.session + .filter((s) => s.parentID === props.sessionID) + .reduce( + (acc, child) => + acc + + (sync.data.message[child.id] ?? []).reduce((sum, x) => sum + (x.role === "assistant" ? x.cost : 0), 0), + 0, + ) + // kilocode_change end return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", From 57d378e0c85af566f783d006dda99135a6b1271c Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Tue, 24 Mar 2026 05:04:39 -0400 Subject: [PATCH 010/261] docs(kilo-docs): add platform tabs to code-with-ai agents pages Add VSCode (Pre-release) and CLI tabs to 5 agents pages: - chat-interface.md: Tabbed quick setup, chat UI, suggested responses - using-modes.md: Modes vs agents callout, switching methods, built-in agents - context-mentions.md: Tool-based context model, editor context, @-mentions - model-selection.md: Model config per platform - orchestrator-mode.md: task tool subagent sessions vs new_task/attempt_completion Fixes from validation: - Fix tab order in model-selection (VSCode > Pre-release > CLI) - Fix indentation in model-selection tabs - Soften plan agent description (not a replacement for Architect) - Move orphaned footnotes that referenced classic-only tools Part of the docs platform tabs effort (PR 3 of 8). Depends on #7497 for infrastructure. --- .../code-with-ai/agents/chat-interface.md | 108 ++++++++++++++++++ .../code-with-ai/agents/context-mentions.md | 94 +++++++++++++++ .../code-with-ai/agents/model-selection.md | 26 +++++ .../code-with-ai/agents/orchestrator-mode.md | 27 ++++- .../pages/code-with-ai/agents/using-modes.md | 97 ++++++++++++++-- 5 files changed, 338 insertions(+), 14 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md index 351af9549ec..7f0980cf8be 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md @@ -15,10 +15,26 @@ If you're typing code in the editor and want AI to finish your line or block, ch ## Quick Setup +{% tabs %} +{% tab label="VSCode (Legacy)" %} + Find the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar. Click it to open the chat panel. **Lost the panel?** Go to View > Open View... and search for "Kilo Code" +{% /tab %} +{% tab label="VSCode" %} + +Click the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar to open the sidebar chat. You can also pop it out into an editor tab for a larger workspace. + +{% /tab %} +{% tab label="CLI" %} + +Open your terminal and run `kilo` to launch the interactive TUI. You'll see a prompt where you can start typing requests immediately. The TUI is fully keyboard-driven — no mouse required. + +{% /tab %} +{% /tabs %} + ## How to Talk to Kilo Code **The key insight:** Just type what you want in normal English. No special commands needed. @@ -46,6 +62,9 @@ Find the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar. C ## The Chat Interface +{% tabs %} +{% tab label="VSCode (Legacy)" %} + {% image src="/docs/img/the-chat-interface/the-chat-interface-1.png" alt="Chat interface components labeled with callouts" width="800" caption="Everything you need is right here" /%} **Essential controls:** @@ -56,6 +75,48 @@ Find the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar. C - **Plus button** - Start a new task session - **Mode selector** - Choose how Kilo should approach your task +**Providing context with @-mentions:** + +Reference files and other context directly in your message using `@`: + +- `@file` - Reference a specific file +- `@url` - Include content from a URL +- `@problems` - Include current VS Code problems +- `@terminal` - Include terminal output +- `@git-changes` - Include uncommitted changes +- `@commit` - Reference a specific commit + +{% /tab %} +{% tab label="VSCode" %} + +**Essential controls:** + +- **Input prompt** - Type your requests and press Enter to send +- **Action buttons** - Approve or reject proposed changes +- **Agent dropdown** - Switch between agents (e.g. Code, Ask, Plan) from the sidebar +- **Session management** - Start new sessions or resume previous ones + +**Providing context:** + +The extension automatically passes context from your editor, including your open tabs and active file. You can type `@` in the chat input to get file autocomplete suggestions, or mention file paths naturally in your message (e.g., "update src/utils.ts to add a helper function"). The agent can also discover files on its own using its built-in tools. + +{% /tab %} +{% tab label="CLI" %} + +**Essential controls:** + +- **Input prompt** - Type your requests and press Enter to send +- **Action buttons** - Approve or reject proposed changes +- **Agent cycling** - Switch between agents using keybinds or slash commands +- **Session management** - Start new sessions or resume previous ones + +**Providing context:** + +Type `@` in the TUI to get file autocomplete suggestions, or mention file paths directly in your message (e.g., "look at src/utils.ts") and the agent will read them. When using the non-interactive `kilo run` command, you can pass `-f path/to/file.ts` to explicitly include files (this flag is not available in the TUI). The agent also has `glob`, `grep`, and `read` tools to discover files on its own. + +{% /tab %} +{% /tabs %} + ## Quick Interactions **Click to act:** @@ -87,6 +148,9 @@ Find the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar. C When Kilo Code needs more information to complete a task, it uses the [`ask_followup_question`](/docs/automate/tools/ask-followup-question) tool. To make responding easier and faster, Kilo Code often provides suggested answers alongside the question. +{% tabs %} +{% tab label="VSCode (Legacy)" %} + {% image src="/docs/img/suggested-responses/suggested-responses.png" alt="Example of Kilo Code asking a question with suggested response buttons below it" width="800" caption="Suggested responses appear as clickable buttons below questions" /%} **How it works:** @@ -109,6 +173,18 @@ You have two options for using suggested responses: - _Alternatively_, hover over the suggestion button and click the pencil icon ({% codicon name="edit" /%}) that appears - **Result**: The text of the suggestion is copied into the chat input box. You can then modify the text as needed before pressing Enter to send your customized response. This is useful when a suggestion is close but needs minor adjustments. +{% /tab %} +{% tab label="VSCode & CLI" %} + +**How it works:** + +1. **Question Appears** - Kilo Code asks a question using the `question` tool +2. **Options Displayed** - Selectable options are presented that you can choose from +3. **Selection** - Pick an option or type a custom response + +{% /tab %} +{% /tabs %} + **Benefits:** - **Speed** - Quickly respond without typing full answers @@ -119,6 +195,9 @@ This feature streamlines the interaction when Kilo Code requires clarification, ## Tips for Better Workflow +{% tabs %} +{% tab label="VSCode (Legacy)" %} + {% callout type="tip" %} **Move Kilo Code to the Secondary Side Bar** for a better layout. Right-click on the Kilo Code icon in the Activity Bar and select **Move To → Secondary Side Bar**. This lets you see the Explorer, Search, Source Control, etc. alongside Kilo Code. @@ -129,4 +208,33 @@ This feature streamlines the interaction when Kilo Code requires clarification, **Drag files directly into chat.** Once you have Kilo Code in a separate sidebar from the file explorer, you can drag files from the explorer into the chat window (even multiple at once). Just hold down the Shift key after you start dragging the files. {% /callout %} +{% /tab %} +{% tab label="VSCode" %} + +{% callout type="tip" %} +**Use agents instead of modes.** Switch between agents like Code, Ask, and Plan using the agent dropdown or slash commands. Each agent is tuned for a different type of task. +{% /callout %} + +{% callout type="tip" %} +**Your editor context is automatic.** The extension reads your open tabs and active file, so you don't need to manually reference every file. Focus your message on what you want done. +{% /callout %} + +{% callout type="tip" %} +**Pop out to an editor tab.** If the sidebar feels cramped, pop the chat into a full editor tab for more room. +{% /callout %} + +{% /tab %} +{% tab label="CLI" %} + +{% callout type="tip" %} +**Use agents instead of modes.** Switch between agents like Code, Ask, and Plan using keybinds or slash commands. Each agent is tuned for a different type of task. +{% /callout %} + +{% callout type="tip" %} +**The TUI is keyboard-driven.** Navigate, approve changes, and switch agents entirely from the keyboard — no mouse needed. +{% /callout %} + +{% /tab %} +{% /tabs %} + Ready to start coding? Open the chat panel and describe what you want to build! diff --git a/packages/kilo-docs/pages/code-with-ai/agents/context-mentions.md b/packages/kilo-docs/pages/code-with-ai/agents/context-mentions.md index e4bf59580b0..eab8848c54f 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/context-mentions.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/context-mentions.md @@ -5,6 +5,11 @@ description: "How to provide context to Kilo Code using mentions" # Context Mentions +Providing the right context helps Kilo Code understand your project and perform tasks accurately. How you provide that context depends on which version of Kilo Code you're using — the **VSCode (Legacy)** version uses `@`-mentions in the chat input, while the current **VSCode & CLI** version uses a tool-based approach where the agent automatically discovers the context it needs. + +{% tabs %} +{% tab label="VSCode (Legacy)" %} + Context mentions are a powerful way to provide Kilo Code with specific information about your project, allowing it to perform tasks more accurately and efficiently. You can use mentions to refer to files, folders, problems, and Git commits. Context mentions start with the `@` symbol. {% image src="/docs/img/context-mentions/context-mentions.png" alt="Context Mentions Overview - showing the @ symbol dropdown menu in the chat interface" width="600" caption="Context mentions overview showing the @ symbol dropdown menu in the chat interface." /%} @@ -116,3 +121,92 @@ The dropdown automatically suggests: | **Click mentions** | Click mentions in chat history to open files or view content | | **Eliminate copy-pasting** | Use mentions instead of manually copying code or errors | | **Combine mentions** | "Fix @problems in @/src/component.ts using the pattern from commit @a1b2c3d" | + +{% /tab %} +{% tab label="VSCode" %} + +The current **VSCode** version uses a fundamentally different context model compared to the **VSCode (Legacy)** version. The agent **automatically discovers and reads the context it needs** using built-in tools. You can also type `@` in the chat input to get file autocomplete suggestions, but the agent can also find files on its own using its tools. + +## How Context Works + +When you describe a task, the agent uses its tools — `read`, `grep`, `glob`, and others — to find and read relevant files on its own. You don't need to explicitly point it at files in most cases; just describe what you want done and the agent will locate the right code. + +### Automatic Editor Context + +The agent automatically receives context from your editor: + +| Context | Details | +| --------------- | -------------------------------------------------- | +| **Active file** | The file currently open and focused in your editor | +| **Open tabs** | Files you have open in editor tabs | + +This context is passed to the agent without any explicit mentions — it's included automatically with each message you send. + +{% callout type="note" %} +**Selection** and **diagnostics** are not sent automatically with each message. They are available through VS Code Code Actions (e.g., selecting code and using the lightbulb menu), but are not part of the default editor context. +{% /callout %} + +### Tool-Based File Access + +Rather than attaching file contents up front, the agent reads files on demand during its work: + +| Tool | Purpose | Example | +| -------- | --------------------------------------------- | ------------------------------------------- | +| **read** | Read the contents of a specific file | Agent reads `src/utils.ts` to understand it | +| **glob** | Find files matching a pattern | Agent searches for `**/*.test.ts` | +| **grep** | Search file contents for a pattern | Agent searches for `function handleError` | +| **bash** | Run shell commands including `git` operations | Agent runs `git diff` or `git log` | + +This means the agent can explore your entire project as needed, rather than being limited to files you explicitly mention. + +## Best Practices + +| Practice | Description | +| ------------------------------ | -------------------------------------------------------------------------------------------------- | +| **Describe the task clearly** | The agent finds context on its own — focus on _what_ you want done rather than _where_ the code is | +| **Mention files when helpful** | If you know the exact file, mention its path to save the agent a search step | +| **Keep editor tabs relevant** | Open tabs are passed as context, so keep relevant files open | +| **Trust the agent's tools** | The agent can search, read, and explore your codebase — let it do the discovery work | + +{% /tab %} +{% tab label="CLI" %} + +The CLI uses a tool-based context model. The agent **automatically discovers and reads the context it needs** using built-in tools. In the TUI, you can type `@` to get file autocomplete suggestions for quick file references. + +## How Context Works + +When you describe a task, the agent uses its tools — `read`, `grep`, `glob`, and others — to find and read relevant files on its own. You don't need to explicitly point it at files in most cases; just describe what you want done and the agent will locate the right code. + +### Providing File Context + +In the terminal-based TUI, you can provide context in several ways: + +- **Type `@` for file autocomplete** — In the TUI, type `@` followed by a filename to get autocomplete suggestions for quick file references. +- **Mention file paths in your message** — Simply refer to files by path in your conversation text (e.g., "look at src/utils.ts") and the agent will read them. +- **Use `kilo run -f`** — When using the non-interactive `kilo run` command, pass `-f path/to/file.ts` to explicitly include a file's contents in the context. This flag is not available in the interactive TUI. +- **Let the agent find files itself** — The agent has access to `glob` (find files by pattern), `grep` (search file contents), and `read` (read file contents) tools. Describe what you're looking for and it will locate the relevant code. + +### Tool-Based File Access + +Rather than attaching file contents up front, the agent reads files on demand during its work: + +| Tool | Purpose | Example | +| -------- | --------------------------------------------- | ------------------------------------------- | +| **read** | Read the contents of a specific file | Agent reads `src/utils.ts` to understand it | +| **glob** | Find files matching a pattern | Agent searches for `**/*.test.ts` | +| **grep** | Search file contents for a pattern | Agent searches for `function handleError` | +| **bash** | Run shell commands including `git` operations | Agent runs `git diff` or `git log` | + +This means the agent can explore your entire project as needed, rather than being limited to files you explicitly mention. + +## Best Practices + +| Practice | Description | +| ------------------------------ | -------------------------------------------------------------------------------------------------- | +| **Describe the task clearly** | The agent finds context on its own — focus on _what_ you want done rather than _where_ the code is | +| **Mention files when helpful** | If you know the exact file, mention its path to save the agent a search step | +| **Use `kilo run -f`** | Pass key files with `-f` when using `kilo run` for immediate context (not available in the TUI) | +| **Trust the agent's tools** | The agent can search, read, and explore your codebase — let it do the discovery work | + +{% /tab %} +{% /tabs %} diff --git a/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md b/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md index bf090ac3404..ee22b39cf31 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md @@ -19,6 +19,32 @@ This isn't benchmarks from some lab. It's real usage data from developers like y While the specifics change constantly, some principles stay consistent: +### How to Select and Switch Models + +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +- Use the **model dropdown** in the chat panel to select a model for each conversation. +- Configure **API profiles** in Settings to group provider + model combinations and switch between them quickly. +- Models are **sticky per mode** — each mode (Code, Architect, Debug, etc.) remembers the last model you selected. + +{% /tab %} +{% tab label="VSCode" %} + +- Open the **Settings webview** in the extension sidebar to select a model. +- Alternatively, set models directly in the `kilo.json` config file (the extension reads the same config as the CLI). + +{% /tab %} +{% tab label="CLI" %} + +- Set the default model with the `model` key in your `kilo.json` config file. +- In the TUI, use the **model picker** (keybind to cycle through configured models). +- For non-interactive use, pass `--model` flag to `kilo run` (e.g., `kilo run --model claude-sonnet-4-20250514`). +- Configure per-agent models in the agents section of your config. + +{% /tab %} +{% /tabs %} + **For complex coding tasks**: Premium models (Claude Sonnet/Opus, GPT-5 class, Gemini Pro) typically handle nuanced requirements, large refactors, and architectural decisions better. **For everyday coding**: Mid-tier models often provide the best balance of speed, cost, and quality. They're fast enough to keep your flow state intact and capable enough for most tasks. diff --git a/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md b/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md index 9fca04b85c2..84762da247d 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md @@ -7,8 +7,6 @@ description: "Using Orchestrator mode for complex multi-step tasks" Orchestrator Mode (formerly known as Boomerang Tasks) allows you to break down complex projects into smaller, manageable pieces. Think of it like delegating parts of your work to specialized assistants. Each subtask runs in its own context, often using a different Kilo Code mode tailored for that specific job (like [`code`](/docs/code-with-ai/agents/using-modes#code-mode-default), [`architect`](/docs/code-with-ai/agents/using-modes#architect-mode), or [`debug`](/docs/code-with-ai/agents/using-modes#debug-mode)). -{% youtube url="https://www.youtube.com/watch?v=20MmJNeOODo" caption="Orchestrator Mode explained and demonstrated" /%} - ## Why Use Orchestrator Mode? - **Tackle Complexity:** Break large, multi-step projects (e.g., building a full feature) into focused subtasks (e.g., design, implementation, documentation). @@ -37,6 +35,25 @@ Orchestrator Mode provides a powerful way to manage complex development workflow Use 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. {% /callout %} -1. This context is passed via the `message` parameter of the [`new_task`](/docs/automate/tools/new-task) tool. -2. The mode for the subtask is specified via the `mode` parameter of the [`new_task`](/docs/automate/tools/new-task) tool during initiation. -3. This summary is passed via the `result` parameter of the [`attempt_completion`](/docs/automate/tools/attempt-completion) tool when the subtask finishes. +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +{% youtube url="https://www.youtube.com/watch?v=20MmJNeOODo" caption="Orchestrator Mode explained and demonstrated" /%} + +In the **VSCode** version, orchestrator mode uses two tools to manage subtasks: + +1. The [`new_task`](/docs/automate/tools/new-task) tool creates a subtask. Context is passed via the `message` parameter, and the subtask's mode is specified via the `mode` parameter (e.g., `code`, `architect`, `debug`). +2. When a subtask finishes, it calls [`attempt_completion`](/docs/automate/tools/attempt-completion). The summary is passed back to the parent via the `result` parameter. + +{% /tab %} +{% tab label="VSCode & CLI" %} + +In the new CLI and extension, orchestrator mode uses the `task` tool to launch **subagent sessions**: + +- The `task` tool creates a new child session. The agent name is specified as a parameter (e.g., `general`, `explore`, or custom subagent types you define). +- Child sessions are **fully isolated** — they run in their own conversation context and do not share message history with the parent. +- When the subagent completes its work, it returns a single message back to the parent orchestrator with the result. +- The parent orchestrator can launch multiple subagent sessions concurrently for parallel work. + +{% /tab %} +{% /tabs %} diff --git a/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md b/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md index 1f0c4f1e0d9..3f5953d7e55 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md @@ -7,6 +7,10 @@ description: "Understanding and using different modes in Kilo Code" Modes in Kilo Code are specialized personas that tailor the assistant's behavior to your current task. Each mode offers different capabilities, expertise, and access levels to help you accomplish specific goals. +{% callout type="info" %} +The **VSCode (Legacy)** version calls these **modes**, while the current **VSCode & CLI** version calls them **agents**. The concept is the same—specialized personas with distinct tool access and behavior. +{% /callout %} + ## Why Use Different Modes? - **Task specialization:** Get precisely the type of assistance you need for your current task @@ -14,10 +18,13 @@ Modes in Kilo Code are specialized personas that tailor the assistant's behavior - **Focused interactions:** Receive responses optimized for your current activity - **Workflow optimization:** Seamlessly transition between planning, implementing, debugging, and learning -{% youtube url="https://youtu.be/cS4vQfX528w" caption="Explaining the different modes in Kilo Code" /%} - ## Switching Between Modes +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +{% youtube url="https://youtu.be/cS4vQfX528w" caption="Explaining the different modes in Kilo Code" /%} + Four ways to switch modes: 1. **Dropdown menu:** Click the selector to the left of the chat input @@ -49,8 +56,32 @@ Users often confuse `/newtask` and `/smol`. Here's the key difference: {% image src="/docs/img/modes/modes-2.png" alt="Accepting a mode switch suggestion from Kilo Code" width="400" /%} +{% /tab %} +{% tab label="VSCode" %} + +There are several ways to switch agents: + +- **Dropdown menu:** Click the agent selector in the sidebar to switch between agents. +- **Slash commands:** Type `/` in the chat input to switch agents (e.g., `/code`, `/ask`, `/plan`, `/debug`). +- **Keyboard shortcut:** Use a keyboard shortcut to cycle through available agents. + +{% /tab %} +{% tab label="CLI" %} + +There are several ways to switch agents: + +- **Keybinds:** Press the displayed key to cycle through available agents. +- **Slash commands:** Type `/` in the chat input to see available commands, including switching agents (e.g., `/code`, `/ask`, `/plan`, `/debug`). +- **Config file:** Set the `default_agent` key in your configuration to change the default agent on startup. + +{% /tab %} +{% /tabs %} + ## Built-in Modes +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ### Code Mode (Default) | Aspect | Details | @@ -109,13 +140,61 @@ Users often confuse `/newtask` and `/smol`. Here's the key difference: | **Ideal For** | Catching issues early, enforcing code standards, accelerating PR turnaround | | **Special Features** | Code review before committing, surfacing feedback across performance, security, style, and test coverage | +{% /tab %} +{% tab label="VSCode & CLI" %} + +### code (Default) + +| Aspect | Details | +| -------------------- | ----------------------------------------------------------------------------------------------------------------- | +| **Description** | A skilled software engineer with expertise in programming languages, design patterns, and best practices | +| **Tool Access** | Full access to all tools: `read`, `edit`, `glob`, `grep`, `bash`, `task`, `webfetch`, plus tools from MCP servers | +| **Ideal For** | Writing code, implementing features, debugging, and general development | +| **Special Features** | No tool restrictions—full flexibility for all coding tasks | + +### ask + +| Aspect | Details | +| -------------------- | ------------------------------------------------------------------------------------------------- | +| **Description** | A knowledgeable technical assistant focused on answering questions without changing your codebase | +| **Tool Access** | Read-only tools only (cannot edit files or run commands) | +| **Ideal For** | Code explanation, concept exploration, and technical learning | +| **Special Features** | Optimized for informative responses without modifying your project | + +### plan + +| Aspect | Details | +| -------------------- | ---------------------------------------------------------------------------------------------------- | +| **Description** | An experienced technical leader and planner who helps design systems and create implementation plans | +| **Tool Access** | Read-only tools plus restricted file editing (e.g., markdown files only) | +| **Ideal For** | System design, high-level planning, and architecture discussions | +| **Special Features** | Similar to the **VSCode (Legacy)** version's "Architect" mode, with a planning-focused approach | + +### debug + +| Aspect | Details | +| -------------------- | ----------------------------------------------------------------------------------- | +| **Description** | An expert problem solver specializing in systematic troubleshooting and diagnostics | +| **Tool Access** | Full access to all tools | +| **Ideal For** | Tracking down bugs, diagnosing errors, and resolving complex issues | +| **Special Features** | Uses a methodical approach of analyzing, narrowing possibilities, and fixing issues | + +### orchestrator + +| Aspect | Details | +| -------------------- | -------------------------------------------------------------------------------------------------------------------- | +| **Description** | A strategic workflow orchestrator who coordinates complex tasks by delegating them to appropriate specialized agents | +| **Tool Access** | Limited access to create new tasks and coordinate workflows | +| **Ideal For** | Breaking down complex projects into manageable subtasks assigned to specialized agents | +| **Special Features** | Delegates work to other agents; also has access to the **explore** subagent for codebase exploration | + +{% callout type="info" %} +The **VSCode & CLI** version does not include a built-in Review agent. Code review workflows can be handled by the **code** agent or via custom agent configurations. +{% /callout %} + +{% /tab %} +{% /tabs %} + ## Custom Modes Create your own specialized assistants by defining tool access, file permissions, and behavior instructions. Custom modes help enforce team standards or create purpose-specific assistants. See [Custom Modes documentation](/docs/customize/custom-modes) for setup instructions. - - From 064a1f0fc6f8f7a0d9d850f44b6970258f65b790 Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Tue, 24 Mar 2026 05:08:17 -0400 Subject: [PATCH 011/261] docs(kilo-docs): add platform tabs to code-with-ai features pages Add VSCode (Pre-release) and CLI tabs to 7 features pages: - autocomplete/index.md: FIM with Codestral, snooze, Copilot detection - code-actions.md: Pre-release actions, terminal context menu, AM integration - git-commit-generation.md: SCM button via CLI backend - browser-use.md: Playwright MCP approach, browser settings per platform - checkpoints.md: Snapshot config, CLI revert/unrevert, per-file revert - platforms/vscode.md: Feature comparison between VSCode and Pre-release - platforms/cli.md: Fix stale MCP link, add platform:next frontmatter Part of the docs platform tabs effort (PR 4 of 8). Depends on #7497 for infrastructure. --- .../features/autocomplete/index.md | 42 ++++++++ .../code-with-ai/features/browser-use.md | 96 +++++++++++++++++++ .../code-with-ai/features/checkpoints.md | 64 ++++++++++++- .../code-with-ai/features/code-actions.md | 34 +++++++ .../features/git-commit-generation.md | 17 ++++ .../pages/code-with-ai/platforms/cli.md | 3 +- .../pages/code-with-ai/platforms/vscode.md | 54 +++++++++++ 7 files changed, 304 insertions(+), 6 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md b/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md index 311ae3e0b87..42c6ebb7afe 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md +++ b/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md @@ -7,6 +7,9 @@ description: "AI-powered code autocompletion in Kilo Code" Kilo Code's autocomplete feature provides intelligent code suggestions and completions while you're typing, helping you write code faster and more efficiently. It offers both automatic and manual triggering options. +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ## How Autocomplete Works Autocomplete analyzes your code context and provides: @@ -86,6 +89,45 @@ If using Cursor, go to **Settings** > **Cursor Settings** > **Tab**, and toggle {% image src="https://github.com/user-attachments/assets/fd2eeae2-f770-40ca-8a72-a9d5a1c17d47" alt="Disable Cursor autocomplete" width="800" caption="Disable Cursor autocomplete" /%} +{% /tab %} +{% tab label="VSCode" %} + +{% callout type="info" %} +Autocomplete is an **extension-only** feature. It is not available in the CLI/TUI. +{% /callout %} + +## How Autocomplete Works + +The new extension uses **Fill-in-the-Middle (FIM)** completion powered by Codestral (`mistralai/codestral-2508`). It analyzes the code before and after your cursor to generate contextually accurate inline suggestions. + +## Triggering Options + +### Auto-trigger + +Autocomplete is **enabled by default** and automatically shows inline suggestions as you type. Suggestions appear as ghost text that you can accept with `Tab`. + +### Trigger on keybinding (Cmd+L) + +Press `Cmd+L` (Mac) or `Ctrl+L` (Windows/Linux) to manually request a completion at your cursor position. + +## Status Bar + +The extension displays an **autocomplete status indicator** in the VS Code status bar, including: + +- Current autocomplete state (active/snoozed) +- Cumulative cost tracking for autocomplete requests + +### Snooze / Unsnooze + +You can temporarily disable autocomplete by clicking the status bar item to **snooze** it. Click again to **unsnooze** and re-enable suggestions. + +## Copilot Conflict Detection + +The new extension automatically detects if **GitHub Copilot** inline suggestions are enabled and warns you about potential conflicts. Disable Copilot's inline completions for the best experience with Kilo Code autocomplete. + +{% /tab %} +{% /tabs %} + ## Best Practices 1. **Balance speed and quality**: Faster models provide quicker suggestions but may be less accurate diff --git a/packages/kilo-docs/pages/code-with-ai/features/browser-use.md b/packages/kilo-docs/pages/code-with-ai/features/browser-use.md index 8255cf275b6..34e0c5d8fd1 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/browser-use.md +++ b/packages/kilo-docs/pages/code-with-ai/features/browser-use.md @@ -13,6 +13,9 @@ Browser Use requires an advanced agentic model. It is typically most reliable wi ## How Browser Use Works +{% tabs %} +{% tab label="VSCode (Legacy)" %} + By default, Kilo Code uses a built-in browser that: - Launches automatically when you ask Kilo to visit a website @@ -22,6 +25,35 @@ By default, Kilo Code uses a built-in browser that: All of this happens directly within VS Code, with no setup required. +{% /tab %} +{% tab label="VSCode & CLI" %} + +Kilo Code uses [Playwright](https://playwright.dev/) via MCP (`@playwright/mcp@latest`) for browser automation. The Playwright MCP server is registered dynamically as `kilo-playwright`. + +**In the VS Code extension**, browser automation is auto-configured: + +- Toggle it on from **Settings → Browser** tab +- Configure `browserAutomation.headless` and `browserAutomation.useSystemChrome` settings +- Playwright auto-downloads Chromium on first use + +**In CLI-only mode**, you need to manually add the MCP server to your `kilo.json` configuration: + +```json +{ + "mcp": { + "playwright": { + "type": "local", + "command": ["npx", "-y", "@playwright/mcp@latest"] + } + } +} +``` + +Once configured, Playwright downloads Chromium automatically on first use. + +{% /tab %} +{% /tabs %} + ## Using Browser Use A typical browser interaction follows this pattern: @@ -39,6 +71,9 @@ For example: ## How Browser Actions Work +{% tabs %} +{% tab label="VSCode (Legacy)" %} + The browser_action tool controls a browser instance that returns screenshots and console logs after each action, allowing you to see the results of interactions. Key characteristics: @@ -59,8 +94,38 @@ Key characteristics: | `scroll_up` | Scrolls up by one page | Returning to previous content | | `close` | Closes the browser | Ending a browser session | +{% /tab %} +{% tab label="VSCode & CLI" %} + +The Playwright MCP server provides a set of browser tools for interacting with web pages. These tools return screenshots and accessibility snapshots after each action. + +Key characteristics: + +- The browser launches automatically when a browser tool is invoked +- Multiple browser tools can be used in sequence +- Screenshots are captured after each action for visual feedback + +### Available Browser Tools + +| Tool | Description | When to Use | +| -------------------- | ----------------------------------- | ------------------------------------- | +| `browser_navigate` | Navigates to a URL | Opening a web page | +| `browser_click` | Clicks an element on the page | Interacting with buttons, links, etc. | +| `browser_type` | Types text into an input element | Filling forms, search boxes | +| `browser_screenshot` | Captures a screenshot of the page | Inspecting visual state | +| `browser_scroll` | Scrolls the page or a specific area | Viewing content above or below | +| `browser_hover` | Hovers over an element | Revealing tooltips or menus | +| `browser_select` | Selects an option from a dropdown | Choosing from select elements | +| `browser_drag` | Drags an element to a target | Drag-and-drop interactions | + +{% /tab %} +{% /tabs %} + ## Browser Use Settings +{% tabs %} +{% tab label="VSCode (Legacy)" %} + {% callout type="info" title="Default Browser Settings" %} - **Enable browser tool**: Enabled @@ -161,3 +226,34 @@ Connect to a visible Chrome window to observe Kilo's interactions in real-time: ```bash google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug --no-first-run ``` + +{% /tab %} +{% tab label="VSCode & CLI" %} + +### VS Code Extension Settings + +In the VS Code extension, browser automation settings are available under **Settings → Browser**: + +- **Enable browser automation**: Toggle to enable or disable Playwright browser automation +- **Headless mode** (`browserAutomation.headless`): Run the browser without a visible window (default: disabled) +- **Use system Chrome** (`browserAutomation.useSystemChrome`): Use your installed Chrome instead of the bundled Chromium + +### CLI Configuration + +In CLI-only mode, browser automation requires manual MCP configuration in your `kilo.json` file: + +```json +{ + "mcp": { + "playwright": { + "type": "local", + "command": ["npx", "-y", "@playwright/mcp@latest"] + } + } +} +``` + +No additional settings are needed — the Playwright MCP server manages the browser lifecycle automatically. Chromium is downloaded on first use. + +{% /tab %} +{% /tabs %} diff --git a/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md b/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md index 377f9dc108e..08c4abd7b79 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md +++ b/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md @@ -27,6 +27,9 @@ Checkpoints let you: ## Configuration Options +{% tabs %} +{% tab label="VSCode (Legacy)" %} + Access checkpoint settings in Kilo Code settings under the "Checkpoints" section: 1. Open Settings by clicking the gear icon {% codicon name="gear" /%} → Checkpoints @@ -34,6 +37,25 @@ Access checkpoint settings in Kilo Code settings under the "Checkpoints" section {% image src="/docs/img/checkpoints/checkpoints.png" alt="Checkpoint settings in Kilo Code configuration" width="500" /%} +{% /tab %} +{% tab label="VSCode & CLI" %} + +Checkpoints are controlled by the `snapshot` boolean: + +- **Settings UI**: Open Settings → Checkpoints tab and toggle the snapshot setting +- **Config file**: Set `"snapshot": true` or `"snapshot": false` in your `kilo.json` configuration file + +```json +{ + "snapshot": true +} +``` + +When enabled, the system automatically captures snapshots at each step of a task. + +{% /tab %} +{% /tabs %} + ## How Checkpoints Work Kilo Code captures snapshots of your project's state using a shadow Git repository, separate from your main version control system. These snapshots, called checkpoints, automatically record changes throughout your AI-assisted workflow—whenever tasks begin, files change, or commands run. @@ -48,6 +70,9 @@ Checkpoints are stored as Git commits in the shadow repository, capturing: ## Working with Checkpoints +{% tabs %} +{% tab label="VSCode (Legacy)" %} + Checkpoints are integrated directly into your workflow through the chat interface. Checkpoints appear directly in your chat history in two forms: @@ -93,12 +118,34 @@ To restore a project to a previous checkpoint state: {% image src="/docs/img/checkpoints/checkpoints-9.png" alt="Confirmation dialog for restoring checkpoint with files & task" width="300" /%} -### Limitations and Considerations +{% /tab %} +{% tab label="VSCode & CLI" %} -- **Scope**: Checkpoints only capture changes made during active Kilo Code tasks -- **External changes**: Modifications made outside of tasks (manual edits, other tools) aren't included -- **Large files**: Very large binary files may impact performance -- **Unsaved work**: Restoration will overwrite any unsaved changes in your workspace +Checkpoints are captured automatically at each step of a task. The system calls `Snapshot.track()` at `start-step` and `finish-step` events, recording Git tree objects via `git write-tree`. + +### CLI TUI + +In the CLI terminal interface, checkpoints appear as revert points in the conversation. You can revert to any point by selecting the corresponding message. + +### Reverting Changes + +The new platform provides flexible revert capabilities: + +- **Full revert**: Use `SessionRevert.revert({ sessionID, messageID, partID })` to revert your workspace to any point in the conversation +- **Undo a revert**: Use `unrevert()` to restore the state before the last revert +- **Per-file revert**: `Snapshot.revert(patches)` can revert individual files via `git checkout -- `, allowing you to selectively undo changes to specific files while keeping others + +### Viewing Differences + +The system provides detailed diff capabilities: + +- `Snapshot.diff()` returns per-file diffs showing what changed at each step +- `Snapshot.diffFull()` returns full before/after file content for detailed review + +In the **Agent Manager** (VS Code extension), these diffs are displayed in a dedicated `DiffPanel` and `FullScreenDiffView`, providing a visual interface for reviewing all file changes made during a session. + +{% /tab %} +{% /tabs %} ## Technical Implementation @@ -183,6 +230,13 @@ Checkpoints do not support nested Git repositories. The working directory must b Operations are queued to prevent concurrent Git operations that might corrupt repository state. This ensures that rapid checkpoint operations complete safely even when requested in quick succession. +### Limitations and Considerations + +- **Scope**: Checkpoints only capture changes made during active Kilo Code tasks +- **External changes**: Modifications made outside of tasks (manual edits, other tools) aren't included +- **Large files**: Very large binary files may impact performance +- **Unsaved work**: Restoration will overwrite any unsaved changes in your workspace + ## Git Installation Checkpoints require Git to be installed on your system. The implementation uses the `simple-git` library, which relies on Git command-line tools to create and manage shadow repositories. diff --git a/packages/kilo-docs/pages/code-with-ai/features/code-actions.md b/packages/kilo-docs/pages/code-with-ai/features/code-actions.md index c36e900e7f6..323b1fe7127 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/code-actions.md +++ b/packages/kilo-docs/pages/code-with-ai/features/code-actions.md @@ -7,6 +7,13 @@ description: "Quick code actions and refactoring with Kilo Code" Code Actions are a powerful feature of VS Code that provide quick fixes, refactorings, and other code-related suggestions directly within the editor. Kilo Code integrates with this system to offer AI-powered assistance for common coding tasks. +{% callout type="info" %} +Code Actions are a **VS Code extension feature** and are not available in the CLI/TUI. +{% /callout %} + +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ## What are Code Actions? Code Actions appear as a lightbulb icon (💡) in the editor gutter (the area to the left of the line numbers). They can also be accessed via the right-click context menu, or via keyboard shortcut. They are triggered when: @@ -90,4 +97,31 @@ You can customize the prompts used for each Code Action by modifying the "Suppor 3. **Edit the Prompts:** Modify the text in the text area for the prompt you want to customize. You can use placeholders like `${filePath}` and `${selectedText}` to include information about the current file and selection. 4. **Click "Done":** Save your changes. +{% /tab %} +{% tab label="VSCode" %} + +## Available Code Actions + +The new extension provides the same core code actions via the editor context menu and lightbulb: + +- **Add to Context:** Adds selected code (with file path and line numbers) to the active chat session. Keyboard shortcut: `Cmd+K Cmd+A` (Mac) or `Ctrl+K Ctrl+A` (Windows/Linux). +- **Explain Code:** Asks Kilo to explain the selected code. +- **Fix Code:** Asks Kilo to fix problems in the selected code. +- **Improve Code:** Asks Kilo to suggest improvements to the selected code. + +### Agent Manager Integration + +If the **Agent Manager** is active, code actions route to the current Agent Manager session rather than the sidebar chat. This allows code actions to work seamlessly within multi-session workflows. + +### Terminal Context Menu + +The new extension also adds code actions to the **terminal context menu**: + +- **Add Terminal Content:** Adds selected terminal output to the chat context. +- **Fix Command:** Asks Kilo to fix a failed terminal command. +- **Explain Command:** Asks Kilo to explain a terminal command or its output. + +{% /tab %} +{% /tabs %} + By using Kilo Code's Code Actions, you can quickly get AI-powered assistance directly within your coding workflow. This can save you time and help you write better code. diff --git a/packages/kilo-docs/pages/code-with-ai/features/git-commit-generation.md b/packages/kilo-docs/pages/code-with-ai/features/git-commit-generation.md index 31582101198..41fa60a17cd 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/git-commit-generation.md +++ b/packages/kilo-docs/pages/code-with-ai/features/git-commit-generation.md @@ -53,6 +53,9 @@ Common types include: ## Configuration +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ### Customizing the Commit Template You can customize how commit messages are generated by modifying the prompt template: @@ -81,6 +84,20 @@ You can configure which API profile to use for commit message generation: Consider creating a dedicated [API configuration profile](/docs/ai-providers) with a faster, more cost-effective model specifically for commit message generation. {% /callout %} +{% /tab %} +{% tab label="VSCode" %} + +The new extension provides the same **SCM button** in the VS Code Source Control panel. Clicking it generates a commit message using the CLI backend's `client.commitMessage.generate()` API. + +Configuration is handled through the extension's settings or the shared `kilo.json` config file. + +{% callout type="info" %} +Git commit message generation is a **VS Code extension feature**. It is not available in the CLI/TUI. +{% /callout %} + +{% /tab %} +{% /tabs %} + ## Best Practices ### Staging Strategy diff --git a/packages/kilo-docs/pages/code-with-ai/platforms/cli.md b/packages/kilo-docs/pages/code-with-ai/platforms/cli.md index 04d6ff8e2a8..f6e80b3e11d 100644 --- a/packages/kilo-docs/pages/code-with-ai/platforms/cli.md +++ b/packages/kilo-docs/pages/code-with-ai/platforms/cli.md @@ -1,6 +1,7 @@ --- title: "Kilo CLI" description: "Using Kilo Code from the command line" +platform: next --- {% callout type="warning" title="Version Notice" %} @@ -167,7 +168,7 @@ Review your code locally before pushing — catch issues early without waiting f Configuration is managed through: - `/connect` command for provider setup (interactive) -- Config files in **`~/.config/kilo/`**: the CLI (Kilo CLI 1.0 from [Kilo-Org/kilocode](https://github.com/Kilo-Org/kilocode)) merges `config.json`, `opencode.json`, and `opencode.jsonc`. Use **`opencode.json`** (or `opencode.jsonc`) for provider, model, permission, and **MCP** settings. Restart the CLI after editing. See [Using MCP in the CLI](/docs/automate/mcp/using-in-cli) for MCP config format. +- Config files in **`~/.config/kilo/`**: the CLI (Kilo CLI 1.0 from [Kilo-Org/kilocode](https://github.com/Kilo-Org/kilocode)) merges `config.json`, `opencode.json`, and `opencode.jsonc`. Use **`opencode.json`** (or `opencode.jsonc`) for provider, model, permission, and **MCP** settings. Restart the CLI after editing. See [Using MCP in Kilo Code](/docs/automate/mcp/using-in-kilo-code) for MCP config format. - `kilo auth` for credential management ## Slash Commands diff --git a/packages/kilo-docs/pages/code-with-ai/platforms/vscode.md b/packages/kilo-docs/pages/code-with-ai/platforms/vscode.md index a06044fe304..8604b5f96f3 100644 --- a/packages/kilo-docs/pages/code-with-ai/platforms/vscode.md +++ b/packages/kilo-docs/pages/code-with-ai/platforms/vscode.md @@ -5,6 +5,60 @@ description: "Using Kilo Code in Visual Studio Code" # VS Code Extension +Kilo Code is available as two VS Code extensions: the **VSCode (Legacy)** extension and the current **VSCode** version built on the Kilo CLI core. + +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ## Installation {% partial file="install-vscode.md" /%} + +## Key Features + +- **Sidebar chat** — AI-powered chat panel in the VS Code activity bar +- **[Autocomplete](/docs/code-with-ai/features/autocomplete)** — Inline code completions as you type +- **[Code Actions](/docs/code-with-ai/features/code-actions)** — Explain, fix, and improve code from the editor context menu +- **[Modes](/docs/code-with-ai/agents/using-modes)** — Code, Ask, Architect, Debug, Orchestrator, and Review modes +- **[Custom Modes](/docs/customize/custom-modes)** — Define custom modes with `.kilocodemodes` YAML files +- **[MCP](/docs/automate/mcp/overview)** — Connect to MCP servers for extended capabilities +- **[Agent Manager](/docs/automate/agent-manager)** — Multi-session orchestration with git worktree isolation +- **[Git Commit Generation](/docs/code-with-ai/features/git-commit-generation)** — AI-powered commit messages from the Source Control panel +- **[Context Mentions](/docs/code-with-ai/agents/context-mentions)** — Reference files, URLs, diagnostics, and git changes with `@` +- **[Checkpoints](/docs/code-with-ai/features/checkpoints)** — Git-based snapshots for undo/redo + +{% /tab %} +{% tab label="VSCode" %} + +## Installation + +1. Open VS Code +2. Go to Extensions (`Ctrl+Shift+X` / `Cmd+Shift+X`) +3. Search for "Kilo Code" +4. Click the dropdown arrow next to **Install** and select **Install Pre-Release Version** + +The extension bundles its own CLI binary and spawns `kilo serve` as a background process. All communication happens over HTTP + SSE. + +## Key Features + +Key features include: + +- **SolidJS-based UI** — Rebuilt sidebar with a modern component architecture +- **[JSONC config files](/docs/getting-started/settings)** — Portable settings in `kilo.json` instead of VS Code settings +- **[Granular permissions](/docs/getting-started/settings/auto-approving-actions)** — Per-tool permission rules with glob patterns +- **[Agents](/docs/code-with-ai/agents/using-modes)** — Customizable agents (`.kilo/agents/*.md`) replacing the modes system +- **[Agent Manager](/docs/automate/agent-manager)** — Enhanced with diff panel, multi-model comparison, PR import, and code review annotations +- **[Autocomplete](/docs/code-with-ai/features/autocomplete)** — FIM-based with Codestral, status bar cost tracking +- **[Workflows](/docs/customize/workflows)** — Repeatable prompt templates as `.md` files +- **[Skills](/docs/customize/skills)** — Load specialized domain knowledge from SKILL.md files +- **[Custom Subagents](/docs/customize/custom-subagents)** — Define specialized sub-agents for the `task` tool +- **Open in Tab** — Pop the chat out into a full editor tab +- **Sub-Agent Viewer** — Read-only panels for viewing child agent sessions +- **Legacy Migration** — Automatic migration wizard for VSCode extension settings + +## Shared Settings + +The extension shares its configuration with the CLI. Settings in `~/.config/kilo/kilo.json` (global) and `./kilo.json` (project) apply to both the CLI and the extension. + +{% /tab %} +{% /tabs %} From f1b606a23c1c090447994ffb09b8ab4c34e1c846 Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Tue, 24 Mar 2026 05:18:39 -0400 Subject: [PATCH 012/261] docs(kilo-docs): add platform tabs to customize pages Add VSCode (Pre-release) and CLI tabs to 7 customize pages: - custom-modes.md: Agents system, .md frontmatter format, config file format, examples, migration, troubleshooting (massive - 597 lines added) - custom-rules.md: .kilo/rules/ directory, instructions config key - custom-instructions.md: Tabbed instruction methods per platform - agents-md.md: Updated for new agent file format - skills.md: SKILL.md files, skill loading from .kilo/skills/ - context/kilocodeignore.md: Tabbed ignore file configuration - context/context-condensing.md: Tabbed context management Critical fix applied: - Permission YAML format corrected from action-as-key (allow: '*.md') to pattern-as-key ('*.md': 'allow') matching the actual config schema in config.ts:713 (PermissionObject = z.record(string, PermissionAction)) Part of the docs platform tabs effort (PR 5 of 8). Depends on #7497 for infrastructure. --- packages/kilo-docs/lib/nav/customize.ts | 5 +- .../kilo-docs/pages/customize/agents-md.md | 40 +- .../customize/context/codebase-indexing.md | 1 + .../customize/context/context-condensing.md | 101 ++- .../pages/customize/context/kilocodeignore.md | 108 +++- .../pages/customize/context/large-projects.md | 1 + .../pages/customize/custom-instructions.md | 158 ++++- .../kilo-docs/pages/customize/custom-modes.md | 597 +++++++++++++++++- .../kilo-docs/pages/customize/custom-rules.md | 233 ++++++- .../pages/customize/custom-subagents.md | 1 + packages/kilo-docs/pages/customize/skills.md | 250 ++++++-- .../kilo-docs/pages/customize/workflows.md | 1 + 12 files changed, 1409 insertions(+), 87 deletions(-) diff --git a/packages/kilo-docs/lib/nav/customize.ts b/packages/kilo-docs/lib/nav/customize.ts index ca3760e1b5f..7687bad119f 100644 --- a/packages/kilo-docs/lib/nav/customize.ts +++ b/packages/kilo-docs/lib/nav/customize.ts @@ -20,9 +20,10 @@ export const CustomizeNav: NavSection[] = [ { href: "/customize/custom-subagents", children: "Custom Subagents", + platform: "new", }, { href: "/customize/agents-md", children: "agents.md" }, - { href: "/customize/workflows", children: "Workflows" }, + { href: "/customize/workflows", children: "Workflows", platform: "new" }, { href: "/customize/skills", children: "Skills" }, { href: "/customize/prompt-engineering", @@ -36,6 +37,7 @@ export const CustomizeNav: NavSection[] = [ { href: "/customize/context/codebase-indexing", children: "Codebase Indexing", + platform: "legacy", }, { href: "/customize/context/context-condensing", @@ -48,6 +50,7 @@ export const CustomizeNav: NavSection[] = [ { href: "/customize/context/large-projects", children: "Large Projects", + platform: "legacy", }, ], }, diff --git a/packages/kilo-docs/pages/customize/agents-md.md b/packages/kilo-docs/pages/customize/agents-md.md index d451b5e7a7d..ef47a81316a 100644 --- a/packages/kilo-docs/pages/customize/agents-md.md +++ b/packages/kilo-docs/pages/customize/agents-md.md @@ -18,7 +18,7 @@ If you'd like to migrate your memory bank content to AGENTS.md: 1. Examine the contents in `.kilocode/rules/memory-bank/` 2. Move that content into your project's `AGENTS.md` file (or ask Kilo to do it for you) -{% /callout %} + {% /callout %} ## What is AGENTS.md? @@ -138,6 +138,9 @@ When you start a task in Kilo Code: ### Interaction with Other Rules +{% tabs %} +{% tab label="VSCode (Legacy)" %} + AGENTS.md works alongside Kilo Code's other configuration systems: | Feature | Scope | Location | Purpose | Priority | @@ -148,9 +151,28 @@ AGENTS.md works alongside Kilo Code's other configuration systems: | **[Global Custom Rules](/docs/customize/custom-rules)** | Global | `~/.kilocode/rules/` | Global Kilo Code rules | 4 | | **[Custom Instructions](/docs/customize/custom-instructions)** | Global | IDE settings | Personal preferences across all projects | 5 (Lowest) | +{% /tab %} +{% tab label="VSCode & CLI" %} + +In the new platform, AGENTS.md is loaded alongside other instruction sources. The CLI also supports `.claude/` and `.agents/` directories for compatibility with other tools. + +| Source | Scope | Location | Priority | +| ------------------------------------------------ | --------- | ----------------------------------------- | ---------------- | +| **Agent prompt** | Per-agent | `agent..prompt` in config | 1 (Highest) | +| **[Instructions](/docs/customize/custom-rules)** | Project | `instructions` key in project `kilo.json` | 2 | +| **AGENTS.md** | Project | `AGENTS.md` at project root | 3 | +| **[Instructions](/docs/customize/custom-rules)** | Global | `instructions` key in global `kilo.json` | 4 | +| **[Skills](/docs/customize/skills)** | Both | `.kilo/skills/`, config `skills` key | Loaded on demand | + +{% /tab %} +{% /tabs %} + ### Enabling/Disabling AGENTS.md -AGENTS.md support is **enabled by default** in Kilo Code. To disable it, edit `settings.json`: +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +AGENTS.md support is **enabled by default**. To disable it, edit `settings.json`: ```json { @@ -158,6 +180,20 @@ AGENTS.md support is **enabled by default** in Kilo Code. To disable it, edit `s } ``` +{% /tab %} +{% tab label="VSCode & CLI" %} + +AGENTS.md is loaded automatically. To disable external skill directories (`.claude/skills/`, `.agents/skills/`), set the environment variable: + +```bash +export KILO_DISABLE_EXTERNAL_SKILLS=true +``` + +AGENTS.md itself cannot be individually disabled — it is always loaded if present. To override its instructions, use higher-priority sources like the `instructions` config key or agent-specific prompts. + +{% /tab %} +{% /tabs %} + ## Related Features - **[Custom Rules](/docs/customize/custom-rules)** - Kilo Code-specific rules with more control diff --git a/packages/kilo-docs/pages/customize/context/codebase-indexing.md b/packages/kilo-docs/pages/customize/context/codebase-indexing.md index ff6e1312f01..3f38b01a76d 100644 --- a/packages/kilo-docs/pages/customize/context/codebase-indexing.md +++ b/packages/kilo-docs/pages/customize/context/codebase-indexing.md @@ -1,6 +1,7 @@ --- title: "Codebase Indexing" description: "Index your codebase for improved AI understanding" +platform: legacy --- # Codebase Indexing diff --git a/packages/kilo-docs/pages/customize/context/context-condensing.md b/packages/kilo-docs/pages/customize/context/context-condensing.md index 9ab1a2d2a8b..0dfa3136470 100644 --- a/packages/kilo-docs/pages/customize/context/context-condensing.md +++ b/packages/kilo-docs/pages/customize/context/context-condensing.md @@ -17,9 +17,12 @@ Every AI model has a maximum context window - a limit on how much text it can pr - Higher API costs due to increased token usage - Eventually hitting the context limit and being unable to continue +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ## The Solution: Intelligent Condensing -Context Condensing solves this problem by creating a concise summary of your conversation that captures: +**Context Condensing** solves this problem by creating a concise summary of your conversation that captures: - The original task or goal - Key decisions made during the session @@ -63,20 +66,6 @@ Context Condensing uses an AI model to generate summaries. You can configure whi You can configure context condensing thresholds and behavior on a per-profile basis, allowing different settings for different projects or use cases. -## Best Practices - -### When to Condense - -- **Long sessions**: If you've been working for an extended period on a complex task -- **Before major transitions**: When switching to a different aspect of your project -- **When prompted**: When Kilo Code suggests condensing due to context limits - -### Maintaining Context Quality - -- **Be specific in your initial task**: A clear task description helps create better summaries -- **Use AGENTS.md**: Combine with [AGENTS.md](/docs/customize/agents-md) for persistent project context that doesn't need to be condensed -- **Review the summary**: After condensing, the summary is visible in your chat history - ## Troubleshooting ### Context Condensing Error @@ -95,6 +84,88 @@ If the condensed summary doesn't capture important details: - Use clear, specific language when describing your tasks - Important context can be reinforced after condensing by reminding Kilo Code of key details +{% /tab %} +{% tab label="VSCode & CLI" %} + +## The Solution: Auto-Compaction + +The new platform uses a **Compaction** system to manage context automatically. When your conversation approaches the token limit, compaction kicks in and produces a structured summary that captures: + +- The overall goal of the session +- Key discoveries made along the way +- What has been accomplished so far +- Files that were modified + +This summary replaces the earlier conversation history, freeing up context window space while maintaining continuity in your work. + +## How Compaction Works + +### Automatic Compaction + +Compaction triggers automatically when the conversation reaches the `usableWindow` token threshold. The full conversation history is sent to a dedicated **compaction agent**, which produces a structured summary. This happens in the background without interrupting your workflow. + +### Context Pruning + +In addition to compaction, the system can **prune** old tool outputs to reclaim context space incrementally. Tool results older than a 40,000-token recency window are replaced with `"[Old tool result content cleared]"`. This is a lighter-weight mechanism that runs alongside full compaction. + +### Manual Compaction + +You can also trigger compaction manually: + +- **CLI TUI**: Press `c` to compact the current session +- **Extension Webview**: Send a `CompactRequest` message to trigger compaction + +{% callout type="info" %} +There is no `/condense` chat command on the new platform. Use the keybinding or message-based invocation instead. +{% /callout %} + +### The Compaction Process + +When compaction is triggered: + +1. **Threshold Check**: The system detects that context usage has reached the `usableWindow` limit +2. **Agent Summarization**: The full conversation history is sent to a dedicated compaction agent +3. **Structured Summary**: The agent produces a summary covering the goal, discoveries, accomplishments, and modified files +4. **Replacement**: The detailed history is replaced with the compacted summary +5. **Continuation**: You continue working with the freed-up context space + +## Configuration Options + +Compaction is configured in your `kilo.json` file: + +```jsonc +{ + "compaction": { + "auto": true, // Enable or disable automatic compaction + "reserved": 4096, // Number of tokens to reserve (keep free) after compaction + "prune": true, // Enable pruning of old tool outputs beyond the recency window + }, +} +``` + +| Option | Type | Description | +| --------------------- | ------- | ------------------------------------------------------------------------ | +| `compaction.auto` | boolean | Enable or disable automatic compaction when the context threshold is hit | +| `compaction.reserved` | number | Number of tokens to reserve after compaction | +| `compaction.prune` | boolean | Enable pruning of old tool outputs outside the 40K token recency window | + +{% /tab %} +{% /tabs %} + +## Best Practices + +### When to Condense + +- **Long sessions**: If you've been working for an extended period on a complex task +- **Before major transitions**: When switching to a different aspect of your project +- **When prompted**: When Kilo Code suggests condensing or compaction due to context limits + +### Maintaining Context Quality + +- **Be specific in your initial task**: A clear task description helps create better summaries +- **Use AGENTS.md**: Combine with [AGENTS.md](/docs/customize/agents-md) for persistent project context that doesn't need to be condensed +- **Review the summary**: After condensing or compaction, the summary is visible in your chat history + ## Related Features - [AGENTS.md](/docs/customize/agents-md) - Persistent context storage across sessions diff --git a/packages/kilo-docs/pages/customize/context/kilocodeignore.md b/packages/kilo-docs/pages/customize/context/kilocodeignore.md index c929aab46ff..5000534b31e 100644 --- a/packages/kilo-docs/pages/customize/context/kilocodeignore.md +++ b/packages/kilo-docs/pages/customize/context/kilocodeignore.md @@ -13,6 +13,9 @@ If no `.kilocodeignore` file exists, Kilo Code can access all files in the works ## Quick Start +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. Create a `.kilocodeignore` file at the root of your project. 2. Add patterns for files or folders you want Kilo Code to avoid. 3. Save the file. Kilo Code will pick up the changes automatically. @@ -34,6 +37,35 @@ coverage/ !secrets/README.md ``` +{% /tab %} +{% tab label="VSCode & CLI" %} + +The primary mechanism for controlling file access is the **permission system** in `kilo.json`. You define tool-level permissions with glob patterns: + +```json +{ + "permission": { + "read": { "*.env": "deny", "*": "allow" }, + "edit": { "dist/**": "deny", "*": "allow" } + } +} +``` + +If you have an existing `.kilocodeignore` file, it is still supported. The **IgnoreMigrator** automatically converts `.kilocodeignore` patterns into permission `deny` rules on `read` and `edit` tools, so your existing rules continue to work without manual changes. + +You can also exclude paths from the file watcher separately using `config.watcher.ignore`: + +```json +{ + "watcher": { + "ignore": ["tmp/**", "logs/**"] + } +} +``` + +{% /tab %} +{% /tabs %} + ## Pattern Rules `.kilocodeignore` follows the same rules as `.gitignore`: @@ -47,6 +79,9 @@ Patterns are evaluated relative to the workspace root. ## What It Affects +{% tabs %} +{% tab label="VSCode (Legacy)" %} + Kilo Code checks `.kilocodeignore` before accessing files in tools like: - [`read_file`](/docs/automate/tools/read-file) @@ -58,17 +93,82 @@ Kilo Code checks `.kilocodeignore` before accessing files in tools like: If a file is blocked, Kilo Code will return an "access denied" message and suggest updating your `.kilocodeignore` rules. -## Visibility in Lists +{% /tab %} +{% tab label="VSCode & CLI" %} + +File access is controlled through **permission-based access control**. Each tool (`read`, `edit`, `glob`, `grep`, `write`, `bash`, etc.) has its own permission rules evaluated against glob patterns. + +In addition to your explicit permission rules: + +- **Hardcoded directory ignores** — 27 directories are always skipped (e.g. `node_modules`, `.git`, `dist`, `build`, `.cache`, `__pycache__`, `vendor`, and others). +- **Hardcoded file pattern ignores** — 11 file patterns are always skipped (e.g. lock files, binary artifacts). +- **`.gitignore` and `.ignore` files** are also respected when listing and searching files. + +If a file is denied by a permission rule, the tool will report that access was blocked. + +{% /tab %} +{% /tabs %} + +## Configuration Details + +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +### Visibility in Lists By default, ignored files are hidden from file lists. You can show them with a lock icon by enabling: Settings -> Context -> **Show .kilocodeignore'd files in lists and searches** +{% /tab %} +{% tab label="VSCode & CLI" %} + +### Permission Rules + +Permission rules are defined per-tool in `kilo.json`. Patterns are evaluated in order — the last matching rule wins: + +```json +{ + "permission": { + "read": { + "*.env": "deny", + "secrets/**": "deny", + "*": "allow" + }, + "edit": { + "dist/**": "deny", + "*.lock": "deny", + "*": "allow" + } + } +} +``` + +### Migrating from .kilocodeignore + +If you already have a `.kilocodeignore` file, you don't need to do anything — the IgnoreMigrator reads your existing patterns and applies them as `deny` rules on `read` and `edit` tools automatically. You can optionally move your rules into `kilo.json` for more granular control (e.g. denying edits but allowing reads). + +### File Watcher Exclusions + +The `config.watcher.ignore` setting controls which paths the file watcher skips. This is separate from tool permissions and only affects change detection: + +```json +{ + "watcher": { + "ignore": ["tmp/**", "logs/**", ".build/**"] + } +} +``` + +{% /tab %} +{% /tabs %} + ## Checkpoints vs .kilocodeignore -Checkpoint tracking is separate from file access rules. Files blocked by `.kilocodeignore` can still be checkpointed if they are not excluded by `.gitignore`. See the [Checkpoints](/docs/code-with-ai/features/checkpoints) documentation for details. +Checkpoint tracking is separate from file access rules. Files blocked by `.kilocodeignore` or permission rules can still be checkpointed if they are not excluded by `.gitignore`. See the [Checkpoints](/docs/code-with-ai/features/checkpoints) documentation for details. ## Troubleshooting -- **Kilo can't access a file you want:** Remove or narrow the matching rule in `.kilocodeignore`. -- **A file still appears in lists:** Check the setting that shows ignored files in lists and searches. +- **Kilo can't access a file you want:** Remove or narrow the matching rule in `.kilocodeignore` (classic) or adjust the permission rules in `kilo.json` (new extension & CLI). +- **A file still appears in lists:** In the classic extension, check the setting that shows ignored files in lists and searches. In the new extension & CLI, verify your permission and watcher ignore configuration. +- **`.kilocodeignore` patterns not working in the new platform:** Ensure the file is at the workspace root. The IgnoreMigrator reads it automatically — check that your patterns use valid `.gitignore` syntax. diff --git a/packages/kilo-docs/pages/customize/context/large-projects.md b/packages/kilo-docs/pages/customize/context/large-projects.md index a0aab196f0a..101fb1621b6 100644 --- a/packages/kilo-docs/pages/customize/context/large-projects.md +++ b/packages/kilo-docs/pages/customize/context/large-projects.md @@ -1,6 +1,7 @@ --- title: "Large Projects" description: "Best practices for using Kilo Code with large codebases" +platform: legacy --- # Working with Large Projects diff --git a/packages/kilo-docs/pages/customize/custom-instructions.md b/packages/kilo-docs/pages/customize/custom-instructions.md index b7ea7b7d8fb..4682608ba1b 100644 --- a/packages/kilo-docs/pages/customize/custom-instructions.md +++ b/packages/kilo-docs/pages/customize/custom-instructions.md @@ -5,18 +5,21 @@ description: "Provide custom instructions to guide Kilo Code" # Custom Instructions -Custom Instructions allow you to personalize how Kilo Code behaves, providing specific guidance that shapes responses, coding style, and decision-making processes. +Custom Instructions allow you to personalize how Kilo Code behaves, providing specific guidance that shapes responses, coding style, and decision-making processes. Both the **VSCode** and **VSCode & CLI** versions support custom instructions, though the mechanisms differ. ## What Are Custom Instructions? Custom Instructions define specific Extension behaviors, preferences, and constraints beyond Kilo's basic role definition. Examples include coding style, documentation standards, testing requirements, and workflow guidelines. +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +## Setting Custom Instructions + {% callout type="info" title="Custom Instructions vs Rules" %} Custom Instructions are IDE-wide and are applied across all workspaces and maintain your preferences regardless of which project you're working on. Unlike Instructions, [Custom Rules](/docs/customize/custom-rules) are project specific and allow you to setup workspace-based ruleset. {% /callout %} -## Setting Custom Instructions - **How to set them:** {% image src="/docs/img/custom-instructions/custom-instructions.png" alt="Kilo Code Modes tab showing global custom instructions interface" width="600" caption="Kilo Code Modes tab showing global custom instructions interface" /%} @@ -37,8 +40,9 @@ Mode-specific instructions can be set using the Modes Tab * **Save Changes:** Click "Done" to save your changes {% callout type="info" title="Global Mode Rules" %} - If the mode itself is global (not workspace-specific), any custom instructions you set for it will also apply globally for that mode across all workspaces. - {% /callout %} + +If the mode itself is global (not workspace-specific), any custom instructions you set for it will also apply globally for that mode across all workspaces. +{% /callout %} ## Mode-Specific Instructions from Files @@ -51,6 +55,150 @@ For version-controlled mode instructions, use the mode rules file paths document Older naming like `.clinerules-{mode-slug}` is not the recommended path for current Kilo mode-specific instructions. {% /callout %} +{% /tab %} +{% tab label="VSCode" %} + +The new extension provides multiple layers of instruction configuration — from per-agent prompts in the Settings UI to auto-discovered files in your project and global config. + +## Per-Agent Prompts + +Each agent can have its own custom prompt configured through the settings UI: + +1. Open **Settings → Agent Behaviour → Agents** subtab +2. Select the agent you want to customize +3. Enter your instructions in the markdown text area under the agent's `prompt` field +4. Save your changes + +These prompts are injected into the agent's system prompt and apply across all sessions using that agent. + +## Instruction Files + +Kilo automatically discovers instruction files at your project root and in parent directories (via `findUp`). The following filenames are recognized: + +- **`AGENTS.md`** — The primary instruction file for Kilo +- **`CLAUDE.md`** — Also supported for compatibility +- **`CONTEXT.md`** — Additional project context + +Place any of these files at your project root to provide project-wide instructions to the agent. + +### Global Instructions + +For instructions that apply across all your projects, place an `AGENTS.md` file in your global config directory: + +- **Kilo:** `~/.config/kilo/AGENTS.md` +- **Claude-compatible:** `~/.claude/CLAUDE.md` + +Global instructions are loaded before project-level instructions and apply to every session. + +### Per-Directory Instructions + +You can place `AGENTS.md` files in any subdirectory of your project. These are loaded dynamically — when the agent's Read tool accesses a file in that directory, the corresponding `AGENTS.md` is discovered and its contents are injected into the conversation as `` tags. + +This is useful for providing context-specific guidance for different parts of a monorepo or project. + +## Additional Instruction Sources + +The `config.instructions` setting accepts an array of paths, globs, or URLs pointing to additional instruction files. You can manage these in **Settings → Agent Behaviour → Rules** subtab. + +```yaml +# Examples of instruction sources +instructions: + - ./docs/coding-standards.md + - ./teams/frontend-rules.md + - https://example.com/team-instructions.md +``` + +{% callout type="info" title="URL-Based Instructions" %} +URL-based instruction sources are fetched at session start with a 5-second timeout. If the URL is unreachable, the instruction source is silently skipped. +{% /callout %} + +## Legacy `.kilocoderules` Support + +If your project contains `.kilocoderules` files from the VSCode extension, these are still loaded via auto-migration. However, migrating to `AGENTS.md` is recommended for new projects. + +{% /tab %} +{% tab label="CLI" %} + +The CLI provides multiple layers of instruction configuration — from per-agent prompts in agent definition files to auto-discovered files in your project and global config. + +## Per-Agent Prompts + +Each agent can have its own custom prompt defined in its `.md` file (the markdown body) or via the `agent..prompt` key in `kilo.json`: + +```jsonc +// kilo.json +{ + "agent": { + "code": { + "prompt": "You are a Python specialist. Follow PEP8 strictly.", + }, + }, +} +``` + +Or as the markdown body in `.kilo/agents/code.md`: + +```markdown +--- +description: Python specialist +--- + +You are a Python specialist. Follow PEP8 strictly. +``` + +These prompts are injected into the agent's system prompt and apply across all sessions using that agent. + +## Instruction Files + +Kilo automatically discovers instruction files at your project root and in parent directories (via `findUp`). The following filenames are recognized: + +- **`AGENTS.md`** — The primary instruction file for Kilo +- **`CLAUDE.md`** — Also supported for compatibility +- **`CONTEXT.md`** — Additional project context + +Place any of these files at your project root to provide project-wide instructions to the agent. + +### Global Instructions + +For instructions that apply across all your projects, place an `AGENTS.md` file in your global config directory: + +- **Kilo:** `~/.config/kilo/AGENTS.md` +- **Claude-compatible:** `~/.claude/CLAUDE.md` + +Global instructions are loaded before project-level instructions and apply to every session. + +### Per-Directory Instructions + +You can place `AGENTS.md` files in any subdirectory of your project. These are loaded dynamically — when the agent's Read tool accesses a file in that directory, the corresponding `AGENTS.md` is discovered and its contents are injected into the conversation as `` tags. + +This is useful for providing context-specific guidance for different parts of a monorepo or project. + +## Additional Instruction Sources + +The `config.instructions` setting accepts an array of paths, globs, or URLs pointing to additional instruction files. Configure these in your `kilo.json`: + +```jsonc +// kilo.json +{ + "instructions": [ + "./docs/coding-standards.md", + "./teams/frontend-rules.md", + "https://example.com/team-instructions.md", + ], +} +``` + +{% callout type="info" title="URL-Based Instructions" %} +URL-based instruction sources are fetched at session start with a 5-second timeout. If the URL is unreachable, the instruction source is silently skipped. +{% /callout %} + +## Legacy `.kilocoderules` Support + +If your project contains `.kilocoderules` files from the VSCode extension, these are still loaded via auto-migration. However, migrating to `AGENTS.md` is recommended for new projects. + +{% /tab %} +{% /tabs %} + ## Related Features - [Custom Modes](/docs/customize/custom-modes) diff --git a/packages/kilo-docs/pages/customize/custom-modes.md b/packages/kilo-docs/pages/customize/custom-modes.md index 86bcc17a2c4..7713e4e2c39 100644 --- a/packages/kilo-docs/pages/customize/custom-modes.md +++ b/packages/kilo-docs/pages/customize/custom-modes.md @@ -7,10 +7,6 @@ description: "Create and configure custom modes in Kilo Code" Kilo Code allows you to create **custom modes** to tailor Kilo's behavior to specific tasks or workflows. Custom modes can be either **global** (available across all projects) or **project-specific** (defined within a single project). -## Sticky Models for Efficient Workflow - -Each mode—including custom ones—features **Sticky Models**. This means Kilo Code automatically remembers and selects the last model you used with a particular mode. This lets you assign different preferred models to different tasks without constant reconfiguration, as Kilo switches between models when you change modes. - ## Why Use Custom Modes? - **Specialization:** Create modes optimized for specific tasks, like "Documentation Writer," "Test Engineer," or "Refactoring Expert" @@ -18,6 +14,13 @@ Each mode—including custom ones—features **Sticky Models**. This means Kilo - **Experimentation:** Safely experiment with different prompts and configurations without affecting other modes - **Team Collaboration:** Share custom modes with your team to standardize workflows +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +## Sticky Models for Efficient Workflow + +Each mode—including custom ones—features **Sticky Models**. This means Kilo Code automatically remembers and selects the last model you used with a particular mode. This lets you assign different preferred models to different tasks without constant reconfiguration, as Kilo switches between models when you change modes. + {% callout type="tip" %} **Keep custom modes on track:** Limit the types of files that they're allowed to edit using the `fileRegex` option in the `groups` configuration. This prevents modes from accidentally modifying files outside their intended scope. {% /callout %} @@ -135,8 +138,6 @@ If you see both YAML and JSON mode files, this is usually from legacy configurat YAML is now the preferred format for defining custom modes due to better readability, comment support, and cleaner multi-line strings. -### YAML Example - ```yaml customModes: - slug: docs-writer @@ -388,9 +389,456 @@ customModes: - command ``` +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +In the new extension, custom behavioral profiles are called **agents** instead of modes. Agents are defined as Markdown files with YAML frontmatter or as entries in the `agent` key of your config file. + +## What's Included in a Custom Agent? + +| Property | Description | +| --------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| **name** (filename) | The agent's identifier, derived from the `.md` filename (e.g., `docs-writer.md` creates an agent named `docs-writer`) | +| **description** | A short summary displayed in the agent picker and used by the orchestrator for delegation | +| **model** | Pin a specific model in `provider/model` format (e.g., `anthropic/claude-sonnet-4-20250514`) | +| **prompt** (markdown body) | The system prompt text — the markdown body of the file, injected into the agent's system prompt | +| **mode** | Role classification: `primary` (user-selectable), `subagent` (only invoked by other agents), or `all` (both) | +| **permission** | Per-agent permission overrides controlling which tools the agent can use (e.g., deny `edit`, `bash`) | +| **color** | Hex color (`#FF5733`) or theme keyword (`primary`, `accent`, `warning`, etc.) for the agent picker UI | +| **steps** | Maximum agentic iterations before forcing a text-only response | +| **temperature** / **top_p** | Sampling parameters for the agent's model | +| **variant** | Default model variant | +| **hidden** | If `true`, the agent is hidden from the UI (only meaningful for subagents) | +| **disable** | If `true`, removes the agent entirely | + +## Methods for Creating and Configuring Agents + +### 1. Ask Kilo! (Recommended) + +Ask Kilo to create an agent for you: + +``` +Create a new agent called "docs-writer" that can only read files and edit Markdown files. +``` + +Kilo will generate the agent definition and write it to `.kilo/agent/` in your project. + +### 2. Using the Settings UI + +You can manage agents through the **Settings → Agent Behaviour → Agents** subtab in the extension. This lets you view, create, and edit agent configurations — including the agent's prompt, model, permissions, and other properties. + +### 3. Markdown Files with YAML Frontmatter + +Create `.md` files in any of these directories: + +``` +.kilo/agents/my-agent.md +.kilo/agent/my-agent.md +.opencode/agents/my-agent.md +``` + +For global agents, place files in your global config directory: + +``` +~/.config/kilo/agent/my-agent.md +``` + +The **filename** (minus `.md`) becomes the agent name. Nested directories create namespaced names (e.g., `agents/backend/sql.md` becomes agent `backend/sql`). + +**Example agent file** (`.kilo/agents/docs-writer.md`): + +```markdown +--- +description: Specialized for writing and editing technical documentation +mode: primary +color: "#10B981" +permission: + edit: + "*.md": "allow" + "*": "deny" + bash: deny +--- + +You are a technical documentation specialist. Your expertise includes: + +- Writing clear, well-structured documentation +- Following markdown best practices +- Creating helpful code examples + +Focus on clarity and completeness. Only edit Markdown files. +``` + +### 4. Config File (`kilo.json`) + +Define agents under the `agent` key in your project's `kilo.json` (or `opencode.jsonc`): + +```jsonc +{ + "agent": { + "docs-writer": { + "description": "Specialized for writing and editing technical documentation", + "mode": "primary", + "color": "#10B981", + "prompt": "You are a technical documentation specialist...", + "permission": { + "edit": "deny", + "bash": "deny", + }, + }, + // Override a built-in agent + "code": { + "model": "anthropic/claude-sonnet-4-20250514", + "temperature": 0.3, + }, + }, +} +``` + +## Agent Property Reference + +### `mode` + +Controls where the agent appears: + +| Value | Behavior | +| ---------- | -------------------------------------------------------------------------------------- | +| `primary` | Shown in the agent picker — the user can select it directly | +| `subagent` | Only invokable by other agents via the `task` tool | +| `all` | Available both as a top-level pick and as a subagent (default for user-defined agents) | + +### `permission` + +An ordered set of rules controlling tool access. Permissions support three actions: `allow`, `deny`, and `ask` (prompt the user). You can use glob patterns to scope rules to specific files or commands: + +```yaml +permission: + edit: + "*.md": "allow" + "*": "deny" + bash: deny + read: allow +``` + +Known permission types include: `read`, `edit`, `bash`, `glob`, `grep`, `list`, `task`, `webfetch`, `websearch`, `codesearch`, `todowrite`, `todoread`, and more. + +### `model` + +Pin a specific model using the `provider/model` format: + +```yaml +model: anthropic/claude-sonnet-4-20250514 +``` + +### `steps` + +Limits the number of agentic iterations (tool call rounds) before the agent is forced to respond with text only. Useful for preventing runaway agents: + +```yaml +steps: 25 +``` + +## Configuration Precedence + +Agent configurations merge from lowest to highest priority: + +1. Built-in (native) agent defaults +2. Global config (`~/.config/kilo/kilo.json`) +3. Project config (`kilo.json` at project root) +4. `.kilo/` / `.opencode/` directory configs and agent `.md` files +5. Environment variable overrides (`KILO_CONFIG_CONTENT`) + +When the same agent name appears at multiple levels, properties are merged (not replaced wholesale), so you can override just a model or temperature without redefining the entire agent. + +## Overriding Built-in Agents + +Override any built-in agent (**code**, **plan**, **debug**, **ask**, **orchestrator**, **explore**, **general**) by defining an agent with the same name: + +```jsonc +// kilo.json — override the built-in "code" agent +{ + "agent": { + "code": { + "model": "openai/gpt-4o", + "temperature": 0.2, + "permission": { + "edit": { + "*.py": "allow", + "*": "deny", + }, + }, + }, + }, +} +``` + +Or as a `.md` file (`.kilo/agents/code.md`): + +```markdown +--- +model: openai/gpt-4o +temperature: 0.2 +permission: + edit: + "*.py": "allow" + "*": "deny" +--- + +You are a Python specialist. Only edit Python files. +``` + +## Migration from VSCode Extension Modes + +If you have existing `.kilocodemodes` or `custom_modes.yaml` files from the VSCode extension, the new extension automatically migrates them on startup. The migration converts: + +- `slug` to the agent name (key) +- `roleDefinition` + `customInstructions` to `prompt` +- `groups` (e.g., `["read", "edit", "browser"]`) to `permission` rules +- `whenToUse` / `description` to `description` +- Mode is set to `primary` + +Built-in mode slugs (`code`, `ask`, `debug`, `orchestrator`) are skipped since they have native agent equivalents. + +{% /tab %} +{% tab label="CLI" %} + +In the CLI, custom behavioral profiles are called **agents** instead of modes. Agents are defined as Markdown files with YAML frontmatter or as entries in the `agent` key of your config file. + +## What's Included in a Custom Agent? + +| Property | Description | +| --------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| **name** (filename) | The agent's identifier, derived from the `.md` filename (e.g., `docs-writer.md` creates an agent named `docs-writer`) | +| **description** | A short summary displayed in the agent picker and used by the orchestrator for delegation | +| **model** | Pin a specific model in `provider/model` format (e.g., `anthropic/claude-sonnet-4-20250514`) | +| **prompt** (markdown body) | The system prompt text — the markdown body of the file, injected into the agent's system prompt | +| **mode** | Role classification: `primary` (user-selectable), `subagent` (only invoked by other agents), or `all` (both) | +| **permission** | Per-agent permission overrides controlling which tools the agent can use (e.g., deny `edit`, `bash`) | +| **color** | Hex color (`#FF5733`) or theme keyword (`primary`, `accent`, `warning`, etc.) for the agent picker UI | +| **steps** | Maximum agentic iterations before forcing a text-only response | +| **temperature** / **top_p** | Sampling parameters for the agent's model | +| **variant** | Default model variant | +| **hidden** | If `true`, the agent is hidden from the UI (only meaningful for subagents) | +| **disable** | If `true`, removes the agent entirely | + +## Methods for Creating and Configuring Agents + +### 1. Ask Kilo! (Recommended) + +Ask Kilo to create an agent for you: + +``` +Create a new agent called "docs-writer" that can only read files and edit Markdown files. +``` + +Kilo will generate the agent definition and write it to `.kilo/agent/` in your project. + +### 2. Using `kilo agent create` + +The CLI provides an interactive command: + +```bash +kilo agent create +``` + +This walks you through selecting a description, mode, and tools, then uses an LLM to generate the agent's system prompt and writes a `.md` file with YAML frontmatter. + +### 3. Markdown Files with YAML Frontmatter + +Create `.md` files in any of these directories: + +``` +.kilo/agents/my-agent.md +.kilo/agent/my-agent.md +.opencode/agents/my-agent.md +``` + +For global agents, place files in your global config directory: + +``` +~/.config/kilo/agent/my-agent.md +``` + +The **filename** (minus `.md`) becomes the agent name. Nested directories create namespaced names (e.g., `agents/backend/sql.md` becomes agent `backend/sql`). + +**Example agent file** (`.kilo/agents/docs-writer.md`): + +```markdown +--- +description: Specialized for writing and editing technical documentation +mode: primary +color: "#10B981" +permission: + edit: + "*.md": "allow" + "*": "deny" + bash: deny +--- + +You are a technical documentation specialist. Your expertise includes: + +- Writing clear, well-structured documentation +- Following markdown best practices +- Creating helpful code examples + +Focus on clarity and completeness. Only edit Markdown files. +``` + +### 4. Config File (`kilo.json`) + +Define agents under the `agent` key in your project's `kilo.json` (or `opencode.jsonc`): + +```jsonc +{ + "agent": { + "docs-writer": { + "description": "Specialized for writing and editing technical documentation", + "mode": "primary", + "color": "#10B981", + "prompt": "You are a technical documentation specialist...", + "permission": { + "edit": "deny", + "bash": "deny", + }, + }, + // Override a built-in agent + "code": { + "model": "anthropic/claude-sonnet-4-20250514", + "temperature": 0.3, + }, + }, +} +``` + +## Agent Property Reference + +### `mode` + +Controls where the agent appears: + +| Value | Behavior | +| ---------- | -------------------------------------------------------------------------------------- | +| `primary` | Shown in the agent picker — the user can select it directly | +| `subagent` | Only invokable by other agents via the `task` tool | +| `all` | Available both as a top-level pick and as a subagent (default for user-defined agents) | + +### `permission` + +An ordered set of rules controlling tool access. Permissions support three actions: `allow`, `deny`, and `ask` (prompt the user). You can use glob patterns to scope rules to specific files or commands: + +```yaml +permission: + edit: + "*.md": "allow" + "*": "deny" + bash: deny + read: allow +``` + +Known permission types include: `read`, `edit`, `bash`, `glob`, `grep`, `list`, `task`, `webfetch`, `websearch`, `codesearch`, `todowrite`, `todoread`, and more. + +### `model` + +Pin a specific model using the `provider/model` format: + +```yaml +model: anthropic/claude-sonnet-4-20250514 +``` + +### `steps` + +Limits the number of agentic iterations (tool call rounds) before the agent is forced to respond with text only. Useful for preventing runaway agents: + +```yaml +steps: 25 +``` + +## Configuration Precedence + +Agent configurations merge from lowest to highest priority: + +1. Built-in (native) agent defaults +2. Global config (`~/.config/kilo/kilo.json`) +3. Project config (`kilo.json` at project root) +4. `.kilo/` / `.opencode/` directory configs and agent `.md` files +5. Environment variable overrides (`KILO_CONFIG_CONTENT`) + +When the same agent name appears at multiple levels, properties are merged (not replaced wholesale), so you can override just a model or temperature without redefining the entire agent. + +## Overriding Built-in Agents + +Override any built-in agent (**code**, **plan**, **debug**, **ask**, **orchestrator**, **explore**, **general**) by defining an agent with the same name: + +```jsonc +// kilo.json — override the built-in "code" agent +{ + "agent": { + "code": { + "model": "openai/gpt-4o", + "temperature": 0.2, + "permission": { + "edit": { + "*.py": "allow", + "*": "deny", + }, + }, + }, + }, +} +``` + +Or as a `.md` file (`.kilo/agents/code.md`): + +```markdown +--- +model: openai/gpt-4o +temperature: 0.2 +permission: + edit: + "*.py": "allow" + "*": "deny" +--- + +You are a Python specialist. Only edit Python files. +``` + +## Migration from VSCode Extension Modes + +If you have existing `.kilocodemodes` or `custom_modes.yaml` files from the VSCode extension, the CLI automatically migrates them on startup. The migration converts: + +- `slug` to the agent name (key) +- `roleDefinition` + `customInstructions` to `prompt` +- `groups` (e.g., `["read", "edit", "browser"]`) to `permission` rules +- `whenToUse` / `description` to `description` +- Mode is set to `primary` + +Built-in mode slugs (`code`, `ask`, `debug`, `orchestrator`) are skipped since they have native agent equivalents. + +{% /tab %} +{% /tabs %} + ## Understanding Regex in Custom Modes -Regular expressions (`fileRegex`) offer fine-grained control over file editing permissions. +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +Regular expressions (`fileRegex`) in the **VSCode** version offer fine-grained control over file editing permissions within tool groups. + +{% /tab %} +{% tab label="VSCode & CLI" %} + +The new extension and CLI use **permission rules with glob patterns** instead of regex. Permissions are defined per-tool (e.g., `edit`, `bash`, `read`) and support `allow`, `deny`, and `ask` actions with glob matching: + +```yaml +permission: + edit: + "*.md": "allow" + "*": "deny" +``` + +The **VSCode** version's `fileRegex` approach is automatically converted to permission rules during migration. + +{% /tab %} +{% /tabs %} {% callout type="tip" %} @@ -445,6 +893,9 @@ When a mode attempts to edit a file that doesn't match its `fileRegex` pattern, ## Example Configurations +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ### Basic Documentation Writer (YAML) ```yaml @@ -498,8 +949,101 @@ customModes: - browser ``` +{% /tab %} +{% tab label="VSCode & CLI" %} + +### Basic Documentation Writer (`.kilo/agents/docs-writer.md`) + +```markdown +--- +description: Specialized for writing and editing technical documentation +mode: primary +color: "#10B981" +permission: + edit: + "*.md": "allow" + "*": "deny" + bash: deny +--- + +You are a technical writer specializing in clear documentation. +Focus on clear explanations and examples. +``` + +### Test Engineer (`.kilo/agents/test-engineer.md`) + +```markdown +--- +description: Focused on writing and maintaining test suites +mode: primary +color: "#F59E0B" +permission: + edit: + "*.{test,spec}.{js,ts}": "allow" + "*": "deny" +--- + +You are a test engineer focused on code quality. +Use for writing tests, debugging test failures, and improving test coverage. +``` + +### Security Reviewer (`.kilo/agents/security-review.md`) + +```markdown +--- +description: Read-only security analysis and vulnerability assessment +mode: primary +color: "#EF4444" +permission: + edit: deny + bash: deny +--- + +You are a security specialist reviewing code for vulnerabilities. + +Focus on: + +- Input validation issues +- Authentication and authorization flaws +- Data exposure risks +- Injection vulnerabilities +``` + +### Config File Example (`kilo.json`) + +```jsonc +{ + "agent": { + "docs-writer": { + "description": "Specialized for writing and editing technical documentation", + "mode": "primary", + "color": "#10B981", + "prompt": "You are a technical writer specializing in clear documentation.", + "permission": { + "edit": { "*.md": "allow", "*": "deny" }, + "bash": "deny", + }, + }, + "test-engineer": { + "description": "Focused on writing and maintaining test suites", + "mode": "primary", + "prompt": "You are a test engineer focused on code quality.", + "permission": { + "edit": { "*.{test,spec}.{js,ts}": "allow", "*": "deny" }, + }, + }, + }, +} +``` + +{% /tab %} +{% /tabs %} + ## Troubleshooting +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ### Common Issues - **Mode not appearing:** After creating or importing a mode, you may need to reload the VS Code window @@ -514,6 +1058,43 @@ customModes: - **Hyphens for List Items:** List items start with a hyphen and a space (e.g., `- read`) - **Validate Your YAML:** Use online YAML validators or your editor's built-in validation +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +### Common Issues + +- **Agent not appearing:** Ensure the `.md` file is in a recognized directory (`.kilo/agents/`, `.kilo/agent/`, `.opencode/agents/`). Check that the `mode` property is `primary` or `all` if you expect it in the agent picker. +- **Permission errors:** Permission rules are evaluated last-match-wins. If an agent can't use a tool you expect, check that an `allow` rule appears after any `deny` rules for that permission. +- **YAML frontmatter parse errors:** Ensure the frontmatter block starts and ends with `---` on its own line. Validate that YAML keys match expected property names (e.g., `top_p` not `topP`). +- **Agent overrides not working:** Config merges from global to project level. If a global config sets a property, your project config can override it, but both must use the same agent name. + +### Tips for Agent Definitions + +- **Keep prompts focused:** The markdown body is your system prompt — write it as if briefing a colleague +- **Use `mode: subagent`** for helper agents that shouldn't be directly selectable by users +- **Use the Settings UI** to view and edit agents through the **Settings → Agent Behaviour → Agents** subtab +- **Legacy modes are auto-migrated:** If you have `.kilocodemodes` files, they'll be converted on startup — no manual migration needed + +{% /tab %} +{% tab label="CLI" %} + +### Common Issues + +- **Agent not appearing:** Ensure the `.md` file is in a recognized directory (`.kilo/agents/`, `.kilo/agent/`, `.opencode/agents/`). Check that the `mode` property is `primary` or `all` if you expect it in the agent picker. +- **Permission errors:** Permission rules are evaluated last-match-wins. If an agent can't use a tool you expect, check that an `allow` rule appears after any `deny` rules for that permission. +- **YAML frontmatter parse errors:** Ensure the frontmatter block starts and ends with `---` on its own line. Validate that YAML keys match expected property names (e.g., `top_p` not `topP`). +- **Agent overrides not working:** Config merges from global to project level. If a global config sets a property, your project config can override it, but both must use the same agent name. + +### Tips for Agent Definitions + +- **Keep prompts focused:** The markdown body is your system prompt — write it as if briefing a colleague +- **Use `mode: subagent`** for helper agents that shouldn't be directly selectable by users +- **Test with `kilo agent create`** to see how the CLI generates agent definitions, then customize from there +- **Legacy modes are auto-migrated:** If you have `.kilocodemodes` files, they'll be converted on startup — no manual migration needed + +{% /tab %} +{% /tabs %} + ## Community Gallery -Ready to explore more? Check out the [Show and Tell](https://github.com/Kilo-Org/kilocode/discussions/categories/show-and-tell) to discover and share custom modes created by the community! +Ready to explore more? Check out the [Show and Tell](https://github.com/Kilo-Org/kilocode/discussions/categories/show-and-tell) to discover and share custom modes and agents created by the community! diff --git a/packages/kilo-docs/pages/customize/custom-rules.md b/packages/kilo-docs/pages/customize/custom-rules.md index ccecb0528ec..d89be15ed5e 100644 --- a/packages/kilo-docs/pages/customize/custom-rules.md +++ b/packages/kilo-docs/pages/customize/custom-rules.md @@ -26,12 +26,11 @@ Kilo Code supports two types of custom rules: - **Project Rules**: Apply only to the current project workspace - **Global Rules**: Apply across all projects and workspaces -{% callout type="note" title="UI Support" %} -The built-in rules management UI is available for general rules only. Mode-specific rules must be managed through the file system. -{% /callout %} - ## Rule Location +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ### Project Rules Custom rules are primarily loaded from the **`.kilocode/rules/` directory**. This is the recommended approach for organizing your project-specific rules. Each rule is typically placed in its own Markdown file with a descriptive name: @@ -59,8 +58,86 @@ Global rules are stored in your home directory and apply to all projects: │ └── documentation_style.md ``` +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +### Project Rules + +Project rules are configured via the `instructions` key in your project's `kilo.json` file. You can edit this file directly or use the **Settings** webview to manage the `instructions` configuration. Each entry points to a file path or glob pattern: + +```jsonc +// kilo.json +{ + "instructions": [".kilo/rules/formatting.md", ".kilo/rules/*.md"], +} +``` + +You can also place rule files in the **`.kilo/`** directory structure: + +``` +project/ +├── .kilo/ +│ ├── rules/ +│ │ ├── formatting.md +│ │ ├── restricted_files.md +│ │ └── naming_conventions.md +├── kilo.json +├── src/ +└── ... +``` + +### Global Rules + +Global rules are configured via the `instructions` key in your global `kilo.json` config file (typically at `~/.config/kilo/kilo.json`). + +{% callout type="note" title="Migration" %} +The new extension is backward compatible with `.kilocode/rules/` directories. Existing rules will continue to work, but migrating to `kilo.json` is recommended. +{% /callout %} + +{% /tab %} +{% tab label="CLI" %} + +### Project Rules + +Project rules are configured via the `instructions` key in your project's `kilo.json` file. Each entry points to a file path or glob pattern: + +```jsonc +// kilo.json +{ + "instructions": [".kilo/rules/formatting.md", ".kilo/rules/*.md"], +} +``` + +You can also place rule files in the **`.kilo/`** directory structure: + +``` +project/ +├── .kilo/ +│ ├── rules/ +│ │ ├── formatting.md +│ │ ├── restricted_files.md +│ │ └── naming_conventions.md +├── kilo.json +├── src/ +└── ... +``` + +### Global Rules + +Global rules are configured via the `instructions` key in your global `kilo.json` config file (typically at `~/.config/kilo/kilo.json`). + +{% callout type="note" title="Migration" %} +The CLI is backward compatible with `.kilocode/rules/` directories. Existing rules will continue to work, but migrating to `kilo.json` is recommended. +{% /callout %} + +{% /tab %} +{% /tabs %} + ## Managing Rules Through the UI +{% tabs %} +{% tab label="VSCode (Legacy)" %} + Kilo Code provides a built-in interface for managing your custom rules without manually editing files in the `.kilocode/rules/` directories. To access the UI, click on the icon in the **bottom right corner** of the Kilo Code window. You can access the rules management UI to: @@ -70,8 +147,58 @@ You can access the rules management UI to: - Create and edit rules directly in the interface - Organize rules by category and priority +{% callout type="note" title="UI Support" %} +The built-in rules management UI is available for general rules only. Mode-specific rules must be managed through the file system. +{% /callout %} + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +Rules are managed by editing the `instructions` array in your `kilo.json` config file. You can also use the **Settings** webview in VS Code to edit the configuration. + +- **Add a rule**: Add a file path or glob pattern to the `instructions` array +- **Remove a rule**: Remove the entry from the array +- **Disable a rule temporarily**: Comment out the line in `kilo.json` (JSONC supports `//` comments) + +```jsonc +// kilo.json +{ + "instructions": [ + ".kilo/rules/formatting.md", + // ".kilo/rules/experimental.md" -- temporarily disabled + ".kilo/rules/naming_conventions.md", + ], +} +``` + +{% /tab %} +{% tab label="CLI" %} + +Rules are managed by editing the `instructions` array in your `kilo.json` config file directly. + +- **Add a rule**: Add a file path or glob pattern to the `instructions` array +- **Remove a rule**: Remove the entry from the array +- **Disable a rule temporarily**: Comment out the line in `kilo.json` (JSONC supports `//` comments) + +```jsonc +// kilo.json +{ + "instructions": [ + ".kilo/rules/formatting.md", + // ".kilo/rules/experimental.md" -- temporarily disabled + ".kilo/rules/naming_conventions.md", + ], +} +``` + +{% /tab %} +{% /tabs %} + ## Rule Loading Order +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ### General Rules (Any Mode) Rules are loaded in the following priority order: @@ -86,21 +213,40 @@ Rules are loaded in the following priority order: When both global and project rules exist, they are combined with project rules taking precedence over global rules for conflicting directives. {% callout type="note" %} -We strongly recommend keeping your rules in the `.kilocode/rules/` folder as it provides better organization and is the preferred approach for future versions. The folder-based structure allows for more granular rule organization and clearer separation of concerns. The legacy file-based approach is maintained for backward compatibility but may be subject to change in future releases. +We strongly recommend keeping your rules in the `.kilocode/rules/` folder as it provides better organization and is the preferred approach for future versions. The legacy file-based approach is maintained for backward compatibility but may be subject to change in future releases. {% /callout %} ### Mode-Specific Rules -Additionally, the system supports mode-specific rules, which are loaded separately and have their own priority order: +The system also supports mode-specific rules with their own priority order: 1. First, it checks for `.kilocode/rules-${mode}/` directory 2. If that doesn't exist or is empty, it falls back to `.kilocoderules-${mode}` file (deprecated) -Currently, mode-specific rules are only supported at the project level. -When both generic rules and mode-specific rules exist, the mode-specific rules are given priority in the final output. +Mode-specific rules are only supported at the project level. When both generic and mode-specific rules exist, mode-specific rules take priority. + +{% /tab %} +{% tab label="VSCode & CLI" %} + +Rules are loaded in the order they appear in the `instructions` array in `kilo.json`: + +1. **Global instructions** from the global `kilo.json` config +2. **Project instructions** from the project's `kilo.json` + +Files matched by glob patterns are loaded in filesystem order. Project-level instructions take precedence over global instructions for conflicting directives. + +{% callout type="note" title="Backward Compatibility" %} +If `.kilocode/rules/` directories exist in your project, their contents are automatically included for backward compatibility. To fully migrate, move your rule files and reference them in `kilo.json`. +{% /callout %} + +{% /tab %} +{% /tabs %} ## Creating Custom Rules +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ### Using the UI Interface {% image src="/docs/img/custom-rules/rules-ui.png" alt="Rules tab in Kilo Code" width="400" /%} @@ -132,6 +278,47 @@ To create rules manually: Rules will be automatically applied to all future Kilo Code interactions. Any new changes will be applied immediately. +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +### Using the Settings UI or Config File + +1. Create a `kilo.json` file in your project root (if it doesn't exist) +2. Create a `.kilo/rules/` directory (or any directory you prefer) +3. Write your rule as a Markdown file in that directory +4. Add the file path or a glob pattern to the `instructions` array in `kilo.json` + +```jsonc +// kilo.json +{ + "instructions": [".kilo/rules/my-new-rule.md"], +} +``` + +Rules are applied on the next interaction. You can also edit `kilo.json` through the **Settings** webview in VS Code. + +{% /tab %} +{% tab label="CLI" %} + +### Using the Config File + +1. Create a `kilo.json` file in your project root (if it doesn't exist) +2. Create a `.kilo/rules/` directory (or any directory you prefer) +3. Write your rule as a Markdown file in that directory +4. Add the file path or a glob pattern to the `instructions` array in `kilo.json` + +```jsonc +// kilo.json +{ + "instructions": [".kilo/rules/my-new-rule.md"], +} +``` + +Rules are applied on the next interaction. + +{% /tab %} +{% /tabs %} + ## Example Rules ### Example 1: Table Formatting @@ -207,14 +394,30 @@ When working in team environments, placing `.kilocode/rules/codestyle.md` files If your custom rules aren't being properly followed: -1. **Check rule status in the UI**: Use the rules management interface to verify that your rules are active and properly loaded 1. **Verify rule formatting**: Ensure that your rules are properly formatted with clear Markdown structure -1. **Check rule locations**: Ensure that your rules are located in supported locations: - - Global rules: `~/.kilocode/rules/` directory - - Project rules: `.kilocode/rules/` directory - - Legacy files: `.kilocoderules`, `.roorules`, or `.clinerules` -1. **Rule specificity**: Verify that the rules are specific and unambiguous -1. **Restart VS Code**: Restart VS Code to ensure the rules are properly loaded +2. **Rule specificity**: Verify that the rules are specific and unambiguous +3. **Check rule locations**: + +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +- **Check rule status in the UI**: Use the rules management interface to verify that your rules are active and properly loaded +- Ensure rules are in supported locations: + - Global rules: `~/.kilocode/rules/` directory + - Project rules: `.kilocode/rules/` directory + - Legacy files: `.kilocoderules`, `.roorules`, or `.clinerules` +- **Restart VS Code** to ensure the rules are properly loaded + +{% /tab %} +{% tab label="VSCode & CLI" %} + +- Verify that your `kilo.json` file is valid JSON (with comments) +- Ensure the `instructions` paths resolve to existing files +- Check that glob patterns match the intended files +- Run `kilo` to see if rules are loaded in the output + +{% /tab %} +{% /tabs %} ## Related Features diff --git a/packages/kilo-docs/pages/customize/custom-subagents.md b/packages/kilo-docs/pages/customize/custom-subagents.md index e97090c4a1e..7fa87c195af 100644 --- a/packages/kilo-docs/pages/customize/custom-subagents.md +++ b/packages/kilo-docs/pages/customize/custom-subagents.md @@ -1,6 +1,7 @@ --- title: "Custom Subagents" description: "Create and configure custom subagents in Kilo Code's CLI" +platform: new --- # Custom Subagents diff --git a/packages/kilo-docs/pages/customize/skills.md b/packages/kilo-docs/pages/customize/skills.md index 8f553d681ef..8d49fbb7e64 100644 --- a/packages/kilo-docs/pages/customize/skills.md +++ b/packages/kilo-docs/pages/customize/skills.md @@ -47,6 +47,9 @@ This means: Skills are loaded from multiple locations, allowing both personal skills and project-specific instructions. +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ### Global Skills (User-Level) Global skills are located in the `.kilocode` directory within your Home directory. @@ -84,9 +87,68 @@ your-project/ └── SKILL.md ``` +{% /tab %} +{% tab label="VSCode & CLI" %} + +### Global Skills (User-Level) + +Global skills are located in the `.kilo` directory within your Home directory: + +- Mac and Linux: `~/.kilo/skills/` +- Windows: `\Users\\.kilo\skills\` + +``` +~/.kilo/ +└── skills/ # Generic skills (all modes) + ├── my-skill/ + │ └── SKILL.md + └── another-skill/ + └── SKILL.md +``` + +### Project Skills (Workspace-Level) + +Located in `.kilo/skills/` within your project: + +``` +your-project/ +└── .kilo/ + └── skills/ # Generic skills for this project + └── project-conventions/ + └── SKILL.md +``` + +### Compatibility Directories + +For interoperability with other tools, the CLI also loads skills from: + +- `.claude/skills/` — Claude Code compatibility +- `.agents/skills/` — Open agent standard + +### Additional Skill Paths and Remote URLs + +You can configure extra skill locations and remote skill URLs in your `kilo.json` config (project or global): + +```jsonc +{ + "skills": { + "paths": ["/path/to/shared/skills"], + "urls": ["https://example.com/skills/my-skill/SKILL.md"], + }, +} +``` + +The `skills.paths` key accepts absolute paths to additional skill directories. The `skills.urls` key accepts URLs pointing to remote `SKILL.md` files that are fetched on demand. + +{% /tab %} +{% /tabs %} + ## Mode-Specific Skills -To create a skill that only appears in a specific mode: +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +To create a skill that only appears in a specific mode, place it in a `skills-{mode-slug}` directory: ```bash # For Code mode only @@ -98,8 +160,21 @@ mkdir -p ~/.kilocode/skills-architect/microservices The directory naming pattern is `skills-{mode-slug}` where `{mode-slug}` matches the mode's identifier (e.g., `code`, `architect`, `ask`, `debug`). +{% /tab %} +{% tab label="VSCode & CLI" %} + +The new platform does not use mode-specific skill directories. All skills are loaded into a shared pool and the agent decides which skill to invoke based on the skill's `description` field and the current task context. + +If you need a skill to only apply in certain situations, write a clear and specific `description` in the SKILL.md frontmatter so the agent knows when to use it. + +{% /tab %} +{% /tabs %} + ## Priority and Overrides +{% tabs %} +{% tab label="VSCode (Legacy)" %} + When multiple skills share the same name, Kilo Code uses these priority rules: 1. **Project skills override global skills** - A project skill with the same name takes precedence @@ -111,8 +186,19 @@ This allows you to: - Override them per-project when needed - Customize behavior for specific modes +{% /tab %} +{% tab label="VSCode & CLI" %} + +When multiple skills share the same name, project-level skills (`.kilo/skills/`) take precedence over global skills (`~/.kilo/skills/`). Skills from compatibility directories (`.claude/skills/`, `.agents/skills/`) and additional configured paths are loaded alongside project and global skills. + +{% /tab %} +{% /tabs %} + ## When Skills Are Loaded +{% tabs %} +{% tab label="VSCode (Legacy)" %} + Skills are discovered when Kilo Code initializes: - When VSCode starts @@ -126,6 +212,19 @@ Skills directories are monitored for changes to `SKILL.md` files. However, the m You can symlink skills directories to share skills across machines or from a central repository. When using symlinks, the skill's `name` field must match the **symlink name**, not the target directory name. +{% /tab %} +{% tab label="VSCode & CLI" %} + +Skills are discovered when a session starts. The CLI scans all configured skill directories and reads metadata (name, description, file path) for each skill. + +- In the **CLI**: Skills are loaded when you start a new session or run `kilo run` +- In the **VS Code extension**: Skills are loaded when the extension connects to the CLI server + +Skills are re-scanned at the start of each new session. To pick up newly added or modified skills, start a new session. + +{% /tab %} +{% /tabs %} + ## SKILL.md Format The `SKILL.md` file uses YAML frontmatter followed by Markdown content containing the instructions: @@ -213,62 +312,101 @@ These additional files can be referenced from your skill's instructions, allowin ## Example: Creating a Skill +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. Create the skill directory: ```bash mkdir -p ~/.kilocode/skills/api-design ``` -2. Create `SKILL.md`: - - ```markdown - --- - name: api-design - description: REST API design best practices and conventions - --- - - # API Design Guidelines - - When designing REST APIs, follow these conventions: - - ## URL Structure - - - Use plural nouns for resources: `/users`, `/orders` - - Use kebab-case for multi-word resources: `/order-items` - - Nest related resources: `/users/{id}/orders` - - ## HTTP Methods - - - GET: Retrieve resources - - POST: Create new resources - - PUT: Replace entire resource - - PATCH: Partial update - - DELETE: Remove resource - - ## Response Codes - - - 200: Success - - 201: Created - - 400: Bad Request - - 404: Not Found - - 500: Server Error - ``` +2. Create `SKILL.md` (see content below) 3. Reload VSCode to load the skill 4. The skill will now be available in all modes +{% /tab %} +{% tab label="VSCode & CLI" %} + +1. Create the skill directory: + + ```bash + mkdir -p ~/.kilo/skills/api-design + ``` + +2. Create `SKILL.md` (see content below) + +3. Start a new session to pick up the skill + +{% /tab %} +{% /tabs %} + +Example `SKILL.md`: + +```markdown +--- +name: api-design +description: REST API design best practices and conventions +--- + +# API Design Guidelines + +When designing REST APIs, follow these conventions: + +## URL Structure + +- Use plural nouns for resources: `/users`, `/orders` +- Use kebab-case for multi-word resources: `/order-items` +- Nest related resources: `/users/{id}/orders` + +## HTTP Methods + +- GET: Retrieve resources +- POST: Create new resources +- PUT: Replace entire resource +- PATCH: Partial update +- DELETE: Remove resource + +## Response Codes + +- 200: Success +- 201: Created +- 400: Bad Request +- 404: Not Found +- 500: Server Error +``` + ## Finding Skills +{% tabs %} +{% tab label="VSCode (Legacy)" %} + You can discover and install community-created skills through: -- **Kilo Marketplace** - Browse skills directly in the Kilo Code extension via the Marketplace tab, or explore the [Kilo Marketplace repository](https://github.com/Kilo-Org/kilo-marketplace) on GitHub -- [Agent Skills Specification](https://agentskills.io/home) - The open specification that skills follow, enabling interoperability across different AI agents +- **Kilo Marketplace** — Browse skills directly in the Kilo Code extension via the Marketplace tab, or explore the [Kilo Marketplace repository](https://github.com/Kilo-Org/kilo-marketplace) on GitHub +- [Agent Skills Specification](https://agentskills.io/home) — The open specification that skills follow, enabling interoperability across different AI agents + +{% /tab %} +{% tab label="VSCode & CLI" %} + +The new platform does not have a marketplace UI yet. You can find and share skills through: + +- **[Kilo Marketplace repository](https://github.com/Kilo-Org/kilo-marketplace)** — Browse community skills on GitHub and manually download them into your skills directory +- **[Agent Skills Specification](https://agentskills.io/home)** — The open specification that skills follow, enabling interoperability across different AI agents +- **Remote URLs** — Use the `skills.urls` config key to load skills directly from URLs without manually downloading them + +{% /tab %} +{% /tabs %} ## Troubleshooting ### Skill Not Loading? +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Check the Output panel**: Open `View` → `Output` → Select "Kilo Code" from dropdown. Look for skill-related errors. 2. **Verify frontmatter**: Ensure `name` exactly matches the directory name and `description` is present. @@ -277,6 +415,20 @@ You can discover and install community-created skills through: 4. **Check file location**: Ensure `SKILL.md` is directly inside the skill directory, not nested further. +{% /tab %} +{% tab label="VSCode & CLI" %} + +1. **Verify frontmatter**: Ensure `name` exactly matches the directory name and `description` is present. + +2. **Start a new session**: Skills are scanned at session start. Begin a new session to pick up changes. + +3. **Check file location**: Ensure `SKILL.md` is directly inside the skill directory (e.g., `.kilo/skills/my-skill/SKILL.md`), not nested further. + +4. **Check config paths**: If using `skills.paths` or `skills.urls`, verify the paths and URLs are correct in your `kilo.json`. + +{% /tab %} +{% /tabs %} + ### Verifying a Skill is Available To confirm a skill is properly loaded and available to the agent, you can ask the agent directly. Simply send a message like: @@ -291,10 +443,21 @@ If the agent confirms the skill is available, you're ready to use it. If not, ch ### Checking if a Skill Was Used +{% tabs %} +{% tab label="VSCode (Legacy)" %} + To see if a skill was actually used during a conversation, look for a `read_file` tool call in the chat that targets a `SKILL.md` file. When the agent decides to use a skill, it reads the full skill file into context—this appears as a file read operation in the conversation. There's currently no dedicated UI indicator showing "Skill X was activated." The `read_file` call is the most reliable way to confirm a skill was used. +{% /tab %} +{% tab label="VSCode & CLI" %} + +When the agent uses a skill, it invokes the `skill` tool with the skill's name. Look for a `skill` tool call in the conversation to confirm a skill was loaded. The tool output includes the full skill content injected into context. + +{% /tab %} +{% /tabs %} + ### Common Errors | Error | Cause | Solution | @@ -307,6 +470,19 @@ There's currently no dedicated UI indicator showing "Skill X was activated." The Have you created a skill that others might find useful? Share it with the community by contributing to the [Kilo Marketplace](https://github.com/Kilo-Org/kilo-marketplace)! +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +Skills submitted to the marketplace are browsable and installable directly from the Marketplace tab in the **VSCode** version. + +{% /tab %} +{% tab label="VSCode & CLI" %} + +While the new platform does not yet have a built-in marketplace UI, skills from the [Kilo Marketplace repository](https://github.com/Kilo-Org/kilo-marketplace) can be manually downloaded into your `.kilo/skills/` directory or loaded via `skills.urls` in config. + +{% /tab %} +{% /tabs %} + ### How to Submit Your Skill 1. **Prepare your skill**: Ensure your skill directory contains a valid `SKILL.md` file with proper frontmatter diff --git a/packages/kilo-docs/pages/customize/workflows.md b/packages/kilo-docs/pages/customize/workflows.md index c18a0030fb8..4b8fed926af 100644 --- a/packages/kilo-docs/pages/customize/workflows.md +++ b/packages/kilo-docs/pages/customize/workflows.md @@ -1,6 +1,7 @@ --- title: "Workflows" description: "Create automated workflows with Kilo Code" +platform: new --- # Workflows From 8304cf44dc082393f962ff30a5aa82fcb492584a Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Tue, 24 Mar 2026 05:29:32 -0400 Subject: [PATCH 013/261] docs(kilo-docs): add platform tabs to MCP and shell integration pages Add VSCode (Pre-release) and CLI tabs to 3 automate pages: - mcp/using-in-kilo-code.md: Tabbed config tables, CLI commands (including logout and debug), transport types, troubleshooting - extending/shell-integration.md: Platform-specific shell integration - automate/index.md: Fix stale link to deleted using-in-cli page MCP timeout correctly shown as 30000ms (verified against mcp/index.ts:29 DEFAULT_TIMEOUT = 30_000). Part of the docs platform tabs effort (PR 7 of 8). Depends on #7497 for infrastructure. --- packages/kilo-docs/lib/nav/automate.ts | 5 +- .../automate/extending/shell-integration.md | 77 +++++ packages/kilo-docs/pages/automate/index.md | 2 +- .../pages/automate/mcp/using-in-kilo-code.md | 319 +++++++++++++++--- 4 files changed, 362 insertions(+), 41 deletions(-) diff --git a/packages/kilo-docs/lib/nav/automate.ts b/packages/kilo-docs/lib/nav/automate.ts index e8ae1c02a8d..d4d9bb487e8 100644 --- a/packages/kilo-docs/lib/nav/automate.ts +++ b/packages/kilo-docs/lib/nav/automate.ts @@ -29,6 +29,7 @@ export const AutomateNav: NavSection[] = [ { href: "/automate/extending/auto-launch", children: "Auto-launch Configuration", + platform: "legacy", }, { href: "/automate/mcp/overview", @@ -53,8 +54,8 @@ export const AutomateNav: NavSection[] = [ { title: "Tools", links: [ - { href: "/automate/how-tools-work", children: "How Tools Work" }, - { href: "/automate/tools", children: "Tools Details" }, + { href: "/automate/how-tools-work", children: "How Tools Work", platform: "legacy" }, + { href: "/automate/tools", children: "Tools Details", platform: "legacy" }, ], }, ] diff --git a/packages/kilo-docs/pages/automate/extending/shell-integration.md b/packages/kilo-docs/pages/automate/extending/shell-integration.md index 5c7a88187ac..c88399a1f61 100644 --- a/packages/kilo-docs/pages/automate/extending/shell-integration.md +++ b/packages/kilo-docs/pages/automate/extending/shell-integration.md @@ -7,6 +7,9 @@ description: "Integrate Kilo Code with your shell environment" Terminal Shell Integration is a key feature that enables Kilo Code to execute commands in your terminal and intelligently process their output. This bidirectional communication between the AI and your development environment unlocks powerful automation capabilities. +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ## What is Shell Integration? Shell integration is automatically enabled in Kilo Code and connects directly to your terminal's command execution lifecycle without requiring any setup from you. This built-in feature allows Kilo Code to: @@ -340,6 +343,80 @@ The [VS Code Terminal Integration Test Extension](https://github.com/KJ7LNW/vsce - Note your environment (OS, VS Code version, shell, and any shell prompt customization) - Open an issue with these details to help improve shell integration +{% /tab %} +{% tab label="VSCode & CLI" %} + +## How Shell Execution Works + +The new CLI and extension take a fundamentally different approach to shell execution. Instead of relying on VS Code's terminal shell integration, the CLI spawns and manages shell processes directly using the `bash` tool. + +This means: + +- **No VS Code shell integration required** — the CLI handles shell execution independently +- **No shell integration setup or troubleshooting** — it works out of the box +- **Consistent behavior** across environments — the same shell execution logic runs whether you use the CLI directly or through the VS Code extension + +## The `bash` Tool + +The `bash` tool is the primary way the agent executes shell commands. It spawns a persistent shell session and runs commands within it. + +### Key Features + +- **Working directory control**: Use the `workdir` parameter to run commands in a specific directory, instead of `cd && ` patterns +- **Configurable timeout**: Set a per-command timeout in milliseconds (defaults to 2 minutes) +- **Real-time output streaming**: Command output is streamed back as it's produced +- **Process tree management**: The tool manages the full process tree, ensuring child processes are properly cleaned up + +### Security Analysis + +Commands are parsed using **Tree-sitter** before execution, enabling: + +- Path resolution to detect file access patterns +- External directory detection to flag commands that reach outside the project +- Structured analysis of command intent for safer auto-approval decisions + +### Shell Detection + +The CLI automatically detects the appropriate shell for your platform using `Shell.acceptable()`. This selects a compatible shell (bash, zsh, etc.) without requiring manual configuration. + +## Agent Manager Terminals (VS Code Extension) + +When using the Kilo Code VS Code extension with the Agent Manager, each agent session gets its own dedicated VS Code terminal. + +### Per-Session Terminals + +- Each session creates a terminal named **`Agent: {branch}`**, where `{branch}` is the git branch or worktree the session is working in +- The terminal's working directory is automatically set to the session's worktree directory +- Terminals are standard VS Code integrated terminals — you can interact with them directly + +### Keyboard Shortcuts + +| Shortcut | Action | +| --------------------------- | --------------------------------------- | +| Cmd+/ | Focus the session's terminal | +| Cmd+. | Return focus to the Agent Manager panel | + +### Terminal Context Menu Actions + +Right-click in an Agent Manager terminal to access these actions: + +- **Add Terminal Content to Context** — sends the terminal's visible output to the agent as context +- **Fix This Command** — asks the agent to diagnose and fix the last failed command +- **Explain This Command** — asks the agent to explain what a command does + +## Troubleshooting + +Shell execution in the new CLI is significantly simpler than the **VSCode** version's terminal integration. Most issues are resolved by ensuring: + +1. **A supported shell is installed**: bash or zsh on macOS/Linux, PowerShell on Windows +2. **The shell is on your PATH**: The CLI needs to find the shell binary +3. **File permissions are correct**: The CLI needs execute permission on the shell binary + +If commands fail to execute, check the CLI's log output for error details. The CLI logs the shell it detected and any errors during command execution. + +{% /tab %} +{% /tabs %} + ## Support If you've followed these steps and are still experiencing problems, please: diff --git a/packages/kilo-docs/pages/automate/index.md b/packages/kilo-docs/pages/automate/index.md index 453f0163c50..9616faf4a7e 100644 --- a/packages/kilo-docs/pages/automate/index.md +++ b/packages/kilo-docs/pages/automate/index.md @@ -36,7 +36,7 @@ Connect Kilo Code to external tools and services: - [**Using MCP in Kilo Code**](/docs/automate/mcp/using-in-kilo-code) — Configuration guide - [**STDIO & SSE Transports**](/docs/automate/mcp/server-transports) — Local and remote server options - [**MCP vs API**](/docs/automate/mcp/mcp-vs-api) — When to use MCP -- [**Using MCP in CLI**](/docs/automate/mcp/using-in-cli) — CLI-specific MCP setup +- [**Using MCP in Kilo Code**](/docs/automate/mcp/using-in-kilo-code) — Configure MCP servers ## Integrations diff --git a/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md b/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md index 43dd907c755..f0ef4d68a98 100644 --- a/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md +++ b/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md @@ -7,31 +7,46 @@ description: "How to use MCP servers in Kilo Code" Model Context Protocol (MCP) extends Kilo Code's capabilities by connecting to external tools and services. This guide covers everything you need to know about using MCP with Kilo Code. -{% youtube url="https://youtu.be/6O9RQoQRX8A" caption="Demostrating MCP installation in Kilo Code" /%} +{% youtube url="https://youtu.be/6O9RQoQRX8A" caption="Demonstrating MCP installation in Kilo Code" /%} ## Configuring MCP Servers -MCP server configurations can be managed at two levels: +MCP server configurations can be managed at two levels: **global** (applies across all workspaces) and **project-level** (specific to a single project). Project-level configuration takes precedence over global settings. -1. **Global Configuration**: Stored in the `mcp_settings.json` file, accessible via VS Code settings (see below). These settings apply across all your workspaces unless overridden by a project-level configuration. -2. **Project-level Configuration**: Defined in a `.kilocode/mcp.json` file within your project's root directory. This allows you to set up project-specific servers and share configurations with your team by committing the file to version control. Kilo Code automatically detects and loads this file if it exists. +{% tabs %} +{% tab label="VSCode (Legacy)" %} -**Precedence**: If a server name exists in both global and project configurations, the **project-level configuration takes precedence**. +| Scope | Path | Description | +| ----------- | -------------------- | --------------------------------------------------------------- | +| **Global** | `mcp_settings.json` | Accessible via VS Code settings. Applies across all workspaces. | +| **Project** | `.kilocode/mcp.json` | In your project root. Auto-detected by Kilo Code. | -### Editing MCP Settings Files +Project-level configs can be committed to version control to share with your team. -You can edit both global and project-level MCP configuration files directly from the Kilo Code settings. +{% /tab %} +{% tab label="VSCode" %} -1. Click the {% codicon name="gear" /%} icon in the top navigation of the Kilo Code pane to open `Settings`. -2. Click the `Agent Behaviour` tab on the left side -3. Select the `MCP Servers` sub-tab -4. Click the appropriate button: - - **`Edit Global MCP`**: Opens the global `mcp_settings.json` file. - - **`Edit Project MCP`**: Opens the project-specific `.kilocode/mcp.json` file. If this file doesn't exist, Kilo Code will create it for you. +In the VS Code extension, open **Settings → MCP** to add and manage MCP servers through the UI. Under the hood the extension reads the same config files as the CLI — see the **CLI** tab for file paths and format. -{% image src="/docs/img/using-mcp-in-kilo-code/mcp-installed-config.png" alt="Edit Global MCP and Edit Project MCP buttons" width="600" caption="Edit Global MCP and Edit Project MCP buttons" /%} +{% /tab %} +{% tab label="CLI" %} -Both files use a JSON format with a `mcpServers` object containing named server configurations: +The CLI accepts several config filenames. The recommended file is `kilo.json`: + +| Scope | Recommended Path | Also supported | +| ----------- | ------------------------------------ | -------------------------------------------------------------- | +| **Global** | `~/.config/kilo/kilo.json` | `kilo.jsonc`, `opencode.json`, `opencode.jsonc`, `config.json` | +| **Project** | `./kilo.json` or `./.kilo/kilo.json` | `kilo.jsonc`, `opencode.jsonc`, `opencode.json` | + +{% /tab %} +{% /tabs %} + +## Configuration Format + +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +Both global and project-level files use a JSON format with a `mcpServers` object containing named server configurations: ```json { @@ -51,6 +66,33 @@ Both files use a JSON format with a `mcpServers` object containing named server _Example of MCP Server config in Kilo Code (STDIO Transport)_ +{% /tab %} +{% tab label="VSCode" %} + +In the VS Code extension, open **Settings → MCP** and click **Add Server** to configure a new server through the UI. You can also edit the config files directly — see the **CLI** tab for the JSON format. + +{% /tab %} +{% tab label="CLI" %} + +Add MCP servers under the `mcp` key in your config file. Each server has a unique name that you can reference in prompts. + +```json +{ + "mcp": { + "my-server": { + "type": "local", + "command": ["npx", "-y", "my-mcp-command"], + "enabled": true + } + } +} +``` + +You can disable a server by setting `enabled` to `false` without removing it from your config. + +{% /tab %} +{% /tabs %} + ### Understanding Transport Types MCP supports three transport types for server communication: @@ -69,6 +111,9 @@ For more in-depth information about how STDIO transport works, see [STDIO Transp STDIO configuration example: +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ```json { "mcpServers": { @@ -85,6 +130,42 @@ STDIO configuration example: } ``` +{% /tab %} +{% tab label="VSCode" %} + +In the VS Code extension, open **Settings → MCP**, click **Add Server**, and choose **Local (stdio)**. Fill in the command, arguments, and optional environment variables through the UI. You can also edit the config files directly — see the **CLI** tab for the JSON format. + +{% /tab %} +{% tab label="CLI" %} + +```json +{ + "mcp": { + "my-local-server": { + "type": "local", + "command": ["npx", "-y", "my-mcp-command"], + "enabled": true, + "environment": { + "API_KEY": "your_api_key" + } + } + } +} +``` + +#### Local Server Options + +| Option | Type | Required | Description | +| ------------- | ------- | -------- | --------------------------------------------------------------------- | +| `type` | String | Yes | Must be `"local"`. | +| `command` | Array | Yes | Command and arguments to run the MCP server. | +| `environment` | Object | No | Environment variables to set when running the server. | +| `enabled` | Boolean | No | Enable or disable the MCP server on startup. | +| `timeout` | Number | No | Timeout in ms for fetching tools from the MCP server. Default: 30000. | + +{% /tab %} +{% /tabs %} + #### Streamable HTTP Transport Used for remote servers accessed over HTTP/HTTPS: @@ -94,7 +175,8 @@ Used for remote servers accessed over HTTP/HTTPS: - Requires network access - Allows centralized deployment and management -Streamable HTTP transport configuration example: +{% tabs %} +{% tab label="VSCode (Legacy)" %} ```json { @@ -112,7 +194,43 @@ Streamable HTTP transport configuration example: } ``` -#### SSE Transport +{% /tab %} +{% tab label="VSCode" %} + +In the VS Code extension, open **Settings → MCP**, click **Add Server**, and choose **Remote (HTTP)**. Enter the server URL and optional headers through the UI. You can also edit the config files directly — see the **CLI** tab for the JSON format. + +{% /tab %} +{% tab label="CLI" %} + +```json +{ + "mcp": { + "my-remote-server": { + "type": "remote", + "url": "https://my-mcp-server.com/mcp", + "enabled": true, + "headers": { + "Authorization": "Bearer MY_API_KEY" + } + } + } +} +``` + +#### Remote Server Options + +| Option | Type | Required | Description | +| --------- | ------- | -------- | --------------------------------------------------------------------- | +| `type` | String | Yes | Must be `"remote"`. | +| `url` | String | Yes | URL of the remote MCP server. | +| `enabled` | Boolean | No | Enable or disable the MCP server on startup. | +| `headers` | Object | No | HTTP headers to send with requests. | +| `timeout` | Number | No | Timeout in ms for fetching tools from the MCP server. Default: 30000. | + +{% /tab %} +{% /tabs %} + +### SSE Transport ⚠️ DEPRECATED: The SSE Transport has been deprecated as of MCP specification version 2025-03-26. Please use the HTTP Stream Transport instead, which implements the new Streamable HTTP transport specification. @@ -143,6 +261,24 @@ SSE configuration example: } ``` +## Managing MCP Servers + +{% tabs %} +{% tab label="VSCode (Legacy)" %} + +### Editing MCP Settings Files + +You can edit both global and project-level MCP configuration files directly from the Kilo Code settings. + +1. Click the {% codicon name="gear" /%} icon in the top navigation of the Kilo Code pane to open `Settings`. +2. Click the `Agent Behaviour` tab on the left side +3. Select the `MCP Servers` sub-tab +4. Click the appropriate button: + - **`Edit Global MCP`**: Opens the global `mcp_settings.json` file. + - **`Edit Project MCP`**: Opens the project-specific `.kilocode/mcp.json` file. If this file doesn't exist, Kilo Code will create it for you. + +{% image src="/docs/img/using-mcp-in-kilo-code/mcp-installed-config.png" alt="Edit Global MCP and Edit Project MCP buttons" width="600" caption="Edit Global MCP and Edit Project MCP buttons" /%} + ### Deleting a Server 1. Press the {% codicon name="trash" /%} next to the MCP server you would like to delete @@ -178,41 +314,58 @@ MCP tool auto-approval works on a per-tool basis and is disabled by default. To When enabled, Kilo Code will automatically approve this specific tool without prompting. Note that the global "Use MCP servers" setting takes precedence - if it's disabled, no MCP tools will be auto-approved. -## Finding and Installing MCP Servers +{% /tab %} +{% tab label="VSCode" %} -Kilo Code does not come with any pre-installed MCP servers. You'll need to find and install them separately. +In the VS Code extension, manage MCP servers from **Settings → MCP**: -- **Community Repositories:** Check for community-maintained lists of MCP servers on GitHub -- **Ask Kilo Code:** You can ask Kilo Code to help you find or even create MCP servers -- **Build Your Own:** Create custom MCP servers using the SDK to extend Kilo Code with your own tools +- **Add a server**: Click **Add Server** and fill in the details +- **Enable/disable**: Toggle a server on or off without removing its configuration +- **Delete**: Remove a server from the list -For full SDK documentation, visit the [MCP GitHub repository](https://github.com/modelcontextprotocol/). +The extension also supports the `{env:VARIABLE_NAME}` syntax in config files to reference environment variables (see the **CLI** tab for details). -## Using MCP Tools in Your Workflow +{% /tab %} +{% tab label="CLI" %} -After configuring an MCP server, Kilo Code will automatically detect available tools and resources. To use them: +### CLI Commands -1. Type your request in the Kilo Code chat interface -2. Kilo Code will identify when an MCP tool can help with your task -3. Approve the tool use when prompted (or use auto-approval) +| Command | Description | +| ----------------- | ------------------------------- | +| `kilo mcp list` | List all configured MCP servers | +| `kilo mcp add` | Add an MCP server | +| `kilo mcp auth` | Authenticate with an MCP server | +| `kilo mcp logout` | Log out from an MCP server | +| `kilo mcp debug` | Debug an MCP server connection | -Example: "Analyze the performance of my API" might use an MCP tool that tests API endpoints. +Inside the interactive TUI, use the `/mcps` slash command to toggle MCP servers on or off. -## Troubleshooting MCP Servers +### Environment Variables -Common issues and solutions: +Use `{env:VARIABLE_NAME}` syntax in config files to reference environment variables: -- **Server Not Responding:** Check if the server process is running and verify network connectivity -- **Permission Errors:** Ensure proper API keys and credentials are configured in your `mcp_settings.json` (for global settings) or `.kilocode/mcp.json` (for project settings). -- **Tool Not Available:** Confirm the server is properly implementing the tool and it's not disabled in settings -- **Slow Performance:** Try adjusting the network timeout value for the specific MCP server +```json +{ + "mcp": { + "my-server": { + "type": "remote", + "url": "https://mcp.example.com/mcp", + "headers": { + "Authorization": "Bearer {env:MY_API_KEY}" + } + } + } +} +``` -{% callout type="tip" %} -**Reduce system prompt size:** If you're not using MCP, turn it off in Settings > Agent Behaviour > MCP Servers to significantly cut down the size of the system prompt and improve performance. -{% /callout %} +{% /tab %} +{% /tabs %} ## Platform-Specific MCP Configuration Examples +{% tabs %} +{% tab label="VSCode (Legacy)" %} + ### Windows Configuration Example When setting up MCP servers on Windows, you'll need to use the Windows Command Prompt (`cmd`) to execute commands. Here's an example of configuring a Puppeteer MCP server on Windows: @@ -253,3 +406,93 @@ For macOS or Linux, you would use a different configuration: {% /callout %} The same approach can be used for other MCP servers on Windows, adjusting the package name as needed for different server types. + +{% /tab %} +{% tab label="VSCode" %} + +In the VS Code extension, use **Settings → MCP → Add Server** to add any of the examples below through the UI. You can also edit the config files directly — see the **CLI** tab for the JSON format. + +{% /tab %} +{% tab label="CLI" %} + +### Figma Desktop + +Connect to the Figma Desktop app's MCP server: + +```json +{ + "mcp": { + "Figma Desktop": { + "type": "remote", + "url": "http://127.0.0.1:3845/mcp" + } + } +} +``` + +### Context7 + +Add the [Context7](https://github.com/upstash/context7) MCP server for documentation search: + +```json +{ + "mcp": { + "context7": { + "type": "remote", + "url": "https://mcp.context7.com/mcp" + } + } +} +``` + +### Everything Test Server + +Add the test MCP server for development: + +```json +{ + "mcp": { + "mcp_everything": { + "type": "local", + "command": ["npx", "-y", "@modelcontextprotocol/server-everything"] + } + } +} +``` + +{% /tab %} +{% /tabs %} + +## Finding and Installing MCP Servers + +Kilo Code does not come with any pre-installed MCP servers. You'll need to find and install them separately. + +- **Kilo Marketplace:** Browse community-contributed MCP server configurations and agent skills in the [Kilo Marketplace](https://github.com/Kilo-Org/kilo-marketplace). The marketplace includes ready-to-use configs for popular tools like Figma, Sentry, and more. +- **Community Repositories:** Check for community-maintained lists of MCP servers on GitHub +- **Ask Kilo Code:** You can ask Kilo Code to help you find or even create MCP servers +- **Build Your Own:** Create custom MCP servers using the SDK to extend Kilo Code with your own tools + +For full SDK documentation, visit the [MCP GitHub repository](https://github.com/modelcontextprotocol/). + +## Using MCP Tools in Your Workflow + +After configuring an MCP server, Kilo Code will automatically detect available tools and resources. To use them: + +1. Type your request in the Kilo Code chat interface +2. Kilo Code will identify when an MCP tool can help with your task +3. Approve the tool use when prompted (or use auto-approval) + +Example: "Analyze the performance of my API" might use an MCP tool that tests API endpoints. + +## Troubleshooting MCP Servers + +Common issues and solutions: + +- **Server Not Responding:** Check if the server process is running and verify network connectivity +- **Permission Errors:** Ensure proper API keys and credentials are configured in your `mcp_settings.json` (for global settings) or `.kilocode/mcp.json` (for project settings). +- **Tool Not Available:** Confirm the server is properly implementing the tool and it's not disabled in settings +- **Slow Performance:** Try adjusting the network timeout value for the specific MCP server + +{% callout type="tip" %} +**Reduce system prompt size:** If you're not using MCP, turn it off in Settings > Agent Behaviour > MCP Servers to significantly cut down the size of the system prompt and improve performance. +{% /callout %} From 6e602f4ad37f89e80ee8c08aa9e3ec7e0c846e1e Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Tue, 24 Mar 2026 05:35:14 -0400 Subject: [PATCH 014/261] docs(kilo-docs): add platform tabs to AI provider pages Add VSCode (Pre-release) and CLI tabs to all 30 AI provider pages: - index.md: Overview with platform-specific provider configuration - 29 individual provider pages: Each gets VSCode, Pre-release, and CLI configuration tabs with correct provider IDs and env vars Provider IDs verified against packages/opencode/src/provider/: - amazon-bedrock (not bedrock) - fireworks-ai (not fireworks) - chutes (not chutes-ai) - moonshotai (not moonshot) - vercel (not vercel-ai-gateway) Env vars verified: - AI_GATEWAY_API_KEY (not VERCEL_AI_GATEWAY_API_KEY) - OVHCLOUD_API_KEY (not OVH_AI_ENDPOINTS_ACCESS_TOKEN) - GOOGLE_CLOUD_LOCATION (not GOOGLE_CLOUD_REGION) - AICORE_SERVICE_KEY (not SAP_AI_CORE_*) Providers not available in CLI (glama, unbound) show warning callouts. Part of the docs platform tabs effort (PR 8 of 8). Depends on #7497 for infrastructure. --- .../kilo-docs/pages/ai-providers/anthropic.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/bedrock.md | 50 +++++++++++++++++ .../kilo-docs/pages/ai-providers/cerebras.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/chutes-ai.md | 44 +++++++++++++++ .../pages/ai-providers/claude-code.md | 49 +++++++++++++++++ .../kilo-docs/pages/ai-providers/deepseek.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/fireworks.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/gemini.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/glama.md | 20 +++++++ packages/kilo-docs/pages/ai-providers/groq.md | 54 ++++++++++++++----- .../kilo-docs/pages/ai-providers/inception.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/index.md | 6 +-- .../kilo-docs/pages/ai-providers/lmstudio.md | 38 +++++++++++++ .../kilo-docs/pages/ai-providers/minimax.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/mistral.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/moonshot.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/ollama.md | 38 +++++++++++++ .../ai-providers/openai-chatgpt-plus-pro.md | 40 ++++++++++++++ .../pages/ai-providers/openai-compatible.md | 45 ++++++++++++++++ .../kilo-docs/pages/ai-providers/openai.md | 44 +++++++++++++++ .../pages/ai-providers/openrouter.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/ovhcloud.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/requesty.md | 44 +++++++++++++++ .../pages/ai-providers/sap-ai-core.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/unbound.md | 20 +++++++ packages/kilo-docs/pages/ai-providers/v0.md | 45 ++++++++++++++++ .../pages/ai-providers/vercel-ai-gateway.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/vertex.md | 47 ++++++++++++++++ packages/kilo-docs/pages/ai-providers/xai.md | 44 +++++++++++++++ .../kilo-docs/pages/ai-providers/zenmux.md | 44 +++++++++++++++ 30 files changed, 1227 insertions(+), 17 deletions(-) diff --git a/packages/kilo-docs/pages/ai-providers/anthropic.md b/packages/kilo-docs/pages/ai-providers/anthropic.md index 80897edd3cc..767aed584cb 100644 --- a/packages/kilo-docs/pages/ai-providers/anthropic.md +++ b/packages/kilo-docs/pages/ai-providers/anthropic.md @@ -17,12 +17,56 @@ Anthropic is an AI safety and research company that builds reliable, interpretab ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Anthropic" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Anthropic API key into the "Anthropic API Key" field. 4. **Select Model:** Choose your desired Claude model from the "Model" dropdown. 5. **(Optional) Custom Base URL:** If you need to use a custom base URL for the Anthropic API, check "Use custom base URL" and enter the URL. Most people won't need to adjust this. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Anthropic and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export ANTHROPIC_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "anthropic": { + "env": ["ANTHROPIC_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "anthropic/claude-sonnet-4-20250514", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Prompt Caching:** Claude 3 models support [prompt caching](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching), which can significantly reduce costs and latency for repeated prompts. diff --git a/packages/kilo-docs/pages/ai-providers/bedrock.md b/packages/kilo-docs/pages/ai-providers/bedrock.md index ecdb8a6c86d..457955576e5 100644 --- a/packages/kilo-docs/pages/ai-providers/bedrock.md +++ b/packages/kilo-docs/pages/ai-providers/bedrock.md @@ -34,6 +34,9 @@ You have three options for configuring AWS credentials: ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Bedrock" from the "API Provider" dropdown. 3. **Select Authentication Method:** @@ -48,6 +51,53 @@ You have three options for configuring AWS credentials: 5. **(Optional) Cross-Region Inference:** Check "Use cross-region inference" if you want to access models in a region different from your configured AWS region. 6. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add AWS Bedrock. The extension uses the AWS credentials chain for authentication — configure your AWS credentials using the AWS CLI or environment variables before adding the provider. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Bedrock uses the AWS credentials chain for authentication. Configure your AWS credentials using the AWS CLI or environment variables: + +**Environment variables:** + +```bash +export AWS_ACCESS_KEY_ID="your-access-key" +export AWS_SECRET_ACCESS_KEY="your-secret-key" +export AWS_REGION="us-east-1" +``` + +Or use an AWS profile: + +```bash +aws configure --profile bedrock +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "amazon-bedrock": {}, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "bedrock/anthropic.claude-sonnet-4-20250514-v1:0", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Permissions:** Ensure your IAM user or role has the necessary permissions to invoke Bedrock models. The `bedrock:InvokeModel` permission is required. diff --git a/packages/kilo-docs/pages/ai-providers/cerebras.md b/packages/kilo-docs/pages/ai-providers/cerebras.md index 7f965ece593..24c19bdc421 100644 --- a/packages/kilo-docs/pages/ai-providers/cerebras.md +++ b/packages/kilo-docs/pages/ai-providers/cerebras.md @@ -17,11 +17,55 @@ Cerebras is known for their ultra-fast AI inference powered by the Cerebras CS-3 ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Cerebras" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Cerebras API key into the "Cerebras API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Cerebras and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export CEREBRAS_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "cerebras": { + "env": ["CEREBRAS_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "cerebras/llama-4-scout-17b-16e-instruct", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Inference Speed:** Cerebras models deliver some of the fastest inference speeds available, reducing wait times during development. diff --git a/packages/kilo-docs/pages/ai-providers/chutes-ai.md b/packages/kilo-docs/pages/ai-providers/chutes-ai.md index d0a4a14f62f..b72af388f2a 100644 --- a/packages/kilo-docs/pages/ai-providers/chutes-ai.md +++ b/packages/kilo-docs/pages/ai-providers/chutes-ai.md @@ -20,11 +20,55 @@ Always refer to the official Chutes AI documentation or your dashboard for the m ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Chutes AI" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Chutes AI API key into the "Chutes AI API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Chutes AI and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export CHUTES_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "chutes": { + "env": ["CHUTES_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "chutes-ai/model-name", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Free Access:** Chutes AI provides free API access, making it an excellent option for experimentation and development without immediate costs. diff --git a/packages/kilo-docs/pages/ai-providers/claude-code.md b/packages/kilo-docs/pages/ai-providers/claude-code.md index 7cd5136a435..699a4af7f95 100644 --- a/packages/kilo-docs/pages/ai-providers/claude-code.md +++ b/packages/kilo-docs/pages/ai-providers/claude-code.md @@ -34,11 +34,60 @@ The specific models available depend on your Claude subscription and plan. See [ ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Claude Code" from the "API Provider" dropdown. 3. **Select Model:** Choose your desired Claude model from the "Model" dropdown. 4. **(Optional) Custom CLI Path:** If you installed Claude Code to a location other than the default `claude` command, enter the full path to your Claude executable in the "Claude Code Path" field. Most users won't need to change this. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab. Claude Code uses your existing Anthropic credentials from the `claude` CLI — make sure it is installed and authenticated before adding the provider. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Claude Code uses your existing Anthropic credentials (from the `claude` CLI). Make sure the Claude Code CLI is installed and authenticated: + +```bash +claude --version +claude auth login +``` + +If you have an `ANTHROPIC_API_KEY` environment variable set, the Claude CLI will use it automatically: + +```bash +export ANTHROPIC_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "anthropic": { + "env": ["ANTHROPIC_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "anthropic/claude-sonnet-4-20250514", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **No API Keys Required:** Claude Code uses your existing CLI authentication, so you don't need to manage separate API keys. diff --git a/packages/kilo-docs/pages/ai-providers/deepseek.md b/packages/kilo-docs/pages/ai-providers/deepseek.md index dea4ad27bf8..d70c070f3e8 100644 --- a/packages/kilo-docs/pages/ai-providers/deepseek.md +++ b/packages/kilo-docs/pages/ai-providers/deepseek.md @@ -17,11 +17,55 @@ Kilo Code supports accessing models through the DeepSeek API, including `deepsee ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "DeepSeek" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your DeepSeek API key into the "DeepSeek API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add DeepSeek and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export DEEPSEEK_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "deepseek": { + "env": ["DEEPSEEK_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "deepseek/deepseek-chat", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Pricing:** Refer to the [DeepSeek Pricing](https://api-docs.deepseek.com/quick_start/pricing/) page for details on model costs. diff --git a/packages/kilo-docs/pages/ai-providers/fireworks.md b/packages/kilo-docs/pages/ai-providers/fireworks.md index d89a0796df6..18f08ad7911 100644 --- a/packages/kilo-docs/pages/ai-providers/fireworks.md +++ b/packages/kilo-docs/pages/ai-providers/fireworks.md @@ -17,11 +17,55 @@ Fireworks AI is a high-performance platform for running AI models that offers fa ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Fireworks AI" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Fireworks AI API key into the "Fireworks AI API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Fireworks AI and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export FIREWORKS_AI_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "fireworks-ai": { + "env": ["FIREWORKS_AI_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "fireworks/accounts/fireworks/models/llama4-scout-instruct-basic", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Performance:** Fireworks AI is optimized for speed and offers excellent performance for both chat and completion tasks. diff --git a/packages/kilo-docs/pages/ai-providers/gemini.md b/packages/kilo-docs/pages/ai-providers/gemini.md index 4914f9ea7b6..3a0ffe09eec 100644 --- a/packages/kilo-docs/pages/ai-providers/gemini.md +++ b/packages/kilo-docs/pages/ai-providers/gemini.md @@ -17,11 +17,55 @@ Kilo Code supports Google's Gemini family of models through the Google AI Gemini ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Google Gemini" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Gemini API key into the "Gemini API Key" field. 4. **Select Model:** Choose your desired Gemini model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Google Gemini and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export GOOGLE_GENERATIVE_AI_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "google": { + "env": ["GOOGLE_GENERATIVE_AI_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "google/gemini-2.5-pro", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Pricing:** Gemini API usage is priced based on input and output tokens. Refer to the [Gemini pricing page](https://ai.google.dev/pricing) for detailed information. diff --git a/packages/kilo-docs/pages/ai-providers/glama.md b/packages/kilo-docs/pages/ai-providers/glama.md index bc50910b431..fb000fc64bb 100644 --- a/packages/kilo-docs/pages/ai-providers/glama.md +++ b/packages/kilo-docs/pages/ai-providers/glama.md @@ -26,11 +26,31 @@ Refer to the [Glama documentation](https://glama.ai/models) for the most up-to-d ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Glama" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Glama API key into the "Glama API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Glama and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +{% callout type="warning" %} +Glama is not yet available as a CLI provider. Check the [Kilo Code releases](https://github.com/Kilo-Org/kilocode/releases) for updates on provider support. +{% /callout %} + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Pricing:** Glama operates on a pay-per-use basis. Pricing varies depending on the model you choose. diff --git a/packages/kilo-docs/pages/ai-providers/groq.md b/packages/kilo-docs/pages/ai-providers/groq.md index 77bb3efadbc..58fcf4f1657 100644 --- a/packages/kilo-docs/pages/ai-providers/groq.md +++ b/packages/kilo-docs/pages/ai-providers/groq.md @@ -20,17 +20,54 @@ Kilo Code will attempt to fetch the list of available models from the Groq API. ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Groq" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Groq API key into the "Groq API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. -## Tips and Notes +{% /tab %} +{% tab label="VSCode" %} -- **High-Speed Inference:** Groq's LPUs provide exceptionally fast response times, making it ideal for interactive development workflows. -- **Token Limits:** Some models have specific `max_tokens` limits that are automatically handled by Kilo Code (e.g., the `moonshotai/kimi-k2-instruct` model). -- **Cost Efficiency:** Groq often provides competitive pricing for high-speed inference compared to other providers. -- **Model Selection:** Choose models based on your specific needs - larger models like `llama3-70b-8192` for complex reasoning tasks, or smaller models like `llama3-8b-8192` for faster, simpler operations. +Open **Settings** (gear icon) and go to the **Providers** tab to add Groq and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export GROQ_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "groq": { + "env": ["GROQ_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "groq/llama-3.3-70b-versatile", +} +``` + +{% /tab %} +{% /tabs %} ## Supported Models @@ -46,13 +83,6 @@ Kilo Code supports the following models through Groq: **Note:** Model availability may change. Refer to the [Groq documentation](https://console.groq.com/docs/models) for the latest model list and specifications. -## Configuration in Kilo Code - -1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. -2. **Select Provider:** Choose "Groq" from the "API Provider" dropdown. -3. **Enter API Key:** Paste your Groq API key into the "Groq API Key" field. -4. **Select Model:** Choose your desired model from the "Model" dropdown. - ## Model-Specific Features ### Kimi K2 Model diff --git a/packages/kilo-docs/pages/ai-providers/inception.md b/packages/kilo-docs/pages/ai-providers/inception.md index 6a8f302e391..8431a37fc6f 100644 --- a/packages/kilo-docs/pages/ai-providers/inception.md +++ b/packages/kilo-docs/pages/ai-providers/inception.md @@ -23,11 +23,55 @@ Refer to Inception's current website and developer documentation for the most up ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Inception" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Inception API key into the "Inception API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Inception and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export INCEPTION_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "inception": { + "env": ["INCEPTION_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "inception/mercury-coder-small-beta", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Enterprise Focus:** Inception is designed for production-grade AI applications with emphasis on reliability and consistency. diff --git a/packages/kilo-docs/pages/ai-providers/index.md b/packages/kilo-docs/pages/ai-providers/index.md index 4f75c4e985a..6981043e579 100644 --- a/packages/kilo-docs/pages/ai-providers/index.md +++ b/packages/kilo-docs/pages/ai-providers/index.md @@ -58,11 +58,7 @@ Route requests through unified APIs with additional features: - **Regional** - Better latency in certain locations {% callout type="note" %} -All API keys use VS Code's Secret Storage—never stored in plain text. -{% /callout %} - -{% callout type="warning" title="Time-to-first-byte timeout" %} -For all providers, there is a **five-minute timeout** on time to first token. This means if a provider does not begin streaming a response within five minutes of the request being sent, the request will be cancelled. This is a constraint of the Bun runtime and cannot be easily configured. +In the **VSCode (Legacy)** version, API keys use VS Code's Secret Storage. In the current **VSCode & CLI** version, keys are set via environment variables or referenced in `kilo.json` config files. See individual provider pages for setup instructions for each platform. {% /callout %} ## Next Steps diff --git a/packages/kilo-docs/pages/ai-providers/lmstudio.md b/packages/kilo-docs/pages/ai-providers/lmstudio.md index 13efa7b8361..e22058308b2 100644 --- a/packages/kilo-docs/pages/ai-providers/lmstudio.md +++ b/packages/kilo-docs/pages/ai-providers/lmstudio.md @@ -27,12 +27,50 @@ Kilo Code supports running models locally using LM Studio. LM Studio provides a ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "LM Studio" from the "API Provider" dropdown. 3. **Enter Model ID:** Enter the _file name_ of the model you loaded in LM Studio (e.g., `codellama-7b.Q4_0.gguf`). You can find this in the LM Studio "Local Server" tab. 4. **(Optional) Base URL:** By default, Kilo Code will connect to LM Studio at `http://localhost:1234`. If you've configured LM Studio to use a different address or port, enter the full URL here. 5. **(Optional) Timeout:** By default, API requests time out after 10 minutes. Local models can be slow, if you hit this timeout you can consider increasing it here: VS Code Extensions panel > Kilo Code gear menu > Settings > API Request Timeout. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add LM Studio. No API key is needed since LM Studio runs locally. You can configure the base URL if LM Studio is running on a different host or port. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +LM Studio runs locally, so no API key is needed. Configure the base URL if LM Studio is running on a different host or port: + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "lmstudio": { + "baseURL": "http://localhost:1234/v1", + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "lmstudio/codellama-7b", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Resource Requirements:** Running large language models locally can be resource-intensive. Make sure your computer meets the minimum requirements for the model you choose. diff --git a/packages/kilo-docs/pages/ai-providers/minimax.md b/packages/kilo-docs/pages/ai-providers/minimax.md index 4c6fd6adc5b..4f36072519f 100644 --- a/packages/kilo-docs/pages/ai-providers/minimax.md +++ b/packages/kilo-docs/pages/ai-providers/minimax.md @@ -17,11 +17,55 @@ MiniMax is a global AI foundation model company focused on fast, cost-efficient ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Navigate to **Providers**. Choose **MiniMax** from the API Provider dropdown. 3. **Enter API Key:** Paste your MiniMax API key into the MiniMax API Key field. 4. **Select Model:** Choose your desired MiniMax model from the Model dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add MiniMax and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export MINIMAX_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "minimax": { + "env": ["MINIMAX_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "minimax/MiniMax-M1", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Performance:** MiniMax M2.1 emphasizes fast inference, strong coding ability, and exceptional tool-calling performance. diff --git a/packages/kilo-docs/pages/ai-providers/mistral.md b/packages/kilo-docs/pages/ai-providers/mistral.md index 8a902adb401..e1ce39948b2 100644 --- a/packages/kilo-docs/pages/ai-providers/mistral.md +++ b/packages/kilo-docs/pages/ai-providers/mistral.md @@ -17,11 +17,55 @@ Kilo Code supports accessing models through the Mistral AI API, including both s ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Mistral" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Mistral API key into the "Mistral API Key" field if you're using a `mistral` model. If you intend to use `codestral-latest`, see the "Codestral" section below. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Mistral and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export MISTRAL_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "mistral": { + "env": ["MISTRAL_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "mistral/mistral-large-latest", +} +``` + +{% /tab %} +{% /tabs %} + ## Using Codestral [Codestral](https://docs.mistral.ai/capabilities/code_generation/) is a model specifically designed for code generation and interaction. diff --git a/packages/kilo-docs/pages/ai-providers/moonshot.md b/packages/kilo-docs/pages/ai-providers/moonshot.md index 44ee85619a1..c1b97cfe8d6 100644 --- a/packages/kilo-docs/pages/ai-providers/moonshot.md +++ b/packages/kilo-docs/pages/ai-providers/moonshot.md @@ -17,11 +17,55 @@ Moonshot.ai is a Chinese AI company known for their **Kimi** models featuring ul ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Moonshot.ai" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Moonshot.ai API key into the "Moonshot.ai API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Moonshot.ai and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export MOONSHOT_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "moonshotai": { + "env": ["MOONSHOT_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "moonshot/moonshot-v1-auto", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Ultra-Long Context:** Kimi models excel at handling large codebases and complex projects with their extended context windows. diff --git a/packages/kilo-docs/pages/ai-providers/ollama.md b/packages/kilo-docs/pages/ai-providers/ollama.md index d50417072ca..33f8199e24e 100644 --- a/packages/kilo-docs/pages/ai-providers/ollama.md +++ b/packages/kilo-docs/pages/ai-providers/ollama.md @@ -72,12 +72,50 @@ By default, API requests time out after 10 minutes. Local models can be slow, if ### Configure Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + - Open the Kilo Code panel ({% kiloCodeIcon size="1em" /%}). - Click the Settings gear icon ({% codicon name="gear" /%}). - Select "Ollama" as the API Provider. - Select the model configured in the previous step. - (Optional) You can configure the base URL if you're running Ollama on a different machine. The default is `http://localhost:11434`. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Ollama. No API key is needed since Ollama runs locally. You can configure the base URL if Ollama is running on a different host. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Ollama runs locally, so no API key is needed. Configure the base URL if Ollama is running on a different host: + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "ollama": { + "baseURL": "http://localhost:11434/v1", + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "ollama/qwen3-coder:30b", +} +``` + +{% /tab %} +{% /tabs %} + ## Further Reading Refer to the [Ollama documentation](https://ollama.com/docs) for more information on installing, configuring and using Ollama. diff --git a/packages/kilo-docs/pages/ai-providers/openai-chatgpt-plus-pro.md b/packages/kilo-docs/pages/ai-providers/openai-chatgpt-plus-pro.md index 2e2105f8367..4f24ddc2908 100644 --- a/packages/kilo-docs/pages/ai-providers/openai-chatgpt-plus-pro.md +++ b/packages/kilo-docs/pages/ai-providers/openai-chatgpt-plus-pro.md @@ -4,6 +4,9 @@ sidebar_label: ChatGPT Plus/Pro # Using ChatGPT Subscriptions With Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. Open Kilo Code settings (click the gear icon {% codicon name="gear" /%} in the Kilo Code panel). 2. In **API Provider**, select **OpenAI – ChatGPT Plus/Pro**. 3. Click **Sign in to OpenAI Codex**. @@ -11,6 +14,43 @@ sidebar_label: ChatGPT Plus/Pro 5. Back in Kilo Code settings, pick a model from the dropdown. 6. Save. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab. ChatGPT Plus/Pro uses OAuth authentication — follow the sign-in flow to connect your ChatGPT subscription. + +{% /tab %} +{% tab label="CLI" %} + +ChatGPT Plus/Pro uses OAuth authentication, which is only available in the VS Code extension. For the CLI, use the [OpenAI API provider](/docs/ai-providers/openai) with an API key instead: + +```bash +export OPENAI_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "openai": { + "env": ["OPENAI_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "openai/gpt-4.1", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Subscription Required:** You need an active ChatGPT Plus or Pro subscription. This provider won't work with free ChatGPT accounts. See [OpenAI's ChatGPT plans](https://openai.com/chatgpt/pricing) for more information. diff --git a/packages/kilo-docs/pages/ai-providers/openai-compatible.md b/packages/kilo-docs/pages/ai-providers/openai-compatible.md index f550cbab7cb..5e373573752 100644 --- a/packages/kilo-docs/pages/ai-providers/openai-compatible.md +++ b/packages/kilo-docs/pages/ai-providers/openai-compatible.md @@ -14,6 +14,9 @@ This document focuses on setting up providers _other than_ the official OpenAI A ## General Configuration +{% tabs %} +{% tab label="VSCode (Legacy)" %} + The key to using an OpenAI-compatible provider is to configure two main settings: 1. **Base URL:** This is the API endpoint for the provider. It will _not_ be `https://api.openai.com/v1` (that's for the official OpenAI API). @@ -34,6 +37,48 @@ You'll find these settings in the Kilo Code settings panel (click the {% codicon - Input Price - Output Price +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add an OpenAI Compatible provider. Enter your API key and the provider's base URL. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key and base URL as environment variables or configure them in your `kilo.json` config file: + +**Environment variable:** + +```bash +export OPENAI_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "openai-compatible": { + "env": ["OPENAI_API_KEY"], + "baseURL": "https://api.your-provider.com/v1", + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "openai-compatible/model-name", +} +``` + +{% /tab %} +{% /tabs %} + ### Full Endpoint URL Support Kilo Code supports full endpoint URLs in the Base URL field, providing greater flexibility for provider configuration: diff --git a/packages/kilo-docs/pages/ai-providers/openai.md b/packages/kilo-docs/pages/ai-providers/openai.md index 73dbb8904c7..4c5a379b539 100644 --- a/packages/kilo-docs/pages/ai-providers/openai.md +++ b/packages/kilo-docs/pages/ai-providers/openai.md @@ -17,11 +17,55 @@ Kilo Code supports accessing models directly through the official OpenAI API. ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "OpenAI" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your OpenAI API key into the "OpenAI API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add OpenAI and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export OPENAI_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "openai": { + "env": ["OPENAI_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "openai/gpt-4.1", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Pricing:** Refer to the [OpenAI Pricing](https://openai.com/pricing) page for details on model costs. diff --git a/packages/kilo-docs/pages/ai-providers/openrouter.md b/packages/kilo-docs/pages/ai-providers/openrouter.md index 84019fa69e9..bdcbbf1a528 100644 --- a/packages/kilo-docs/pages/ai-providers/openrouter.md +++ b/packages/kilo-docs/pages/ai-providers/openrouter.md @@ -16,12 +16,56 @@ OpenRouter is an AI platform that provides access to a wide variety of language ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "OpenRouter" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your OpenRouter API key into the "OpenRouter API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. 5. **(Optional) Custom Base URL:** If you need to use a custom base URL for the OpenRouter API, check "Use custom base URL" and enter the URL. Leave this blank for most users. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add OpenRouter and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export OPENROUTER_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "openrouter": { + "env": ["OPENROUTER_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "openrouter/anthropic/claude-sonnet-4-20250514", +} +``` + +{% /tab %} +{% /tabs %} + ## Supported Transforms OpenRouter provides an [optional "middle-out" message transform](https://openrouter.ai/docs/features/message-transforms) to help with prompts that exceed the maximum context size of a model. You can enable it by checking the "Compress prompts and message chains to the context size" box. diff --git a/packages/kilo-docs/pages/ai-providers/ovhcloud.md b/packages/kilo-docs/pages/ai-providers/ovhcloud.md index 344cb130e9b..7b9890a2598 100644 --- a/packages/kilo-docs/pages/ai-providers/ovhcloud.md +++ b/packages/kilo-docs/pages/ai-providers/ovhcloud.md @@ -24,7 +24,51 @@ You can report any bugs or feedbacks by chatting with us in our [Discord server] ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "OVHcloud AI Endpoints" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your AI Endpoints API key into the "OVHcloud AI Endpoints API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. + +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add OVHcloud AI Endpoints and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export OVHCLOUD_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "ovhcloud": { + "env": ["OVHCLOUD_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "ovhcloud/model-name", +} +``` + +{% /tab %} +{% /tabs %} diff --git a/packages/kilo-docs/pages/ai-providers/requesty.md b/packages/kilo-docs/pages/ai-providers/requesty.md index 6fc4a656d9a..fda3c5796e3 100644 --- a/packages/kilo-docs/pages/ai-providers/requesty.md +++ b/packages/kilo-docs/pages/ai-providers/requesty.md @@ -15,11 +15,55 @@ Kilo Code supports accessing models through the [Requesty](https://www.requesty. ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Requesty" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Requesty API key into the "Requesty API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Requesty and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export REQUESTY_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "requesty": { + "env": ["REQUESTY_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "requesty/anthropic/claude-sonnet-4-20250514", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Optimizations**: Requesty offers range of in-flight cost optimizations to lower your costs. diff --git a/packages/kilo-docs/pages/ai-providers/sap-ai-core.md b/packages/kilo-docs/pages/ai-providers/sap-ai-core.md index 6c110a58cc8..16dfec8bbdf 100644 --- a/packages/kilo-docs/pages/ai-providers/sap-ai-core.md +++ b/packages/kilo-docs/pages/ai-providers/sap-ai-core.md @@ -77,6 +77,9 @@ The exact list of available models depends on your SAP AI Core configuration and ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "SAP AI Core" from the "API Provider" dropdown. 3. **Enter Credentials:** @@ -91,6 +94,47 @@ The exact list of available models depends on your SAP AI Core configuration and 5. **Select Model:** Choose your desired model from the dropdown 6. **Select Deployment:** (Foundation Models Mode only) Choose an active deployment for your selected model +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add SAP AI Core. Enter your OAuth2 client credentials (Client ID, Client Secret, Base URL, and Auth URL) in the provider settings. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +SAP AI Core uses OAuth2 client credentials for authentication. Set the credentials as environment variables or in your config file: + +**Environment variables:** + +```bash +export AICORE_SERVICE_KEY='{"your": "service-key-json"}' +export AICORE_DEPLOYMENT_ID="your-deployment-id" +export AICORE_RESOURCE_GROUP="your-resource-group" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "sap-ai-core": {}, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "sap-ai-core/model-name", +} +``` + +{% /tab %} +{% /tabs %} + ## Deployments (Foundation Models Mode) When using Foundation Models mode: diff --git a/packages/kilo-docs/pages/ai-providers/unbound.md b/packages/kilo-docs/pages/ai-providers/unbound.md index 11e061a91ab..fd7f6fb6e27 100644 --- a/packages/kilo-docs/pages/ai-providers/unbound.md +++ b/packages/kilo-docs/pages/ai-providers/unbound.md @@ -20,11 +20,31 @@ Unbound allows you configure a list of supported models in your application, and ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Unbound" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Unbound API key into the "Unbound API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Unbound and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +{% callout type="warning" %} +Unbound is not yet available as a CLI provider. Check the [Kilo Code releases](https://github.com/Kilo-Org/kilocode/releases) for updates on provider support. +{% /callout %} + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Security Focus:** Unbound emphasizes security features for enterprise use. If your organization has strict security requirements for AI usage, Unbound might be a good option. diff --git a/packages/kilo-docs/pages/ai-providers/v0.md b/packages/kilo-docs/pages/ai-providers/v0.md index 5d8d0280bc3..2ba2ba4ac67 100644 --- a/packages/kilo-docs/pages/ai-providers/v0.md +++ b/packages/kilo-docs/pages/ai-providers/v0.md @@ -15,6 +15,9 @@ To use v0 with Kilo Code, you'll need: ## Configuration +{% tabs %} +{% tab label="VSCode (Legacy)" %} + Setting up v0 in Kilo Code is straightforward: 1. In Kilo Code settings (click the {% codicon name="gear" /%} icon): @@ -26,6 +29,48 @@ Setting up v0 in Kilo Code is straightforward: +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add an OpenAI Compatible provider. Set the base URL to `https://api.v0.dev/v1` and enter your v0 API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +v0 uses the OpenAI-compatible provider. Set the API key and base URL in your config: + +**Environment variable:** + +```bash +export OPENAI_API_KEY="your-v0-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "openai-compatible": { + "env": ["OPENAI_API_KEY"], + "baseURL": "https://api.v0.dev/v1", + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "openai-compatible/v0-1.0-md", +} +``` + +{% /tab %} +{% /tabs %} + ## Troubleshooting - **"Invalid API Key":** Double-check that you've entered the API key correctly. diff --git a/packages/kilo-docs/pages/ai-providers/vercel-ai-gateway.md b/packages/kilo-docs/pages/ai-providers/vercel-ai-gateway.md index 3147a1ac9a2..aba308e59e3 100644 --- a/packages/kilo-docs/pages/ai-providers/vercel-ai-gateway.md +++ b/packages/kilo-docs/pages/ai-providers/vercel-ai-gateway.md @@ -54,11 +54,55 @@ Check the model description in the dropdown for specific capabilities. ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "Vercel AI Gateway" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your Vercel AI Gateway API key into the "Vercel AI Gateway API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add Vercel AI Gateway and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export AI_GATEWAY_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "vercel": { + "env": ["AI_GATEWAY_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "vercel-ai-gateway/anthropic/claude-sonnet-4", +} +``` + +{% /tab %} +{% /tabs %} + --- ## Prompt Caching diff --git a/packages/kilo-docs/pages/ai-providers/vertex.md b/packages/kilo-docs/pages/ai-providers/vertex.md index 994a84b7b31..abbb56da3b8 100644 --- a/packages/kilo-docs/pages/ai-providers/vertex.md +++ b/packages/kilo-docs/pages/ai-providers/vertex.md @@ -20,6 +20,9 @@ Kilo Code supports accessing models through Google Cloud Platform's Vertex AI, a ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "GCP Vertex AI" from the "API Provider" dropdown. 3. **Configure Authentication:** @@ -31,6 +34,50 @@ Kilo Code supports accessing models through Google Cloud Platform's Vertex AI, a 5. **Select Region:** Choose the region where your Vertex AI resources are located (e.g., `us-east5`). 6. **Select Model:** Choose your desired model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add GCP Vertex AI. The extension uses Google Application Default Credentials (ADC) for authentication — run `gcloud auth application-default login` before adding the provider. Set your project ID and region in the provider settings. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Vertex AI uses Google Application Default Credentials (ADC) for authentication. Set up ADC using the Google Cloud CLI: + +```bash +gcloud auth application-default login +``` + +Set your project and region as environment variables: + +```bash +export GOOGLE_CLOUD_PROJECT="your-project-id" +export GOOGLE_CLOUD_LOCATION="us-east5" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "google-vertex": {}, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "google-vertex/claude-sonnet-4@20250514", +} +``` + +{% /tab %} +{% /tabs %} + ## Tips and Notes - **Permissions:** Ensure your Google Cloud account has the necessary permissions to access Vertex AI and the specific models you want to use. diff --git a/packages/kilo-docs/pages/ai-providers/xai.md b/packages/kilo-docs/pages/ai-providers/xai.md index 309bd4f0c35..5435c6c7ecd 100644 --- a/packages/kilo-docs/pages/ai-providers/xai.md +++ b/packages/kilo-docs/pages/ai-providers/xai.md @@ -17,11 +17,55 @@ xAI is the company behind Grok, a large language model known for its conversatio ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon ({% codicon name="gear" /%}) in the Kilo Code panel. 2. **Select Provider:** Choose "xAI" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your xAI API key into the "xAI API Key" field. 4. **Select Model:** Choose your desired Grok model from the "Model" dropdown. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add xAI and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export XAI_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "xai": { + "env": ["XAI_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "xai/grok-3", +} +``` + +{% /tab %} +{% /tabs %} + ## Reasoning Capabilities Some models feature specialized reasoning capabilities, allowing them to "think before responding" - particularly useful for complex problem-solving tasks. diff --git a/packages/kilo-docs/pages/ai-providers/zenmux.md b/packages/kilo-docs/pages/ai-providers/zenmux.md index 1e646d1b258..de7985830eb 100644 --- a/packages/kilo-docs/pages/ai-providers/zenmux.md +++ b/packages/kilo-docs/pages/ai-providers/zenmux.md @@ -16,12 +16,56 @@ import Codicon from "@site/src/components/Codicon"; ## Configuration in Kilo Code +{% tabs %} +{% tab label="VSCode (Legacy)" %} + 1. **Open Kilo Code Settings:** Click the gear icon () in the Kilo Code panel. 2. **Select Provider:** Choose "ZenMux" from the "API Provider" dropdown. 3. **Enter API Key:** Paste your ZenMux API key into the "ZenMux API Key" field. 4. **Select Model:** Choose your desired model from the "Model" dropdown. 5. **(Optional) Custom Base URL:** If you need to use a custom base URL for the ZenMux API, check "Use custom base URL" and enter the URL. Leave this blank for most users. +{% /tab %} +{% tab label="VSCode" %} + +Open **Settings** (gear icon) and go to the **Providers** tab to add ZenMux and enter your API key. + +The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable or configure it in your `kilo.json` config file: + +**Environment variable:** + +```bash +export ZENMUX_API_KEY="your-api-key" +``` + +**Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): + +```jsonc +{ + "provider": { + "zenmux": { + "env": ["ZENMUX_API_KEY"], + }, + }, +} +``` + +Then set your default model: + +```jsonc +{ + "model": "zenmux/openai/gpt-5", +} +``` + +{% /tab %} +{% /tabs %} + ## Supported Models ZenMux supports a wide range of models from various providers: From 6e3d227f0bbdfb6b6b1ff8425275901a528aab6e Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 25 Mar 2026 11:16:35 +0200 Subject: [PATCH 015/261] feat(cli): add config path detection for permission protection Add ConfigProtection namespace with utilities to detect when a permission request targets CLI config files. This covers: - Project-relative paths (.kilo/, .kilocode/, .opencode/ dirs, kilo.json, AGENTS.md) - Absolute paths (~/.config/kilo/, ~/.kilo/, ~/.kilocode/) - Multi-file requests from apply_patch (metadata.files[], comma-joined filepath) --- .../src/kilocode/permission/config-paths.ts | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 packages/opencode/src/kilocode/permission/config-paths.ts diff --git a/packages/opencode/src/kilocode/permission/config-paths.ts b/packages/opencode/src/kilocode/permission/config-paths.ts new file mode 100644 index 00000000000..1e0047675d2 --- /dev/null +++ b/packages/opencode/src/kilocode/permission/config-paths.ts @@ -0,0 +1,84 @@ +import path from "path" +import { Global } from "@/global" +import { KilocodePaths } from "@/kilocode/paths" + +export namespace ConfigProtection { + /** + * Config directory prefixes (relative paths, forward-slash normalized). + * Matches .kilo/, .kilocode/, .opencode/ at any depth within the project. + */ + const CONFIG_DIRS = [".kilo/", ".kilocode/", ".opencode/"] + + /** + * Root-level config files that must be protected. + * Matched only when the relative path has no directory component. + */ + const CONFIG_ROOT_FILES = new Set(["kilo.json", "kilo.jsonc", "opencode.json", "opencode.jsonc", "AGENTS.md"]) + + function normalize(p: string): string { + return p.replaceAll("\\", "/") + } + + /** Check if a project-relative path points to a config file or directory. */ + export function isRelative(pattern: string): boolean { + const normalized = normalize(pattern) + for (const dir of CONFIG_DIRS) { + if (normalized === dir.slice(0, -1) || normalized.startsWith(dir)) return true + } + return CONFIG_ROOT_FILES.has(normalized) + } + + /** Check if an absolute path is inside a known CLI config directory. */ + export function isAbsolute(filepath: string): boolean { + const resolved = path.resolve(filepath) + + // ~/.config/kilo/ (XDG config) + const xdg = path.resolve(Global.Path.config) + if (resolved === xdg || resolved.startsWith(xdg + path.sep)) return true + + // ~/.kilo/ and ~/.kilocode/ (legacy global dirs) + for (const dir of KilocodePaths.globalDirs()) { + const abs = path.resolve(dir) + if (resolved === abs || resolved.startsWith(abs + path.sep)) return true + } + + return false + } + + /** + * Determine if a permission request targets config files. + * Only checks `edit` permission — read access is not restricted. + */ + export function isRequest(request: { + permission: string + patterns: string[] + metadata?: Record + }): boolean { + if (request.permission !== "edit") return false + + // Check relative patterns (edit tool, apply_patch) + for (const pattern of request.patterns) { + if (isRelative(pattern)) return true + } + + // Check metadata.filepath (absolute for edit, comma-joined relative for apply_patch) + const fp = request.metadata?.filepath + if (typeof fp === "string") { + // apply_patch joins relative paths with ", " + const parts = fp.includes(", ") ? fp.split(", ") : [fp] + for (const part of parts) { + if (path.isAbsolute(part) ? isAbsolute(part) : isRelative(part)) return true + } + } + + // Check metadata.files[] (apply_patch file objects with absolute filePath) + const files = request.metadata?.files + if (Array.isArray(files)) { + for (const file of files) { + if (typeof file?.filePath === "string" && isAbsolute(file.filePath)) return true + } + } + + return false + } +} From 2455a4374434bff264c0d588084aa908a53dba2a Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 25 Mar 2026 11:16:44 +0200 Subject: [PATCH 016/261] feat(cli): force permission prompt for config file edits Override 'allow' to 'ask' in the permission engine when editing config files. Sets disableAlways metadata flag for UI clients. Safety nets prevent persistent rule creation for config paths: - reply() downgrades 'always' to 'once' (no rules saved) - saveAlwaysRules() skips entirely for config requests - drainCovered() never auto-resolves config file permissions --- .../opencode/src/kilocode/permission/drain.ts | 3 +++ packages/opencode/src/permission/next.ts | 23 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/kilocode/permission/drain.ts b/packages/opencode/src/kilocode/permission/drain.ts index 608932a4f0b..cfd6949c45d 100644 --- a/packages/opencode/src/kilocode/permission/drain.ts +++ b/packages/opencode/src/kilocode/permission/drain.ts @@ -1,6 +1,7 @@ import { Bus } from "@/bus" import { Wildcard } from "@/util/wildcard" import type { PermissionNext } from "@/permission/next" +import { ConfigProtection } from "@/kilocode/permission/config-paths" /** * Auto-resolve pending permissions now fully covered by approved or denied rules. @@ -25,6 +26,8 @@ export async function drainCovered( ) { for (const [id, entry] of Object.entries(pending)) { if (id === exclude) continue + // Never auto-resolve config file edit permissions + if (ConfigProtection.isRequest(entry.info)) continue const actions = entry.info.patterns.map((pattern) => evaluate(entry.info.permission, pattern, entry.ruleset, approved), ) diff --git a/packages/opencode/src/permission/next.ts b/packages/opencode/src/permission/next.ts index 5534572da26..9f0a486ff8a 100644 --- a/packages/opencode/src/permission/next.ts +++ b/packages/opencode/src/permission/next.ts @@ -9,6 +9,7 @@ import { fn } from "@/util/fn" import { Log } from "@/util/log" import { Wildcard } from "@/util/wildcard" import { drainCovered } from "@/kilocode/permission/drain" // kilocode_change +import { ConfigProtection } from "@/kilocode/permission/config-paths" // kilocode_change import os from "os" import z from "zod" @@ -188,18 +189,27 @@ export namespace PermissionNext { async (input) => { const s = await state() const { ruleset, ...request } = input + // kilocode_change start — force "ask" for config file edits + const protected_ = ConfigProtection.isRequest(request) + // kilocode_change end for (const pattern of request.patterns ?? []) { const rule = evaluate(request.permission, pattern, ruleset, s.approved) log.info("evaluated", { permission: request.permission, pattern, action: rule }) if (rule.action === "deny") throw new DeniedError(ruleset.filter((r) => Wildcard.match(request.permission, r.permission))) - if (rule.action === "ask") { + // kilocode_change start — override "allow" to "ask" for config paths + if (rule.action === "ask" || (rule.action === "allow" && protected_)) { const id = input.id ?? Identifier.ascending("permission") return new Promise((resolve, reject) => { const info: Request = { id, ...request, + metadata: { + ...request.metadata, + ...(protected_ ? { disableAlways: true } : {}), + }, } + // kilocode_change end s.pending[id] = { info, ruleset, // kilocode_change @@ -227,6 +237,10 @@ export namespace PermissionNext { const existing = s.pending[input.requestID] if (!existing) throw new NotFoundError({ message: `Permission request ${input.requestID} not found` }) + // kilocode_change start — skip rule persistence for config file edits + if (ConfigProtection.isRequest(existing.info)) return + // kilocode_change end + // Combine metadata.rules (bash hierarchy) and always (all tools). // Set preserves insertion order and deduplicates. const validRules = new Set([...(existing.info.metadata?.rules ?? []), ...existing.info.always]) @@ -289,6 +303,13 @@ export namespace PermissionNext { return } if (input.reply === "always") { + // kilocode_change start — downgrade "always" to "once" for config file edits + if (ConfigProtection.isRequest(existing.info)) { + existing.resolve() + return + } + // kilocode_change end + for (const pattern of existing.info.always) { s.approved.push({ permission: existing.info.permission, From 21902b1dd12df7c844e902079938ee2f553fb313 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 25 Mar 2026 11:16:51 +0200 Subject: [PATCH 017/261] feat(cli): hide 'Always allow' in TUI for config file edits When the disableAlways metadata flag is set on a permission request, only show 'Allow once' and 'Reject' options in the TUI prompt. --- .../src/cli/cmd/tui/routes/session/permission.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx index c2cd4d17d9c..50b9d15f228 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx @@ -428,12 +428,18 @@ export function PermissionPrompt(props: { request: PermissionRequest }) { ) + // kilocode_change start — hide "Always allow" for config file edits + const options: Record = props.request.metadata?.disableAlways + ? { once: "Allow once", reject: "Reject" } + : { once: "Allow once", always: "Allow always", reject: "Reject" } + // kilocode_change end + const body = ( { From c2969d296ed53a8165ec99b373a24244e724cef3 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 25 Mar 2026 11:52:42 +0200 Subject: [PATCH 018/261] fix(cli): close absolute-path bypass and extract DISABLE_ALWAYS_KEY constant - Check absolute patterns in isRequest via isAbsolute() to match the existing metadata.filepath dual-dispatch logic, preventing a bypass where tools pass absolute project-level config paths in patterns - Export ConfigProtection.DISABLE_ALWAYS_KEY constant to replace the 'disableAlways' magic string across config-paths.ts, next.ts, and permission.tsx so renames/typos are caught at compile time --- .../opencode/src/cli/cmd/tui/routes/session/permission.tsx | 3 ++- packages/opencode/src/kilocode/permission/config-paths.ts | 7 +++++-- packages/opencode/src/permission/next.ts | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx index 50b9d15f228..667761cd890 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx @@ -16,6 +16,7 @@ import { Locale } from "@/util/locale" import { Global } from "@/global" import { useDialog } from "../../ui/dialog" import { useTuiConfig } from "../../context/tui-config" +import { ConfigProtection } from "@/kilocode/permission/config-paths" // kilocode_change type PermissionStage = "permission" | "always" | "reject" @@ -429,7 +430,7 @@ export function PermissionPrompt(props: { request: PermissionRequest }) { ) // kilocode_change start — hide "Always allow" for config file edits - const options: Record = props.request.metadata?.disableAlways + const options: Record = props.request.metadata?.[ConfigProtection.DISABLE_ALWAYS_KEY] ? { once: "Allow once", reject: "Reject" } : { once: "Allow once", always: "Allow always", reject: "Reject" } // kilocode_change end diff --git a/packages/opencode/src/kilocode/permission/config-paths.ts b/packages/opencode/src/kilocode/permission/config-paths.ts index 1e0047675d2..35b554c78b8 100644 --- a/packages/opencode/src/kilocode/permission/config-paths.ts +++ b/packages/opencode/src/kilocode/permission/config-paths.ts @@ -15,6 +15,9 @@ export namespace ConfigProtection { */ const CONFIG_ROOT_FILES = new Set(["kilo.json", "kilo.jsonc", "opencode.json", "opencode.jsonc", "AGENTS.md"]) + /** Metadata key used to signal the UI to hide the "Allow always" option. */ + export const DISABLE_ALWAYS_KEY = "disableAlways" as const + function normalize(p: string): string { return p.replaceAll("\\", "/") } @@ -56,9 +59,9 @@ export namespace ConfigProtection { }): boolean { if (request.permission !== "edit") return false - // Check relative patterns (edit tool, apply_patch) + // Check patterns — handle both relative and absolute (mirrors metadata.filepath logic) for (const pattern of request.patterns) { - if (isRelative(pattern)) return true + if (path.isAbsolute(pattern) ? isAbsolute(pattern) : isRelative(pattern)) return true } // Check metadata.filepath (absolute for edit, comma-joined relative for apply_patch) diff --git a/packages/opencode/src/permission/next.ts b/packages/opencode/src/permission/next.ts index 9f0a486ff8a..b68fafd1f8a 100644 --- a/packages/opencode/src/permission/next.ts +++ b/packages/opencode/src/permission/next.ts @@ -206,7 +206,7 @@ export namespace PermissionNext { ...request, metadata: { ...request.metadata, - ...(protected_ ? { disableAlways: true } : {}), + ...(protected_ ? { [ConfigProtection.DISABLE_ALWAYS_KEY]: true } : {}), }, } // kilocode_change end From 1bb6c6618c62f388d750c66e5759022367f07937 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 12:38:11 +0000 Subject: [PATCH 019/261] docs(kilo-docs): add 1Password integration documentation to KiloClaw Tools --- docs/kiloclaw/tools.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 docs/kiloclaw/tools.md diff --git a/docs/kiloclaw/tools.md b/docs/kiloclaw/tools.md new file mode 100644 index 00000000000..207c4ea3e4a --- /dev/null +++ b/docs/kiloclaw/tools.md @@ -0,0 +1,33 @@ +# Tools + +## 1Password Integration for KiloClaw + +Connect your KiloClaw agent to 1Password to securely manage credentials and automate vault lookups without exposing sensitive keys in plain text. + +> ⚠️ **Warning:** This integration grants your agent read/write access to the vaults you specify. We strongly recommend creating a dedicated vault containing only the specific credentials your agent requires. + +### Setup Instructions + +#### 1. Create a Service Account + +Visit the [1Password Developer Portal](https://developer.1password.com/) and create a new Service Account. This provides the secure bridge between 1Password and KiloClaw. + +#### 2. Scope to a Dedicated Vault + +Grant the Service Account access to a specific "Agent" vault. Do not use your primary personal or team vault. Ensure only the necessary items (API keys, passwords, etc.) are stored here. + +#### 3. Copy the Token + +Copy the generated Service Account token (it will begin with `ops_`). Navigate to your **KiloClaw Settings** and paste this token into the **1Password configuration** field. + +#### 4. Save and Upgrade + +After saving the token, select **Upgrade to latest** (do not use **Redeploy**) to activate the integration. + +### Usage + +Once active, your agent can interact with the vault using the `op` CLI. Example command: + +```bash +op item get "My Login" +``` From 31a047ef9d98aab1d0e6daf94a4a1875e6865f57 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 12:43:52 +0000 Subject: [PATCH 020/261] docs(kilo-docs): add Brave Search and AgentCard integration sections to KiloClaw tools --- docs/kiloclaw/tools.md | 70 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/docs/kiloclaw/tools.md b/docs/kiloclaw/tools.md index 207c4ea3e4a..05de6c4650b 100644 --- a/docs/kiloclaw/tools.md +++ b/docs/kiloclaw/tools.md @@ -31,3 +31,73 @@ Once active, your agent can interact with the vault using the `op` CLI. Example ```bash op item get "My Login" ``` + +--- + +## Brave Search Integration + +Equip your KiloClaw agent with real-time web browsing capabilities by integrating the Brave Search API. This allows the agent to fetch up-to-date information, perform market research, and verify facts beyond its training data. + +### How to Generate a Brave Search API Key + +To get started, you will need to obtain a "BSA" (Brave Search API) key from the Brave developer portal. + +#### 1. Access the Brave Search Dashboard + +Go to [api.search.brave.com](https://api.search.brave.com) and sign in or create a developer account. + +#### 2. Choose a Subscription Plan + +Brave offers a **Free Tier** (limited queries per month) for testing and paid tiers for high-volume production use. Select the plan that fits your needs. + +#### 3. Create an API Key + +Once your account is active, navigate to the **API Keys** section and click **"Create New Key."** + +#### 4. Copy the Key + +Your key will typically begin with the prefix `BSA`. Copy this key immediately, as it may not be displayed again for security reasons. + +--- + +## AgentCard Integration + +Enable your KiloClaw agents to perform financial transactions by creating and managing virtual debit cards. This integration allows for automated purchasing and expense management within set limits. + +> ⚠️ **Important:** This tool permits your agent to spend real money. Use extreme caution with budget limits. AgentCard is currently in Beta; card issuance may be limited or waitlisted. + +### Setup Instructions + +#### 1. Create an AgentCard Account + +Install the AgentCard CLI and sign up via your terminal: + +```bash +agent-cards signup +``` + +#### 2. Add a Payment Method + +Link your funding source (via Stripe) to enable the creation of virtual cards: + +```bash +agent-cards payment-method +``` + +#### 3. Retrieve Your API Key + +Open your local configuration file located at `~/.agent-cards/config.json`. Copy the value assigned to the `jwt` key. + +#### 4. Configure KiloClaw + +1. Paste the **JWT** into the AgentCard setup field in your KiloClaw settings. +2. Click **Save**. +3. Use **Upgrade** (not Redeploy) to install the latest image and activate the feature. + +### Available Tools + +Once activated, your agent will have access to: + +- `create_card`: Generate a new virtual debit card. +- `list_cards`: View existing cards and their statuses. +- `check_balance`: Monitor available funds. From 60d2a8e19801abac7ceb3749ca1ba32e3b4fd75e Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 12:47:03 +0000 Subject: [PATCH 021/261] fix(kilo-docs): move KiloClaw tools page to correct directory and add nav entry Move docs/kiloclaw/tools.md to packages/kilo-docs/pages/kiloclaw/tools.mdx where published docs are sourced from, add frontmatter, and register the Tools page in the KiloClaw navigation config. --- packages/kilo-docs/lib/nav/kiloclaw.ts | 1 + .../tools.md => packages/kilo-docs/pages/kiloclaw/tools.mdx | 5 +++++ 2 files changed, 6 insertions(+) rename docs/kiloclaw/tools.md => packages/kilo-docs/pages/kiloclaw/tools.mdx (97%) diff --git a/packages/kilo-docs/lib/nav/kiloclaw.ts b/packages/kilo-docs/lib/nav/kiloclaw.ts index 50262d29f6f..37c673c7088 100644 --- a/packages/kilo-docs/lib/nav/kiloclaw.ts +++ b/packages/kilo-docs/lib/nav/kiloclaw.ts @@ -17,6 +17,7 @@ export const KiloClawNav: NavSection[] = [ { href: "/kiloclaw/development-tools/google", children: "Google Workspace" }, ], }, + { href: "/kiloclaw/tools", children: "Tools" }, { href: "/kiloclaw/version-pinning", children: "Version Pinning" }, { href: "/kiloclaw/troubleshooting", children: "Troubleshooting" }, { href: "/kiloclaw/pricing", children: "Pricing" }, diff --git a/docs/kiloclaw/tools.md b/packages/kilo-docs/pages/kiloclaw/tools.mdx similarity index 97% rename from docs/kiloclaw/tools.md rename to packages/kilo-docs/pages/kiloclaw/tools.mdx index 05de6c4650b..8fbd5ca0138 100644 --- a/docs/kiloclaw/tools.md +++ b/packages/kilo-docs/pages/kiloclaw/tools.mdx @@ -1,3 +1,8 @@ +--- +title: "Tools" +description: "Third-party tool integrations for your KiloClaw agent" +--- + # Tools ## 1Password Integration for KiloClaw From 61f3e8c5dbdb0c52c89b3a9da51c1cc5218cacc1 Mon Sep 17 00:00:00 2001 From: Ligia Zanchet Date: Wed, 25 Mar 2026 13:48:23 +0100 Subject: [PATCH 022/261] Apply suggestions from code review Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com> --- packages/kilo-docs/pages/kiloclaw/tools.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-docs/pages/kiloclaw/tools.mdx b/packages/kilo-docs/pages/kiloclaw/tools.mdx index 8fbd5ca0138..495771f2713 100644 --- a/packages/kilo-docs/pages/kiloclaw/tools.mdx +++ b/packages/kilo-docs/pages/kiloclaw/tools.mdx @@ -27,7 +27,7 @@ Copy the generated Service Account token (it will begin with `ops_`). Navigate t #### 4. Save and Upgrade -After saving the token, select **Upgrade to latest** (do not use **Redeploy**) to activate the integration. +After saving the token, use **Redeploy** to apply the new secret. Only use **Upgrade & Redeploy** if you also need to move to the latest platform version. ### Usage From df29396d774cf8933083b6ee3570526c8caba336 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 25 Mar 2026 14:51:41 +0200 Subject: [PATCH 023/261] feat(cli): add built-in kilo-config skill for on-demand config reference --- .../opencode/src/kilocode/skills/builtin.ts | 21 +++ .../src/kilocode/skills/kilo-config.md | 158 ++++++++++++++++++ packages/opencode/src/md.d.ts | 4 + packages/opencode/src/skill/skill.ts | 14 ++ packages/opencode/src/tool/skill.ts | 40 ++++- 5 files changed, 230 insertions(+), 7 deletions(-) create mode 100644 packages/opencode/src/kilocode/skills/builtin.ts create mode 100644 packages/opencode/src/kilocode/skills/kilo-config.md create mode 100644 packages/opencode/src/md.d.ts diff --git a/packages/opencode/src/kilocode/skills/builtin.ts b/packages/opencode/src/kilocode/skills/builtin.ts new file mode 100644 index 00000000000..f2d90d25735 --- /dev/null +++ b/packages/opencode/src/kilocode/skills/builtin.ts @@ -0,0 +1,21 @@ +// kilocode_change - new file +// Built-in skills that ship inside the CLI binary. +// Content is inlined at compile time via Bun's static import of .md files. +// Registered before all discovery phases so user skills with the same name override. + +import KILO_CONFIG from "./kilo-config.md" + +export interface BuiltinSkill { + name: string + description: string + content: string +} + +export const BUILTIN_SKILLS: BuiltinSkill[] = [ + { + name: "kilo-config", + description: + "Guide for configuring Kilo CLI: commands, agents, MCP servers, skills, permissions, instructions, plugins, providers, and all kilo.json fields. Use when the user asks about configuring or customizing Kilo.", + content: KILO_CONFIG, + }, +] diff --git a/packages/opencode/src/kilocode/skills/kilo-config.md b/packages/opencode/src/kilocode/skills/kilo-config.md new file mode 100644 index 00000000000..a7d394acfcd --- /dev/null +++ b/packages/opencode/src/kilocode/skills/kilo-config.md @@ -0,0 +1,158 @@ +# Kilo CLI Configuration Reference + +All config lives in `kilo.json` (or `kilo.jsonc`). Precedence low-to-high: remote well-known, global (`~/.config/kilo/kilo.json`), env `KILO_CONFIG`, project `./kilo.json`, `.kilo/kilo.json`, `KILO_CONFIG_CONTENT`, managed (`/etc/kilo/`). Deep-merged; later wins. + +## Commands (`.kilo/command/*.md`) + +Markdown files with YAML frontmatter. The filename (minus `.md`) becomes the command name invoked via `/name`. + +```yaml +--- +description: Run tests # optional, shown in command list +agent: code # optional, route to a specific agent +model: anthropic/claude-sonnet # optional, override model +subtask: true # optional, run as subtask +--- +Run all tests in $1 and fix failures. +Use $ARGUMENTS for the full arg string. +Reference files with @file and shell output with !`cmd`. +``` + +Template variables: `$1`-`$N` (positional args), `$ARGUMENTS` (full string), `@file` (file contents), `` !`cmd` `` (shell output). + +## Agents (`.kilo/agent/*.md`) + +```yaml +--- +description: When to use this agent +mode: primary # primary | subagent | all +model: anthropic/claude-sonnet # optional override +steps: 25 # max agentic iterations +hidden: false # hide from @ menu (subagent only) +color: "#FF5733" # hex or theme name +permission: # optional, agent-level permissions + bash: allow + edit: + "src/**": allow + "*": ask +--- +System prompt for this agent. +``` + +`mode` values: `primary` = selectable as main agent, `subagent` = only via Task tool, `all` = both. + +## Permissions + +Scalar form applies to all patterns. Object form maps glob patterns to actions. Evaluated top-to-bottom; first match wins. + +```jsonc +{ + "permission": { + "bash": "allow", // scalar: allow all bash + "edit": { + // object: pattern-matched + "src/**": "allow", + "*.lock": "deny", + "*": "ask", // fallback + }, + "read": "ask", + "skill": { "my-skill": "allow" }, + "external_directory": "deny", + }, +} +``` + +Actions: `"allow"`, `"ask"`, `"deny"`. Set `null` to delete an inherited key. + +Tool permissions: `read`, `edit`, `glob`, `grep`, `list`, `bash`, `task`, `webfetch`, `websearch`, `codesearch`, `lsp`, `skill`, `external_directory`, `todowrite`, `todoread`, `question`, `doom_loop`. + +## MCP Servers + +```jsonc +{ + "mcp": { + "local-server": { + "type": "local", + "command": ["node", "server.js"], + "environment": { "PORT": "3000" }, + "enabled": true, + "timeout": 10000, + }, + "remote-server": { + "type": "remote", + "url": "https://mcp.example.com", + "headers": { "Authorization": "Bearer ..." }, + "oauth": { "clientId": "...", "scope": "read" }, + "enabled": true, + }, + }, +} +``` + +Disable an inherited server: `{ "server-name": { "enabled": false } }`. + +## Providers + +```jsonc +{ + "provider": { + "anthropic": { + "options": { + "apiKey": "sk-...", + "baseURL": "https://custom.endpoint/v1", + "timeout": 300000, + }, + "models": { + "custom-model": { "name": "My Model" }, + }, + "whitelist": ["claude-*"], + "blacklist": ["claude-2*"], + }, + }, + "disabled_providers": ["openai"], + "enabled_providers": ["anthropic"], +} +``` + +## Skills + +Additional skill directories and remote URLs: + +```jsonc +{ + "skills": { + "paths": ["./my-skills", "~/shared-skills"], + "urls": ["https://example.com/.well-known/skills/"], + }, +} +``` + +Skills are markdown files at `skills//SKILL.md` with `name` and `description` in frontmatter. + +## Other Top-Level Fields + +| Field | Type | Description | +| ------------------ | ------------------------------ | --------------------------------------------------- | +| `model` | `"provider/model"` | Default model | +| `small_model` | `"provider/model"` | Model for titles/summaries | +| `default_agent` | `string` | Default primary agent (fallback: `code`) | +| `instructions` | `string[]` | Glob patterns for additional instruction files | +| `plugin` | `string[]` | Plugin specifiers (npm packages or `file://` paths) | +| `snapshot` | `boolean` | Enable git snapshots | +| `share` | `"manual"\|"auto"\|"disabled"` | Session sharing mode | +| `autoupdate` | `boolean\|"notify"` | Auto-update behavior | +| `username` | `string` | Display name override | +| `compaction.auto` | `boolean` | Auto-compact when context full (default: true) | +| `compaction.prune` | `boolean` | Prune old tool outputs (default: true) | + +## Config File Locations + +| Scope | Path | +| ------------ | ----------------------------------------------------------------------- | +| Project | `./kilo.json`, `./.kilo/kilo.json` | +| Global | `~/.config/kilo/kilo.json` | +| Managed | `/etc/kilo/kilo.json` (enterprise, highest priority) | +| Commands | `.kilo/command/*.md` (project), `~/.config/kilo/command/*.md` (global) | +| Agents | `.kilo/agent/*.md` (project), `~/.config/kilo/agent/*.md` (global) | +| Skills | `.kilo/skill/*/SKILL.md`, `.kilo/skills/*/SKILL.md` | +| Instructions | `AGENTS.md`, `.kilo/instructions.md`, glob patterns from `instructions` | diff --git a/packages/opencode/src/md.d.ts b/packages/opencode/src/md.d.ts new file mode 100644 index 00000000000..eb3e3b92d66 --- /dev/null +++ b/packages/opencode/src/md.d.ts @@ -0,0 +1,4 @@ +declare module "*.md" { + const content: string + export default content +} diff --git a/packages/opencode/src/skill/skill.ts b/packages/opencode/src/skill/skill.ts index d4c1d97144b..aaf6cc291f5 100644 --- a/packages/opencode/src/skill/skill.ts +++ b/packages/opencode/src/skill/skill.ts @@ -16,6 +16,7 @@ import { Discovery } from "./discovery" import { Glob } from "../util/glob" import { KilocodePaths } from "../kilocode/paths" // kilocode_change +import { BUILTIN_SKILLS } from "../kilocode/skills/builtin" // kilocode_change export namespace Skill { const log = Log.create({ service: "skill" }) @@ -52,10 +53,23 @@ export namespace Skill { const KILO_SKILL_PATTERN = "{skill,skills}/**/SKILL.md" const SKILL_PATTERN = "**/SKILL.md" + export const BUILTIN_LOCATION = "builtin" // kilocode_change + export const state = Instance.state(async () => { const skills: Record = {} const dirs = new Set() + // kilocode_change start - Register built-in skills first (lowest precedence, any external skill with same name overrides) + for (const skill of BUILTIN_SKILLS) { + skills[skill.name] = { + name: skill.name, + description: skill.description, + location: BUILTIN_LOCATION, + content: skill.content, + } + } + // kilocode_change end + const addSkill = async (match: string) => { const md = await ConfigMarkdown.parse(match).catch((err) => { const message = ConfigMarkdown.FrontmatterError.isInstance(err) diff --git a/packages/opencode/src/tool/skill.ts b/packages/opencode/src/tool/skill.ts index 8fcfb592dee..b092c6e8bfb 100644 --- a/packages/opencode/src/tool/skill.ts +++ b/packages/opencode/src/tool/skill.ts @@ -7,6 +7,8 @@ import { PermissionNext } from "../permission/next" import { Ripgrep } from "../file/ripgrep" import { iife } from "@/util/iife" +const BUILTIN = Skill.BUILTIN_LOCATION // kilocode_change + export const SkillTool = Tool.define("skill", async (ctx) => { const skills = await Skill.all() @@ -35,13 +37,18 @@ export const SkillTool = Tool.define("skill", async (ctx) => { "Invoke this tool to load a skill when a task matches one of the available skills listed below:", "", "", - ...accessibleSkills.flatMap((skill) => [ - ` `, - ` ${skill.name}`, - ` ${skill.description}`, - ` ${pathToFileURL(skill.location).href}`, - ` `, - ]), + // kilocode_change start - guard pathToFileURL for builtin skills + ...accessibleSkills.flatMap((skill) => { + const loc = skill.location === BUILTIN ? BUILTIN : pathToFileURL(skill.location).href + return [ + ` `, + ` ${skill.name}`, + ` ${skill.description}`, + ` ${loc}`, + ` `, + ] + }), + // kilocode_change end "", ].join("\n") @@ -73,6 +80,25 @@ export const SkillTool = Tool.define("skill", async (ctx) => { metadata: {}, }) + // kilocode_change start - built-in skills have no filesystem directory + if (skill.location === BUILTIN) { + return { + title: `Loaded skill: ${skill.name}`, + output: [ + ``, + `# Skill: ${skill.name}`, + "", + skill.content.trim(), + "", + ].join("\n"), + metadata: { + name: skill.name, + dir: BUILTIN, + }, + } + } + // kilocode_change end + const dir = path.dirname(skill.location) const base = pathToFileURL(dir).href From b53105a4eb85f5a278bdbaa56c52e2e72846d89d Mon Sep 17 00:00:00 2001 From: Ligia Zanchet Date: Wed, 25 Mar 2026 14:10:46 +0100 Subject: [PATCH 024/261] Update packages/kilo-docs/pages/kiloclaw/tools.mdx Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com> --- packages/kilo-docs/pages/kiloclaw/tools.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-docs/pages/kiloclaw/tools.mdx b/packages/kilo-docs/pages/kiloclaw/tools.mdx index 495771f2713..7a9708ecf28 100644 --- a/packages/kilo-docs/pages/kiloclaw/tools.mdx +++ b/packages/kilo-docs/pages/kiloclaw/tools.mdx @@ -97,7 +97,7 @@ Open your local configuration file located at `~/.agent-cards/config.json`. Copy 1. Paste the **JWT** into the AgentCard setup field in your KiloClaw settings. 2. Click **Save**. -3. Use **Upgrade** (not Redeploy) to install the latest image and activate the feature. +3. Use **Redeploy** to apply the new secret. Only use **Upgrade & Redeploy** if you also need the latest platform version. ### Available Tools From cd02ad416deacc7131cdd5a51bdf17c74415e4dc Mon Sep 17 00:00:00 2001 From: Ligia Zanchet Date: Wed, 25 Mar 2026 17:20:39 +0100 Subject: [PATCH 025/261] docs: restructure KiloClaw nav with nested sub-pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Split tools.mdx → tools/{1password,brave-search,agentcard}.md - Split chat-platforms.md → chat-platforms/{telegram,discord,slack}.md - Split control-ui.md → control-ui/{overview,changing-models,exec-approvals,version-pinning}.md - Split troubleshooting.md → troubleshooting/{common-questions,gateway-process,architecture}.md - Add faq/{general,pricing}.md as new top-level FAQ section - Update lib/nav/kiloclaw.ts with subLinks for all nested sections - Remove standalone Version Pinning and Pricing nav entries - Fix 1Password section: rewrite as step-by-step guide - Fix Brave Search: remove incorrect free tier mention --- packages/kilo-docs/lib/nav/kiloclaw.ts | 51 +++++++++++++-- .../pages/kiloclaw/chat-platforms/discord.md | 61 ++++++++++++++++++ .../pages/kiloclaw/chat-platforms/slack.md | 55 ++++++++++++++++ .../pages/kiloclaw/chat-platforms/telegram.md | 24 +++++++ .../kiloclaw/control-ui/changing-models.md | 22 +++++++ .../kiloclaw/control-ui/exec-approvals.md | 64 +++++++++++++++++++ .../pages/kiloclaw/control-ui/overview.md | 32 ++++++++++ .../kiloclaw/control-ui/version-pinning.md | 47 ++++++++++++++ .../kilo-docs/pages/kiloclaw/faq/general.md | 27 ++++++++ .../kilo-docs/pages/kiloclaw/faq/pricing.md | 31 +++++++++ .../pages/kiloclaw/{tools.mdx => tools.md} | 45 ++++++------- .../pages/kiloclaw/tools/1password.md | 37 +++++++++++ .../pages/kiloclaw/tools/agentcard.md | 46 +++++++++++++ .../pages/kiloclaw/tools/brave-search.md | 28 ++++++++ .../kiloclaw/troubleshooting/architecture.md | 14 ++++ .../troubleshooting/common-questions.md | 48 ++++++++++++++ .../pages/kiloclaw/troubleshooting/faq.md | 27 ++++++++ .../troubleshooting/gateway-process.md | 15 +++++ 18 files changed, 646 insertions(+), 28 deletions(-) create mode 100644 packages/kilo-docs/pages/kiloclaw/chat-platforms/discord.md create mode 100644 packages/kilo-docs/pages/kiloclaw/chat-platforms/slack.md create mode 100644 packages/kilo-docs/pages/kiloclaw/chat-platforms/telegram.md create mode 100644 packages/kilo-docs/pages/kiloclaw/control-ui/changing-models.md create mode 100644 packages/kilo-docs/pages/kiloclaw/control-ui/exec-approvals.md create mode 100644 packages/kilo-docs/pages/kiloclaw/control-ui/overview.md create mode 100644 packages/kilo-docs/pages/kiloclaw/control-ui/version-pinning.md create mode 100644 packages/kilo-docs/pages/kiloclaw/faq/general.md create mode 100644 packages/kilo-docs/pages/kiloclaw/faq/pricing.md rename packages/kilo-docs/pages/kiloclaw/{tools.mdx => tools.md} (62%) create mode 100644 packages/kilo-docs/pages/kiloclaw/tools/1password.md create mode 100644 packages/kilo-docs/pages/kiloclaw/tools/agentcard.md create mode 100644 packages/kilo-docs/pages/kiloclaw/tools/brave-search.md create mode 100644 packages/kilo-docs/pages/kiloclaw/troubleshooting/architecture.md create mode 100644 packages/kilo-docs/pages/kiloclaw/troubleshooting/common-questions.md create mode 100644 packages/kilo-docs/pages/kiloclaw/troubleshooting/faq.md create mode 100644 packages/kilo-docs/pages/kiloclaw/troubleshooting/gateway-process.md diff --git a/packages/kilo-docs/lib/nav/kiloclaw.ts b/packages/kilo-docs/lib/nav/kiloclaw.ts index 37c673c7088..1aac3c672a8 100644 --- a/packages/kilo-docs/lib/nav/kiloclaw.ts +++ b/packages/kilo-docs/lib/nav/kiloclaw.ts @@ -7,8 +7,25 @@ export const KiloClawNav: NavSection[] = [ { href: "/kiloclaw/overview", children: "Overview" }, { href: "/kiloclaw/dashboard", children: "Dashboard" }, { href: "/kiloclaw/pre-installed-software", children: "Pre-installed Software" }, - { href: "/kiloclaw/control-ui", children: "Control UI" }, - { href: "/kiloclaw/chat-platforms", children: "Chat Platforms" }, + { + href: "/kiloclaw/control-ui/overview", + children: "Control UI", + subLinks: [ + { href: "/kiloclaw/control-ui/overview", children: "Overview" }, + { href: "/kiloclaw/control-ui/changing-models", children: "Changing Models" }, + { href: "/kiloclaw/control-ui/exec-approvals", children: "Exec Approvals" }, + { href: "/kiloclaw/control-ui/version-pinning", children: "Version Pinning" }, + ], + }, + { + href: "/kiloclaw/chat-platforms/telegram", + children: "Chat Platforms", + subLinks: [ + { href: "/kiloclaw/chat-platforms/telegram", children: "Telegram" }, + { href: "/kiloclaw/chat-platforms/discord", children: "Discord" }, + { href: "/kiloclaw/chat-platforms/slack", children: "Slack" }, + ], + }, { href: "/kiloclaw/development-tools/github", children: "Development Tools", @@ -17,10 +34,32 @@ export const KiloClawNav: NavSection[] = [ { href: "/kiloclaw/development-tools/google", children: "Google Workspace" }, ], }, - { href: "/kiloclaw/tools", children: "Tools" }, - { href: "/kiloclaw/version-pinning", children: "Version Pinning" }, - { href: "/kiloclaw/troubleshooting", children: "Troubleshooting" }, - { href: "/kiloclaw/pricing", children: "Pricing" }, + { + href: "/kiloclaw/tools/1password", + children: "Tools", + subLinks: [ + { href: "/kiloclaw/tools/1password", children: "1Password" }, + { href: "/kiloclaw/tools/brave-search", children: "Brave Search" }, + { href: "/kiloclaw/tools/agentcard", children: "AgentCard" }, + ], + }, + { + href: "/kiloclaw/troubleshooting/common-questions", + children: "Troubleshooting", + subLinks: [ + { href: "/kiloclaw/troubleshooting/common-questions", children: "Common Questions" }, + { href: "/kiloclaw/troubleshooting/gateway-process", children: "Gateway Process States" }, + { href: "/kiloclaw/troubleshooting/architecture", children: "Architecture Notes" }, + ], + }, + { + href: "/kiloclaw/faq/general", + children: "FAQ", + subLinks: [ + { href: "/kiloclaw/faq/general", children: "General" }, + { href: "/kiloclaw/faq/pricing", children: "Pricing" }, + ], + }, ], }, ] diff --git a/packages/kilo-docs/pages/kiloclaw/chat-platforms/discord.md b/packages/kilo-docs/pages/kiloclaw/chat-platforms/discord.md new file mode 100644 index 00000000000..9f36f74b03c --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/chat-platforms/discord.md @@ -0,0 +1,61 @@ +--- +title: "Discord" +description: "Connect your KiloClaw agent to Discord" +--- + +# Discord + +Connect your KiloClaw agent to Discord by creating a bot in the Discord Developer Portal and linking it to your KiloClaw dashboard. + +## Create an Application and Bot + +1. Go to the [Discord Developer Portal](https://discord.com/developers/applications) and log in +2. Click **New Application**, give it a name, and click **Create** +3. Click **Bot** on the left sidebar +4. Click **Add Bot** and confirm + +## Enable Privileged Intents + +On the **Bot** page, scroll down to **Privileged Gateway Intents** and enable: + +- **Message Content Intent** (required) +- **Server Members Intent** (recommended — needed for role allowlists and name matching) +- **Presence Intent** (optional) + +## Copy Your Bot Token + +1. Scroll back up on the **Bot** page and click **Reset Token** + +> 📝 **Note** +> Despite the name, this generates your first token — nothing is being "reset." + +2. Copy the token that appears and paste it into the **Discord Bot Token** field in your KiloClaw dashboard. + +{% image src="/docs/img/kiloclaw/discord.png" alt="Connect account screen" width="800" caption="Discord bot token entry" /%} + +Enter the token in the Settings tab and click **Save**. You can remove or replace a configured token at any time. + +## Generate an Invite URL and Add the Bot to Your Server + +1. Click **OAuth2** on the sidebar +2. Scroll down to **OAuth2 URL Generator** and enable: + - `bot` + - `applications.commands` +3. A **Bot Permissions** section will appear below. Enable: + - View Channels + - Send Messages + - Read Message History + - Embed Links + - Attach Files + - Add Reactions (optional) +4. Copy the generated URL at the bottom +5. Paste it into your browser, select your server, and click **Continue** +6. You should now see your bot in the Discord server + +## Start Chatting with the Bot + +1. Right-click on the Bot in Discord and click **Message** +2. DM the bot `/pair` +3. You should get a response back with a pairing code +4. Return to [app.kilocode.ai/claw](https://app.kilocode.ai/claw) and confirm the pairing code and approve +5. You should now be able to chat with the bot from Discord diff --git a/packages/kilo-docs/pages/kiloclaw/chat-platforms/slack.md b/packages/kilo-docs/pages/kiloclaw/chat-platforms/slack.md new file mode 100644 index 00000000000..08fbb66f7b6 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/chat-platforms/slack.md @@ -0,0 +1,55 @@ +--- +title: "Slack" +description: "Connect your KiloClaw agent to Slack" +--- + +# Slack + +Connect your KiloClaw agent to Slack by creating a Slack app from the OpenClaw manifest and linking it to your KiloClaw dashboard. + +## Step 1: Create a Slack App from the OpenClaw Manifest + +1. Go to [Slack App Management](https://api.slack.com/apps) and click **Create New App** → **From a Manifest** +2. Copy the manifest from the [OpenClaw docs](https://docs.openclaw.ai/channels/slack#manifest-and-scope-checklist) +3. Paste the manifest JSON into Slack's manifest editor +4. Customize the manifest before creating: + - Rename the app to your preferred name wherever it appears + - Update the slash command if desired (e.g., `/kiloclaw`) +5. Click **Create** + +## Step 2: Generate Tokens + +You need two tokens from Slack: + +**App-Level Token** + +1. In your Slack app settings, scroll down to **App-Level Tokens** +2. Click **Generate Token** +3. Add the `connections:write` scope +4. Generate and copy the token (starts with `xapp-`) + +**Bot User OAuth Token** + +1. In the left sidebar, click **Install App** +2. Install the app to your workspace +3. Copy the **Bot User OAuth Token** (starts with `xoxb-`) + +## Step 3: Connect Slack to KiloClaw + +1. In the [KiloClaw UI](https://app.kilo.ai/claw), find the Slack integration section (may show "not configured") +2. Enter both tokens: + - The `xapp-` app-level token + - The `xoxb-` bot user OAuth token +3. Click **Save** +4. Scroll to the top of the KiloClaw UI and click **Redeploy**. Wait for the instance to come back up + +## Step 4: Pair Slack with KiloClaw + +1. In Slack, DM the app and type your slash command (e.g., `/claw`) followed by anything — this triggers the pairing flow + +> 📝 **Note** +> The slash command is whatever you defined in the manifest. Any text after the command will work to trigger pairing. + +2. The app will return a pairing code +3. Return to [app.kilocode.ai/claw](https://app.kilocode.ai/claw) and confirm the pairing code and approve +4. You should now be able to chat with the bot from Slack diff --git a/packages/kilo-docs/pages/kiloclaw/chat-platforms/telegram.md b/packages/kilo-docs/pages/kiloclaw/chat-platforms/telegram.md new file mode 100644 index 00000000000..8fd8d7b524d --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/chat-platforms/telegram.md @@ -0,0 +1,24 @@ +--- +title: "Telegram" +description: "Connect your KiloClaw agent to Telegram" +--- + +# Telegram + +Connect your KiloClaw agent to Telegram by creating a bot via BotFather and linking it to your KiloClaw dashboard. + +1. Open Telegram and search for [@BotFather](https://t.me/BotFather) +2. Send `/newbot` and follow the prompts to create your bot +3. Copy the **Bot Token** that BotFather gives you +4. Go to the **Settings** tab on your [KiloClaw dashboard](/docs/kiloclaw/dashboard) +5. Paste the token into the **Telegram Bot Token** field +6. Click **Save** +7. Redeploy your KiloClaw instance +8. Send a direct message to your bot in Telegram: `/start` + +{% image src="/docs/img/kiloclaw/telegram.png" alt="Connect account screen" width="800" caption="Telegram bot token entry" /%} + +You can remove or replace a configured token at any time. + +> ℹ️ **Info** +> Advanced settings such as DM policy, allow lists, and groups can be configured in the OpenClaw Control UI after connecting. diff --git a/packages/kilo-docs/pages/kiloclaw/control-ui/changing-models.md b/packages/kilo-docs/pages/kiloclaw/control-ui/changing-models.md new file mode 100644 index 00000000000..63c7fb77c62 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/control-ui/changing-models.md @@ -0,0 +1,22 @@ +--- +title: "Changing Models" +description: "Browse and switch models from the Control UI chat" +--- + +# Changing Models + +The Control UI Chat tab doubles as a command line for model management. KiloClaw exposes 335+ models through the `kilocode` provider and you can browse and switch between them without leaving the chat. + +| Command | Description | +| ------------------------------------ | ------------------------------------------------------------------------------- | +| `/model status` | View the currently active model and provider | +| `/models kilocode` | Browse available models (paginated, 20 per page) | +| `/models kilocode ` | Jump to a specific page (e.g. `/models kilocode 2`) | +| `/model kilocode//` | Switch to a specific model (e.g. `/model kilocode/anthropic/claude-sonnet-4.6`) | +| `/models kilocode all` | List every available model at once | + +Each `/models` response includes helper text at the bottom with shortcuts for switching, paging, and listing all models. + +To change the default model for all new sessions, edit `agents.defaults.model.primary` in your `openclaw.json` via **Config** in the Control UI (or the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#changing-the-model) for a quick dropdown pick). + +For the full list of providers, advanced configuration, and CLI commands, see the [OpenClaw Model Providers documentation](https://docs.openclaw.ai/providers). diff --git a/packages/kilo-docs/pages/kiloclaw/control-ui/exec-approvals.md b/packages/kilo-docs/pages/kiloclaw/control-ui/exec-approvals.md new file mode 100644 index 00000000000..1188f545c43 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/control-ui/exec-approvals.md @@ -0,0 +1,64 @@ +--- +title: "Exec Approvals" +description: "Control which commands your KiloClaw agent can run on the host machine" +--- + +# Exec Approvals + +Exec approvals are the safety interlock that controls which commands your agent can run on the host machine (gateway or node). By default, **all host exec requests are denied** — you must explicitly allowlist the commands you want your agent to run independently. This prevents accidental execution of destructive commands. + +{% callout type="warning" %} +The default security policy is `deny`. You must configure an allowlist before your agent can execute any host commands. +{% /callout %} + +## How It Works + +Approvals are enforced locally on the execution host and sit on top of tool policy and elevated gating. The effective policy is always the **stricter** of `tools.exec.*` and the approvals defaults. Settings are stored in `~/.openclaw/exec-approvals.json` on the host. + +## Security Policies + +| Policy | Behavior | +| ----------- | ---------------------------------------------- | +| `deny` | Block all host exec requests (default) | +| `allowlist` | Allow only commands matching the allowlist | +| `full` | Allow everything (equivalent to elevated mode) | + +## Ask Behavior + +The `ask` setting controls when the user is prompted for approval: + +| Setting | Behavior | +| --------- | ------------------------------------------------------- | +| `off` | Never prompt | +| `on-miss` | Prompt only when the allowlist does not match (default) | +| `always` | Prompt on every command | + +If a prompt is required but no UI is reachable, the `askFallback` setting decides the outcome (`deny` by default). + +## Allowlists + +Allowlists are **per agent** — each agent has its own set of allowed command patterns. Patterns are case-insensitive globs that must resolve to binary paths (basename-only entries are ignored). + +Example patterns: + +``` +~/Projects/**/bin/rg +~/.local/bin/* +/opt/homebrew/bin/rg +``` + +Each entry tracks last-used metadata (timestamp, command, resolved path) so you can audit and keep the list tidy. + +## Approval Flow + +When a command requires approval, the gateway broadcasts the request to connected operator clients. The approval dialog shows the command, arguments, working directory, agent ID, and resolved path. You can: + +- **Allow once** — run the command now +- **Allow always** — add to the allowlist and run +- **Deny** — block the request + +Approval prompts can also be forwarded to chat channels (Slack, Telegram, Discord, etc.) and resolved with `/approve`. + +## Editing in the Control UI + +Navigate to **Nodes > Exec Approvals** in the Control UI to edit defaults, per-agent overrides, and allowlists. Select a scope (Defaults or a specific agent), adjust the policy, add or remove allowlist patterns, then save. diff --git a/packages/kilo-docs/pages/kiloclaw/control-ui/overview.md b/packages/kilo-docs/pages/kiloclaw/control-ui/overview.md new file mode 100644 index 00000000000..564e11364eb --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/control-ui/overview.md @@ -0,0 +1,32 @@ +--- +title: "Control UI Overview" +description: "Browser-based dashboard for managing your OpenClaw instance" +--- + +# OpenClaw Control UI + +The Control UI is a browser-based dashboard (built with Vite + Lit) served by the OpenClaw Gateway on the same port as the gateway itself (default: `http://localhost:18789/`). It connects via WebSocket and gives you real-time control over your agent, channels, sessions, and system configuration. For KiloClaw users, see [Accessing the Control UI](/docs/kiloclaw/dashboard#accessing-the-control-ui) to get started. + +## Features + +- **Chat** — Send messages, stream responses with live tool-call output, view history, and abort runs. +- **Channels** — View the status of connected messaging platforms, scan QR codes for login, and edit per-channel config. +- **Sessions** — List active sessions with thinking and verbose overrides. +- **Cron Jobs** — Create, edit, enable/disable, run, and view history of scheduled tasks. +- **Skills** — View status, enable/disable, install, and manage API keys for skills. +- **Nodes** — List paired devices and their capabilities. +- **Exec Approvals** — Edit gateway or node command allowlists. See [Exec Approvals](/docs/kiloclaw/control-ui/exec-approvals). +- **Config** — View and edit `openclaw.json` with schema-based form rendering and a raw JSON editor. +- **Logs** — Live tail of gateway logs with filtering and export. +- **Debug** — Status, health, model snapshots, event log, and manual RPC calls. +- **Update** — Run package updates and restart the gateway. + +For more details, please see the official [OpenClaw documentation](https://docs.openclaw.ai/web/control-ui). + +{% callout type="warning" %} +Do not use the **Update** feature in the Control UI to update KiloClaw. Use **Redeploy** from the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#redeploy) instead. Updating via the Control UI will not apply the correct KiloClaw platform image and may break your instance. +{% /callout %} + +## Authentication + +Auth is handled via token or password on the WebSocket handshake. Remote connections require one-time device pairing — the pairing request appears on the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#pairing-requests) or in the Control UI itself. diff --git a/packages/kilo-docs/pages/kiloclaw/control-ui/version-pinning.md b/packages/kilo-docs/pages/kiloclaw/control-ui/version-pinning.md new file mode 100644 index 00000000000..9905620b83a --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/control-ui/version-pinning.md @@ -0,0 +1,47 @@ +--- +title: "Version Pinning" +description: "Pin your KiloClaw instance to a specific OpenClaw version and variant" +--- + +# Version Pinning + +Version pinning lets you lock your KiloClaw instance to a specific OpenClaw version and variant. This gives you control over when your instance upgrades — it stays on the pinned version until you explicitly change it. + +## When to Use Version Pinning + +Version pinning is useful when: + +- A changelog entry is marked **Redeploy Required** and you're not ready to upgrade yet +- You're running a workflow that depends on specific OpenClaw behavior +- You want to test the impact of an upgrade before committing to it + +## How to Pin a Version + +1. Go to your [KiloClaw dashboard](https://app.kilo.ai/profile) +2. Open the **Settings** tab +3. Scroll to the **Version Pinning** section +4. Select a **version** and **variant** from the dropdowns +5. Click **Save** + +Your instance will stay on the selected version until you change or clear the pin. + +{% callout type="info" %} +After saving a version pin, you need to **Redeploy** for the change to take effect on your running instance. +{% /callout %} + +## Variants + +Each OpenClaw version is available in one or more variants. Variants may differ in included tools, default configuration, or base image. Select the variant that matches your use case, or use the default if unsure. + +## Clearing a Pin + +To return to automatic updates: + +1. Go to **Settings > Version Pinning** +2. Clear the version selection +3. Click **Save** +4. Use **Upgrade & Redeploy** from the dashboard to apply the latest platform version + +{% callout type="warning" %} +Clearing a pin and running **Upgrade & Redeploy** will update your instance to the latest supported platform version. Review the changelog before upgrading to check for breaking changes. +{% /callout %} diff --git a/packages/kilo-docs/pages/kiloclaw/faq/general.md b/packages/kilo-docs/pages/kiloclaw/faq/general.md new file mode 100644 index 00000000000..6a63a54d016 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/faq/general.md @@ -0,0 +1,27 @@ +--- +title: "FAQ" +description: "Frequently asked questions about KiloClaw" +--- + +# FAQ + +## How can I change my model? + +You can change the model in two ways: + +- **From chat** — Type `/model` in the Chat window within the OpenClaw Control UI to switch models directly. +- **From the dashboard** — Go to [https://app.kilo.ai/claw](https://app.kilo.ai/claw), select the model you want, and click **Save**. No redeploy is needed. + +## Can I access the filesystem? + +You can access instance files in `/root/.openclaw/` directly from the [KiloClaw Dashboard](https://app.kilo.ai/claw). This is useful for examining or restoring config files. You can also interact with files through your OpenClaw agent using its built-in file tools. + +## Can I access my KiloClaw via SSH? + +For security reasons, SSH access is currently disabled for all KiloClaw instances. Our primary goal is to provide a secure environment for all users, and restricting direct SSH access is one of the many measures we take to ensure the platform remains safe and protected for everyone. + +## How can I update my OpenClaw? + +Do **not** click **Update Now** inside the OpenClaw Control UI — this is not supported for KiloClaw instances and may break your setup. + +Updates are managed by the KiloClaw platform team to ensure stability. When a new version is available, it will be announced in the **Changelog** on your dashboard. To apply the update, click **Upgrade & Redeploy** from the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#redeploy). diff --git a/packages/kilo-docs/pages/kiloclaw/faq/pricing.md b/packages/kilo-docs/pages/kiloclaw/faq/pricing.md new file mode 100644 index 00000000000..e63d9aa99b2 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/faq/pricing.md @@ -0,0 +1,31 @@ +--- +title: "Pricing" +description: "Pricing details for KiloClaw instances and model inference" +--- + +# Pricing + +KiloClaw uses Kilo Gateway credits by default — if you route requests through BYOK, model usage is billed directly by your provider instead. + +## Instance Hosting + +KiloClaw hosting is **free during the beta period**. Each user gets a dedicated machine (2 shared vCPUs, 3 GB RAM, 10 GB SSD) at no cost. + +> ℹ️ **Info** +> Beta pricing is subject to change. Paid hosting tiers may be introduced after the beta period ends. Any changes will be announced in advance. + +## Model Inference + +Model usage is charged against your [Gateway credit balance](/docs/gateway/usage-and-billing). Costs vary by model — premium models like Claude Opus or GPT-5.4-pro cost more per token than smaller models. + +## Free Models + +Several models are available at **no additional cost** to your Gateway balance. These are great for getting started or for tasks that don't need the most powerful models. + +To see which models are currently free, check the [Kilo Leaderboard](https://kilo.ai/leaderboard#all-models) — free models are marked accordingly. + +## Adding Credits + +You can add Gateway credits from your [Kilo account](https://app.kilo.ai). Credits are shared across all Kilo products (VSCode extension, CLI, Cloud Agents, and KiloClaw). + +See [Adding Credits](/docs/getting-started/adding-credits) and [Gateway Usage and Billing](/docs/gateway/usage-and-billing) for details. diff --git a/packages/kilo-docs/pages/kiloclaw/tools.mdx b/packages/kilo-docs/pages/kiloclaw/tools.md similarity index 62% rename from packages/kilo-docs/pages/kiloclaw/tools.mdx rename to packages/kilo-docs/pages/kiloclaw/tools.md index 7a9708ecf28..601e67e6dfd 100644 --- a/packages/kilo-docs/pages/kiloclaw/tools.mdx +++ b/packages/kilo-docs/pages/kiloclaw/tools.md @@ -5,37 +5,38 @@ description: "Third-party tool integrations for your KiloClaw agent" # Tools -## 1Password Integration for KiloClaw +## 1Password Integration Guide -Connect your KiloClaw agent to 1Password to securely manage credentials and automate vault lookups without exposing sensitive keys in plain text. +Connect your KiloClaw agent to 1Password to securely manage credentials. This allows your agent to fetch API keys or passwords without ever seeing them in plain text. -> ⚠️ **Warning:** This integration grants your agent read/write access to the vaults you specify. We strongly recommend creating a dedicated vault containing only the specific credentials your agent requires. +### Step 1: Create a Dedicated Vault -### Setup Instructions +For maximum security, do not give the bot access to your personal vault. -#### 1. Create a Service Account +1. Log in to your 1Password account. +2. Create a **New Vault** (e.g., name it `Kilo-Agent-Vault`). +3. Move only the specific items/keys you want the bot to use into this vault. -Visit the [1Password Developer Portal](https://developer.1password.com/) and create a new Service Account. This provides the secure bridge between 1Password and KiloClaw. +### Step 2: Generate a Service Account Token -#### 2. Scope to a Dedicated Vault +1. Go to the [1Password Developer Portal](https://developer.1password.com/). +2. Select **Service Accounts** and click **Create a Service Account**. +3. **Important:** When prompted for permissions, select only the dedicated vault you created in Step 1. +4. Copy the generated token (it will begin with `ops_`). -Grant the Service Account access to a specific "Agent" vault. Do not use your primary personal or team vault. Ensure only the necessary items (API keys, passwords, etc.) are stored here. +### Step 3: Configure KiloClaw -#### 3. Copy the Token +1. Navigate to your KiloClaw dashboard: [app.kilo.ai/claw](https://app.kilo.ai/claw). +2. Go to **Settings > Tools** (or **Edit Files**). +3. Paste your `ops_` token into the **1Password Setup** field. +4. Click **Save**. -Copy the generated Service Account token (it will begin with `ops_`). Navigate to your **KiloClaw Settings** and paste this token into the **1Password configuration** field. +### Step 4: Activate the Integration -#### 4. Save and Upgrade +To apply the changes and inject the 1Password CLI into your environment: -After saving the token, use **Redeploy** to apply the new secret. Only use **Upgrade & Redeploy** if you also need to move to the latest platform version. - -### Usage - -Once active, your agent can interact with the vault using the `op` CLI. Example command: - -```bash -op item get "My Login" -``` +1. Select **Upgrade to latest**. +2. Perform a **Redeploy** to restart the agent with the new permissions active. --- @@ -53,7 +54,7 @@ Go to [api.search.brave.com](https://api.search.brave.com) and sign in or create #### 2. Choose a Subscription Plan -Brave offers a **Free Tier** (limited queries per month) for testing and paid tiers for high-volume production use. Select the plan that fits your needs. +Brave Search API requires a paid subscription. Select the plan that fits your usage volume. #### 3. Create an API Key @@ -71,7 +72,7 @@ Enable your KiloClaw agents to perform financial transactions by creating and ma > ⚠️ **Important:** This tool permits your agent to spend real money. Use extreme caution with budget limits. AgentCard is currently in Beta; card issuance may be limited or waitlisted. -### Setup Instructions +### AgentCard Setup #### 1. Create an AgentCard Account diff --git a/packages/kilo-docs/pages/kiloclaw/tools/1password.md b/packages/kilo-docs/pages/kiloclaw/tools/1password.md new file mode 100644 index 00000000000..10868c41ef4 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/tools/1password.md @@ -0,0 +1,37 @@ +--- +title: "1Password Integration" +description: "Connect your KiloClaw agent to 1Password to securely manage credentials" +--- + +# 1Password Integration Guide + +Connect your KiloClaw agent to 1Password to securely manage credentials. This allows your agent to fetch API keys or passwords without ever seeing them in plain text. + +## Step 1: Create a Dedicated Vault + +For maximum security, do not give the bot access to your personal vault. + +1. Log in to your 1Password account. +2. Create a **New Vault** (e.g., name it `Kilo-Agent-Vault`). +3. Move only the specific items/keys you want the bot to use into this vault. + +## Step 2: Generate a Service Account Token + +1. Go to the [1Password Developer Portal](https://developer.1password.com/). +2. Select **Service Accounts** and click **Create a Service Account**. +3. **Important:** When prompted for permissions, select only the dedicated vault you created in Step 1. +4. Copy the generated token (it will begin with `ops_`). + +## Step 3: Configure KiloClaw + +1. Navigate to your KiloClaw dashboard: [app.kilo.ai/claw](https://app.kilo.ai/claw). +2. Go to **Settings > Tools** (or **Edit Files**). +3. Paste your `ops_` token into the **1Password Setup** field. +4. Click **Save**. + +## Step 4: Activate the Integration + +To apply the changes and inject the 1Password CLI into your environment: + +1. Select **Upgrade to latest**. +2. Perform a **Redeploy** to restart the agent with the new permissions active. diff --git a/packages/kilo-docs/pages/kiloclaw/tools/agentcard.md b/packages/kilo-docs/pages/kiloclaw/tools/agentcard.md new file mode 100644 index 00000000000..9903871c8be --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/tools/agentcard.md @@ -0,0 +1,46 @@ +--- +title: "AgentCard Integration" +description: "Enable your KiloClaw agents to perform financial transactions with virtual debit cards" +--- + +# AgentCard Integration + +Enable your KiloClaw agents to perform financial transactions by creating and managing virtual debit cards. This integration allows for automated purchasing and expense management within set limits. + +> ⚠️ **Important:** This tool permits your agent to spend real money. Use extreme caution with budget limits. AgentCard is currently in Beta; card issuance may be limited or waitlisted. + +## AgentCard Setup + +### 1. Create an AgentCard Account + +Install the AgentCard CLI and sign up via your terminal: + +```bash +agent-cards signup +``` + +### 2. Add a Payment Method + +Link your funding source (via Stripe) to enable the creation of virtual cards: + +```bash +agent-cards payment-method +``` + +### 3. Retrieve Your API Key + +Open your local configuration file located at `~/.agent-cards/config.json`. Copy the value assigned to the `jwt` key. + +### 4. Configure KiloClaw + +1. Paste the **JWT** into the AgentCard setup field in your KiloClaw settings. +2. Click **Save**. +3. Use **Redeploy** to apply the new secret. Only use **Upgrade & Redeploy** if you also need the latest platform version. + +## Available Tools + +Once activated, your agent will have access to: + +- `create_card`: Generate a new virtual debit card. +- `list_cards`: View existing cards and their statuses. +- `check_balance`: Monitor available funds. diff --git a/packages/kilo-docs/pages/kiloclaw/tools/brave-search.md b/packages/kilo-docs/pages/kiloclaw/tools/brave-search.md new file mode 100644 index 00000000000..6d448c3dada --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/tools/brave-search.md @@ -0,0 +1,28 @@ +--- +title: "Brave Search Integration" +description: "Equip your KiloClaw agent with real-time web browsing via the Brave Search API" +--- + +# Brave Search Integration + +Equip your KiloClaw agent with real-time web browsing capabilities by integrating the Brave Search API. This allows the agent to fetch up-to-date information, perform market research, and verify facts beyond its training data. + +## How to Generate a Brave Search API Key + +To get started, you will need to obtain a "BSA" (Brave Search API) key from the Brave developer portal. + +### 1. Access the Brave Search Dashboard + +Go to [api.search.brave.com](https://api.search.brave.com) and sign in or create a developer account. + +### 2. Choose a Subscription Plan + +Brave Search API requires a paid subscription. Select the plan that fits your usage volume. + +### 3. Create an API Key + +Once your account is active, navigate to the **API Keys** section and click **"Create New Key."** + +### 4. Copy the Key + +Your key will typically begin with the prefix `BSA`. Copy this key immediately, as it may not be displayed again for security reasons. diff --git a/packages/kilo-docs/pages/kiloclaw/troubleshooting/architecture.md b/packages/kilo-docs/pages/kiloclaw/troubleshooting/architecture.md new file mode 100644 index 00000000000..2290fb1b9c2 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/troubleshooting/architecture.md @@ -0,0 +1,14 @@ +--- +title: "Architecture Notes" +description: "How KiloClaw instances are structured" +--- + +# Architecture Notes + +For advanced users — how KiloClaw instances are structured: + +- **Dedicated machine** — Each user gets their own machine and persistent volume. There is no shared infrastructure between users. +- **Region-pinned storage** — Your persistent volume stays in the region where your instance was originally created. +- **Network isolation** — OpenClaw binds to loopback only; external traffic is proxied through a Kilo controller. +- **Per-user authentication** — The gateway token is derived per-user for authenticating requests to your machine. +- **Encryption at rest** — Sensitive data (API keys, channel tokens) is encrypted at rest in the machine configuration. diff --git a/packages/kilo-docs/pages/kiloclaw/troubleshooting/common-questions.md b/packages/kilo-docs/pages/kiloclaw/troubleshooting/common-questions.md new file mode 100644 index 00000000000..1c49d2a39df --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/troubleshooting/common-questions.md @@ -0,0 +1,48 @@ +--- +title: "Common Questions" +description: "Answers to common KiloClaw troubleshooting questions" +--- + +# Common Questions + +## OpenClaw Doctor + +OpenClaw Doctor is the recommended first step when something isn't working. It runs diagnostics on your instance and automatically fixes common configuration issues. + +To use it: + +1. Make sure your instance is running +2. Click **OpenClaw Doctor** on your [dashboard](/docs/kiloclaw/dashboard) +3. Watch the output as it runs — results appear in real time + +## Does Redeploy reset my instance? + +No. Redeploy does **not** delete your files, git repos, or cron jobs. It stops the machine, applies the latest platform image and your current configuration, and starts it again with the same persistent storage. Think of it as "update and restart." + +## When should I use Restart OpenClaw vs Redeploy? + +- **Restart OpenClaw** — Restarts just the OpenClaw process. The machine stays up. Use this for quick recovery from a process-level issue or when you want to apply openclaw config changes. +- **Redeploy** — Stops and restarts the entire machine with the latest image and config. Use this when the changelog shows a redeploy hint, or after changing channel tokens or secrets. + +## My bot isn't responding on Telegram/Discord/Slack + +1. Check that the channel token is configured in [Settings](/docs/kiloclaw/dashboard#channels) +2. Make sure you **Redeployed** or **Restarted OpenClaw** after saving tokens +3. Check for pending pairing requests — the user may need to be approved +4. Try running **OpenClaw Doctor** + +## Accessing and Restoring Config Files + +You can directly access the files in `/root/.openclaw/` on the [KiloClaw Dashboard](https://app.kilo.ai/claw) using the file browser of the edit files dialog. This can be a useful way to examine or update the config files (especially `openclaw.json`) if you run into an issue. There may also be backups in the form of `openclaw.bak` files that you can manually restore from if needed. + +## The gateway shows "Crashed" + +The OpenClaw process is automatically restarted when it crashes. Check the Gateway Process tab on your dashboard for the exit code and restart count. If it keeps crashing: + +1. Run **OpenClaw Doctor** +2. Try a **Redeploy** to apply the latest platform image +3. If the issue persists, join the [Kilo Discord](https://kilo.ai/discord) and share details in the KiloClaw channel + +## I changed the model but the agent is still using the old one + +After selecting a new model, click **Save & Provision** to apply it. This refreshes the API key and saves the new model. You may also need to **Restart OpenClaw** for the change to take full effect. diff --git a/packages/kilo-docs/pages/kiloclaw/troubleshooting/faq.md b/packages/kilo-docs/pages/kiloclaw/troubleshooting/faq.md new file mode 100644 index 00000000000..6a63a54d016 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/troubleshooting/faq.md @@ -0,0 +1,27 @@ +--- +title: "FAQ" +description: "Frequently asked questions about KiloClaw" +--- + +# FAQ + +## How can I change my model? + +You can change the model in two ways: + +- **From chat** — Type `/model` in the Chat window within the OpenClaw Control UI to switch models directly. +- **From the dashboard** — Go to [https://app.kilo.ai/claw](https://app.kilo.ai/claw), select the model you want, and click **Save**. No redeploy is needed. + +## Can I access the filesystem? + +You can access instance files in `/root/.openclaw/` directly from the [KiloClaw Dashboard](https://app.kilo.ai/claw). This is useful for examining or restoring config files. You can also interact with files through your OpenClaw agent using its built-in file tools. + +## Can I access my KiloClaw via SSH? + +For security reasons, SSH access is currently disabled for all KiloClaw instances. Our primary goal is to provide a secure environment for all users, and restricting direct SSH access is one of the many measures we take to ensure the platform remains safe and protected for everyone. + +## How can I update my OpenClaw? + +Do **not** click **Update Now** inside the OpenClaw Control UI — this is not supported for KiloClaw instances and may break your setup. + +Updates are managed by the KiloClaw platform team to ensure stability. When a new version is available, it will be announced in the **Changelog** on your dashboard. To apply the update, click **Upgrade & Redeploy** from the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#redeploy). diff --git a/packages/kilo-docs/pages/kiloclaw/troubleshooting/gateway-process.md b/packages/kilo-docs/pages/kiloclaw/troubleshooting/gateway-process.md new file mode 100644 index 00000000000..045139fa11c --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/troubleshooting/gateway-process.md @@ -0,0 +1,15 @@ +--- +title: "Gateway Process States" +description: "Understanding KiloClaw gateway process states" +--- + +# Gateway Process States + +The Gateway Process tab shows the current state of the OpenClaw process inside your machine: + +- **Running** — The process is up and handling requests +- **Stopped** — The process is not running +- **Starting** — The process is booting up +- **Stopping** — The process is shutting down gracefully +- **Crashed** — The process exited unexpectedly and will be automatically restarted +- **Shutting Down** — The process is stopping as part of a machine stop or redeploy From e198bfed1a29dd6453e99db51c5221eab87a3702 Mon Sep 17 00:00:00 2001 From: Ligia Zanchet Date: Wed, 25 Mar 2026 17:22:46 +0100 Subject: [PATCH 026/261] docs: remove AgentCard beta warning and clarify Brave Search has no free tier --- packages/kilo-docs/pages/kiloclaw/tools/agentcard.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/kilo-docs/pages/kiloclaw/tools/agentcard.md b/packages/kilo-docs/pages/kiloclaw/tools/agentcard.md index 9903871c8be..79a23bf4622 100644 --- a/packages/kilo-docs/pages/kiloclaw/tools/agentcard.md +++ b/packages/kilo-docs/pages/kiloclaw/tools/agentcard.md @@ -7,8 +7,6 @@ description: "Enable your KiloClaw agents to perform financial transactions with Enable your KiloClaw agents to perform financial transactions by creating and managing virtual debit cards. This integration allows for automated purchasing and expense management within set limits. -> ⚠️ **Important:** This tool permits your agent to spend real money. Use extreme caution with budget limits. AgentCard is currently in Beta; card issuance may be limited or waitlisted. - ## AgentCard Setup ### 1. Create an AgentCard Account From 284094a3788d45ded46b151c4efb60d8327c4f05 Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Wed, 25 Mar 2026 23:35:23 -0400 Subject: [PATCH 027/261] =?UTF-8?q?docs(kilo-docs):=20reorder=20tabs=20to?= =?UTF-8?q?=20VSCode=20=E2=86=92=20CLI=20=E2=86=92=20Legacy,=20fix=20combi?= =?UTF-8?q?ned=20tabs=20and=20wording?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Reorder all tab groups to VSCode → CLI → VSCode (Legacy) - Split combined 'VSCode & CLI' tabs into separate tabs - Replace kilo.json with kilo.jsonc references - Fix 'new CLI/extension' → 'the extension/CLI' wording - Fix 'current VSCode & CLI version' → platform-neutral phrasing --- .../code-with-ai/agents/chat-interface.md | 115 ++++++----- .../code-with-ai/agents/context-mentions.md | 174 ++++++++-------- .../code-with-ai/agents/model-selection.md | 28 +-- .../code-with-ai/agents/orchestrator-mode.md | 34 +-- .../pages/code-with-ai/agents/using-modes.md | 194 +++++++++++------- 5 files changed, 308 insertions(+), 237 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md index 7f0980cf8be..a0612fe2838 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md @@ -16,13 +16,6 @@ If you're typing code in the editor and want AI to finish your line or block, ch ## Quick Setup {% tabs %} -{% tab label="VSCode (Legacy)" %} - -Find the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar. Click it to open the chat panel. - -**Lost the panel?** Go to View > Open View... and search for "Kilo Code" - -{% /tab %} {% tab label="VSCode" %} Click the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar to open the sidebar chat. You can also pop it out into an editor tab for a larger workspace. @@ -32,6 +25,13 @@ Click the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar t Open your terminal and run `kilo` to launch the interactive TUI. You'll see a prompt where you can start typing requests immediately. The TUI is fully keyboard-driven — no mouse required. +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +Find the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar. Click it to open the chat panel. + +**Lost the panel?** Go to View > Open View... and search for "Kilo Code" + {% /tab %} {% /tabs %} @@ -63,30 +63,6 @@ Open your terminal and run `kilo` to launch the interactive TUI. You'll see a pr ## The Chat Interface {% tabs %} -{% tab label="VSCode (Legacy)" %} - -{% image src="/docs/img/the-chat-interface/the-chat-interface-1.png" alt="Chat interface components labeled with callouts" width="800" caption="Everything you need is right here" /%} - -**Essential controls:** - -- **Chat history** - See your conversation and task history -- **Input field** - Type your requests here (press Enter to send) -- **Action buttons** - Approve or reject Kilo's proposed changes -- **Plus button** - Start a new task session -- **Mode selector** - Choose how Kilo should approach your task - -**Providing context with @-mentions:** - -Reference files and other context directly in your message using `@`: - -- `@file` - Reference a specific file -- `@url` - Include content from a URL -- `@problems` - Include current VS Code problems -- `@terminal` - Include terminal output -- `@git-changes` - Include uncommitted changes -- `@commit` - Reference a specific commit - -{% /tab %} {% tab label="VSCode" %} **Essential controls:** @@ -114,6 +90,30 @@ The extension automatically passes context from your editor, including your open Type `@` in the TUI to get file autocomplete suggestions, or mention file paths directly in your message (e.g., "look at src/utils.ts") and the agent will read them. When using the non-interactive `kilo run` command, you can pass `-f path/to/file.ts` to explicitly include files (this flag is not available in the TUI). The agent also has `glob`, `grep`, and `read` tools to discover files on its own. +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +{% image src="/docs/img/the-chat-interface/the-chat-interface-1.png" alt="Chat interface components labeled with callouts" width="800" caption="Everything you need is right here" /%} + +**Essential controls:** + +- **Chat history** - See your conversation and task history +- **Input field** - Type your requests here (press Enter to send) +- **Action buttons** - Approve or reject Kilo's proposed changes +- **Plus button** - Start a new task session +- **Mode selector** - Choose how Kilo should approach your task + +**Providing context with @-mentions:** + +Reference files and other context directly in your message using `@`: + +- `@file` - Reference a specific file +- `@url` - Include content from a URL +- `@problems` - Include current VS Code problems +- `@terminal` - Include terminal output +- `@git-changes` - Include uncommitted changes +- `@commit` - Reference a specific commit + {% /tab %} {% /tabs %} @@ -149,6 +149,24 @@ Type `@` in the TUI to get file autocomplete suggestions, or mention file paths When Kilo Code needs more information to complete a task, it uses the [`ask_followup_question`](/docs/automate/tools/ask-followup-question) tool. To make responding easier and faster, Kilo Code often provides suggested answers alongside the question. {% tabs %} +{% tab label="VSCode" %} + +**How it works:** + +1. **Question Appears** - Kilo Code asks a question using the `question` tool +2. **Options Displayed** - Selectable options are presented that you can choose from +3. **Selection** - Pick an option or type a custom response + +{% /tab %} +{% tab label="CLI" %} + +**How it works:** + +1. **Question Appears** - Kilo Code asks a question using the `question` tool +2. **Options Displayed** - Selectable options are presented that you can choose from +3. **Selection** - Pick an option or type a custom response + +{% /tab %} {% tab label="VSCode (Legacy)" %} {% image src="/docs/img/suggested-responses/suggested-responses.png" alt="Example of Kilo Code asking a question with suggested response buttons below it" width="800" caption="Suggested responses appear as clickable buttons below questions" /%} @@ -173,15 +191,6 @@ You have two options for using suggested responses: - _Alternatively_, hover over the suggestion button and click the pencil icon ({% codicon name="edit" /%}) that appears - **Result**: The text of the suggestion is copied into the chat input box. You can then modify the text as needed before pressing Enter to send your customized response. This is useful when a suggestion is close but needs minor adjustments. -{% /tab %} -{% tab label="VSCode & CLI" %} - -**How it works:** - -1. **Question Appears** - Kilo Code asks a question using the `question` tool -2. **Options Displayed** - Selectable options are presented that you can choose from -3. **Selection** - Pick an option or type a custom response - {% /tab %} {% /tabs %} @@ -196,19 +205,6 @@ This feature streamlines the interaction when Kilo Code requires clarification, ## Tips for Better Workflow {% tabs %} -{% tab label="VSCode (Legacy)" %} - -{% callout type="tip" %} -**Move Kilo Code to the Secondary Side Bar** for a better layout. Right-click on the Kilo Code icon in the Activity Bar and select **Move To → Secondary Side Bar**. This lets you see the Explorer, Search, Source Control, etc. alongside Kilo Code. - -{% image src="/docs/img/move-to-secondary.png" alt="Move to Secondary Side Bar" width="600" caption="Move Kilo Code to the Secondary Side Bar for better workspace organization" /%} -{% /callout %} - -{% callout type="tip" %} -**Drag files directly into chat.** Once you have Kilo Code in a separate sidebar from the file explorer, you can drag files from the explorer into the chat window (even multiple at once). Just hold down the Shift key after you start dragging the files. -{% /callout %} - -{% /tab %} {% tab label="VSCode" %} {% callout type="tip" %} @@ -234,6 +230,19 @@ This feature streamlines the interaction when Kilo Code requires clarification, **The TUI is keyboard-driven.** Navigate, approve changes, and switch agents entirely from the keyboard — no mouse needed. {% /callout %} +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +{% callout type="tip" %} +**Move Kilo Code to the Secondary Side Bar** for a better layout. Right-click on the Kilo Code icon in the Activity Bar and select **Move To → Secondary Side Bar**. This lets you see the Explorer, Search, Source Control, etc. alongside Kilo Code. + +{% image src="/docs/img/move-to-secondary.png" alt="Move to Secondary Side Bar" width="600" caption="Move Kilo Code to the Secondary Side Bar for better workspace organization" /%} +{% /callout %} + +{% callout type="tip" %} +**Drag files directly into chat.** Once you have Kilo Code in a separate sidebar from the file explorer, you can drag files from the explorer into the chat window (even multiple at once). Just hold down the Shift key after you start dragging the files. +{% /callout %} + {% /tab %} {% /tabs %} diff --git a/packages/kilo-docs/pages/code-with-ai/agents/context-mentions.md b/packages/kilo-docs/pages/code-with-ai/agents/context-mentions.md index eab8848c54f..0a3bcfdc170 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/context-mentions.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/context-mentions.md @@ -5,9 +5,95 @@ description: "How to provide context to Kilo Code using mentions" # Context Mentions -Providing the right context helps Kilo Code understand your project and perform tasks accurately. How you provide that context depends on which version of Kilo Code you're using — the **VSCode (Legacy)** version uses `@`-mentions in the chat input, while the current **VSCode & CLI** version uses a tool-based approach where the agent automatically discovers the context it needs. +Providing the right context helps Kilo Code understand your project and perform tasks accurately. How you provide that context depends on which platform you're using — the **VSCode** extension and **CLI** use a tool-based approach where the agent automatically discovers the context it needs, while the **VSCode (Legacy)** extension uses `@`-mentions in the chat input. {% tabs %} +{% tab label="VSCode" %} + +The **VSCode** extension uses a tool-based context model. The agent **automatically discovers and reads the context it needs** using built-in tools. You can also type `@` in the chat input to get file autocomplete suggestions, but the agent can also find files on its own using its tools. + +## How Context Works + +When you describe a task, the agent uses its tools — `read`, `grep`, `glob`, and others — to find and read relevant files on its own. You don't need to explicitly point it at files in most cases; just describe what you want done and the agent will locate the right code. + +### Automatic Editor Context + +The agent automatically receives context from your editor: + +| Context | Details | +| --------------- | -------------------------------------------------- | +| **Active file** | The file currently open and focused in your editor | +| **Open tabs** | Files you have open in editor tabs | + +This context is passed to the agent without any explicit mentions — it's included automatically with each message you send. + +{% callout type="note" %} +**Selection** and **diagnostics** are not sent automatically with each message. They are available through VS Code Code Actions (e.g., selecting code and using the lightbulb menu), but are not part of the default editor context. +{% /callout %} + +### Tool-Based File Access + +Rather than attaching file contents up front, the agent reads files on demand during its work: + +| Tool | Purpose | Example | +| -------- | --------------------------------------------- | ------------------------------------------- | +| **read** | Read the contents of a specific file | Agent reads `src/utils.ts` to understand it | +| **glob** | Find files matching a pattern | Agent searches for `**/*.test.ts` | +| **grep** | Search file contents for a pattern | Agent searches for `function handleError` | +| **bash** | Run shell commands including `git` operations | Agent runs `git diff` or `git log` | + +This means the agent can explore your entire project as needed, rather than being limited to files you explicitly mention. + +## Best Practices + +| Practice | Description | +| ------------------------------ | -------------------------------------------------------------------------------------------------- | +| **Describe the task clearly** | The agent finds context on its own — focus on _what_ you want done rather than _where_ the code is | +| **Mention files when helpful** | If you know the exact file, mention its path to save the agent a search step | +| **Keep editor tabs relevant** | Open tabs are passed as context, so keep relevant files open | +| **Trust the agent's tools** | The agent can search, read, and explore your codebase — let it do the discovery work | + +{% /tab %} +{% tab label="CLI" %} + +The CLI uses a tool-based context model. The agent **automatically discovers and reads the context it needs** using built-in tools. In the TUI, you can type `@` to get file autocomplete suggestions for quick file references. + +## How Context Works + +When you describe a task, the agent uses its tools — `read`, `grep`, `glob`, and others — to find and read relevant files on its own. You don't need to explicitly point it at files in most cases; just describe what you want done and the agent will locate the right code. + +### Providing File Context + +In the terminal-based TUI, you can provide context in several ways: + +- **Type `@` for file autocomplete** — In the TUI, type `@` followed by a filename to get autocomplete suggestions for quick file references. +- **Mention file paths in your message** — Simply refer to files by path in your conversation text (e.g., "look at src/utils.ts") and the agent will read them. +- **Use `kilo run -f`** — When using the non-interactive `kilo run` command, pass `-f path/to/file.ts` to explicitly include a file's contents in the context. This flag is not available in the interactive TUI. +- **Let the agent find files itself** — The agent has access to `glob` (find files by pattern), `grep` (search file contents), and `read` (read file contents) tools. Describe what you're looking for and it will locate the relevant code. + +### Tool-Based File Access + +Rather than attaching file contents up front, the agent reads files on demand during its work: + +| Tool | Purpose | Example | +| -------- | --------------------------------------------- | ------------------------------------------- | +| **read** | Read the contents of a specific file | Agent reads `src/utils.ts` to understand it | +| **glob** | Find files matching a pattern | Agent searches for `**/*.test.ts` | +| **grep** | Search file contents for a pattern | Agent searches for `function handleError` | +| **bash** | Run shell commands including `git` operations | Agent runs `git diff` or `git log` | + +This means the agent can explore your entire project as needed, rather than being limited to files you explicitly mention. + +## Best Practices + +| Practice | Description | +| ------------------------------ | -------------------------------------------------------------------------------------------------- | +| **Describe the task clearly** | The agent finds context on its own — focus on _what_ you want done rather than _where_ the code is | +| **Mention files when helpful** | If you know the exact file, mention its path to save the agent a search step | +| **Use `kilo run -f`** | Pass key files with `-f` when using `kilo run` for immediate context (not available in the TUI) | +| **Trust the agent's tools** | The agent can search, read, and explore your codebase — let it do the discovery work | + +{% /tab %} {% tab label="VSCode (Legacy)" %} Context mentions are a powerful way to provide Kilo Code with specific information about your project, allowing it to perform tasks more accurately and efficiently. You can use mentions to refer to files, folders, problems, and Git commits. Context mentions start with the `@` symbol. @@ -122,91 +208,5 @@ The dropdown automatically suggests: | **Eliminate copy-pasting** | Use mentions instead of manually copying code or errors | | **Combine mentions** | "Fix @problems in @/src/component.ts using the pattern from commit @a1b2c3d" | -{% /tab %} -{% tab label="VSCode" %} - -The current **VSCode** version uses a fundamentally different context model compared to the **VSCode (Legacy)** version. The agent **automatically discovers and reads the context it needs** using built-in tools. You can also type `@` in the chat input to get file autocomplete suggestions, but the agent can also find files on its own using its tools. - -## How Context Works - -When you describe a task, the agent uses its tools — `read`, `grep`, `glob`, and others — to find and read relevant files on its own. You don't need to explicitly point it at files in most cases; just describe what you want done and the agent will locate the right code. - -### Automatic Editor Context - -The agent automatically receives context from your editor: - -| Context | Details | -| --------------- | -------------------------------------------------- | -| **Active file** | The file currently open and focused in your editor | -| **Open tabs** | Files you have open in editor tabs | - -This context is passed to the agent without any explicit mentions — it's included automatically with each message you send. - -{% callout type="note" %} -**Selection** and **diagnostics** are not sent automatically with each message. They are available through VS Code Code Actions (e.g., selecting code and using the lightbulb menu), but are not part of the default editor context. -{% /callout %} - -### Tool-Based File Access - -Rather than attaching file contents up front, the agent reads files on demand during its work: - -| Tool | Purpose | Example | -| -------- | --------------------------------------------- | ------------------------------------------- | -| **read** | Read the contents of a specific file | Agent reads `src/utils.ts` to understand it | -| **glob** | Find files matching a pattern | Agent searches for `**/*.test.ts` | -| **grep** | Search file contents for a pattern | Agent searches for `function handleError` | -| **bash** | Run shell commands including `git` operations | Agent runs `git diff` or `git log` | - -This means the agent can explore your entire project as needed, rather than being limited to files you explicitly mention. - -## Best Practices - -| Practice | Description | -| ------------------------------ | -------------------------------------------------------------------------------------------------- | -| **Describe the task clearly** | The agent finds context on its own — focus on _what_ you want done rather than _where_ the code is | -| **Mention files when helpful** | If you know the exact file, mention its path to save the agent a search step | -| **Keep editor tabs relevant** | Open tabs are passed as context, so keep relevant files open | -| **Trust the agent's tools** | The agent can search, read, and explore your codebase — let it do the discovery work | - -{% /tab %} -{% tab label="CLI" %} - -The CLI uses a tool-based context model. The agent **automatically discovers and reads the context it needs** using built-in tools. In the TUI, you can type `@` to get file autocomplete suggestions for quick file references. - -## How Context Works - -When you describe a task, the agent uses its tools — `read`, `grep`, `glob`, and others — to find and read relevant files on its own. You don't need to explicitly point it at files in most cases; just describe what you want done and the agent will locate the right code. - -### Providing File Context - -In the terminal-based TUI, you can provide context in several ways: - -- **Type `@` for file autocomplete** — In the TUI, type `@` followed by a filename to get autocomplete suggestions for quick file references. -- **Mention file paths in your message** — Simply refer to files by path in your conversation text (e.g., "look at src/utils.ts") and the agent will read them. -- **Use `kilo run -f`** — When using the non-interactive `kilo run` command, pass `-f path/to/file.ts` to explicitly include a file's contents in the context. This flag is not available in the interactive TUI. -- **Let the agent find files itself** — The agent has access to `glob` (find files by pattern), `grep` (search file contents), and `read` (read file contents) tools. Describe what you're looking for and it will locate the relevant code. - -### Tool-Based File Access - -Rather than attaching file contents up front, the agent reads files on demand during its work: - -| Tool | Purpose | Example | -| -------- | --------------------------------------------- | ------------------------------------------- | -| **read** | Read the contents of a specific file | Agent reads `src/utils.ts` to understand it | -| **glob** | Find files matching a pattern | Agent searches for `**/*.test.ts` | -| **grep** | Search file contents for a pattern | Agent searches for `function handleError` | -| **bash** | Run shell commands including `git` operations | Agent runs `git diff` or `git log` | - -This means the agent can explore your entire project as needed, rather than being limited to files you explicitly mention. - -## Best Practices - -| Practice | Description | -| ------------------------------ | -------------------------------------------------------------------------------------------------- | -| **Describe the task clearly** | The agent finds context on its own — focus on _what_ you want done rather than _where_ the code is | -| **Mention files when helpful** | If you know the exact file, mention its path to save the agent a search step | -| **Use `kilo run -f`** | Pass key files with `-f` when using `kilo run` for immediate context (not available in the TUI) | -| **Trust the agent's tools** | The agent can search, read, and explore your codebase — let it do the discovery work | - {% /tab %} {% /tabs %} diff --git a/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md b/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md index ee22b39cf31..6ec0ada9b0b 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md @@ -22,26 +22,26 @@ While the specifics change constantly, some principles stay consistent: ### How to Select and Switch Models {% tabs %} +{% tab label="VSCode" %} + +- Open the **Settings webview** in the extension sidebar to select a model. +- Alternatively, set models directly in the `kilo.jsonc` config file (the extension reads the same config as the CLI). + +{% /tab %} +{% tab label="CLI" %} + +- Set the default model with the `model` key in your `kilo.jsonc` config file. +- In the TUI, use the **model picker** (keybind to cycle through configured models). +- For non-interactive use, pass `--model` flag to `kilo run` (e.g., `kilo run --model claude-sonnet-4-20250514`). +- Configure per-agent models in the agents section of your config. + +{% /tab %} {% tab label="VSCode (Legacy)" %} - Use the **model dropdown** in the chat panel to select a model for each conversation. - Configure **API profiles** in Settings to group provider + model combinations and switch between them quickly. - Models are **sticky per mode** — each mode (Code, Architect, Debug, etc.) remembers the last model you selected. -{% /tab %} -{% tab label="VSCode" %} - -- Open the **Settings webview** in the extension sidebar to select a model. -- Alternatively, set models directly in the `kilo.json` config file (the extension reads the same config as the CLI). - -{% /tab %} -{% tab label="CLI" %} - -- Set the default model with the `model` key in your `kilo.json` config file. -- In the TUI, use the **model picker** (keybind to cycle through configured models). -- For non-interactive use, pass `--model` flag to `kilo run` (e.g., `kilo run --model claude-sonnet-4-20250514`). -- Configure per-agent models in the agents section of your config. - {% /tab %} {% /tabs %} diff --git a/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md b/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md index 84762da247d..9aff3db2104 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md @@ -36,24 +36,34 @@ Use subtasks to maintain clarity. If a request significantly shifts focus or req {% /callout %} {% tabs %} -{% tab label="VSCode (Legacy)" %} +{% tab label="VSCode" %} -{% youtube url="https://www.youtube.com/watch?v=20MmJNeOODo" caption="Orchestrator Mode explained and demonstrated" /%} - -In the **VSCode** version, orchestrator mode uses two tools to manage subtasks: - -1. The [`new_task`](/docs/automate/tools/new-task) tool creates a subtask. Context is passed via the `message` parameter, and the subtask's mode is specified via the `mode` parameter (e.g., `code`, `architect`, `debug`). -2. When a subtask finishes, it calls [`attempt_completion`](/docs/automate/tools/attempt-completion). The summary is passed back to the parent via the `result` parameter. - -{% /tab %} -{% tab label="VSCode & CLI" %} - -In the new CLI and extension, orchestrator mode uses the `task` tool to launch **subagent sessions**: +Orchestrator mode uses the `task` tool to launch **subagent sessions**: - The `task` tool creates a new child session. The agent name is specified as a parameter (e.g., `general`, `explore`, or custom subagent types you define). - Child sessions are **fully isolated** — they run in their own conversation context and do not share message history with the parent. - When the subagent completes its work, it returns a single message back to the parent orchestrator with the result. - The parent orchestrator can launch multiple subagent sessions concurrently for parallel work. +{% /tab %} +{% tab label="CLI" %} + +Orchestrator mode uses the `task` tool to launch **subagent sessions**: + +- The `task` tool creates a new child session. The agent name is specified as a parameter (e.g., `general`, `explore`, or custom subagent types you define). +- Child sessions are **fully isolated** — they run in their own conversation context and do not share message history with the parent. +- When the subagent completes its work, it returns a single message back to the parent orchestrator with the result. +- The parent orchestrator can launch multiple subagent sessions concurrently for parallel work. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +{% youtube url="https://www.youtube.com/watch?v=20MmJNeOODo" caption="Orchestrator Mode explained and demonstrated" /%} + +In the legacy extension, orchestrator mode uses two tools to manage subtasks: + +1. The [`new_task`](/docs/automate/tools/new-task) tool creates a subtask. Context is passed via the `message` parameter, and the subtask's mode is specified via the `mode` parameter (e.g., `code`, `architect`, `debug`). +2. When a subtask finishes, it calls [`attempt_completion`](/docs/automate/tools/attempt-completion). The summary is passed back to the parent via the `result` parameter. + {% /tab %} {% /tabs %} diff --git a/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md b/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md index 3f5953d7e55..3d1f1c9a7c5 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md @@ -8,7 +8,7 @@ description: "Understanding and using different modes in Kilo Code" Modes in Kilo Code are specialized personas that tailor the assistant's behavior to your current task. Each mode offers different capabilities, expertise, and access levels to help you accomplish specific goals. {% callout type="info" %} -The **VSCode (Legacy)** version calls these **modes**, while the current **VSCode & CLI** version calls them **agents**. The concept is the same—specialized personas with distinct tool access and behavior. +The **VSCode** extension and **CLI** call these **agents**, while the **VSCode (Legacy)** extension calls them **modes**. The concept is the same — specialized personas with distinct tool access and behavior. {% /callout %} ## Why Use Different Modes? @@ -21,6 +21,24 @@ The **VSCode (Legacy)** version calls these **modes**, while the current **VSCod ## Switching Between Modes {% tabs %} +{% tab label="VSCode" %} + +There are several ways to switch agents: + +- **Dropdown menu:** Click the agent selector in the sidebar to switch between agents. +- **Slash commands:** Type `/` in the chat input to switch agents (e.g., `/code`, `/ask`, `/plan`, `/debug`). +- **Keyboard shortcut:** Use a keyboard shortcut to cycle through available agents. + +{% /tab %} +{% tab label="CLI" %} + +There are several ways to switch agents: + +- **Keybinds:** Press the displayed key to cycle through available agents. +- **Slash commands:** Type `/` in the chat input to see available commands, including switching agents (e.g., `/code`, `/ask`, `/plan`, `/debug`). +- **Config file:** Set the `default_agent` key in your configuration to change the default agent on startup. + +{% /tab %} {% tab label="VSCode (Legacy)" %} {% youtube url="https://youtu.be/cS4vQfX528w" caption="Explaining the different modes in Kilo Code" /%} @@ -56,30 +74,116 @@ Users often confuse `/newtask` and `/smol`. Here's the key difference: {% image src="/docs/img/modes/modes-2.png" alt="Accepting a mode switch suggestion from Kilo Code" width="400" /%} -{% /tab %} -{% tab label="VSCode" %} - -There are several ways to switch agents: - -- **Dropdown menu:** Click the agent selector in the sidebar to switch between agents. -- **Slash commands:** Type `/` in the chat input to switch agents (e.g., `/code`, `/ask`, `/plan`, `/debug`). -- **Keyboard shortcut:** Use a keyboard shortcut to cycle through available agents. - -{% /tab %} -{% tab label="CLI" %} - -There are several ways to switch agents: - -- **Keybinds:** Press the displayed key to cycle through available agents. -- **Slash commands:** Type `/` in the chat input to see available commands, including switching agents (e.g., `/code`, `/ask`, `/plan`, `/debug`). -- **Config file:** Set the `default_agent` key in your configuration to change the default agent on startup. - {% /tab %} {% /tabs %} ## Built-in Modes {% tabs %} +{% tab label="VSCode" %} + +### code (Default) + +| Aspect | Details | +| -------------------- | ----------------------------------------------------------------------------------------------------------------- | +| **Description** | A skilled software engineer with expertise in programming languages, design patterns, and best practices | +| **Tool Access** | Full access to all tools: `read`, `edit`, `glob`, `grep`, `bash`, `task`, `webfetch`, plus tools from MCP servers | +| **Ideal For** | Writing code, implementing features, debugging, and general development | +| **Special Features** | No tool restrictions — full flexibility for all coding tasks | + +### ask + +| Aspect | Details | +| -------------------- | ------------------------------------------------------------------------------------------------- | +| **Description** | A knowledgeable technical assistant focused on answering questions without changing your codebase | +| **Tool Access** | Read-only tools only (cannot edit files or run commands) | +| **Ideal For** | Code explanation, concept exploration, and technical learning | +| **Special Features** | Optimized for informative responses without modifying your project | + +### plan + +| Aspect | Details | +| -------------------- | ---------------------------------------------------------------------------------------------------- | +| **Description** | An experienced technical leader and planner who helps design systems and create implementation plans | +| **Tool Access** | Read-only tools plus restricted file editing (e.g., markdown files only) | +| **Ideal For** | System design, high-level planning, and architecture discussions | +| **Special Features** | Similar to the legacy extension's "Architect" mode, with a planning-focused approach | + +### debug + +| Aspect | Details | +| -------------------- | ----------------------------------------------------------------------------------- | +| **Description** | An expert problem solver specializing in systematic troubleshooting and diagnostics | +| **Tool Access** | Full access to all tools | +| **Ideal For** | Tracking down bugs, diagnosing errors, and resolving complex issues | +| **Special Features** | Uses a methodical approach of analyzing, narrowing possibilities, and fixing issues | + +### orchestrator + +| Aspect | Details | +| -------------------- | -------------------------------------------------------------------------------------------------------------------- | +| **Description** | A strategic workflow orchestrator who coordinates complex tasks by delegating them to appropriate specialized agents | +| **Tool Access** | Limited access to create new tasks and coordinate workflows | +| **Ideal For** | Breaking down complex projects into manageable subtasks assigned to specialized agents | +| **Special Features** | Delegates work to other agents; also has access to the **explore** subagent for codebase exploration | + +{% callout type="info" %} +The VSCode extension and CLI do not include a built-in Review agent. Code review workflows can be handled by the **code** agent or via custom agent configurations. +{% /callout %} + +{% /tab %} +{% tab label="CLI" %} + +### code (Default) + +| Aspect | Details | +| -------------------- | ----------------------------------------------------------------------------------------------------------------- | +| **Description** | A skilled software engineer with expertise in programming languages, design patterns, and best practices | +| **Tool Access** | Full access to all tools: `read`, `edit`, `glob`, `grep`, `bash`, `task`, `webfetch`, plus tools from MCP servers | +| **Ideal For** | Writing code, implementing features, debugging, and general development | +| **Special Features** | No tool restrictions — full flexibility for all coding tasks | + +### ask + +| Aspect | Details | +| -------------------- | ------------------------------------------------------------------------------------------------- | +| **Description** | A knowledgeable technical assistant focused on answering questions without changing your codebase | +| **Tool Access** | Read-only tools only (cannot edit files or run commands) | +| **Ideal For** | Code explanation, concept exploration, and technical learning | +| **Special Features** | Optimized for informative responses without modifying your project | + +### plan + +| Aspect | Details | +| -------------------- | ---------------------------------------------------------------------------------------------------- | +| **Description** | An experienced technical leader and planner who helps design systems and create implementation plans | +| **Tool Access** | Read-only tools plus restricted file editing (e.g., markdown files only) | +| **Ideal For** | System design, high-level planning, and architecture discussions | +| **Special Features** | Similar to the legacy extension's "Architect" mode, with a planning-focused approach | + +### debug + +| Aspect | Details | +| -------------------- | ----------------------------------------------------------------------------------- | +| **Description** | An expert problem solver specializing in systematic troubleshooting and diagnostics | +| **Tool Access** | Full access to all tools | +| **Ideal For** | Tracking down bugs, diagnosing errors, and resolving complex issues | +| **Special Features** | Uses a methodical approach of analyzing, narrowing possibilities, and fixing issues | + +### orchestrator + +| Aspect | Details | +| -------------------- | -------------------------------------------------------------------------------------------------------------------- | +| **Description** | A strategic workflow orchestrator who coordinates complex tasks by delegating them to appropriate specialized agents | +| **Tool Access** | Limited access to create new tasks and coordinate workflows | +| **Ideal For** | Breaking down complex projects into manageable subtasks assigned to specialized agents | +| **Special Features** | Delegates work to other agents; also has access to the **explore** subagent for codebase exploration | + +{% callout type="info" %} +The VSCode extension and CLI do not include a built-in Review agent. Code review workflows can be handled by the **code** agent or via custom agent configurations. +{% /callout %} + +{% /tab %} {% tab label="VSCode (Legacy)" %} ### Code Mode (Default) @@ -140,58 +244,6 @@ There are several ways to switch agents: | **Ideal For** | Catching issues early, enforcing code standards, accelerating PR turnaround | | **Special Features** | Code review before committing, surfacing feedback across performance, security, style, and test coverage | -{% /tab %} -{% tab label="VSCode & CLI" %} - -### code (Default) - -| Aspect | Details | -| -------------------- | ----------------------------------------------------------------------------------------------------------------- | -| **Description** | A skilled software engineer with expertise in programming languages, design patterns, and best practices | -| **Tool Access** | Full access to all tools: `read`, `edit`, `glob`, `grep`, `bash`, `task`, `webfetch`, plus tools from MCP servers | -| **Ideal For** | Writing code, implementing features, debugging, and general development | -| **Special Features** | No tool restrictions—full flexibility for all coding tasks | - -### ask - -| Aspect | Details | -| -------------------- | ------------------------------------------------------------------------------------------------- | -| **Description** | A knowledgeable technical assistant focused on answering questions without changing your codebase | -| **Tool Access** | Read-only tools only (cannot edit files or run commands) | -| **Ideal For** | Code explanation, concept exploration, and technical learning | -| **Special Features** | Optimized for informative responses without modifying your project | - -### plan - -| Aspect | Details | -| -------------------- | ---------------------------------------------------------------------------------------------------- | -| **Description** | An experienced technical leader and planner who helps design systems and create implementation plans | -| **Tool Access** | Read-only tools plus restricted file editing (e.g., markdown files only) | -| **Ideal For** | System design, high-level planning, and architecture discussions | -| **Special Features** | Similar to the **VSCode (Legacy)** version's "Architect" mode, with a planning-focused approach | - -### debug - -| Aspect | Details | -| -------------------- | ----------------------------------------------------------------------------------- | -| **Description** | An expert problem solver specializing in systematic troubleshooting and diagnostics | -| **Tool Access** | Full access to all tools | -| **Ideal For** | Tracking down bugs, diagnosing errors, and resolving complex issues | -| **Special Features** | Uses a methodical approach of analyzing, narrowing possibilities, and fixing issues | - -### orchestrator - -| Aspect | Details | -| -------------------- | -------------------------------------------------------------------------------------------------------------------- | -| **Description** | A strategic workflow orchestrator who coordinates complex tasks by delegating them to appropriate specialized agents | -| **Tool Access** | Limited access to create new tasks and coordinate workflows | -| **Ideal For** | Breaking down complex projects into manageable subtasks assigned to specialized agents | -| **Special Features** | Delegates work to other agents; also has access to the **explore** subagent for codebase exploration | - -{% callout type="info" %} -The **VSCode & CLI** version does not include a built-in Review agent. Code review workflows can be handled by the **code** agent or via custom agent configurations. -{% /callout %} - {% /tab %} {% /tabs %} From 3ccd762cbe1f2b270ff82af36b13c5683a36539b Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Thu, 26 Mar 2026 00:57:59 -0400 Subject: [PATCH 028/261] docs(kilo-docs): address review comments on code-with-ai/agents tabs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - model-selection: fix config key `agents` → `agent` (singular) - using-modes: fix slash commands to reference `/agents` (not /code etc.) - using-modes: fix plan agent permissions (plan files in .kilo/plans/ only) - orchestrator-mode: rewrite intro to mention subagents (general, explore) instead of primary modes (code, architect, debug) - chat-interface: remove legacy ask_followup_question from shared intro - chat-interface: make closing CTA platform-neutral --- .../kilo-docs/pages/code-with-ai/agents/chat-interface.md | 4 ++-- .../pages/code-with-ai/agents/model-selection.md | 2 +- .../pages/code-with-ai/agents/orchestrator-mode.md | 2 +- .../kilo-docs/pages/code-with-ai/agents/using-modes.md | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md index a0612fe2838..ba8eb64948e 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md @@ -146,7 +146,7 @@ Reference files and other context directly in your message using `@`: ## Suggested Responses -When Kilo Code needs more information to complete a task, it uses the [`ask_followup_question`](/docs/automate/tools/ask-followup-question) tool. To make responding easier and faster, Kilo Code often provides suggested answers alongside the question. +When Kilo Code needs more information to complete a task, it asks a follow-up question and often provides suggested answers to make responding faster. {% tabs %} {% tab label="VSCode" %} @@ -246,4 +246,4 @@ This feature streamlines the interaction when Kilo Code requires clarification, {% /tab %} {% /tabs %} -Ready to start coding? Open the chat panel and describe what you want to build! +Ready to start coding? Start a session in Kilo Code and describe what you want to build! diff --git a/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md b/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md index 6ec0ada9b0b..5884e850e6c 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md @@ -33,7 +33,7 @@ While the specifics change constantly, some principles stay consistent: - Set the default model with the `model` key in your `kilo.jsonc` config file. - In the TUI, use the **model picker** (keybind to cycle through configured models). - For non-interactive use, pass `--model` flag to `kilo run` (e.g., `kilo run --model claude-sonnet-4-20250514`). -- Configure per-agent models in the agents section of your config. +- Configure per-agent models in the `agent` section of your config. {% /tab %} {% tab label="VSCode (Legacy)" %} diff --git a/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md b/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md index 9aff3db2104..fecb036ffb9 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md @@ -5,7 +5,7 @@ description: "Using Orchestrator mode for complex multi-step tasks" # Orchestrator Mode: Coordinate Complex Workflows -Orchestrator Mode (formerly known as Boomerang Tasks) allows you to break down complex projects into smaller, manageable pieces. Think of it like delegating parts of your work to specialized assistants. Each subtask runs in its own context, often using a different Kilo Code mode tailored for that specific job (like [`code`](/docs/code-with-ai/agents/using-modes#code-mode-default), [`architect`](/docs/code-with-ai/agents/using-modes#architect-mode), or [`debug`](/docs/code-with-ai/agents/using-modes#debug-mode)). +Orchestrator Mode allows you to break down complex projects into smaller, manageable pieces. Think of it like delegating parts of your work to specialized assistants. Each subtask runs in its own context using a subagent (such as `general` for autonomous work or `explore` for codebase research) tailored for that specific job. ## Why Use Orchestrator Mode? diff --git a/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md b/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md index 3d1f1c9a7c5..7bbf77dae3a 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/using-modes.md @@ -26,7 +26,7 @@ The **VSCode** extension and **CLI** call these **agents**, while the **VSCode ( There are several ways to switch agents: - **Dropdown menu:** Click the agent selector in the sidebar to switch between agents. -- **Slash commands:** Type `/` in the chat input to switch agents (e.g., `/code`, `/ask`, `/plan`, `/debug`). +- **Slash commands:** Type `/` in the chat input to see available commands, including `/agents` to open the agent picker. - **Keyboard shortcut:** Use a keyboard shortcut to cycle through available agents. {% /tab %} @@ -35,7 +35,7 @@ There are several ways to switch agents: There are several ways to switch agents: - **Keybinds:** Press the displayed key to cycle through available agents. -- **Slash commands:** Type `/` in the chat input to see available commands, including switching agents (e.g., `/code`, `/ask`, `/plan`, `/debug`). +- **Slash commands:** Type `/` in the chat input to see available commands, including `/agents` to open the agent picker. - **Config file:** Set the `default_agent` key in your configuration to change the default agent on startup. {% /tab %} @@ -105,7 +105,7 @@ Users often confuse `/newtask` and `/smol`. Here's the key difference: | Aspect | Details | | -------------------- | ---------------------------------------------------------------------------------------------------- | | **Description** | An experienced technical leader and planner who helps design systems and create implementation plans | -| **Tool Access** | Read-only tools plus restricted file editing (e.g., markdown files only) | +| **Tool Access** | Read-only tools plus restricted file editing (plan files in `.kilo/plans/` only) | | **Ideal For** | System design, high-level planning, and architecture discussions | | **Special Features** | Similar to the legacy extension's "Architect" mode, with a planning-focused approach | @@ -157,7 +157,7 @@ The VSCode extension and CLI do not include a built-in Review agent. Code review | Aspect | Details | | -------------------- | ---------------------------------------------------------------------------------------------------- | | **Description** | An experienced technical leader and planner who helps design systems and create implementation plans | -| **Tool Access** | Read-only tools plus restricted file editing (e.g., markdown files only) | +| **Tool Access** | Read-only tools plus restricted file editing (plan files in `.kilo/plans/` only) | | **Ideal For** | System design, high-level planning, and architecture discussions | | **Special Features** | Similar to the legacy extension's "Architect" mode, with a planning-focused approach | From 9bde55133110e2fa306a4d087e89ad3f3fe927c5 Mon Sep 17 00:00:00 2001 From: Christiaan Arnoldus Date: Thu, 26 Mar 2026 10:38:20 +0100 Subject: [PATCH 029/261] Update Vercel AI SDK OpenAI Provider for phase support --- bun.lock | 14 ++++++++++---- packages/kilo-gateway/package.json | 2 +- packages/opencode/package.json | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/bun.lock b/bun.lock index 125fa325254..393a4bf3e11 100644 --- a/bun.lock +++ b/bun.lock @@ -174,7 +174,7 @@ "version": "7.1.4", "dependencies": { "@ai-sdk/anthropic": "2.0.65", - "@ai-sdk/openai": "2.0.89", + "@ai-sdk/openai": "2.0.101", "@ai-sdk/openai-compatible": "1.0.32", "@clack/prompts": "1.0.0-alpha.1", "@kilocode/plugin": "workspace:*", @@ -344,7 +344,7 @@ "@ai-sdk/google-vertex": "3.0.106", "@ai-sdk/groq": "2.0.34", "@ai-sdk/mistral": "2.0.27", - "@ai-sdk/openai": "2.0.89", + "@ai-sdk/openai": "2.0.101", "@ai-sdk/openai-compatible": "1.0.32", "@ai-sdk/perplexity": "2.0.23", "@ai-sdk/provider": "2.0.1", @@ -665,7 +665,7 @@ "@ai-sdk/mistral": ["@ai-sdk/mistral@2.0.27", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-gaptHgaXjMw3+eA0Q4FABcsj5nQNP6EpFaGUR+Pj5WJy7Kn6mApl975/x57224MfeJIShNpt8wFKK3tvh5ewKg=="], - "@ai-sdk/openai": ["@ai-sdk/openai@2.0.89", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-4+qWkBCbL9HPKbgrUO/F2uXZ8GqrYxHa8SWEYIzxEJ9zvWw3ISr3t1/27O1i8MGSym+PzEyHBT48EV4LAwWaEw=="], + "@ai-sdk/openai": ["@ai-sdk/openai@2.0.101", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.22" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kQ52HLV45T3bQbRzWExXW6+pkg3Nvq4dUnZHUPJXWgkUUsAhZjxHrXqPOc/0yfn/4+Dn2uLmIgAkP9IfzMMcNg=="], "@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.32", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-YspqqyJPzHjqWrjt4y/Wgc2aJgCcQj5uIJgZpq2Ar/lH30cEVhgE+keePDbjKpetD9UwNggCj7u6kO3unS23OQ=="], @@ -4357,6 +4357,8 @@ "@ai-sdk/amazon-bedrock/aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="], + "@ai-sdk/azure/@ai-sdk/openai": ["@ai-sdk/openai@2.0.89", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-4+qWkBCbL9HPKbgrUO/F2uXZ8GqrYxHa8SWEYIzxEJ9zvWw3ISr3t1/27O1i8MGSym+PzEyHBT48EV4LAwWaEw=="], + "@ai-sdk/azure/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], "@ai-sdk/cerebras/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], @@ -4381,7 +4383,7 @@ "@ai-sdk/mistral/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], - "@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], + "@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.22", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-fFT1KfUUKktfAFm5mClJhS1oux9tP2qgzmEZVl5UdwltQ1LO/s8hd7znVrgKzivwv1s1FIPza0s9OpJaNB/vHw=="], "@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], @@ -4835,6 +4837,8 @@ "ai-gateway-provider/@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.90", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.56", "@ai-sdk/google": "2.0.46", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-C9MLe1KZGg1ZbupV2osygHtL5qngyCDA6ATatunyfTbIe8TXKG8HGni/3O6ifbnI5qxTidIn150Ox7eIFZVMYg=="], + "ai-gateway-provider/@ai-sdk/openai": ["@ai-sdk/openai@2.0.89", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-4+qWkBCbL9HPKbgrUO/F2uXZ8GqrYxHa8SWEYIzxEJ9zvWw3ISr3t1/27O1i8MGSym+PzEyHBT48EV4LAwWaEw=="], + "ajv-keywords/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], @@ -5599,6 +5603,8 @@ "ai-gateway-provider/@ai-sdk/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], + "ai-gateway-provider/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], + "ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], "app-builder-lib/@electron/get/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index 248ef1b32a8..e8ab135b336 100644 --- a/packages/kilo-gateway/package.json +++ b/packages/kilo-gateway/package.json @@ -30,7 +30,7 @@ "@kilocode/plugin": "workspace:*", "@kilocode/sdk": "workspace:*", "@ai-sdk/anthropic": "2.0.65", - "@ai-sdk/openai": "2.0.89", + "@ai-sdk/openai": "2.0.101", "@ai-sdk/openai-compatible": "1.0.32", "@openrouter/ai-sdk-provider": "1.5.4", "@clack/prompts": "1.0.0-alpha.1", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 4d53caa617b..b36606860e6 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -69,7 +69,7 @@ "@ai-sdk/google-vertex": "3.0.106", "@ai-sdk/groq": "2.0.34", "@ai-sdk/mistral": "2.0.27", - "@ai-sdk/openai": "2.0.89", + "@ai-sdk/openai": "2.0.101", "@ai-sdk/openai-compatible": "1.0.32", "@ai-sdk/perplexity": "2.0.23", "@ai-sdk/provider": "2.0.1", From 3898716a36fa29034e16ba5a7f610100f095abaf Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 25 Mar 2026 14:34:12 +0100 Subject: [PATCH 030/261] feat(vscode): add import/export for agent mode definitions Add an Export button (download icon) to the agent edit view that serializes the agent config to a .agent.json file. Add an Import button to the agents list view that opens a file picker, validates the JSON structure, and creates the agent in config. Import validates the name format, checks for duplicates, and shows error messages for invalid files. The JSON format includes name, description, prompt, model, mode, temperature, top_p, and steps. Closes #7592 --- .../components/settings/AgentBehaviourTab.tsx | 73 ++++++++++++++++++- .../src/components/settings/ModeEditView.tsx | 35 +++++++-- .../kilo-vscode/webview-ui/src/i18n/ar.ts | 6 ++ .../kilo-vscode/webview-ui/src/i18n/br.ts | 7 ++ .../kilo-vscode/webview-ui/src/i18n/bs.ts | 7 ++ .../kilo-vscode/webview-ui/src/i18n/da.ts | 6 ++ .../kilo-vscode/webview-ui/src/i18n/de.ts | 7 ++ .../kilo-vscode/webview-ui/src/i18n/en.ts | 6 ++ .../kilo-vscode/webview-ui/src/i18n/es.ts | 7 ++ .../kilo-vscode/webview-ui/src/i18n/fr.ts | 7 ++ .../kilo-vscode/webview-ui/src/i18n/ja.ts | 7 ++ .../kilo-vscode/webview-ui/src/i18n/ko.ts | 6 ++ .../kilo-vscode/webview-ui/src/i18n/nl.ts | 7 ++ .../kilo-vscode/webview-ui/src/i18n/no.ts | 6 ++ .../kilo-vscode/webview-ui/src/i18n/pl.ts | 7 ++ .../kilo-vscode/webview-ui/src/i18n/ru.ts | 7 ++ .../kilo-vscode/webview-ui/src/i18n/th.ts | 6 ++ .../kilo-vscode/webview-ui/src/i18n/tr.ts | 7 ++ .../kilo-vscode/webview-ui/src/i18n/zh.ts | 6 ++ .../kilo-vscode/webview-ui/src/i18n/zht.ts | 6 ++ 20 files changed, 215 insertions(+), 11 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index 83dd16956e7..c63cbe922a5 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -10,7 +10,7 @@ import { useDialog } from "@kilocode/kilo-ui/context/dialog" import { useConfig } from "../../context/config" import { useSession } from "../../context/session" import { useLanguage } from "../../context/language" -import type { AgentInfo, SkillInfo } from "../../types/messages" +import type { AgentConfig, AgentInfo, SkillInfo } from "../../types/messages" import ModeEditView from "./ModeEditView" import ModeCreateView from "./ModeCreateView" import WorkflowsTab from "./agent-behaviour/WorkflowsTab" @@ -227,6 +227,54 @@ const AgentBehaviourTab: Component = () => { setEditingAgent("") } + const [importError, setImportError] = createSignal("") + + const importMode = (file: File) => { + setImportError("") + const reader = new FileReader() + reader.onload = () => { + try { + const data = JSON.parse(reader.result as string) + const name = typeof data.name === "string" ? data.name.trim() : "" + if (!name || !/^[a-z][a-z0-9-]*$/.test(name)) { + setImportError(language.t("settings.agentBehaviour.importMode.invalidName")) + return + } + if (agentNames().includes(name)) { + setImportError(language.t("settings.agentBehaviour.importMode.nameTaken")) + return + } + const partial: Partial = {} + if (typeof data.description === "string") partial.description = data.description + if (typeof data.prompt === "string") partial.prompt = data.prompt + if (typeof data.model === "string") partial.model = data.model + if (typeof data.mode === "string") partial.mode = data.mode as AgentConfig["mode"] + if (typeof data.temperature === "number") partial.temperature = data.temperature + if (typeof data.top_p === "number") partial.top_p = data.top_p + if (typeof data.steps === "number") partial.steps = data.steps + const existing = config().agent ?? {} + updateConfig({ + agent: { ...existing, [name]: { ...partial, mode: partial.mode ?? "primary" } }, + }) + setImportError("") + } catch { + setImportError(language.t("settings.agentBehaviour.importMode.invalidJson")) + } + } + reader.readAsText(file) + } + + const triggerImport = () => { + const input = document.createElement("input") + input.type = "file" + input.accept = ".json" + input.onchange = () => { + const file = input.files?.[0] + if (file) importMode(file) + } + input.click() + } + const renderAgentsSubtab = () => { const view = agentView() if (view === "create") return @@ -270,11 +318,28 @@ const AgentBehaviourTab: Component = () => { }} >
{language.t("settings.agentBehaviour.availableAgents")}
- +
+ + +
+ +
+ {importError()} +
+
+ {/* Agents list - clickable to edit */} 0} diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx index 7ae4b12c8f2..d8c47b1f279 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx @@ -40,6 +40,18 @@ const ModeEditView: Component = (props) => { }) } + const exportMode = () => { + const data = { name: props.name, ...cfg() } + const json = JSON.stringify(data, null, 2) + const blob = new Blob([json], { type: "application/json" }) + const url = URL.createObjectURL(blob) + const anchor = document.createElement("a") + anchor.href = url + anchor.download = `${props.name}.agent.json` + anchor.click() + URL.revokeObjectURL(url) + } + return (
= (props) => { {language.t("settings.agentBehaviour.editMode")} — {props.name}
- +
{ - const a = agent() - if (a) props.onRemove(a) - }} + icon="download" + title={language.t("settings.agentBehaviour.exportMode")} + onClick={exportMode} /> - + + { + const a = agent() + if (a) props.onRemove(a) + }} + /> + +
diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index 8416cc7f23b..fa67562b107 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1059,6 +1059,12 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "الاسم مطلوب", "settings.agentBehaviour.createMode.nameInvalid": "يجب أن يحتوي الاسم على أحرف صغيرة وأرقام وشرطات فقط", "settings.agentBehaviour.createMode.nameTaken": "يوجد وضع بهذا الاسم بالفعل", + "settings.agentBehaviour.importMode": "استيراد", + "settings.agentBehaviour.importMode.invalidName": + "اسم الوضع في الملف غير صالح. يجب أن يبدأ الاسم بحرف صغير ويحتوي فقط على أحرف صغيرة وأرقام وشرطات.", + "settings.agentBehaviour.importMode.nameTaken": "يوجد وضع بهذا الاسم بالفعل.", + "settings.agentBehaviour.importMode.invalidJson": "ملف JSON غير صالح. يرجى اختيار ملف تعريف وكيل صالح.", + "settings.agentBehaviour.exportMode": "تصدير تعريف الوكيل", "settings.agentBehaviour.editMode": "تعديل الوضع", "settings.agentBehaviour.editMode.description": "الوصف", "settings.agentBehaviour.editMode.prompt": "موجه النظام", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 6a195aaa1b0..9eae713f139 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1072,6 +1072,13 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "Nome é obrigatório", "settings.agentBehaviour.createMode.nameInvalid": "O nome deve conter apenas letras minúsculas, números e hífens", "settings.agentBehaviour.createMode.nameTaken": "Já existe um modo com este nome", + "settings.agentBehaviour.importMode": "Importar", + "settings.agentBehaviour.importMode.invalidName": + "Nome de modo inválido no arquivo. O nome deve começar com uma letra minúscula e conter apenas letras minúsculas, números e hífens.", + "settings.agentBehaviour.importMode.nameTaken": "Já existe um modo com este nome.", + "settings.agentBehaviour.importMode.invalidJson": + "Arquivo JSON inválido. Por favor, selecione um arquivo de definição de agente válido.", + "settings.agentBehaviour.exportMode": "Exportar definição do agente", "settings.agentBehaviour.editMode": "Editar Modo", "settings.agentBehaviour.editMode.description": "Descrição", "settings.agentBehaviour.editMode.prompt": "Prompt do Sistema", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 83e392192b0..891421178a4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1072,6 +1072,13 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "Naziv je obavezan", "settings.agentBehaviour.createMode.nameInvalid": "Naziv smije sadržavati samo mala slova, brojeve i crtice", "settings.agentBehaviour.createMode.nameTaken": "Mod s ovim nazivom već postoji", + "settings.agentBehaviour.importMode": "Uvezi", + "settings.agentBehaviour.importMode.invalidName": + "Nevažeći naziv moda u datoteci. Naziv mora počinjati malim slovom i sadržavati samo mala slova, brojeve i crtice.", + "settings.agentBehaviour.importMode.nameTaken": "Mod s ovim nazivom već postoji.", + "settings.agentBehaviour.importMode.invalidJson": + "Nevažeća JSON datoteka. Molimo odaberite važeću datoteku definicije agenta.", + "settings.agentBehaviour.exportMode": "Izvezi definiciju agenta", "settings.agentBehaviour.editMode": "Uredi mod", "settings.agentBehaviour.editMode.description": "Opis", "settings.agentBehaviour.editMode.prompt": "Sistemski prompt", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 06f53d140c5..bdd2766d237 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1067,6 +1067,12 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "Navn er påkrævet", "settings.agentBehaviour.createMode.nameInvalid": "Navn må kun indeholde små bogstaver, tal og bindestreger", "settings.agentBehaviour.createMode.nameTaken": "En tilstand med dette navn eksisterer allerede", + "settings.agentBehaviour.importMode": "Importér", + "settings.agentBehaviour.importMode.invalidName": + "Ugyldigt tilstandsnavn i filen. Navnet skal starte med et lille bogstav og kun indeholde små bogstaver, tal og bindestreger.", + "settings.agentBehaviour.importMode.nameTaken": "En tilstand med dette navn eksisterer allerede.", + "settings.agentBehaviour.importMode.invalidJson": "Ugyldig JSON-fil. Vælg venligst en gyldig agentdefinitionsfil.", + "settings.agentBehaviour.exportMode": "Eksportér agentdefinition", "settings.agentBehaviour.editMode": "Rediger tilstand", "settings.agentBehaviour.editMode.description": "Beskrivelse", "settings.agentBehaviour.editMode.prompt": "Systemprompt", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 7e7bd1184b5..4ab9b9a8cdc 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1085,6 +1085,13 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "Name ist erforderlich", "settings.agentBehaviour.createMode.nameInvalid": "Name darf nur Kleinbuchstaben, Zahlen und Bindestriche enthalten", "settings.agentBehaviour.createMode.nameTaken": "Ein Modus mit diesem Namen existiert bereits", + "settings.agentBehaviour.importMode": "Importieren", + "settings.agentBehaviour.importMode.invalidName": + "Ungültiger Modusname in der Datei. Der Name muss mit einem Kleinbuchstaben beginnen und darf nur Kleinbuchstaben, Zahlen und Bindestriche enthalten.", + "settings.agentBehaviour.importMode.nameTaken": "Ein Modus mit diesem Namen existiert bereits.", + "settings.agentBehaviour.importMode.invalidJson": + "Ungültige JSON-Datei. Bitte wählen Sie eine gültige Agenten-Definitionsdatei aus.", + "settings.agentBehaviour.exportMode": "Agenten-Definition exportieren", "settings.agentBehaviour.editMode": "Modus bearbeiten", "settings.agentBehaviour.editMode.description": "Beschreibung", "settings.agentBehaviour.editMode.prompt": "System-Prompt", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 58789081d5a..9f71815b809 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1104,6 +1104,12 @@ export const dict = { "settings.agentBehaviour.createMode.nameInvalid": "Name must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens", "settings.agentBehaviour.createMode.nameTaken": "A mode with this name already exists", + "settings.agentBehaviour.importMode": "Import", + "settings.agentBehaviour.importMode.invalidName": + "Invalid mode name in file. Name must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.", + "settings.agentBehaviour.importMode.nameTaken": "A mode with this name already exists.", + "settings.agentBehaviour.importMode.invalidJson": "Invalid JSON file. Please select a valid agent definition file.", + "settings.agentBehaviour.exportMode": "Export agent definition", "settings.agentBehaviour.editMode": "Edit Mode", "settings.agentBehaviour.editMode.description": "Description", "settings.agentBehaviour.editMode.prompt": "System Prompt", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 9b2d1da3261..bfdf1e6c0cf 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1076,6 +1076,13 @@ export const dict = { "settings.agentBehaviour.createMode.nameInvalid": "El nombre solo puede contener letras minúsculas, números y guiones", "settings.agentBehaviour.createMode.nameTaken": "Ya existe un modo con este nombre", + "settings.agentBehaviour.importMode": "Importar", + "settings.agentBehaviour.importMode.invalidName": + "Nombre de modo no válido en el archivo. El nombre debe comenzar con una letra minúscula y contener solo letras minúsculas, números y guiones.", + "settings.agentBehaviour.importMode.nameTaken": "Ya existe un modo con este nombre.", + "settings.agentBehaviour.importMode.invalidJson": + "Archivo JSON no válido. Por favor, seleccione un archivo de definición de agente válido.", + "settings.agentBehaviour.exportMode": "Exportar definición del agente", "settings.agentBehaviour.editMode": "Editar modo", "settings.agentBehaviour.editMode.description": "Descripción", "settings.agentBehaviour.editMode.prompt": "Prompt del sistema", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 0b507379ae4..4ac7648b85b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1089,6 +1089,13 @@ export const dict = { "settings.agentBehaviour.createMode.nameInvalid": "Le nom ne doit contenir que des minuscules, des chiffres et des tirets", "settings.agentBehaviour.createMode.nameTaken": "Un mode avec ce nom existe déjà", + "settings.agentBehaviour.importMode": "Importer", + "settings.agentBehaviour.importMode.invalidName": + "Nom de mode invalide dans le fichier. Le nom doit commencer par une lettre minuscule et ne contenir que des lettres minuscules, des chiffres et des tirets.", + "settings.agentBehaviour.importMode.nameTaken": "Un mode avec ce nom existe déjà.", + "settings.agentBehaviour.importMode.invalidJson": + "Fichier JSON invalide. Veuillez sélectionner un fichier de définition d'agent valide.", + "settings.agentBehaviour.exportMode": "Exporter la définition de l'agent", "settings.agentBehaviour.editMode": "Modifier le mode", "settings.agentBehaviour.editMode.description": "Description", "settings.agentBehaviour.editMode.prompt": "Prompt système", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 21464079b85..44dcae200eb 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1067,6 +1067,13 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "名前は必須です", "settings.agentBehaviour.createMode.nameInvalid": "名前には小文字、数字、ハイフンのみ使用できます", "settings.agentBehaviour.createMode.nameTaken": "この名前のモードはすでに存在します", + "settings.agentBehaviour.importMode": "インポート", + "settings.agentBehaviour.importMode.invalidName": + "ファイル内のモード名が無効です。名前は小文字で始まり、小文字、数字、ハイフンのみを含む必要があります。", + "settings.agentBehaviour.importMode.nameTaken": "この名前のモードはすでに存在します。", + "settings.agentBehaviour.importMode.invalidJson": + "無効なJSONファイルです。有効なエージェント定義ファイルを選択してください。", + "settings.agentBehaviour.exportMode": "エージェント定義をエクスポート", "settings.agentBehaviour.editMode": "モードを編集", "settings.agentBehaviour.editMode.description": "説明", "settings.agentBehaviour.editMode.prompt": "システムプロンプト", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 4d262f0b16e..b7d88e7f0f4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1063,6 +1063,12 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "이름은 필수입니다", "settings.agentBehaviour.createMode.nameInvalid": "이름에는 소문자, 숫자, 하이픈만 포함될 수 있습니다", "settings.agentBehaviour.createMode.nameTaken": "이 이름의 모드가 이미 존재합니다", + "settings.agentBehaviour.importMode": "가져오기", + "settings.agentBehaviour.importMode.invalidName": + "파일의 모드 이름이 잘못되었습니다. 이름은 소문자로 시작하고 소문자, 숫자, 하이픈만 포함해야 합니다.", + "settings.agentBehaviour.importMode.nameTaken": "이 이름의 모드가 이미 존재합니다.", + "settings.agentBehaviour.importMode.invalidJson": "잘못된 JSON 파일입니다. 유효한 에이전트 정의 파일을 선택하세요.", + "settings.agentBehaviour.exportMode": "에이전트 정의 내보내기", "settings.agentBehaviour.editMode": "모드 편집", "settings.agentBehaviour.editMode.description": "설명", "settings.agentBehaviour.editMode.prompt": "시스템 프롬프트", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 6c18764d272..3a633caab01 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1060,6 +1060,13 @@ export const dict = { "Geen skills ontdekt. Voeg hieronder skill mappaden of URL's toe om skills beschikbaar te maken.", "settings.agentBehaviour.availableModes": "Beschikbare Aangepaste Modi", "settings.agentBehaviour.noModesFound": "Geen modi gevonden.", + "settings.agentBehaviour.importMode": "Importeren", + "settings.agentBehaviour.importMode.invalidName": + "Ongeldige modusnaam in bestand. De naam moet beginnen met een kleine letter en mag alleen kleine letters, cijfers en streepjes bevatten.", + "settings.agentBehaviour.importMode.nameTaken": "Er bestaat al een modus met deze naam.", + "settings.agentBehaviour.importMode.invalidJson": + "Ongeldig JSON-bestand. Selecteer een geldig agentdefinitiebestand.", + "settings.agentBehaviour.exportMode": "Agentdefinitie exporteren", "settings.agentBehaviour.removeMode.title": "Verwijder modus", "settings.agentBehaviour.removeMode.confirm": 'Modus "{{name}}" verwijderen? Dit zal de modus uitschakelen door je configuratie bij te werken.', diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 5f2f58e8515..f992b989b1b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1070,6 +1070,12 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "Navn er påkrevd", "settings.agentBehaviour.createMode.nameInvalid": "Navn kan bare inneholde små bokstaver, tall og bindestreker", "settings.agentBehaviour.createMode.nameTaken": "En modus med dette navnet eksisterer allerede", + "settings.agentBehaviour.importMode": "Importer", + "settings.agentBehaviour.importMode.invalidName": + "Ugyldig modusnavn i filen. Navnet må starte med en liten bokstav og bare inneholde små bokstaver, tall og bindestreker.", + "settings.agentBehaviour.importMode.nameTaken": "En modus med dette navnet eksisterer allerede.", + "settings.agentBehaviour.importMode.invalidJson": "Ugyldig JSON-fil. Vennligst velg en gyldig agentdefinisjonsfil.", + "settings.agentBehaviour.exportMode": "Eksporter agentdefinisjon", "settings.agentBehaviour.editMode": "Rediger modus", "settings.agentBehaviour.editMode.description": "Beskrivelse", "settings.agentBehaviour.editMode.prompt": "Systemprompt", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 0a616ea4bfb..236644814ca 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1071,6 +1071,13 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "Nazwa jest wymagana", "settings.agentBehaviour.createMode.nameInvalid": "Nazwa może zawierać tylko małe litery, cyfry i myślniki", "settings.agentBehaviour.createMode.nameTaken": "Tryb o tej nazwie już istnieje", + "settings.agentBehaviour.importMode": "Importuj", + "settings.agentBehaviour.importMode.invalidName": + "Nieprawidłowa nazwa trybu w pliku. Nazwa musi zaczynać się od małej litery i zawierać tylko małe litery, cyfry i myślniki.", + "settings.agentBehaviour.importMode.nameTaken": "Tryb o tej nazwie już istnieje.", + "settings.agentBehaviour.importMode.invalidJson": + "Nieprawidłowy plik JSON. Proszę wybrać prawidłowy plik definicji agenta.", + "settings.agentBehaviour.exportMode": "Eksportuj definicję agenta", "settings.agentBehaviour.editMode": "Edytuj tryb", "settings.agentBehaviour.editMode.description": "Opis", "settings.agentBehaviour.editMode.prompt": "Prompt systemowy", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 825f2578ef1..b409161caa1 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1074,6 +1074,13 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "Название обязательно", "settings.agentBehaviour.createMode.nameInvalid": "Название может содержать только строчные буквы, цифры и дефисы", "settings.agentBehaviour.createMode.nameTaken": "Режим с таким названием уже существует", + "settings.agentBehaviour.importMode": "Импорт", + "settings.agentBehaviour.importMode.invalidName": + "Недопустимое имя режима в файле. Имя должно начинаться со строчной буквы и содержать только строчные буквы, цифры и дефисы.", + "settings.agentBehaviour.importMode.nameTaken": "Режим с таким названием уже существует.", + "settings.agentBehaviour.importMode.invalidJson": + "Недопустимый файл JSON. Пожалуйста, выберите корректный файл определения агента.", + "settings.agentBehaviour.exportMode": "Экспортировать определение агента", "settings.agentBehaviour.editMode": "Редактировать режим", "settings.agentBehaviour.editMode.description": "Описание", "settings.agentBehaviour.editMode.prompt": "Системный промпт", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index b31301d5e4f..5ee2f6cd441 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1059,6 +1059,12 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "ต้องระบุชื่อ", "settings.agentBehaviour.createMode.nameInvalid": "ชื่อต้องประกอบด้วยตัวอักษรพิมพ์เล็ก ตัวเลข และขีดกลางเท่านั้น", "settings.agentBehaviour.createMode.nameTaken": "มีโหมดที่มีชื่อนี้อยู่แล้ว", + "settings.agentBehaviour.importMode": "นำเข้า", + "settings.agentBehaviour.importMode.invalidName": + "ชื่อโหมดในไฟล์ไม่ถูกต้อง ชื่อต้องขึ้นต้นด้วยตัวอักษรพิมพ์เล็กและประกอบด้วยตัวอักษรพิมพ์เล็ก ตัวเลข และขีดกลางเท่านั้น", + "settings.agentBehaviour.importMode.nameTaken": "มีโหมดที่มีชื่อนี้อยู่แล้ว", + "settings.agentBehaviour.importMode.invalidJson": "ไฟล์ JSON ไม่ถูกต้อง กรุณาเลือกไฟล์นิยามเอเจนต์ที่ถูกต้อง", + "settings.agentBehaviour.exportMode": "ส่งออกนิยามเอเจนต์", "settings.agentBehaviour.editMode": "แก้ไขโหมด", "settings.agentBehaviour.editMode.description": "คำอธิบาย", "settings.agentBehaviour.editMode.prompt": "System Prompt", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 63b7acf3d7f..af107a4382e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1059,6 +1059,13 @@ export const dict = { "Keşfedilen beceri yok. Becerileri kullanılabilir kılmak için aşağıya beceri klasör yolları veya URL'ler ekleyin.", "settings.agentBehaviour.availableModes": "Mevcut Özel Modlar", "settings.agentBehaviour.noModesFound": "Mod bulunamadı.", + "settings.agentBehaviour.importMode": "İçe Aktar", + "settings.agentBehaviour.importMode.invalidName": + "Dosyadaki mod adı geçersiz. Ad küçük harfle başlamalı ve yalnızca küçük harfler, rakamlar ve tire içermelidir.", + "settings.agentBehaviour.importMode.nameTaken": "Bu ada sahip bir mod zaten mevcut.", + "settings.agentBehaviour.importMode.invalidJson": + "Geçersiz JSON dosyası. Lütfen geçerli bir ajan tanım dosyası seçin.", + "settings.agentBehaviour.exportMode": "Ajan tanımını dışa aktar", "settings.agentBehaviour.removeMode.title": "Modu kaldır", "settings.agentBehaviour.removeMode.confirm": '"{{name}}" modu kaldırılsın mı? Bu, yapılandırmanızı güncelleyerek modu devre dışı bırakacak.', diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index a9a95d68151..956d0828d6b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1050,6 +1050,12 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "名称为必填项", "settings.agentBehaviour.createMode.nameInvalid": "名称只能包含小写字母、数字和连字符", "settings.agentBehaviour.createMode.nameTaken": "此名称的模式已存在", + "settings.agentBehaviour.importMode": "导入", + "settings.agentBehaviour.importMode.invalidName": + "文件中的模式名称无效。名称必须以小写字母开头,且仅包含小写字母、数字和连字符。", + "settings.agentBehaviour.importMode.nameTaken": "此名称的模式已存在。", + "settings.agentBehaviour.importMode.invalidJson": "无效的 JSON 文件。请选择有效的代理定义文件。", + "settings.agentBehaviour.exportMode": "导出代理定义", "settings.agentBehaviour.editMode": "编辑模式", "settings.agentBehaviour.editMode.description": "描述", "settings.agentBehaviour.editMode.prompt": "系统提示", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index afcda94a457..46133a76f65 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1052,6 +1052,12 @@ export const dict = { "settings.agentBehaviour.createMode.nameRequired": "名稱為必填項", "settings.agentBehaviour.createMode.nameInvalid": "名稱只能包含小寫字母、數字和連字號", "settings.agentBehaviour.createMode.nameTaken": "此名稱的模式已存在", + "settings.agentBehaviour.importMode": "匯入", + "settings.agentBehaviour.importMode.invalidName": + "檔案中的模式名稱無效。名稱必須以小寫字母開頭,且僅包含小寫字母、數字和連字號。", + "settings.agentBehaviour.importMode.nameTaken": "此名稱的模式已存在。", + "settings.agentBehaviour.importMode.invalidJson": "無效的 JSON 檔案。請選擇有效的代理定義檔案。", + "settings.agentBehaviour.exportMode": "匯出代理定義", "settings.agentBehaviour.editMode": "編輯模式", "settings.agentBehaviour.editMode.description": "描述", "settings.agentBehaviour.editMode.prompt": "系統提示", From edee1141228c52f85f8c16ea352bb2e1fdb71dad Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 25 Mar 2026 14:40:18 +0100 Subject: [PATCH 031/261] fix(vscode): restrict export to custom modes and validate mode field on import Hide export button for native/built-in agents since their full definition is not available from config overrides alone. Validate the mode field on import against the allowed values (subagent, primary, all) instead of blindly casting. --- .../components/settings/AgentBehaviourTab.tsx | 3 ++- .../src/components/settings/ModeEditView.tsx | 22 +++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index c63cbe922a5..ff55cc54392 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -248,7 +248,8 @@ const AgentBehaviourTab: Component = () => { if (typeof data.description === "string") partial.description = data.description if (typeof data.prompt === "string") partial.prompt = data.prompt if (typeof data.model === "string") partial.model = data.model - if (typeof data.mode === "string") partial.mode = data.mode as AgentConfig["mode"] + const modes = ["subagent", "primary", "all"] as const + if (typeof data.mode === "string" && modes.includes(data.mode)) partial.mode = data.mode if (typeof data.temperature === "number") partial.temperature = data.temperature if (typeof data.top_p === "number") partial.top_p = data.top_p if (typeof data.steps === "number") partial.steps = data.steps diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx index d8c47b1f279..88a12774b5f 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx @@ -68,15 +68,15 @@ const ModeEditView: Component = (props) => { {language.t("settings.agentBehaviour.editMode")} — {props.name} -
- - + +
+ = (props) => { if (a) props.onRemove(a) }} /> - -
+
+
From 66a9358cda625c5aa89d74c7c5966d8a39f47256 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Thu, 26 Mar 2026 12:20:00 +0100 Subject: [PATCH 032/261] test(vscode): add visual regression story for ModeEditView export button --- .../src/stories/settings.stories.tsx | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx b/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx index e77d6154a9e..eac45bde9b6 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx @@ -10,6 +10,7 @@ import { SessionContext } from "../context/session" import Settings from "../components/settings/Settings" import ProvidersTab from "../components/settings/ProvidersTab" import AgentBehaviourTab from "../components/settings/AgentBehaviourTab" +import ModeEditView from "../components/settings/ModeEditView" import type { AgentConfig, CommandConfig } from "../types/messages" const meta: Meta = { @@ -214,3 +215,35 @@ export const AgentBehaviourWorkflowsEmpty: Story = { ) }, } + +export const ModeEditExport: Story = { + name: "ModeEditView — export button", + render: () => { + const cfg: Record = { + reviewer: { + description: "Review code for quality and best practices", + prompt: "You are a code reviewer. Focus on code quality, best practices, and potential bugs.", + model: "anthropic/claude-sonnet-4-20250514", + temperature: 0.3, + }, + } + const session = { + ...mockSessionValue({ id: "export-story", status: "idle" }), + agents: () => MOCK_AGENTS, + removeMode: noop, + removeMcp: noop, + skills: () => [], + refreshSkills: noop, + removeSkill: noop, + } + return ( + + +
+ +
+
+
+ ) + }, +} From f95e1a9be91cf85c44c1dac0b4bd7b79c7d5872e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 26 Mar 2026 11:29:19 +0000 Subject: [PATCH 033/261] chore: update kilo-vscode visual regression baselines --- .../settings/mode-edit-export-chromium-linux.png | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mode-edit-export-chromium-linux.png diff --git a/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mode-edit-export-chromium-linux.png b/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mode-edit-export-chromium-linux.png new file mode 100644 index 00000000000..f7c6fb041c5 --- /dev/null +++ b/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mode-edit-export-chromium-linux.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4dcc9ddf87e9c5b6e5cf736bfa5d42005020d14e2bb6fe7cd99a82a149db3e5c +size 37073 From 435d82ca080f4949097c3f71d18ad5ba0353ab68 Mon Sep 17 00:00:00 2001 From: Evgeny Shurakov Date: Thu, 26 Mar 2026 12:54:28 +0100 Subject: [PATCH 034/261] fix(cli): add configurable session retry limit --- packages/opencode/src/flag/flag.ts | 16 +- packages/opencode/src/session/processor.ts | 7 +- .../session-processor-retry-limit.test.ts | 196 ++++++++++++++++++ 3 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 packages/opencode/test/kilocode/session-processor-retry-limit.test.ts diff --git a/packages/opencode/src/flag/flag.ts b/packages/opencode/src/flag/flag.ts index 1ece6b10cbe..fbebfb3b03a 100644 --- a/packages/opencode/src/flag/flag.ts +++ b/packages/opencode/src/flag/flag.ts @@ -35,7 +35,6 @@ export namespace Flag { export const KILO_SERVER_PASSWORD = process.env["KILO_SERVER_PASSWORD"] export const KILO_SERVER_USERNAME = process.env["KILO_SERVER_USERNAME"] export const KILO_ENABLE_QUESTION_TOOL = truthy("KILO_ENABLE_QUESTION_TOOL") - // Experimental export const KILO_EXPERIMENTAL = truthy("KILO_EXPERIMENTAL") export const KILO_EXPERIMENTAL_FILEWATCHER = truthy("KILO_EXPERIMENTAL_FILEWATCHER") @@ -58,6 +57,7 @@ export namespace Flag { export const KILO_MODELS_URL = process.env["KILO_MODELS_URL"] export const KILO_MODELS_PATH = process.env["KILO_MODELS_PATH"] export const KILO_SKIP_MIGRATIONS = truthy("KILO_SKIP_MIGRATIONS") + export declare const KILO_SESSION_RETRY_LIMIT: number | undefined function number(key: string) { const value = process.env[key] @@ -110,3 +110,17 @@ Object.defineProperty(Flag, "KILO_CLIENT", { enumerable: true, configurable: false, }) + +// Dynamic getter for KILO_SESSION_RETRY_LIMIT +// This must be evaluated at access time, not module load time, +// because tests and runtime tooling may set this env var later +Object.defineProperty(Flag, "KILO_SESSION_RETRY_LIMIT", { + get() { + const value = process.env["KILO_SESSION_RETRY_LIMIT"] + if (!value) return undefined + const parsed = Number(value) + return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined + }, + enumerable: true, + configurable: false, +}) diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts index 585facce3d4..81b50c7b244 100644 --- a/packages/opencode/src/session/processor.ts +++ b/packages/opencode/src/session/processor.ts @@ -16,6 +16,7 @@ import { SessionCompaction } from "./compaction" import { PermissionNext } from "@/permission/next" import { Question } from "@/question" import { Telemetry } from "@kilocode/kilo-telemetry" // kilocode_change +import { Flag } from "@/flag/flag" // kilocode_change export namespace SessionProcessor { const DOOM_LOOP_THRESHOLD = 3 @@ -387,7 +388,11 @@ export namespace SessionProcessor { }) } else { const retry = SessionRetry.retryable(error) - if (retry !== undefined) { + if ( + retry !== undefined && + (Flag.KILO_SESSION_RETRY_LIMIT === undefined || attempt < Flag.KILO_SESSION_RETRY_LIMIT) + ) { + // kilocode_change attempt++ const delay = SessionRetry.delay(attempt, error.name === "APIError" ? error : undefined) SessionStatus.set(input.sessionID, { diff --git a/packages/opencode/test/kilocode/session-processor-retry-limit.test.ts b/packages/opencode/test/kilocode/session-processor-retry-limit.test.ts new file mode 100644 index 00000000000..4f90bd8e0d6 --- /dev/null +++ b/packages/opencode/test/kilocode/session-processor-retry-limit.test.ts @@ -0,0 +1,196 @@ +import { afterEach, describe, expect, mock, spyOn, test } from "bun:test" + +mock.module("@/kilo-sessions/remote-sender", () => ({ + RemoteSender: { + create() { + return { + queue() {}, + flush: async () => undefined, + } + }, + }, +})) + +import { APICallError } from "ai" +import { Bus } from "../../src/bus" +import { Flag } from "../../src/flag/flag" +import { Identifier } from "../../src/id/id" +import { Instance } from "../../src/project/instance" +import type { Provider } from "../../src/provider/provider" +import { LLM } from "../../src/session/llm" +import type { LLM as LLMType } from "../../src/session/llm" +import { MessageV2 } from "../../src/session/message-v2" +import { SessionRetry } from "../../src/session/retry" +import { SessionStatus } from "../../src/session/status" +import { Log } from "../../src/util/log" +import { tmpdir } from "../fixture/fixture" + +Log.init({ print: false }) + +function createModel(): Provider.Model { + return { + id: "gpt-4", + providerID: "openai", + name: "GPT-4", + limit: { + context: 128000, + input: 0, + output: 4096, + }, + cost: { input: 0, output: 0, cache: { read: 0, write: 0 } }, + capabilities: { + toolcall: true, + attachment: false, + reasoning: false, + temperature: true, + input: { text: true, image: false, audio: false, video: false }, + output: { text: true, image: false, audio: false, video: false }, + }, + api: { id: "openai", url: "https://api.openai.com/v1", npm: "@ai-sdk/openai" }, + options: {}, + headers: {}, + } as Provider.Model +} + +function retryable429() { + return new APICallError({ + message: "429 status code (no body)", + url: "https://api.openai.com/v1/chat/completions", + requestBodyValues: {}, + statusCode: 429, + responseHeaders: { "content-type": "application/json" }, + isRetryable: true, + }) +} + +function sentinel() { + return new Error("unexpected extra llm call") +} + +async function seed(model: Provider.Model) { + const { Session } = await import("../../src/session") + const session = await Session.create({}) + const user = (await Session.updateMessage({ + id: Identifier.ascending("message"), + role: "user", + sessionID: session.id, + time: { created: Date.now() }, + agent: "code", + model: { providerID: model.providerID, modelID: model.id }, + tools: {}, + })) as MessageV2.User + const assistant = (await Session.updateMessage({ + id: Identifier.ascending("message"), + parentID: user.id, + role: "assistant", + mode: "code", + agent: "code", + path: { + cwd: Instance.directory, + root: Instance.worktree, + }, + cost: 0, + tokens: { + input: 0, + output: 0, + reasoning: 0, + cache: { read: 0, write: 0 }, + }, + modelID: model.id, + providerID: model.providerID, + time: { created: Date.now() }, + sessionID: session.id, + })) as MessageV2.Assistant + return { assistant, session, user } +} + +function input(model: Provider.Model, sessionID: string, user: MessageV2.User): LLMType.StreamInput { + return { + user, + sessionID, + model, + agent: { name: "code", mode: "primary", permission: [], options: {} } as any, + system: [], + abort: AbortSignal.any([]), + messages: [], + tools: {}, + } +} + +afterEach(() => { + delete process.env.KILO_SESSION_RETRY_LIMIT +}) + +describe("session processor retry limit", () => { + test("stops after two retries with the normalized retryable error", async () => { + await using tmp = await tmpdir({ git: true }) + process.env.KILO_SESSION_RETRY_LIMIT = "2" + + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const { Session } = await import("../../src/session") + const { SessionProcessor } = await import("../../src/session/processor") + const model = createModel() + const seeded = await seed(model) + const retry: number[] = [] + const errors: Array = [] + const unsubStatus = Bus.subscribe(SessionStatus.Event.Status, (event) => { + if (event.properties.sessionID !== seeded.session.id) return + if (event.properties.status.type !== "retry") return + retry.push(event.properties.status.attempt) + }) + const unsubError = Bus.subscribe(Session.Event.Error, (event) => { + if (event.properties.sessionID !== seeded.session.id) return + errors.push(event.properties.error) + }) + const llm = spyOn(LLM, "stream") + .mockRejectedValueOnce(retryable429()) + .mockRejectedValueOnce(retryable429()) + .mockRejectedValueOnce(retryable429()) + .mockRejectedValue(sentinel()) + const sleep = spyOn(SessionRetry, "sleep").mockResolvedValue(undefined) + const processor = SessionProcessor.create({ + assistantMessage: seeded.assistant, + sessionID: seeded.session.id, + model, + abort: AbortSignal.any([]), + }) + + try { + const result = await processor.process(input(model, seeded.session.id, seeded.user)) + const expected = MessageV2.fromError(retryable429(), { providerID: "openai" }) + + expect(result).toBe("stop") + expect(llm).toHaveBeenCalledTimes(3) + expect(sleep).toHaveBeenCalledTimes(2) + expect(retry).toStrictEqual([1, 2]) + expect(processor.message.error).toStrictEqual(expected) + expect(errors).toStrictEqual([expected]) + } finally { + unsubStatus() + unsubError() + llm.mockRestore() + sleep.mockRestore() + } + }, + }) + }) + + test("only positive integers enable the limit", () => { + delete process.env.KILO_SESSION_RETRY_LIMIT + expect(Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() + + process.env.KILO_SESSION_RETRY_LIMIT = "0" + expect(Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() + + process.env.KILO_SESSION_RETRY_LIMIT = "-1" + expect(Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() + + process.env.KILO_SESSION_RETRY_LIMIT = "abc" + expect(Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() + + process.env.KILO_SESSION_RETRY_LIMIT = "2" + expect(Flag.KILO_SESSION_RETRY_LIMIT).toBe(2) + }) +}) From b53ce2117d0aefb1a18a62cffefc38f9c735e1c1 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Thu, 26 Mar 2026 13:25:41 +0100 Subject: [PATCH 035/261] fix(vscode): reject agent imports larger than 1 MB Add a file size guard in importMode to refuse files over 1 MB before reading. This prevents the webview from freezing or crashing when a user accidentally selects a very large file. Adds the tooLarge i18n string across all 18 locale files. --- .../src/components/settings/AgentBehaviourTab.tsx | 4 ++++ .../webview-ui/src/components/shared/PopupSelector.tsx | 6 ++---- packages/kilo-vscode/webview-ui/src/i18n/ar.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/br.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/bs.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/da.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/de.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/en.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/es.ts | 2 ++ packages/kilo-vscode/webview-ui/src/i18n/fr.ts | 2 ++ packages/kilo-vscode/webview-ui/src/i18n/ja.ts | 2 ++ packages/kilo-vscode/webview-ui/src/i18n/ko.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/nl.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/no.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/pl.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/ru.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/th.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/tr.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/zh.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/zht.ts | 1 + 20 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index ff55cc54392..fea51ed56a9 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -231,6 +231,10 @@ const AgentBehaviourTab: Component = () => { const importMode = (file: File) => { setImportError("") + if (file.size > 1_048_576) { + setImportError(language.t("settings.agentBehaviour.importMode.tooLarge")) + return + } const reader = new FileReader() reader.onload = () => { try { diff --git a/packages/kilo-vscode/webview-ui/src/components/shared/PopupSelector.tsx b/packages/kilo-vscode/webview-ui/src/components/shared/PopupSelector.tsx index 27426e39242..207e2f7aaff 100644 --- a/packages/kilo-vscode/webview-ui/src/components/shared/PopupSelector.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/shared/PopupSelector.tsx @@ -22,10 +22,8 @@ import { import { Popover } from "@kilocode/kilo-ui/popover" import type { PopoverProps } from "@kilocode/kilo-ui/popover" -export interface PopupSelectorProps extends Omit< - PopoverProps, - "style" | "children" -> { +export interface PopupSelectorProps + extends Omit, "style" | "children"> { /** Whether the selector is in expanded mode (wider + taller). */ expanded: boolean /** Preferred width when collapsed. Default: 250 */ diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index fa67562b107..fff9d4da779 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1064,6 +1064,7 @@ export const dict = { "اسم الوضع في الملف غير صالح. يجب أن يبدأ الاسم بحرف صغير ويحتوي فقط على أحرف صغيرة وأرقام وشرطات.", "settings.agentBehaviour.importMode.nameTaken": "يوجد وضع بهذا الاسم بالفعل.", "settings.agentBehaviour.importMode.invalidJson": "ملف JSON غير صالح. يرجى اختيار ملف تعريف وكيل صالح.", + "settings.agentBehaviour.importMode.tooLarge": "الملف كبير جدًا. يجب أن تكون تعريفات الوكيل أقل من 1 ميجابايت.", "settings.agentBehaviour.exportMode": "تصدير تعريف الوكيل", "settings.agentBehaviour.editMode": "تعديل الوضع", "settings.agentBehaviour.editMode.description": "الوصف", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 9eae713f139..c4d3ff9a2d2 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1078,6 +1078,7 @@ export const dict = { "settings.agentBehaviour.importMode.nameTaken": "Já existe um modo com este nome.", "settings.agentBehaviour.importMode.invalidJson": "Arquivo JSON inválido. Por favor, selecione um arquivo de definição de agente válido.", + "settings.agentBehaviour.importMode.tooLarge": "Arquivo muito grande. Definições de agente devem ter menos de 1 MB.", "settings.agentBehaviour.exportMode": "Exportar definição do agente", "settings.agentBehaviour.editMode": "Editar Modo", "settings.agentBehaviour.editMode.description": "Descrição", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 891421178a4..2b7ccda6db8 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1078,6 +1078,7 @@ export const dict = { "settings.agentBehaviour.importMode.nameTaken": "Mod s ovim nazivom već postoji.", "settings.agentBehaviour.importMode.invalidJson": "Nevažeća JSON datoteka. Molimo odaberite važeću datoteku definicije agenta.", + "settings.agentBehaviour.importMode.tooLarge": "Datoteka je prevelika. Definicije agenta moraju biti manje od 1 MB.", "settings.agentBehaviour.exportMode": "Izvezi definiciju agenta", "settings.agentBehaviour.editMode": "Uredi mod", "settings.agentBehaviour.editMode.description": "Opis", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index bdd2766d237..3106cee9b58 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1072,6 +1072,7 @@ export const dict = { "Ugyldigt tilstandsnavn i filen. Navnet skal starte med et lille bogstav og kun indeholde små bogstaver, tal og bindestreger.", "settings.agentBehaviour.importMode.nameTaken": "En tilstand med dette navn eksisterer allerede.", "settings.agentBehaviour.importMode.invalidJson": "Ugyldig JSON-fil. Vælg venligst en gyldig agentdefinitionsfil.", + "settings.agentBehaviour.importMode.tooLarge": "Filen er for stor. Agentdefinitioner skal være under 1 MB.", "settings.agentBehaviour.exportMode": "Eksportér agentdefinition", "settings.agentBehaviour.editMode": "Rediger tilstand", "settings.agentBehaviour.editMode.description": "Beskrivelse", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 4ab9b9a8cdc..7ffc0479b12 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1091,6 +1091,7 @@ export const dict = { "settings.agentBehaviour.importMode.nameTaken": "Ein Modus mit diesem Namen existiert bereits.", "settings.agentBehaviour.importMode.invalidJson": "Ungültige JSON-Datei. Bitte wählen Sie eine gültige Agenten-Definitionsdatei aus.", + "settings.agentBehaviour.importMode.tooLarge": "Datei ist zu groß. Agentdefinitionen müssen unter 1 MB sein.", "settings.agentBehaviour.exportMode": "Agenten-Definition exportieren", "settings.agentBehaviour.editMode": "Modus bearbeiten", "settings.agentBehaviour.editMode.description": "Beschreibung", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 9f71815b809..0e5216e2ab0 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1109,6 +1109,7 @@ export const dict = { "Invalid mode name in file. Name must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.", "settings.agentBehaviour.importMode.nameTaken": "A mode with this name already exists.", "settings.agentBehaviour.importMode.invalidJson": "Invalid JSON file. Please select a valid agent definition file.", + "settings.agentBehaviour.importMode.tooLarge": "File is too large. Agent definitions must be under 1 MB.", "settings.agentBehaviour.exportMode": "Export agent definition", "settings.agentBehaviour.editMode": "Edit Mode", "settings.agentBehaviour.editMode.description": "Description", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index bfdf1e6c0cf..418987c1be8 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1082,6 +1082,8 @@ export const dict = { "settings.agentBehaviour.importMode.nameTaken": "Ya existe un modo con este nombre.", "settings.agentBehaviour.importMode.invalidJson": "Archivo JSON no válido. Por favor, seleccione un archivo de definición de agente válido.", + "settings.agentBehaviour.importMode.tooLarge": + "El archivo es demasiado grande. Las definiciones de agente deben ser menores de 1 MB.", "settings.agentBehaviour.exportMode": "Exportar definición del agente", "settings.agentBehaviour.editMode": "Editar modo", "settings.agentBehaviour.editMode.description": "Descripción", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 4ac7648b85b..59bd8d059e4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1095,6 +1095,8 @@ export const dict = { "settings.agentBehaviour.importMode.nameTaken": "Un mode avec ce nom existe déjà.", "settings.agentBehaviour.importMode.invalidJson": "Fichier JSON invalide. Veuillez sélectionner un fichier de définition d'agent valide.", + "settings.agentBehaviour.importMode.tooLarge": + "Le fichier est trop volumineux. Les définitions d'agent doivent faire moins de 1 Mo.", "settings.agentBehaviour.exportMode": "Exporter la définition de l'agent", "settings.agentBehaviour.editMode": "Modifier le mode", "settings.agentBehaviour.editMode.description": "Description", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 44dcae200eb..45be6d4f9a7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1073,6 +1073,8 @@ export const dict = { "settings.agentBehaviour.importMode.nameTaken": "この名前のモードはすでに存在します。", "settings.agentBehaviour.importMode.invalidJson": "無効なJSONファイルです。有効なエージェント定義ファイルを選択してください。", + "settings.agentBehaviour.importMode.tooLarge": + "ファイルが大きすぎます。エージェント定義は1 MB以下である必要があります。", "settings.agentBehaviour.exportMode": "エージェント定義をエクスポート", "settings.agentBehaviour.editMode": "モードを編集", "settings.agentBehaviour.editMode.description": "説明", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index b7d88e7f0f4..41fac239ab4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1068,6 +1068,7 @@ export const dict = { "파일의 모드 이름이 잘못되었습니다. 이름은 소문자로 시작하고 소문자, 숫자, 하이픈만 포함해야 합니다.", "settings.agentBehaviour.importMode.nameTaken": "이 이름의 모드가 이미 존재합니다.", "settings.agentBehaviour.importMode.invalidJson": "잘못된 JSON 파일입니다. 유효한 에이전트 정의 파일을 선택하세요.", + "settings.agentBehaviour.importMode.tooLarge": "파일이 너무 큽니다. 에이전트 정의는 1 MB 미만이어야 합니다.", "settings.agentBehaviour.exportMode": "에이전트 정의 내보내기", "settings.agentBehaviour.editMode": "모드 편집", "settings.agentBehaviour.editMode.description": "설명", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 3a633caab01..0d1e1c5de3f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1066,6 +1066,7 @@ export const dict = { "settings.agentBehaviour.importMode.nameTaken": "Er bestaat al een modus met deze naam.", "settings.agentBehaviour.importMode.invalidJson": "Ongeldig JSON-bestand. Selecteer een geldig agentdefinitiebestand.", + "settings.agentBehaviour.importMode.tooLarge": "Bestand is te groot. Agentdefinities moeten kleiner zijn dan 1 MB.", "settings.agentBehaviour.exportMode": "Agentdefinitie exporteren", "settings.agentBehaviour.removeMode.title": "Verwijder modus", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index f992b989b1b..29c3101e140 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1075,6 +1075,7 @@ export const dict = { "Ugyldig modusnavn i filen. Navnet må starte med en liten bokstav og bare inneholde små bokstaver, tall og bindestreker.", "settings.agentBehaviour.importMode.nameTaken": "En modus med dette navnet eksisterer allerede.", "settings.agentBehaviour.importMode.invalidJson": "Ugyldig JSON-fil. Vennligst velg en gyldig agentdefinisjonsfil.", + "settings.agentBehaviour.importMode.tooLarge": "Filen er for stor. Agentdefinisjoner må være under 1 MB.", "settings.agentBehaviour.exportMode": "Eksporter agentdefinisjon", "settings.agentBehaviour.editMode": "Rediger modus", "settings.agentBehaviour.editMode.description": "Beskrivelse", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 236644814ca..fa3afba71a0 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1077,6 +1077,7 @@ export const dict = { "settings.agentBehaviour.importMode.nameTaken": "Tryb o tej nazwie już istnieje.", "settings.agentBehaviour.importMode.invalidJson": "Nieprawidłowy plik JSON. Proszę wybrać prawidłowy plik definicji agenta.", + "settings.agentBehaviour.importMode.tooLarge": "Plik jest za duży. Definicje agentów muszą mieć mniej niż 1 MB.", "settings.agentBehaviour.exportMode": "Eksportuj definicję agenta", "settings.agentBehaviour.editMode": "Edytuj tryb", "settings.agentBehaviour.editMode.description": "Opis", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index b409161caa1..38b19ca396a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1080,6 +1080,7 @@ export const dict = { "settings.agentBehaviour.importMode.nameTaken": "Режим с таким названием уже существует.", "settings.agentBehaviour.importMode.invalidJson": "Недопустимый файл JSON. Пожалуйста, выберите корректный файл определения агента.", + "settings.agentBehaviour.importMode.tooLarge": "Файл слишком большой. Определения агентов должны быть менее 1 МБ.", "settings.agentBehaviour.exportMode": "Экспортировать определение агента", "settings.agentBehaviour.editMode": "Редактировать режим", "settings.agentBehaviour.editMode.description": "Описание", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 5ee2f6cd441..a547d653962 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1064,6 +1064,7 @@ export const dict = { "ชื่อโหมดในไฟล์ไม่ถูกต้อง ชื่อต้องขึ้นต้นด้วยตัวอักษรพิมพ์เล็กและประกอบด้วยตัวอักษรพิมพ์เล็ก ตัวเลข และขีดกลางเท่านั้น", "settings.agentBehaviour.importMode.nameTaken": "มีโหมดที่มีชื่อนี้อยู่แล้ว", "settings.agentBehaviour.importMode.invalidJson": "ไฟล์ JSON ไม่ถูกต้อง กรุณาเลือกไฟล์นิยามเอเจนต์ที่ถูกต้อง", + "settings.agentBehaviour.importMode.tooLarge": "ไฟล์มีขนาดใหญ่เกินไป คำจำกัดความเอเจนต์ต้องมีขนาดไม่เกิน 1 MB", "settings.agentBehaviour.exportMode": "ส่งออกนิยามเอเจนต์", "settings.agentBehaviour.editMode": "แก้ไขโหมด", "settings.agentBehaviour.editMode.description": "คำอธิบาย", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index af107a4382e..0ff31e8ef0a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1065,6 +1065,7 @@ export const dict = { "settings.agentBehaviour.importMode.nameTaken": "Bu ada sahip bir mod zaten mevcut.", "settings.agentBehaviour.importMode.invalidJson": "Geçersiz JSON dosyası. Lütfen geçerli bir ajan tanım dosyası seçin.", + "settings.agentBehaviour.importMode.tooLarge": "Dosya çok büyük. Ajan tanımları 1 MB'den küçük olmalıdır.", "settings.agentBehaviour.exportMode": "Ajan tanımını dışa aktar", "settings.agentBehaviour.removeMode.title": "Modu kaldır", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 956d0828d6b..945344deea7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1055,6 +1055,7 @@ export const dict = { "文件中的模式名称无效。名称必须以小写字母开头,且仅包含小写字母、数字和连字符。", "settings.agentBehaviour.importMode.nameTaken": "此名称的模式已存在。", "settings.agentBehaviour.importMode.invalidJson": "无效的 JSON 文件。请选择有效的代理定义文件。", + "settings.agentBehaviour.importMode.tooLarge": "文件太大。代理定义必须小于 1 MB。", "settings.agentBehaviour.exportMode": "导出代理定义", "settings.agentBehaviour.editMode": "编辑模式", "settings.agentBehaviour.editMode.description": "描述", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 46133a76f65..dede412b8d5 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1057,6 +1057,7 @@ export const dict = { "檔案中的模式名稱無效。名稱必須以小寫字母開頭,且僅包含小寫字母、數字和連字號。", "settings.agentBehaviour.importMode.nameTaken": "此名稱的模式已存在。", "settings.agentBehaviour.importMode.invalidJson": "無效的 JSON 檔案。請選擇有效的代理定義檔案。", + "settings.agentBehaviour.importMode.tooLarge": "檔案太大。代理定義必須小於 1 MB。", "settings.agentBehaviour.exportMode": "匯出代理定義", "settings.agentBehaviour.editMode": "編輯模式", "settings.agentBehaviour.editMode.description": "描述", From 0b9f4f807840ed7769b5f13f1f0170f358c707bf Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 25 Mar 2026 15:21:09 +0100 Subject: [PATCH 036/261] feat(vscode): add hidden/disable toggles for agents in settings Add Hidden and Disabled toggle switches to the agent edit view. Hidden agents are excluded from the mode switcher but remain in settings. Disabled agents are visually dimmed in the agent list with badge indicators. Adds hidden and disable fields to the webview AgentConfig type and writes to config.agent[name].hidden / config.agent[name].disable. Closes #7594 --- .../components/settings/AgentBehaviourTab.tsx | 30 +++++++++++++++++++ .../src/components/settings/ModeEditView.tsx | 21 ++++++++++++- .../kilo-vscode/webview-ui/src/i18n/ar.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/br.ts | 7 +++++ .../kilo-vscode/webview-ui/src/i18n/bs.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/da.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/de.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/en.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/es.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/fr.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/ja.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/ko.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/nl.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/no.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/pl.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/ru.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/th.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/tr.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/zh.ts | 6 ++++ .../kilo-vscode/webview-ui/src/i18n/zht.ts | 6 ++++ .../webview-ui/src/types/messages.ts | 2 ++ 21 files changed, 161 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index 83dd16956e7..007f69610dd 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -296,6 +296,9 @@ const AgentBehaviourTab: Component = () => { {(name, index) => { const agent = () => session.agents().find((a) => a.name === name) const isCustom = () => !agent()?.native + const agentCfg = () => config().agent?.[name] ?? {} + const disabled = () => agentCfg().disable ?? false + const hidden = () => agentCfg().hidden ?? false return (
{ "border-bottom": index() < agentNames().length - 1 ? "1px solid var(--border-weak-base)" : "none", "border-radius": "4px", cursor: "pointer", + opacity: disabled() ? "0.5" : "1", }} onClick={() => startEdit(name)} onMouseEnter={(e) => { @@ -331,6 +335,32 @@ const AgentBehaviourTab: Component = () => { custom + + + {language.t("settings.agentBehaviour.badge.hidden")} + + + + + {language.t("settings.agentBehaviour.badge.disabled")} + +
= (props) => { = (props) => { }} /> + + + update({ hidden: val || undefined })} hideLabel> + {language.t("settings.agentBehaviour.hidden.title")} + + + + + update({ disable: val || undefined })} hideLabel> + {language.t("settings.agentBehaviour.disable.title")} + +
diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index 8416cc7f23b..0d9e5a32530 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1037,6 +1037,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "معامل أخذ العينات النووي (0-1)", "settings.agentBehaviour.maxSteps.title": "الحد الأقصى للخطوات", "settings.agentBehaviour.maxSteps.description": "الحد الأقصى لتكرارات الوكيل", + "settings.agentBehaviour.hidden.title": "مخفي", + "settings.agentBehaviour.hidden.description": "إخفاء هذا الوكيل من مبدل الأوضاع في إدخال الدردشة", + "settings.agentBehaviour.disable.title": "معطل", + "settings.agentBehaviour.disable.description": "تعطيل هذا الوكيل بالكامل — لن يظهر في أي مكان", + "settings.agentBehaviour.badge.hidden": "مخفي", + "settings.agentBehaviour.badge.disabled": "معطل", "settings.agentBehaviour.discoveredSkills": "المهارات المكتشفة", "settings.agentBehaviour.noSkillsFound": "لم يتم العثور على مهارات. أضف مسارات مجلدات أو عناوين URL أدناه لإتاحة المهارات.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 6a195aaa1b0..e6a80d36d71 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1050,6 +1050,13 @@ export const dict = { "settings.agentBehaviour.topP.description": "Parâmetro de amostragem nucleus (0-1)", "settings.agentBehaviour.maxSteps.title": "Passos máximos", "settings.agentBehaviour.maxSteps.description": "Iterações máximas do agente", + "settings.agentBehaviour.hidden.title": "Oculto", + "settings.agentBehaviour.hidden.description": "Ocultar este agente do seletor de modos na entrada do chat", + "settings.agentBehaviour.disable.title": "Desativado", + "settings.agentBehaviour.disable.description": + "Desativar completamente este agente — ele não aparecerá em nenhum lugar", + "settings.agentBehaviour.badge.hidden": "oculto", + "settings.agentBehaviour.badge.disabled": "desativado", "settings.agentBehaviour.discoveredSkills": "Habilidades descobertas", "settings.agentBehaviour.noSkillsFound": "Nenhuma habilidade encontrada. Adicione caminhos de pastas ou URLs abaixo para disponibilizar habilidades.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 83e392192b0..b60e1a2b8f9 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1050,6 +1050,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Nucleus parametar uzorkovanja (0-1)", "settings.agentBehaviour.maxSteps.title": "Maks. koraci", "settings.agentBehaviour.maxSteps.description": "Maksimalne iteracije agenta", + "settings.agentBehaviour.hidden.title": "Skriveno", + "settings.agentBehaviour.hidden.description": "Sakrij ovog agenta iz prebacivača modova u unosu chata", + "settings.agentBehaviour.disable.title": "Onemogućeno", + "settings.agentBehaviour.disable.description": "Potpuno onemogući ovog agenta — neće se pojaviti nigdje", + "settings.agentBehaviour.badge.hidden": "skriveno", + "settings.agentBehaviour.badge.disabled": "onemogućeno", "settings.agentBehaviour.discoveredSkills": "Otkrivene vještine", "settings.agentBehaviour.noSkillsFound": "Nisu pronađene vještine. Dodajte putanje mapa ili URL-ove ispod kako biste učinili vještine dostupnim.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 06f53d140c5..de9bdedb6b8 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1045,6 +1045,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Nucleus-samplingparameter (0-1)", "settings.agentBehaviour.maxSteps.title": "Maks. trin", "settings.agentBehaviour.maxSteps.description": "Maksimale agentiterationer", + "settings.agentBehaviour.hidden.title": "Skjult", + "settings.agentBehaviour.hidden.description": "Skjul denne agent fra tilstandsvælgeren i chatinput", + "settings.agentBehaviour.disable.title": "Deaktiveret", + "settings.agentBehaviour.disable.description": "Deaktiver denne agent fuldstændigt — den vises ingen steder", + "settings.agentBehaviour.badge.hidden": "skjult", + "settings.agentBehaviour.badge.disabled": "deaktiveret", "settings.agentBehaviour.discoveredSkills": "Opdagede skills", "settings.agentBehaviour.noSkillsFound": "Ingen skills fundet. Tilføj skill-mappestier eller URL'er nedenfor for at gøre skills tilgængelige.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 7e7bd1184b5..5ca4068321f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1063,6 +1063,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Nucleus-Sampling-Parameter (0-1)", "settings.agentBehaviour.maxSteps.title": "Max. Schritte", "settings.agentBehaviour.maxSteps.description": "Maximale Agent-Iterationen", + "settings.agentBehaviour.hidden.title": "Versteckt", + "settings.agentBehaviour.hidden.description": "Diesen Agent im Modus-Umschalter der Chat-Eingabe ausblenden", + "settings.agentBehaviour.disable.title": "Deaktiviert", + "settings.agentBehaviour.disable.description": "Diesen Agent vollständig deaktivieren — er wird nirgends angezeigt", + "settings.agentBehaviour.badge.hidden": "versteckt", + "settings.agentBehaviour.badge.disabled": "deaktiviert", "settings.agentBehaviour.discoveredSkills": "Erkannte Skills", "settings.agentBehaviour.noSkillsFound": "Keine Skills gefunden. Fügen Sie unten Skill-Ordnerpfade oder URLs hinzu, um Skills verfügbar zu machen.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 58789081d5a..939090cfbee 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1051,6 +1051,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Nucleus sampling parameter (0-1)", "settings.agentBehaviour.maxSteps.title": "Max Steps", "settings.agentBehaviour.maxSteps.description": "Maximum agentic iterations", + "settings.agentBehaviour.hidden.title": "Hidden", + "settings.agentBehaviour.hidden.description": "Hide this agent from the mode switcher in the chat input", + "settings.agentBehaviour.disable.title": "Disabled", + "settings.agentBehaviour.disable.description": "Fully disable this agent — it will not appear anywhere", + "settings.agentBehaviour.badge.hidden": "hidden", + "settings.agentBehaviour.badge.disabled": "disabled", "settings.agentBehaviour.discoveredSkills": "Discovered Skills", "settings.agentBehaviour.noSkillsFound": "No skills discovered. Add skill folder paths or URLs below to make skills available.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 9b2d1da3261..1c0992b1ab2 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1053,6 +1053,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Parámetro de muestreo nucleus (0-1)", "settings.agentBehaviour.maxSteps.title": "Pasos máximos", "settings.agentBehaviour.maxSteps.description": "Iteraciones máximas del agente", + "settings.agentBehaviour.hidden.title": "Oculto", + "settings.agentBehaviour.hidden.description": "Ocultar este agente del selector de modos en la entrada del chat", + "settings.agentBehaviour.disable.title": "Desactivado", + "settings.agentBehaviour.disable.description": "Desactivar completamente este agente — no aparecerá en ningún lugar", + "settings.agentBehaviour.badge.hidden": "oculto", + "settings.agentBehaviour.badge.disabled": "desactivado", "settings.agentBehaviour.discoveredSkills": "Habilidades descubiertas", "settings.agentBehaviour.noSkillsFound": "No se encontraron habilidades. Agregue rutas de carpetas o URLs abajo para hacer disponibles las habilidades.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 0b507379ae4..ef0770fd619 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1065,6 +1065,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Paramètre d'échantillonnage nucleus (0-1)", "settings.agentBehaviour.maxSteps.title": "Étapes max.", "settings.agentBehaviour.maxSteps.description": "Itérations maximales de l'agent", + "settings.agentBehaviour.hidden.title": "Masqué", + "settings.agentBehaviour.hidden.description": "Masquer cet agent du sélecteur de mode dans la saisie du chat", + "settings.agentBehaviour.disable.title": "Désactivé", + "settings.agentBehaviour.disable.description": "Désactiver complètement cet agent — il n'apparaîtra nulle part", + "settings.agentBehaviour.badge.hidden": "masqué", + "settings.agentBehaviour.badge.disabled": "désactivé", "settings.agentBehaviour.discoveredSkills": "Compétences découvertes", "settings.agentBehaviour.noSkillsFound": "Aucune compétence découverte. Ajoutez des chemins de dossiers ou des URLs ci-dessous pour rendre les compétences disponibles.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 21464079b85..639d601000c 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1045,6 +1045,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "核サンプリングパラメータ(0-1)", "settings.agentBehaviour.maxSteps.title": "最大ステップ数", "settings.agentBehaviour.maxSteps.description": "最大エージェント反復回数", + "settings.agentBehaviour.hidden.title": "非表示", + "settings.agentBehaviour.hidden.description": "チャット入力のモード切り替えからこのエージェントを非表示にする", + "settings.agentBehaviour.disable.title": "無効", + "settings.agentBehaviour.disable.description": "このエージェントを完全に無効にする — どこにも表示されなくなります", + "settings.agentBehaviour.badge.hidden": "非表示", + "settings.agentBehaviour.badge.disabled": "無効", "settings.agentBehaviour.discoveredSkills": "検出されたスキル", "settings.agentBehaviour.noSkillsFound": "スキルが見つかりません。スキルを利用可能にするには、以下にスキルフォルダパスまたはURLを追加してください。", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 4d262f0b16e..73a5e1356d3 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1042,6 +1042,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "핵 샘플링 매개변수 (0-1)", "settings.agentBehaviour.maxSteps.title": "최대 단계", "settings.agentBehaviour.maxSteps.description": "최대 에이전트 반복 횟수", + "settings.agentBehaviour.hidden.title": "숨김", + "settings.agentBehaviour.hidden.description": "채팅 입력의 모드 전환기에서 이 에이전트를 숨기기", + "settings.agentBehaviour.disable.title": "비활성화됨", + "settings.agentBehaviour.disable.description": "이 에이전트를 완전히 비활성화 — 어디에도 표시되지 않습니다", + "settings.agentBehaviour.badge.hidden": "숨김", + "settings.agentBehaviour.badge.disabled": "비활성화됨", "settings.agentBehaviour.discoveredSkills": "검색된 스킬", "settings.agentBehaviour.noSkillsFound": "스킬을 찾을 수 없습니다. 스킬을 사용하려면 아래에 스킬 폴더 경로 또는 URL을 추가하세요.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 6c18764d272..fb5dbdc605a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1055,6 +1055,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Nucleus sampling parameter (0-1)", "settings.agentBehaviour.maxSteps.title": "Max Stappen", "settings.agentBehaviour.maxSteps.description": "Maximale agent iteraties", + "settings.agentBehaviour.hidden.title": "Verborgen", + "settings.agentBehaviour.hidden.description": "Verberg deze agent uit de modusschakelaar in de chatinvoer", + "settings.agentBehaviour.disable.title": "Uitgeschakeld", + "settings.agentBehaviour.disable.description": "Schakel deze agent volledig uit — deze verschijnt nergens", + "settings.agentBehaviour.badge.hidden": "verborgen", + "settings.agentBehaviour.badge.disabled": "uitgeschakeld", "settings.agentBehaviour.discoveredSkills": "Ontdekte Skills", "settings.agentBehaviour.noSkillsFound": "Geen skills ontdekt. Voeg hieronder skill mappaden of URL's toe om skills beschikbaar te maken.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 5f2f58e8515..db32af01f3a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1048,6 +1048,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Nucleus-samplingsparameter (0-1)", "settings.agentBehaviour.maxSteps.title": "Maks. trinn", "settings.agentBehaviour.maxSteps.description": "Maksimale agentiterasjoner", + "settings.agentBehaviour.hidden.title": "Skjult", + "settings.agentBehaviour.hidden.description": "Skjul denne agenten fra modusvelgeren i chatinntastingen", + "settings.agentBehaviour.disable.title": "Deaktivert", + "settings.agentBehaviour.disable.description": "Deaktiver denne agenten fullstendig — den vises ikke noe sted", + "settings.agentBehaviour.badge.hidden": "skjult", + "settings.agentBehaviour.badge.disabled": "deaktivert", "settings.agentBehaviour.discoveredSkills": "Oppdagede ferdigheter", "settings.agentBehaviour.noSkillsFound": "Ingen ferdigheter funnet. Legg til ferdighetsmappestier eller URLer nedenfor for å gjøre ferdigheter tilgjengelige.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 0a616ea4bfb..ab4ff550beb 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1048,6 +1048,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Parametr próbkowania nucleus (0-1)", "settings.agentBehaviour.maxSteps.title": "Maks. kroki", "settings.agentBehaviour.maxSteps.description": "Maksymalna liczba iteracji agenta", + "settings.agentBehaviour.hidden.title": "Ukryty", + "settings.agentBehaviour.hidden.description": "Ukryj tego agenta z przełącznika trybów w polu czatu", + "settings.agentBehaviour.disable.title": "Wyłączony", + "settings.agentBehaviour.disable.description": "Całkowicie wyłącz tego agenta — nie pojawi się nigdzie", + "settings.agentBehaviour.badge.hidden": "ukryty", + "settings.agentBehaviour.badge.disabled": "wyłączony", "settings.agentBehaviour.discoveredSkills": "Wykryte umiejętności", "settings.agentBehaviour.noSkillsFound": "Nie znaleziono umiejętności. Dodaj ścieżki folderów lub adresy URL poniżej, aby udostępnić umiejętności.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 825f2578ef1..b52111108c3 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1051,6 +1051,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Параметр nucleus-сэмплирования (0-1)", "settings.agentBehaviour.maxSteps.title": "Макс. шагов", "settings.agentBehaviour.maxSteps.description": "Максимальное число итераций агента", + "settings.agentBehaviour.hidden.title": "Скрытый", + "settings.agentBehaviour.hidden.description": "Скрыть этого агента из переключателя режимов в поле ввода чата", + "settings.agentBehaviour.disable.title": "Отключён", + "settings.agentBehaviour.disable.description": "Полностью отключить этого агента — он не будет отображаться нигде", + "settings.agentBehaviour.badge.hidden": "скрытый", + "settings.agentBehaviour.badge.disabled": "отключён", "settings.agentBehaviour.discoveredSkills": "Обнаруженные навыки", "settings.agentBehaviour.noSkillsFound": "Навыки не обнаружены. Добавьте пути к папкам навыков или URL-адреса ниже, чтобы сделать навыки доступными.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index b31301d5e4f..2819b062905 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1038,6 +1038,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "พารามิเตอร์ nucleus sampling (0-1)", "settings.agentBehaviour.maxSteps.title": "ขั้นตอนสูงสุด", "settings.agentBehaviour.maxSteps.description": "จำนวนรอบเอเจนต์สูงสุด", + "settings.agentBehaviour.hidden.title": "ซ่อน", + "settings.agentBehaviour.hidden.description": "ซ่อนเอเจนต์นี้จากตัวสลับโหมดในช่องป้อนแชท", + "settings.agentBehaviour.disable.title": "ปิดใช้งาน", + "settings.agentBehaviour.disable.description": "ปิดใช้งานเอเจนต์นี้อย่างสมบูรณ์ — จะไม่ปรากฏที่ใดเลย", + "settings.agentBehaviour.badge.hidden": "ซ่อน", + "settings.agentBehaviour.badge.disabled": "ปิดใช้งาน", "settings.agentBehaviour.discoveredSkills": "ทักษะที่ค้นพบ", "settings.agentBehaviour.noSkillsFound": "ไม่พบทักษะ เพิ่มเส้นทางโฟลเดอร์หรือ URL ด้านล่างเพื่อทำให้ทักษะพร้อมใช้งาน", "settings.agentBehaviour.availableModes": "โหมดกำหนดเองที่ใช้ได้", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 63b7acf3d7f..1fd8c2785c7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1054,6 +1054,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "Çekirdek örnekleme parametresi (0-1)", "settings.agentBehaviour.maxSteps.title": "Maksimum Adım", "settings.agentBehaviour.maxSteps.description": "Maksimum ajanlık yinelemesi", + "settings.agentBehaviour.hidden.title": "Gizli", + "settings.agentBehaviour.hidden.description": "Bu ajanı sohbet girişindeki mod değiştiriciden gizle", + "settings.agentBehaviour.disable.title": "Devre dışı", + "settings.agentBehaviour.disable.description": "Bu ajanı tamamen devre dışı bırak — hiçbir yerde görünmeyecek", + "settings.agentBehaviour.badge.hidden": "gizli", + "settings.agentBehaviour.badge.disabled": "devre dışı", "settings.agentBehaviour.discoveredSkills": "Keşfedilen Beceriler", "settings.agentBehaviour.noSkillsFound": "Keşfedilen beceri yok. Becerileri kullanılabilir kılmak için aşağıya beceri klasör yolları veya URL'ler ekleyin.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index a9a95d68151..369eebc173c 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1031,6 +1031,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "核采样参数(0-1)", "settings.agentBehaviour.maxSteps.title": "最大步数", "settings.agentBehaviour.maxSteps.description": "最大智能体迭代次数", + "settings.agentBehaviour.hidden.title": "隐藏", + "settings.agentBehaviour.hidden.description": "在聊天输入的模式切换器中隐藏此智能体", + "settings.agentBehaviour.disable.title": "已禁用", + "settings.agentBehaviour.disable.description": "完全禁用此智能体 — 它将不会出现在任何地方", + "settings.agentBehaviour.badge.hidden": "隐藏", + "settings.agentBehaviour.badge.disabled": "已禁用", "settings.agentBehaviour.discoveredSkills": "已发现的技能", "settings.agentBehaviour.noSkillsFound": "未发现任何技能。请在下方添加技能文件夹路径或 URL 以使技能可用。", "settings.agentBehaviour.availableModes": "可用自定义模式", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index afcda94a457..8c4ac89c51c 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1032,6 +1032,12 @@ export const dict = { "settings.agentBehaviour.topP.description": "核取樣參數(0-1)", "settings.agentBehaviour.maxSteps.title": "最大步數", "settings.agentBehaviour.maxSteps.description": "最大 Agent 迭代次數", + "settings.agentBehaviour.hidden.title": "隱藏", + "settings.agentBehaviour.hidden.description": "在聊天輸入的模式切換器中隱藏此 Agent", + "settings.agentBehaviour.disable.title": "已停用", + "settings.agentBehaviour.disable.description": "完全停用此 Agent — 它將不會出現在任何地方", + "settings.agentBehaviour.badge.hidden": "隱藏", + "settings.agentBehaviour.badge.disabled": "已停用", "settings.agentBehaviour.discoveredSkills": "已發現的 Skill", "settings.agentBehaviour.noSkillsFound": "未發現任何 Skill。請在下方新增 Skill 資料夾路徑或 URL 以使 Skill 可用。", "settings.agentBehaviour.availableModes": "可用自訂模式", diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index 637759b537b..e5c7a7d96a5 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -324,6 +324,8 @@ export interface AgentConfig { prompt?: string description?: string mode?: "subagent" | "primary" | "all" + hidden?: boolean + disable?: boolean temperature?: number top_p?: number steps?: number From 485de5d7302890704382302e636b19aedfbc0308 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 25 Mar 2026 15:27:14 +0100 Subject: [PATCH 037/261] fix(vscode): clear default_agent when hiding or disabling it Automatically unset default_agent config when the user hides or disables the agent that is currently set as the default, preventing an invalid reference in the config. --- .../src/components/settings/ModeEditView.tsx | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx index c92a9860c71..4c49233126f 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx @@ -172,7 +172,17 @@ const ModeEditView: Component = (props) => { title={language.t("settings.agentBehaviour.hidden.title")} description={language.t("settings.agentBehaviour.hidden.description")} > - update({ hidden: val || undefined })} hideLabel> + { + update({ hidden: val || undefined }) + // Clear default_agent if hiding the current default + if (val && config().default_agent === props.name) { + updateConfig({ default_agent: undefined }) + } + }} + hideLabel + > {language.t("settings.agentBehaviour.hidden.title")} @@ -182,7 +192,17 @@ const ModeEditView: Component = (props) => { description={language.t("settings.agentBehaviour.disable.description")} last > - update({ disable: val || undefined })} hideLabel> + { + update({ disable: val || undefined }) + // Clear default_agent if disabling the current default + if (val && config().default_agent === props.name) { + updateConfig({ default_agent: undefined }) + } + }} + hideLabel + > {language.t("settings.agentBehaviour.disable.title")} From af577537b904661f747800c77d20970e49aa591d Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Thu, 26 Mar 2026 13:27:40 +0100 Subject: [PATCH 038/261] refactor(vscode): extract import/export logic into mode-io module Extract parseImport() and buildExport() from AgentBehaviourTab and ModeEditView into a standalone mode-io.ts module that has no UI dependencies and can be unit tested directly. Add 15 tests covering valid parsing, name validation, mode validation, duplicate detection, invalid JSON, type coercion, and export serialisation. Addresses review feedback from marius-kilocode to extract the import/export logic and write tests. --- .../kilo-vscode/tests/unit/mode-io.test.ts | 139 ++++++++++++++++++ .../components/settings/AgentBehaviourTab.tsx | 44 ++---- .../src/components/settings/ModeEditView.tsx | 3 +- .../src/components/settings/mode-io.ts | 55 +++++++ 4 files changed, 210 insertions(+), 31 deletions(-) create mode 100644 packages/kilo-vscode/tests/unit/mode-io.test.ts create mode 100644 packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts diff --git a/packages/kilo-vscode/tests/unit/mode-io.test.ts b/packages/kilo-vscode/tests/unit/mode-io.test.ts new file mode 100644 index 00000000000..049db8ddb0e --- /dev/null +++ b/packages/kilo-vscode/tests/unit/mode-io.test.ts @@ -0,0 +1,139 @@ +import { describe, it, expect } from "bun:test" +import { parseImport, buildExport, MAX_IMPORT_SIZE } from "../../webview-ui/src/components/settings/mode-io" + +describe("parseImport", () => { + it("parses a valid full definition", () => { + const json = JSON.stringify({ + name: "reviewer", + description: "Reviews code", + prompt: "You review code.", + model: "anthropic/claude-sonnet-4-20250514", + mode: "primary", + temperature: 0.7, + top_p: 0.9, + steps: 10, + }) + const result = parseImport(json, []) + expect(result).toEqual({ + ok: true, + name: "reviewer", + config: { + description: "Reviews code", + prompt: "You review code.", + model: "anthropic/claude-sonnet-4-20250514", + mode: "primary", + temperature: 0.7, + top_p: 0.9, + steps: 10, + }, + }) + }) + + it("defaults mode to primary when omitted", () => { + const json = JSON.stringify({ name: "my-agent" }) + const result = parseImport(json, []) + expect(result).toEqual({ + ok: true, + name: "my-agent", + config: { mode: "primary" }, + }) + }) + + it("rejects invalid JSON", () => { + expect(parseImport("not json", [])).toEqual({ ok: false, error: "invalidJson" }) + }) + + it("rejects missing name", () => { + expect(parseImport("{}", [])).toEqual({ ok: false, error: "invalidName" }) + }) + + it("rejects name starting with number", () => { + expect(parseImport(JSON.stringify({ name: "1agent" }), [])).toEqual({ ok: false, error: "invalidName" }) + }) + + it("rejects name with uppercase", () => { + expect(parseImport(JSON.stringify({ name: "MyAgent" }), [])).toEqual({ ok: false, error: "invalidName" }) + }) + + it("rejects name with spaces", () => { + expect(parseImport(JSON.stringify({ name: "my agent" }), [])).toEqual({ ok: false, error: "invalidName" }) + }) + + it("rejects duplicate name", () => { + const json = JSON.stringify({ name: "existing" }) + expect(parseImport(json, ["existing", "other"])).toEqual({ ok: false, error: "nameTaken" }) + }) + + it("ignores invalid mode values", () => { + const json = JSON.stringify({ name: "test", mode: "bogus" }) + const result = parseImport(json, []) + expect(result).toEqual({ + ok: true, + name: "test", + config: { mode: "primary" }, + }) + }) + + it("accepts all valid mode values", () => { + for (const mode of ["subagent", "primary", "all"] as const) { + const json = JSON.stringify({ name: "test", mode }) + const result = parseImport(json, []) + expect(result).toEqual({ ok: true, name: "test", config: { mode } }) + } + }) + + it("ignores non-string and non-number fields", () => { + const json = JSON.stringify({ + name: "test", + description: 123, + prompt: true, + model: [], + temperature: "hot", + top_p: null, + steps: "many", + }) + const result = parseImport(json, []) + expect(result).toEqual({ ok: true, name: "test", config: { mode: "primary" } }) + }) + + it("trims whitespace from name", () => { + const json = JSON.stringify({ name: " trimmed " }) + // "trimmed" doesn't have hyphens or digits so it should be valid + const result = parseImport(json, []) + expect(result).toEqual({ ok: true, name: "trimmed", config: { mode: "primary" } }) + }) +}) + +describe("buildExport", () => { + it("includes name and all config fields", () => { + const result = buildExport("reviewer", { + description: "Reviews code", + prompt: "You review code.", + model: "anthropic/claude-sonnet-4-20250514", + mode: "primary", + temperature: 0.7, + top_p: 0.9, + steps: 10, + }) + expect(result).toEqual({ + name: "reviewer", + description: "Reviews code", + prompt: "You review code.", + model: "anthropic/claude-sonnet-4-20250514", + mode: "primary", + temperature: 0.7, + top_p: 0.9, + steps: 10, + }) + }) + + it("handles empty config", () => { + expect(buildExport("minimal", {})).toEqual({ name: "minimal" }) + }) +}) + +describe("MAX_IMPORT_SIZE", () => { + it("is 1 MB", () => { + expect(MAX_IMPORT_SIZE).toBe(1_048_576) + }) +}) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index fea51ed56a9..71e451b7676 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -10,10 +10,12 @@ import { useDialog } from "@kilocode/kilo-ui/context/dialog" import { useConfig } from "../../context/config" import { useSession } from "../../context/session" import { useLanguage } from "../../context/language" -import type { AgentConfig, AgentInfo, SkillInfo } from "../../types/messages" +import type { AgentInfo, SkillInfo } from "../../types/messages" import ModeEditView from "./ModeEditView" import ModeCreateView from "./ModeCreateView" import WorkflowsTab from "./agent-behaviour/WorkflowsTab" +import { parseImport, MAX_IMPORT_SIZE } from "./mode-io" +import type { ImportError } from "./mode-io" type SubtabId = "agents" | "mcpServers" | "rules" | "workflows" | "skills" @@ -229,42 +231,24 @@ const AgentBehaviourTab: Component = () => { const [importError, setImportError] = createSignal("") + const errorKey = (tag: ImportError) => `settings.agentBehaviour.importMode.${tag}` as const + const importMode = (file: File) => { setImportError("") - if (file.size > 1_048_576) { - setImportError(language.t("settings.agentBehaviour.importMode.tooLarge")) + if (file.size > MAX_IMPORT_SIZE) { + setImportError(language.t(errorKey("tooLarge"))) return } const reader = new FileReader() reader.onload = () => { - try { - const data = JSON.parse(reader.result as string) - const name = typeof data.name === "string" ? data.name.trim() : "" - if (!name || !/^[a-z][a-z0-9-]*$/.test(name)) { - setImportError(language.t("settings.agentBehaviour.importMode.invalidName")) - return - } - if (agentNames().includes(name)) { - setImportError(language.t("settings.agentBehaviour.importMode.nameTaken")) - return - } - const partial: Partial = {} - if (typeof data.description === "string") partial.description = data.description - if (typeof data.prompt === "string") partial.prompt = data.prompt - if (typeof data.model === "string") partial.model = data.model - const modes = ["subagent", "primary", "all"] as const - if (typeof data.mode === "string" && modes.includes(data.mode)) partial.mode = data.mode - if (typeof data.temperature === "number") partial.temperature = data.temperature - if (typeof data.top_p === "number") partial.top_p = data.top_p - if (typeof data.steps === "number") partial.steps = data.steps - const existing = config().agent ?? {} - updateConfig({ - agent: { ...existing, [name]: { ...partial, mode: partial.mode ?? "primary" } }, - }) - setImportError("") - } catch { - setImportError(language.t("settings.agentBehaviour.importMode.invalidJson")) + const result = parseImport(reader.result as string, agentNames()) + if (!result.ok) { + setImportError(language.t(errorKey(result.error))) + return } + const existing = config().agent ?? {} + updateConfig({ agent: { ...existing, [result.name]: result.config } }) + setImportError("") } reader.readAsText(file) } diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx index 88a12774b5f..948535f17c7 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/ModeEditView.tsx @@ -9,6 +9,7 @@ import { useSession } from "../../context/session" import { useLanguage } from "../../context/language" import type { AgentConfig, AgentInfo } from "../../types/messages" import SettingsRow from "./SettingsRow" +import { buildExport } from "./mode-io" interface Props { name: string @@ -41,7 +42,7 @@ const ModeEditView: Component = (props) => { } const exportMode = () => { - const data = { name: props.name, ...cfg() } + const data = buildExport(props.name, cfg()) const json = JSON.stringify(data, null, 2) const blob = new Blob([json], { type: "application/json" }) const url = URL.createObjectURL(blob) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts b/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts new file mode 100644 index 00000000000..5a0f496d53a --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts @@ -0,0 +1,55 @@ +import type { AgentConfig } from "../../types/messages" + +/** Maximum import file size in bytes (1 MB). */ +export const MAX_IMPORT_SIZE = 1_048_576 + +const NAME_RE = /^[a-z][a-z0-9-]*$/ +const MODES = ["subagent", "primary", "all"] as const + +export type ImportError = "invalidJson" | "invalidName" | "nameTaken" | "tooLarge" + +export type ImportResult = { ok: true; name: string; config: AgentConfig } | { ok: false; error: ImportError } + +/** + * Parse a raw JSON string into a validated agent name + config. + * Returns an error tag (matching the i18n key suffix) on failure. + */ +export function parseImport(json: string, taken: string[]): ImportResult { + let data: Record + try { + data = JSON.parse(json) + } catch { + return { ok: false, error: "invalidJson" } + } + + const name = typeof data.name === "string" ? data.name.trim() : "" + if (!name || !NAME_RE.test(name)) { + return { ok: false, error: "invalidName" } + } + if (taken.includes(name)) { + return { ok: false, error: "nameTaken" } + } + + const partial: Partial = {} + if (typeof data.description === "string") partial.description = data.description + if (typeof data.prompt === "string") partial.prompt = data.prompt + if (typeof data.model === "string") partial.model = data.model + if (typeof data.mode === "string" && (MODES as readonly string[]).includes(data.mode)) + partial.mode = data.mode as AgentConfig["mode"] + if (typeof data.temperature === "number") partial.temperature = data.temperature + if (typeof data.top_p === "number") partial.top_p = data.top_p + if (typeof data.steps === "number") partial.steps = data.steps + + return { + ok: true, + name, + config: { ...partial, mode: partial.mode ?? "primary" }, + } +} + +/** + * Build the JSON-serialisable export payload for a mode. + */ +export function buildExport(name: string, cfg: AgentConfig): Record { + return { name, ...cfg } +} From 1c1d3ed6bc5f04f7397443b188f9ae350270df2f Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Thu, 26 Mar 2026 13:31:52 +0100 Subject: [PATCH 039/261] style(vscode): revert unintended PopupSelector format change --- .../webview-ui/src/components/shared/PopupSelector.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/shared/PopupSelector.tsx b/packages/kilo-vscode/webview-ui/src/components/shared/PopupSelector.tsx index 207e2f7aaff..27426e39242 100644 --- a/packages/kilo-vscode/webview-ui/src/components/shared/PopupSelector.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/shared/PopupSelector.tsx @@ -22,8 +22,10 @@ import { import { Popover } from "@kilocode/kilo-ui/popover" import type { PopoverProps } from "@kilocode/kilo-ui/popover" -export interface PopupSelectorProps - extends Omit, "style" | "children"> { +export interface PopupSelectorProps extends Omit< + PopoverProps, + "style" | "children" +> { /** Whether the selector is in expanded mode (wider + taller). */ expanded: boolean /** Preferred width when collapsed. Default: 250 */ From d6329ae9e821b078f35bf874bc5d75eddb0ef8bd Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Thu, 26 Mar 2026 13:37:05 +0100 Subject: [PATCH 040/261] fix(vscode): preserve permission config during agent import/export The permission field on AgentConfig was silently dropped during import because parseImport did not extract it. This caused a round-trip (export then import) to lose all per-tool permission overrides like read:allow, edit:deny, etc. Add parsePermission() that validates each entry against the allowed levels (allow/ask/deny) and drops invalid values. Add 4 tests covering valid permissions, invalid values, non-object input, and round-trip preservation. --- .../kilo-vscode/tests/unit/mode-io.test.ts | 51 +++++++++++++++++++ .../src/components/settings/mode-io.ts | 19 ++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/tests/unit/mode-io.test.ts b/packages/kilo-vscode/tests/unit/mode-io.test.ts index 049db8ddb0e..faf162c684c 100644 --- a/packages/kilo-vscode/tests/unit/mode-io.test.ts +++ b/packages/kilo-vscode/tests/unit/mode-io.test.ts @@ -102,6 +102,57 @@ describe("parseImport", () => { const result = parseImport(json, []) expect(result).toEqual({ ok: true, name: "trimmed", config: { mode: "primary" } }) }) + + it("preserves valid permission entries", () => { + const json = JSON.stringify({ + name: "reviewer", + permission: { read: "allow", bash: "allow", edit: "deny", mcp: "ask" }, + }) + const result = parseImport(json, []) + expect(result).toEqual({ + ok: true, + name: "reviewer", + config: { + mode: "primary", + permission: { read: "allow", bash: "allow", edit: "deny", mcp: "ask" }, + }, + }) + }) + + it("drops invalid permission values", () => { + const json = JSON.stringify({ + name: "test", + permission: { read: "allow", bad: "nope", num: 42, arr: [] }, + }) + const result = parseImport(json, []) + expect(result).toEqual({ + ok: true, + name: "test", + config: { mode: "primary", permission: { read: "allow" } }, + }) + }) + + it("ignores non-object permission field", () => { + const json = JSON.stringify({ name: "test", permission: "allow" }) + const result = parseImport(json, []) + expect(result).toEqual({ ok: true, name: "test", config: { mode: "primary" } }) + }) + + it("round-trips permission through export and import", () => { + const cfg = { + mode: "primary" as const, + prompt: "Review code", + permission: { read: "allow" as const, edit: "deny" as const }, + } + const exported = buildExport("reviewer", cfg) + const json = JSON.stringify(exported) + const result = parseImport(json, []) + expect(result).toEqual({ + ok: true, + name: "reviewer", + config: { mode: "primary", prompt: "Review code", permission: { read: "allow", edit: "deny" } }, + }) + }) }) describe("buildExport", () => { diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts b/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts index 5a0f496d53a..9b0ef49cefd 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts +++ b/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts @@ -1,15 +1,30 @@ -import type { AgentConfig } from "../../types/messages" +import type { AgentConfig, PermissionConfig } from "../../types/messages" /** Maximum import file size in bytes (1 MB). */ export const MAX_IMPORT_SIZE = 1_048_576 const NAME_RE = /^[a-z][a-z0-9-]*$/ const MODES = ["subagent", "primary", "all"] as const +const LEVELS = new Set(["allow", "ask", "deny"]) export type ImportError = "invalidJson" | "invalidName" | "nameTaken" | "tooLarge" export type ImportResult = { ok: true; name: string; config: AgentConfig } | { ok: false; error: ImportError } +/** Validate and extract a permission map, dropping unknown entries. */ +function parsePermission(raw: unknown): PermissionConfig | undefined { + if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return undefined + const out: PermissionConfig = {} + let count = 0 + for (const [key, val] of Object.entries(raw)) { + if (typeof val === "string" && LEVELS.has(val)) { + out[key] = val as PermissionConfig[string] + count++ + } + } + return count > 0 ? out : undefined +} + /** * Parse a raw JSON string into a validated agent name + config. * Returns an error tag (matching the i18n key suffix) on failure. @@ -39,6 +54,8 @@ export function parseImport(json: string, taken: string[]): ImportResult { if (typeof data.temperature === "number") partial.temperature = data.temperature if (typeof data.top_p === "number") partial.top_p = data.top_p if (typeof data.steps === "number") partial.steps = data.steps + const perms = parsePermission(data.permission) + if (perms) partial.permission = perms return { ok: true, From 5d6d569121d83c0eb7d65a02b5d0120277798df2 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Thu, 26 Mar 2026 13:42:35 +0100 Subject: [PATCH 041/261] fix(vscode): handle null JSON and nested permission rules in import Address kilo-code-bot review feedback: - Guard against JSON.parse returning non-object values (null, arrays, strings, numbers) which would crash on property access - Support nested per-pattern permission rules like bash: { "*": "ask", uname: "allow" } which PermissionRule allows but were previously silently dropped Add 5 tests for non-object JSON rejection and nested permission round-trip. --- .../kilo-vscode/tests/unit/mode-io.test.ts | 32 +++++++++++++ .../src/components/settings/mode-io.ts | 47 ++++++++++++++----- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/packages/kilo-vscode/tests/unit/mode-io.test.ts b/packages/kilo-vscode/tests/unit/mode-io.test.ts index faf162c684c..bb6b99c1ce9 100644 --- a/packages/kilo-vscode/tests/unit/mode-io.test.ts +++ b/packages/kilo-vscode/tests/unit/mode-io.test.ts @@ -43,6 +43,22 @@ describe("parseImport", () => { expect(parseImport("not json", [])).toEqual({ ok: false, error: "invalidJson" }) }) + it("rejects JSON null", () => { + expect(parseImport("null", [])).toEqual({ ok: false, error: "invalidJson" }) + }) + + it("rejects JSON array", () => { + expect(parseImport("[]", [])).toEqual({ ok: false, error: "invalidJson" }) + }) + + it("rejects JSON string", () => { + expect(parseImport('"hello"', [])).toEqual({ ok: false, error: "invalidJson" }) + }) + + it("rejects JSON number", () => { + expect(parseImport("42", [])).toEqual({ ok: false, error: "invalidJson" }) + }) + it("rejects missing name", () => { expect(parseImport("{}", [])).toEqual({ ok: false, error: "invalidName" }) }) @@ -132,6 +148,22 @@ describe("parseImport", () => { }) }) + it("preserves nested per-pattern permission rules", () => { + const json = JSON.stringify({ + name: "test", + permission: { bash: { "*": "ask", uname: "allow" }, read: "allow" }, + }) + const result = parseImport(json, []) + expect(result).toEqual({ + ok: true, + name: "test", + config: { + mode: "primary", + permission: { bash: { "*": "ask", uname: "allow" }, read: "allow" }, + }, + }) + }) + it("ignores non-object permission field", () => { const json = JSON.stringify({ name: "test", permission: "allow" }) const result = parseImport(json, []) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts b/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts index 9b0ef49cefd..79428b38646 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts +++ b/packages/kilo-vscode/webview-ui/src/components/settings/mode-io.ts @@ -11,15 +11,34 @@ export type ImportError = "invalidJson" | "invalidName" | "nameTaken" | "tooLarg export type ImportResult = { ok: true; name: string; config: AgentConfig } | { ok: false; error: ImportError } +/** Check if a value is a valid permission level string. */ +function isLevel(v: unknown): boolean { + return typeof v === "string" && LEVELS.has(v) +} + /** Validate and extract a permission map, dropping unknown entries. */ function parsePermission(raw: unknown): PermissionConfig | undefined { if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return undefined const out: PermissionConfig = {} let count = 0 for (const [key, val] of Object.entries(raw)) { - if (typeof val === "string" && LEVELS.has(val)) { + if (isLevel(val)) { out[key] = val as PermissionConfig[string] count++ + } else if (typeof val === "object" && val !== null && !Array.isArray(val)) { + // Nested per-pattern rules like { "*": "ask", "uname": "allow" } + const nested: Record = {} + let valid = 0 + for (const [pat, lev] of Object.entries(val)) { + if (isLevel(lev)) { + nested[pat] = lev as string + valid++ + } + } + if (valid > 0) { + out[key] = nested as PermissionConfig[string] + count++ + } } } return count > 0 ? out : undefined @@ -30,14 +49,18 @@ function parsePermission(raw: unknown): PermissionConfig | undefined { * Returns an error tag (matching the i18n key suffix) on failure. */ export function parseImport(json: string, taken: string[]): ImportResult { - let data: Record + let data: unknown try { data = JSON.parse(json) } catch { return { ok: false, error: "invalidJson" } } + if (typeof data !== "object" || data === null || Array.isArray(data)) { + return { ok: false, error: "invalidJson" } + } + const obj = data as Record - const name = typeof data.name === "string" ? data.name.trim() : "" + const name = typeof obj.name === "string" ? obj.name.trim() : "" if (!name || !NAME_RE.test(name)) { return { ok: false, error: "invalidName" } } @@ -46,15 +69,15 @@ export function parseImport(json: string, taken: string[]): ImportResult { } const partial: Partial = {} - if (typeof data.description === "string") partial.description = data.description - if (typeof data.prompt === "string") partial.prompt = data.prompt - if (typeof data.model === "string") partial.model = data.model - if (typeof data.mode === "string" && (MODES as readonly string[]).includes(data.mode)) - partial.mode = data.mode as AgentConfig["mode"] - if (typeof data.temperature === "number") partial.temperature = data.temperature - if (typeof data.top_p === "number") partial.top_p = data.top_p - if (typeof data.steps === "number") partial.steps = data.steps - const perms = parsePermission(data.permission) + if (typeof obj.description === "string") partial.description = obj.description + if (typeof obj.prompt === "string") partial.prompt = obj.prompt + if (typeof obj.model === "string") partial.model = obj.model + if (typeof obj.mode === "string" && (MODES as readonly string[]).includes(obj.mode)) + partial.mode = obj.mode as AgentConfig["mode"] + if (typeof obj.temperature === "number") partial.temperature = obj.temperature + if (typeof obj.top_p === "number") partial.top_p = obj.top_p + if (typeof obj.steps === "number") partial.steps = obj.steps + const perms = parsePermission(obj.permission) if (perms) partial.permission = perms return { From 9487b5fc0e8d29f872402f4a97c37359b3b241f4 Mon Sep 17 00:00:00 2001 From: Joshua Lambert <25085430+lambertjosh@users.noreply.github.com> Date: Thu, 26 Mar 2026 08:48:46 -0400 Subject: [PATCH 042/261] Update packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md --- packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md index ba8eb64948e..78e765ce280 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md @@ -6,7 +6,7 @@ description: "Learn how to use the Kilo Code chat interface effectively" # Chatting with Kilo Code {% callout type="tip" %} -**Bottom line:** Kilo Code is an AI coding assistant that lives in VS Code. You chat with it in plain English, and it writes, edits, and explains code for you. +**Bottom line:** Kilo Code is an AI coding assistant. You chat with it in plain English, and it writes, edits, and explains code for you. {% /callout %} {% callout type="note" title="Prefer quick completions?" %} From 79d2567e6c4e5944adce5cc76b0bc82c3c76ba84 Mon Sep 17 00:00:00 2001 From: Marius Date: Thu, 26 Mar 2026 13:59:04 +0100 Subject: [PATCH 043/261] fix(cli): hide commit-message git windows on Windows (#7692) Prevent cmd.exe flashes when commit message generation shells out to git on Windows and add a regression test for the subprocess flags. --- .../src/commit-message/git-context.ts | 3 +- .../kilocode/commit-message-windows.test.ts | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 packages/opencode/test/kilocode/commit-message-windows.test.ts diff --git a/packages/opencode/src/commit-message/git-context.ts b/packages/opencode/src/commit-message/git-context.ts index 3b97f44c58b..d81e8a62cfb 100644 --- a/packages/opencode/src/commit-message/git-context.ts +++ b/packages/opencode/src/commit-message/git-context.ts @@ -133,6 +133,7 @@ function git(args: string[], cwd: string): string { cwd, stdout: "pipe", stderr: "pipe", + windowsHide: true, // kilocode_change - prevent cmd.exe flash on Windows }) return result.stdout.toString().trimEnd() } @@ -144,7 +145,7 @@ function parseNameStatus(output: string): Array<{ status: string; path: string } let path: string if (status!.startsWith("R")) { // Rename: rest = ["old.ts", "new.ts"], use the new path - path = rest[1] ?? rest[0] + path = rest[1] ?? rest[0] ?? "" } else { path = rest.join("\t") } diff --git a/packages/opencode/test/kilocode/commit-message-windows.test.ts b/packages/opencode/test/kilocode/commit-message-windows.test.ts new file mode 100644 index 00000000000..4be42d980e9 --- /dev/null +++ b/packages/opencode/test/kilocode/commit-message-windows.test.ts @@ -0,0 +1,38 @@ +import { describe, expect, spyOn, test } from "bun:test" +import { getGitContext } from "../../src/commit-message/git-context" + +describe("commit-message git context", () => { + test("hides Windows console windows for git subprocesses", async () => { + const out = new Map([ + ["branch --show-current", "main"], + ["log --oneline -5", "abc1234 init"], + ["diff --name-status --cached", "M\tsrc/index.ts"], + ["diff --cached -- src/index.ts", "+console.log('hi')"], + ]) + + const spy = spyOn(Bun, "spawnSync").mockImplementation(((cmd: unknown, opts: unknown) => { + const key = Array.isArray(cmd) ? cmd.slice(1).join(" ") : "" + return { + stdout: Buffer.from(out.get(key) ?? ""), + stderr: Buffer.alloc(0), + } as never + }) as unknown as typeof Bun.spawnSync) + + try { + await getGitContext("/repo") + + expect(spy).toHaveBeenCalledTimes(4) + for (const call of spy.mock.calls) { + expect(call[0]).toEqual(expect.arrayContaining(["git"])) + expect(call[1]).toMatchObject({ + cwd: "/repo", + stdout: "pipe", + stderr: "pipe", + windowsHide: true, + }) + } + } finally { + spy.mockRestore() + } + }) +}) From ad12f73b6e8573efb1c429c542b74e602644dfe5 Mon Sep 17 00:00:00 2001 From: kirillk Date: Thu, 26 Mar 2026 09:16:09 -0400 Subject: [PATCH 044/261] fix(vscode): revert agent manager icon to circuit-board --- packages/kilo-vscode/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 8b66288b51b..782c20c289e 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -77,7 +77,7 @@ { "command": "kilo-code.new.agentManagerOpen", "title": "Agent Manager", - "icon": "$(agent)" + "icon": "$(circuit-board)" }, { "command": "kilo-code.new.marketplaceButtonClicked", From 472efa57dc0631d27bce76eed19e55aedb94393d Mon Sep 17 00:00:00 2001 From: kirillk Date: Thu, 26 Mar 2026 09:33:43 -0400 Subject: [PATCH 045/261] fix(vscode): correct model price display inflated by double 1M multiplication --- .../webview-ui/src/components/shared/ModelPreview.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/shared/ModelPreview.tsx b/packages/kilo-vscode/webview-ui/src/components/shared/ModelPreview.tsx index 34232e52539..9d02cfdd155 100644 --- a/packages/kilo-vscode/webview-ui/src/components/shared/ModelPreview.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/shared/ModelPreview.tsx @@ -9,9 +9,8 @@ interface Props { function fmtPrice(n: number): string { if (n === 0) return "Free" - const per1M = n * 1_000_000 - if (per1M < 0.01) return `$${per1M.toFixed(4)}/1M` - return `$${per1M.toFixed(2)}/1M` + if (n < 0.01) return `$${n.toFixed(4)}/1M` + return `$${n.toFixed(2)}/1M` } function fmtContext(n: number): string { From 606b380ee5b63363adc7aa40aff39cee8f6e3d29 Mon Sep 17 00:00:00 2001 From: kirillk Date: Thu, 26 Mar 2026 09:45:50 -0400 Subject: [PATCH 046/261] test(vscode): add unit tests for model price display formatting --- .../tests/unit/model-price-format.test.ts | 36 +++++++++++++++++++ .../src/components/shared/ModelPreview.tsx | 7 +--- .../components/shared/model-preview-utils.ts | 9 +++++ 3 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 packages/kilo-vscode/tests/unit/model-price-format.test.ts create mode 100644 packages/kilo-vscode/webview-ui/src/components/shared/model-preview-utils.ts diff --git a/packages/kilo-vscode/tests/unit/model-price-format.test.ts b/packages/kilo-vscode/tests/unit/model-price-format.test.ts new file mode 100644 index 00000000000..9203210f352 --- /dev/null +++ b/packages/kilo-vscode/tests/unit/model-price-format.test.ts @@ -0,0 +1,36 @@ +import { describe, it, expect } from "bun:test" +import { fmtPrice } from "../../webview-ui/src/components/shared/model-preview-utils" + +// Prices arriving at fmtPrice are already in $/M tokens (converted by parseApiPrice). +// This test suite guards against the double-multiplication bug where fmtPrice was +// incorrectly multiplying by 1_000_000 again, turning $3.00/1M into $3,000,000.00/1M. + +describe("fmtPrice", () => { + it("formats Claude Sonnet 4.6 input price correctly ($3/1M)", () => { + expect(fmtPrice(3)).toBe("$3.00/1M") + }) + + it("formats Claude Sonnet 4.6 output price correctly ($15/1M)", () => { + expect(fmtPrice(15)).toBe("$15.00/1M") + }) + + it("returns 'Free' for zero price", () => { + expect(fmtPrice(0)).toBe("Free") + }) + + it("uses 4 decimal places for sub-cent prices", () => { + expect(fmtPrice(0.005)).toBe("$0.0050/1M") + }) + + it("uses 2 decimal places at the $0.01 boundary", () => { + expect(fmtPrice(0.01)).toBe("$0.01/1M") + }) + + it("formats a typical cheap model price ($0.50/1M)", () => { + expect(fmtPrice(0.5)).toBe("$0.50/1M") + }) + + it("formats a high-cost model price ($75/1M)", () => { + expect(fmtPrice(75)).toBe("$75.00/1M") + }) +}) diff --git a/packages/kilo-vscode/webview-ui/src/components/shared/ModelPreview.tsx b/packages/kilo-vscode/webview-ui/src/components/shared/ModelPreview.tsx index 9d02cfdd155..3cd4af62786 100644 --- a/packages/kilo-vscode/webview-ui/src/components/shared/ModelPreview.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/shared/ModelPreview.tsx @@ -2,17 +2,12 @@ import { Component, Show, For } from "solid-js" import type { EnrichedModel } from "../../context/provider" import { Markdown } from "@kilocode/kilo-ui/markdown" import { sanitizeName } from "./model-selector-utils" +import { fmtPrice } from "./model-preview-utils" interface Props { model: EnrichedModel | null } -function fmtPrice(n: number): string { - if (n === 0) return "Free" - if (n < 0.01) return `$${n.toFixed(4)}/1M` - return `$${n.toFixed(2)}/1M` -} - function fmtContext(n: number): string { if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(n % 1_000_000 === 0 ? 0 : 1)}M` if (n >= 1_000) return `${(n / 1_000).toFixed(n % 1_000 === 0 ? 0 : 1)}K` diff --git a/packages/kilo-vscode/webview-ui/src/components/shared/model-preview-utils.ts b/packages/kilo-vscode/webview-ui/src/components/shared/model-preview-utils.ts new file mode 100644 index 00000000000..1d7cfcb73a6 --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/components/shared/model-preview-utils.ts @@ -0,0 +1,9 @@ +/** + * Format a model price for display. + * Expects `n` in $/M tokens (as stored in model.cost.input / model.cost.output). + */ +export function fmtPrice(n: number): string { + if (n === 0) return "Free" + if (n < 0.01) return `$${n.toFixed(4)}/1M` + return `$${n.toFixed(2)}/1M` +} From b7fdbe63ea31804c7d48446a273b1df4b143fe6f Mon Sep 17 00:00:00 2001 From: Evgeny Shurakov Date: Thu, 26 Mar 2026 14:08:45 +0100 Subject: [PATCH 047/261] fix(cli): use load-time constant for KILO_SESSION_RETRY_LIMIT --- packages/opencode/src/flag/flag.ts | 18 +- .../session-processor-retry-limit.test.ts | 154 ++++++++++-------- 2 files changed, 86 insertions(+), 86 deletions(-) diff --git a/packages/opencode/src/flag/flag.ts b/packages/opencode/src/flag/flag.ts index fbebfb3b03a..52c38e27817 100644 --- a/packages/opencode/src/flag/flag.ts +++ b/packages/opencode/src/flag/flag.ts @@ -35,6 +35,7 @@ export namespace Flag { export const KILO_SERVER_PASSWORD = process.env["KILO_SERVER_PASSWORD"] export const KILO_SERVER_USERNAME = process.env["KILO_SERVER_USERNAME"] export const KILO_ENABLE_QUESTION_TOOL = truthy("KILO_ENABLE_QUESTION_TOOL") + // Experimental export const KILO_EXPERIMENTAL = truthy("KILO_EXPERIMENTAL") export const KILO_EXPERIMENTAL_FILEWATCHER = truthy("KILO_EXPERIMENTAL_FILEWATCHER") @@ -57,7 +58,6 @@ export namespace Flag { export const KILO_MODELS_URL = process.env["KILO_MODELS_URL"] export const KILO_MODELS_PATH = process.env["KILO_MODELS_PATH"] export const KILO_SKIP_MIGRATIONS = truthy("KILO_SKIP_MIGRATIONS") - export declare const KILO_SESSION_RETRY_LIMIT: number | undefined function number(key: string) { const value = process.env[key] @@ -65,6 +65,8 @@ export namespace Flag { const parsed = Number(value) return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined } + + export const KILO_SESSION_RETRY_LIMIT = number("KILO_SESSION_RETRY_LIMIT") } // Dynamic getter for KILO_DISABLE_PROJECT_CONFIG @@ -110,17 +112,3 @@ Object.defineProperty(Flag, "KILO_CLIENT", { enumerable: true, configurable: false, }) - -// Dynamic getter for KILO_SESSION_RETRY_LIMIT -// This must be evaluated at access time, not module load time, -// because tests and runtime tooling may set this env var later -Object.defineProperty(Flag, "KILO_SESSION_RETRY_LIMIT", { - get() { - const value = process.env["KILO_SESSION_RETRY_LIMIT"] - if (!value) return undefined - const parsed = Number(value) - return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined - }, - enumerable: true, - configurable: false, -}) diff --git a/packages/opencode/test/kilocode/session-processor-retry-limit.test.ts b/packages/opencode/test/kilocode/session-processor-retry-limit.test.ts index 4f90bd8e0d6..4a74eaeffcf 100644 --- a/packages/opencode/test/kilocode/session-processor-retry-limit.test.ts +++ b/packages/opencode/test/kilocode/session-processor-retry-limit.test.ts @@ -1,3 +1,9 @@ +// Set env before any imports that transitively load flag.ts (e.g. LLM, SessionRetry). +// This MUST happen before static imports, but ES module imports are hoisted. +// So we set it here and use mock.module + dynamic imports for modules that +// transitively load flag.ts to ensure the env is captured at load time. +process.env.KILO_SESSION_RETRY_LIMIT = "2" + import { afterEach, describe, expect, mock, spyOn, test } from "bun:test" mock.module("@/kilo-sessions/remote-sender", () => ({ @@ -11,17 +17,11 @@ mock.module("@/kilo-sessions/remote-sender", () => ({ }, })) +// Modules that do NOT transitively import flag.ts can be statically imported. import { APICallError } from "ai" -import { Bus } from "../../src/bus" -import { Flag } from "../../src/flag/flag" -import { Identifier } from "../../src/id/id" -import { Instance } from "../../src/project/instance" import type { Provider } from "../../src/provider/provider" -import { LLM } from "../../src/session/llm" import type { LLM as LLMType } from "../../src/session/llm" -import { MessageV2 } from "../../src/session/message-v2" -import { SessionRetry } from "../../src/session/retry" -import { SessionStatus } from "../../src/session/status" +import type { MessageV2 } from "../../src/session/message-v2" import { Log } from "../../src/util/log" import { tmpdir } from "../fixture/fixture" @@ -67,64 +67,22 @@ function sentinel() { return new Error("unexpected extra llm call") } -async function seed(model: Provider.Model) { - const { Session } = await import("../../src/session") - const session = await Session.create({}) - const user = (await Session.updateMessage({ - id: Identifier.ascending("message"), - role: "user", - sessionID: session.id, - time: { created: Date.now() }, - agent: "code", - model: { providerID: model.providerID, modelID: model.id }, - tools: {}, - })) as MessageV2.User - const assistant = (await Session.updateMessage({ - id: Identifier.ascending("message"), - parentID: user.id, - role: "assistant", - mode: "code", - agent: "code", - path: { - cwd: Instance.directory, - root: Instance.worktree, - }, - cost: 0, - tokens: { - input: 0, - output: 0, - reasoning: 0, - cache: { read: 0, write: 0 }, - }, - modelID: model.id, - providerID: model.providerID, - time: { created: Date.now() }, - sessionID: session.id, - })) as MessageV2.Assistant - return { assistant, session, user } -} - -function input(model: Provider.Model, sessionID: string, user: MessageV2.User): LLMType.StreamInput { - return { - user, - sessionID, - model, - agent: { name: "code", mode: "primary", permission: [], options: {} } as any, - system: [], - abort: AbortSignal.any([]), - messages: [], - tools: {}, - } -} - afterEach(() => { delete process.env.KILO_SESSION_RETRY_LIMIT }) describe("session processor retry limit", () => { test("stops after two retries with the normalized retryable error", async () => { + // Dynamic imports so that flag.ts sees KILO_SESSION_RETRY_LIMIT="2" set above + const { Bus } = await import("../../src/bus") + const { Identifier } = await import("../../src/id/id") + const { Instance } = await import("../../src/project/instance") + const { LLM } = await import("../../src/session/llm") + const { MessageV2 } = await import("../../src/session/message-v2") + const { SessionRetry } = await import("../../src/session/retry") + const { SessionStatus } = await import("../../src/session/status") + await using tmp = await tmpdir({ git: true }) - process.env.KILO_SESSION_RETRY_LIMIT = "2" await Instance.provide({ directory: tmp.path, @@ -132,16 +90,48 @@ describe("session processor retry limit", () => { const { Session } = await import("../../src/session") const { SessionProcessor } = await import("../../src/session/processor") const model = createModel() - const seeded = await seed(model) + const session = await Session.create({}) + const user = (await Session.updateMessage({ + id: Identifier.ascending("message"), + role: "user", + sessionID: session.id, + time: { created: Date.now() }, + agent: "code", + model: { providerID: model.providerID, modelID: model.id }, + tools: {}, + })) as MessageV2.User + const assistant = (await Session.updateMessage({ + id: Identifier.ascending("message"), + parentID: user.id, + role: "assistant", + mode: "code", + agent: "code", + path: { + cwd: Instance.directory, + root: Instance.worktree, + }, + cost: 0, + tokens: { + input: 0, + output: 0, + reasoning: 0, + cache: { read: 0, write: 0 }, + }, + modelID: model.id, + providerID: model.providerID, + time: { created: Date.now() }, + sessionID: session.id, + })) as MessageV2.Assistant + const retry: number[] = [] const errors: Array = [] const unsubStatus = Bus.subscribe(SessionStatus.Event.Status, (event) => { - if (event.properties.sessionID !== seeded.session.id) return + if (event.properties.sessionID !== session.id) return if (event.properties.status.type !== "retry") return retry.push(event.properties.status.attempt) }) const unsubError = Bus.subscribe(Session.Event.Error, (event) => { - if (event.properties.sessionID !== seeded.session.id) return + if (event.properties.sessionID !== session.id) return errors.push(event.properties.error) }) const llm = spyOn(LLM, "stream") @@ -151,14 +141,25 @@ describe("session processor retry limit", () => { .mockRejectedValue(sentinel()) const sleep = spyOn(SessionRetry, "sleep").mockResolvedValue(undefined) const processor = SessionProcessor.create({ - assistantMessage: seeded.assistant, - sessionID: seeded.session.id, + assistantMessage: assistant, + sessionID: session.id, model, abort: AbortSignal.any([]), }) + const inp: LLMType.StreamInput = { + user, + sessionID: session.id, + model, + agent: { name: "code", mode: "primary", permission: [], options: {} } as any, + system: [], + abort: AbortSignal.any([]), + messages: [], + tools: {}, + } + try { - const result = await processor.process(input(model, seeded.session.id, seeded.user)) + const result = await processor.process(inp) const expected = MessageV2.fromError(retryable429(), { providerID: "openai" }) expect(result).toBe("stop") @@ -177,20 +178,31 @@ describe("session processor retry limit", () => { }) }) - test("only positive integers enable the limit", () => { + test("only positive integers enable the limit", async () => { + const key = () => JSON.stringify({ time: Date.now(), rand: Math.random() }) + delete process.env.KILO_SESSION_RETRY_LIMIT - expect(Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() + expect((await import("../../src/flag/flag?" + key())).Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() process.env.KILO_SESSION_RETRY_LIMIT = "0" - expect(Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() + expect((await import("../../src/flag/flag?" + key())).Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() process.env.KILO_SESSION_RETRY_LIMIT = "-1" - expect(Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() + expect((await import("../../src/flag/flag?" + key())).Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() process.env.KILO_SESSION_RETRY_LIMIT = "abc" - expect(Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() + expect((await import("../../src/flag/flag?" + key())).Flag.KILO_SESSION_RETRY_LIMIT).toBeUndefined() process.env.KILO_SESSION_RETRY_LIMIT = "2" - expect(Flag.KILO_SESSION_RETRY_LIMIT).toBe(2) + expect((await import("../../src/flag/flag?" + key())).Flag.KILO_SESSION_RETRY_LIMIT).toBe(2) + }) + + test("does not change after import", async () => { + delete process.env.KILO_SESSION_RETRY_LIMIT + const id = JSON.stringify({ time: Date.now(), rand: Math.random() }) + const { Flag: loaded } = await import("../../src/flag/flag?" + id) + expect(loaded.KILO_SESSION_RETRY_LIMIT).toBeUndefined() + process.env.KILO_SESSION_RETRY_LIMIT = "5" + expect(loaded.KILO_SESSION_RETRY_LIMIT).toBeUndefined() }) }) From 8be2a522183af5f62f94cb4beeb8d8808e3a6c6a Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Thu, 26 Mar 2026 10:09:54 -0400 Subject: [PATCH 048/261] docs(kilo-docs): fix kiloCodeIcon tag name and orchestrator 'modes' wording MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix kilo-code-icon → kiloCodeIcon markdoc tag in chat-interface.md and setup-authentication.md (kebab-case tags don't resolve in @markdoc/next.js) - Replace 'modes' with 'agents' in orchestrator-mode.md shared body text per review feedback (lines 13, 20, 32) --- .../kilo-docs/pages/code-with-ai/agents/chat-interface.md | 4 ++-- .../pages/code-with-ai/agents/orchestrator-mode.md | 6 +++--- .../kilo-docs/pages/getting-started/setup-authentication.md | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md index 78e765ce280..03ad89a54b0 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md @@ -18,7 +18,7 @@ If you're typing code in the editor and want AI to finish your line or block, ch {% tabs %} {% tab label="VSCode" %} -Click the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar to open the sidebar chat. You can also pop it out into an editor tab for a larger workspace. +Click the Kilo Code icon ({% kiloCodeIcon /%}) in VS Code's Primary Side Bar to open the sidebar chat. You can also pop it out into an editor tab for a larger workspace. {% /tab %} {% tab label="CLI" %} @@ -28,7 +28,7 @@ Open your terminal and run `kilo` to launch the interactive TUI. You'll see a pr {% /tab %} {% tab label="VSCode (Legacy)" %} -Find the Kilo Code icon ({% kilo-code-icon /%}) in VS Code's Primary Side Bar. Click it to open the chat panel. +Find the Kilo Code icon ({% kiloCodeIcon /%}) in VS Code's Primary Side Bar. Click it to open the chat panel. **Lost the panel?** Go to View > Open View... and search for "Kilo Code" diff --git a/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md b/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md index fecb036ffb9..546b3b497af 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md @@ -10,14 +10,14 @@ Orchestrator Mode allows you to break down complex projects into smaller, manage ## Why Use Orchestrator Mode? - **Tackle Complexity:** Break large, multi-step projects (e.g., building a full feature) into focused subtasks (e.g., design, implementation, documentation). -- **Use Specialized Modes:** Automatically delegate subtasks to the mode best suited for that specific piece of work, leveraging specialized capabilities for optimal results. +- **Use Specialized Agents:** Automatically delegate subtasks to the agent best suited for that specific piece of work, leveraging specialized capabilities for optimal results. - **Maintain Focus & Efficiency:** Each subtask operates in its own isolated context with a separate conversation history. This prevents the parent (orchestrator) task from becoming cluttered with the detailed execution steps (like code diffs or file analysis results), allowing it to focus efficiently on the high-level workflow and manage the overall process based on concise summaries from completed subtasks. - **Streamline Workflows:** Results from one subtask can be automatically passed to the next, creating a smooth flow (e.g., architectural decisions feeding into the coding task). ## How It Works 1. Using Orchestrator Mode, Kilo can analyze a complex task and suggest breaking it down into a subtask. -2. The parent task pauses, and the new subtask begins in a different mode. +2. The parent task pauses, and the new subtask begins with a dedicated subagent. 3. When the subtask's goal is achieved, Kilo signals completion. 4. The parent task resumes with only the summary of the subtask. The parent uses this summary to continue the main workflow. @@ -29,7 +29,7 @@ Orchestrator Mode allows you to break down complex projects into smaller, manage - **Up:** Via the final summary provided when the subtask finishes. Be mindful that only this summary returns to the parent. - **Navigation:** Kilo's interface helps you see the hierarchy of tasks (which task is the parent, which are children). You can typically navigate between active and paused tasks. -Orchestrator Mode provides a powerful way to manage complex development workflows directly within Kilo Code, leveraging specialized modes for maximum efficiency. +Orchestrator Mode provides a powerful way to manage complex development workflows directly within Kilo Code, leveraging specialized agents for maximum efficiency. {% callout type="tip" title="Keep Tasks Focused" %} Use 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. diff --git a/packages/kilo-docs/pages/getting-started/setup-authentication.md b/packages/kilo-docs/pages/getting-started/setup-authentication.md index 8697970b0bd..13a758f8a11 100644 --- a/packages/kilo-docs/pages/getting-started/setup-authentication.md +++ b/packages/kilo-docs/pages/getting-started/setup-authentication.md @@ -75,7 +75,7 @@ Already have a ChatGPT subscription? You can use it with Kilo Code through the [ ### Configuring Your Provider -1. Click the {% kilo-code-icon /%} icon in the VS Code sidebar +1. Click the {% kiloCodeIcon /%} icon in the VS Code sidebar 2. Select your API provider from the dropdown 3. Paste your API key 4. Choose your model: From 02b5cea71221d1a5e35bfb39c1d254fb3d0126cf Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Thu, 26 Mar 2026 10:29:14 -0400 Subject: [PATCH 049/261] AKG discord updates --- .../pages/kiloclaw/chat-platforms/discord.md | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/packages/kilo-docs/pages/kiloclaw/chat-platforms/discord.md b/packages/kilo-docs/pages/kiloclaw/chat-platforms/discord.md index 9f36f74b03c..219e6799c68 100644 --- a/packages/kilo-docs/pages/kiloclaw/chat-platforms/discord.md +++ b/packages/kilo-docs/pages/kiloclaw/chat-platforms/discord.md @@ -7,12 +7,14 @@ description: "Connect your KiloClaw agent to Discord" Connect your KiloClaw agent to Discord by creating a bot in the Discord Developer Portal and linking it to your KiloClaw dashboard. +## Prerequisites + +Make sure you have a Discord server ready to add the bot to. If you don't have one, open Discord, scroll to the bottom of your server list, click **+**, choose **Create My Own**, then **For me and my friends**, and give it a name. + ## Create an Application and Bot 1. Go to the [Discord Developer Portal](https://discord.com/developers/applications) and log in 2. Click **New Application**, give it a name, and click **Create** -3. Click **Bot** on the left sidebar -4. Click **Add Bot** and confirm ## Enable Privileged Intents @@ -22,19 +24,6 @@ On the **Bot** page, scroll down to **Privileged Gateway Intents** and enable: - **Server Members Intent** (recommended — needed for role allowlists and name matching) - **Presence Intent** (optional) -## Copy Your Bot Token - -1. Scroll back up on the **Bot** page and click **Reset Token** - -> 📝 **Note** -> Despite the name, this generates your first token — nothing is being "reset." - -2. Copy the token that appears and paste it into the **Discord Bot Token** field in your KiloClaw dashboard. - -{% image src="/docs/img/kiloclaw/discord.png" alt="Connect account screen" width="800" caption="Discord bot token entry" /%} - -Enter the token in the Settings tab and click **Save**. You can remove or replace a configured token at any time. - ## Generate an Invite URL and Add the Bot to Your Server 1. Click **OAuth2** on the sidebar @@ -52,10 +41,27 @@ Enter the token in the Settings tab and click **Save**. You can remove or replac 5. Paste it into your browser, select your server, and click **Continue** 6. You should now see your bot in the Discord server +## Copy Your Bot Token + +1. Go back to the **Bot** page on the left sidebar and click **Reset Token** + +> 📝 **Note** +> Despite the name, this generates your first token — nothing is being "reset." + +2. Copy the token that appears and paste it into the **Discord Bot Token** field in your KiloClaw dashboard. + +{% image src="/docs/img/kiloclaw/discord.png" alt="Connect account screen" width="800" caption="Discord bot token entry" /%} + +Enter the token in the Settings tab and click **Save**. You can remove or replace a configured token at any time. + +## Redeploy to Apply Changes + +After saving your token, click **Redeploy** (the yellow button at the top of the KiloClaw dashboard) to apply the changes. The server will restart in about 30–45 seconds. Wait for the redeploy to complete before pairing. + ## Start Chatting with the Bot 1. Right-click on the Bot in Discord and click **Message** 2. DM the bot `/pair` 3. You should get a response back with a pairing code -4. Return to [app.kilocode.ai/claw](https://app.kilocode.ai/claw) and confirm the pairing code and approve +4. Return to [app.kilo.ai/claw](https://app.kilo.ai/claw) and confirm the pairing code and approve 5. You should now be able to chat with the bot from Discord From f65429df6c5d99ea6628c38d046cc29b8aed6d79 Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Thu, 26 Mar 2026 14:31:02 +0000 Subject: [PATCH 050/261] chore: update nix node_modules hashes --- nix/hashes.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/hashes.json b/nix/hashes.json index 8d54b85cb0c..80015c18486 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-85Pa4C5F3yqjMzIGBcWYGe+IitSg9nnTtixqZPRnFps=", - "aarch64-linux": "sha256-qeyu0LS1z8JXGa+2EVd/U94uQIV8zi53ZmymE9/trSU=", - "aarch64-darwin": "sha256-qwedJnAMcM/gTVSCTErsP++HM2lYQtLE+PM1QkT7fy8=", - "x86_64-darwin": "sha256-372zLuwN6TLhn4JIDorEc13mjMpC91UbukxE/Y14c/k=" + "x86_64-linux": "sha256-YjB3YfaA79nztpZoYEAlFBakS//G/Guprlqk4BYFgOA=", + "aarch64-linux": "sha256-ru470M8RVwyOPNGr6I4VfApQRHhYFFMPjOBneTRBJtc=", + "aarch64-darwin": "sha256-M6LIPBHnYH9AtIRAKyW44VN71Kb28nztzFteCkL0588=", + "x86_64-darwin": "sha256-HURoot79BFHYwoEp0XqVdI6cRdV7KGvmRRqOf+hUa9Q=" } } From 59bd809b0cfaa9c262af6220eea6be30a57d3880 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 14:31:33 +0000 Subject: [PATCH 051/261] feat(ui): wire external URL via openUrl in data context introduce OpenUrlFn and expose openUrl in the data store wire DataBridge to accept onOpenUrl and forward to UI update message-part to call data.openUrl for web URLs and enable clickable tool-action --- packages/kilo-ui/src/components/message-part.tsx | 13 +++++++++++-- packages/kilo-vscode/webview-ui/src/App.tsx | 5 +++++ packages/ui/src/context/data.tsx | 4 ++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/kilo-ui/src/components/message-part.tsx b/packages/kilo-ui/src/components/message-part.tsx index ac6b5a4cf21..05a35a149da 100644 --- a/packages/kilo-ui/src/components/message-part.tsx +++ b/packages/kilo-ui/src/components/message-part.tsx @@ -1306,6 +1306,15 @@ function useToolReveal(pending: () => boolean, animate?: () => boolean) { function WebfetchMeta(props: { url: string; animate?: boolean }) { let ref: HTMLSpanElement | undefined useToolFade(() => ref, { wipe: true, animate: props.animate }) + const data = useData() + + const open = (event: MouseEvent) => { + event.stopPropagation() + event.preventDefault() + const handler = data.openUrl + if (handler) return handler(props.url) + window.open(props.url, "_blank", "noopener,noreferrer") + } return ( @@ -1316,11 +1325,11 @@ function WebfetchMeta(props: { url: string; animate?: boolean }) { href={props.url} target="_blank" rel="noopener noreferrer" - onClick={(event) => event.stopPropagation()} + onClick={open} > {props.url} -
+
diff --git a/packages/kilo-vscode/webview-ui/src/App.tsx b/packages/kilo-vscode/webview-ui/src/App.tsx index 05035afd21f..9f535c0fcfa 100644 --- a/packages/kilo-vscode/webview-ui/src/App.tsx +++ b/packages/kilo-vscode/webview-ui/src/App.tsx @@ -109,6 +109,10 @@ export const DataBridge: Component<{ children: any }> = (props) => { vscode.postMessage({ type: "openFile", filePath, line, column }) } + const openUrl = (url: string) => { + vscode.postMessage({ type: "openExternal", url }) + } + const directory = () => { const dir = server.workspaceDirectory() if (!dir) return "" @@ -124,6 +128,7 @@ export const DataBridge: Component<{ children: any }> = (props) => { onQuestionReply={reply} onQuestionReject={reject} onOpenFile={open} + onOpenUrl={openUrl} > {props.children} diff --git a/packages/ui/src/context/data.tsx b/packages/ui/src/context/data.tsx index 50317e5f64f..d51aa9fe765 100644 --- a/packages/ui/src/context/data.tsx +++ b/packages/ui/src/context/data.tsx @@ -28,6 +28,8 @@ export type SessionHrefFn = (sessionID: string) => string export type OpenFileFn = (filePath: string, line?: number, column?: number) => void // kilocode_change +export type OpenUrlFn = (url: string) => void // kilocode_change + export const { use: useData, provider: DataProvider } = createSimpleContext({ name: "Data", init: (props: { @@ -36,6 +38,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ onNavigateToSession?: NavigateToSessionFn onSessionHref?: SessionHrefFn onOpenFile?: OpenFileFn // kilocode_change + onOpenUrl?: OpenUrlFn // kilocode_change }) => { return { get store() { @@ -47,6 +50,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ navigateToSession: props.onNavigateToSession, sessionHref: props.onSessionHref, openFile: props.onOpenFile, // kilocode_change + openUrl: props.onOpenUrl, // kilocode_change } }, }) From 3494a56b27cfdc81e5f5ca6814aae18126fcdef2 Mon Sep 17 00:00:00 2001 From: Ligia Zanchet Date: Thu, 26 Mar 2026 15:38:33 +0100 Subject: [PATCH 052/261] docs: remove old flat pages superseded by nested sub-pages --- .../pages/kiloclaw/chat-platforms.md | 155 ------------------ .../kilo-docs/pages/kiloclaw/control-ui.md | 116 ------------- packages/kilo-docs/pages/kiloclaw/pricing.md | 37 ----- packages/kilo-docs/pages/kiloclaw/tools.md | 109 ------------ .../pages/kiloclaw/troubleshooting.md | 101 ------------ .../pages/kiloclaw/version-pinning.md | 53 ------ 6 files changed, 571 deletions(-) delete mode 100644 packages/kilo-docs/pages/kiloclaw/chat-platforms.md delete mode 100644 packages/kilo-docs/pages/kiloclaw/control-ui.md delete mode 100644 packages/kilo-docs/pages/kiloclaw/pricing.md delete mode 100644 packages/kilo-docs/pages/kiloclaw/tools.md delete mode 100644 packages/kilo-docs/pages/kiloclaw/troubleshooting.md delete mode 100644 packages/kilo-docs/pages/kiloclaw/version-pinning.md diff --git a/packages/kilo-docs/pages/kiloclaw/chat-platforms.md b/packages/kilo-docs/pages/kiloclaw/chat-platforms.md deleted file mode 100644 index 6767956eb36..00000000000 --- a/packages/kilo-docs/pages/kiloclaw/chat-platforms.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -title: "Connecting Chat Platforms" -description: "Connect your KiloClaw agent to Telegram, Discord, Slack, and more" ---- - -# Connecting Chat Platforms - -KiloClaw supports connecting your AI agent to Telegram, Discord, and Slack. You can configure channels from the **Settings** tab on your [KiloClaw dashboard](/docs/kiloclaw/dashboard#channels), or from the OpenClaw Control UI after accessing your instance. - -While the exact steps vary for configuring a chat platform (called a _channel_ by OpenClaw), the steps are to: - -1. Configure the channel -2. Redeploy the KiloClaw instance -3. Initiate the pairing in the chat app -4. Accept the pairing request in the [KiloClaw UI](https://app.kilo.ai/claw) - -Detailed instructions for supported chat apps are below. - -## Chat Apps (Channels) - -### Telegram - -1. Open Telegram and search for [@BotFather](https://t.me/BotFather) -2. Send `/newbot` and follow the prompts to create your bot -3. Copy the **Bot Token** that BotFather gives you -4. Go to the **Settings** tab on your [KiloClaw dashboard](/docs/kiloclaw/dashboard) -5. Paste the token into the **Telegram Bot Token** field -6. Click **Save** -7. Redeploy your KiloClaw instance -8. Send a direct message to your bot in Telegram: `/start` - -{% image src="/docs/img/kiloclaw/telegram.png" alt="Connect account screen" width="800" caption="Telegram bot token entry" /%} - -You can remove or replace a configured token at any time. - -> ℹ️ **Info** -> Advanced settings such as DM policy, allow lists, and groups can be configured in the OpenClaw Control UI after connecting. - -### Discord - -To connect Discord, you need a **Bot Token** from the [Discord Developer Portal](https://discord.com/developers/applications). - -#### Create an Application and Bot - -1. Go to the [Discord Developer Portal](https://discord.com/developers/applications) and log in -2. Click **New Application**, give it a name, and click **Create** -3. Click **Bot** on the left sidebar -4. Click **Add Bot** and confirm - -#### Enable Privileged Intents - -On the **Bot** page, scroll down to **Privileged Gateway Intents** and enable: - -- **Message Content Intent** (required) -- **Server Members Intent** (recommended — needed for role allowlists and name matching) -- **Presence Intent** (optional) - -#### Copy Your Bot Token - -1. Scroll back up on the **Bot** page and click **Reset Token** - -> 📝 **Note** -> Despite the name, this generates your first token — nothing is being "reset." - -2. Copy the token that appears and paste it into the **Discord Bot Token** field in your KiloClaw dashboard. - -{% image src="/docs/img/kiloclaw/discord.png" alt="Connect account screen" width="800" caption="Discord bot token entry" /%} - -Enter the token in the Settings tab and click **Save**. You can remove or replace a configured token at any time. - -#### Generate an Invite URL and Add the Bot to Your Server - -1. Click **OAuth2** on the sidebar -2. Scroll down to **OAuth2 URL Generator** and enable: - - `bot` - - `applications.commands` -3. A **Bot Permissions** section will appear below. Enable: - - View Channels - - Send Messages - - Read Message History - - Embed Links - - Attach Files - - Add Reactions (optional) -4. Copy the generated URL at the bottom -5. Paste it into your browser, select your server, and click **Continue** -6. You should now see your bot in the Discord server - -#### Start Chatting with the Bot - -1. Right-click on the Bot in Discord and click **Message** -2. DM the bot `/pair` -3. You should get a response back with a pairing code -4. Return to [app.kilocode.ai/claw](https://app.kilocode.ai/claw) and confirm the pairing code and approve -5. You should now be able to chat with the bot from Discord - -### Slack - -#### Step 1: Create a Slack App from the OpenClaw Manifest - -1. Go to [Slack App Management](https://api.slack.com/apps) and click **Create New App** → **From a Manifest** -2. Copy the manifest from the [OpenClaw docs](https://docs.openclaw.ai/channels/slack#manifest-and-scope-checklist) -3. Paste the manifest JSON into Slack's manifest editor -4. Customize the manifest before creating: - - Rename the app to your preferred name wherever it appears - - Update the slash command if desired (e.g., `/kiloclaw`) -5. Click **Create** - -#### Step 2: Generate Tokens - -You need two tokens from Slack: - -**App-Level Token** - -1. In your Slack app settings, scroll down to **App-Level Tokens** -2. Click **Generate Token** -3. Add the `connections:write` scope -4. Generate and copy the token (starts with `xapp-`) - -**Bot User OAuth Token** - -1. In the left sidebar, click **Install App** -2. Install the app to your workspace -3. Copy the **Bot User OAuth Token** (starts with `xoxb-`) - -#### Step 3: Connect Slack to KiloClaw - -1. In the [KiloClaw UI](https://app.kilo.ai/claw), find the Slack integration section (may show "not configured") -2. Enter both tokens: - - The `xapp-` app-level token - - The `xoxb-` bot user OAuth token -3. Click **Save** -4. Scroll to the top of the KiloClaw UI and click **Redeploy**. Wait for the instance to come back up - -#### Step 4: Pair Slack with KiloClaw - -1. In Slack, DM the app and type your slash command (e.g., `/claw`) followed by anything — this triggers the pairing flow - -> 📝 **Note** -> The slash command is whatever you defined in the manifest. Any text after the command will work to trigger pairing. - -2. The app will return a pairing code -3. Return to [app.kilocode.ai/claw](https://app.kilocode.ai/claw) and confirm the pairing code and approve -4. You should now be able to chat with the bot from Slack - -## Future Support - -Additional platforms (such as WhatsApp) are planned for future releases. For the latest on supported platforms, refer to the [OpenClaw documentation](https://docs.openclaw.ai). - -## Related - -- [KiloClaw Overview](/docs/kiloclaw/overview) -- [Dashboard Reference](/docs/kiloclaw/dashboard) -- [Troubleshooting](/docs/kiloclaw/troubleshooting) -- [KiloClaw Pricing](/docs/kiloclaw/pricing) -- [OpenClaw Documentation](https://docs.openclaw.ai) diff --git a/packages/kilo-docs/pages/kiloclaw/control-ui.md b/packages/kilo-docs/pages/kiloclaw/control-ui.md deleted file mode 100644 index 03aec4885ca..00000000000 --- a/packages/kilo-docs/pages/kiloclaw/control-ui.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: "OpenClaw Control UI" -description: "Browser-based dashboard for managing your OpenClaw instance" ---- - -# OpenClaw Control UI - -The Control UI is a browser-based dashboard (built with Vite + Lit) served by the OpenClaw Gateway on the same port as the gateway itself (default: `http://localhost:18789/`). It connects via WebSocket and gives you real-time control over your agent, channels, sessions, and system configuration. For KiloClaw users, see [Accessing the Control UI](/docs/kiloclaw/dashboard#accessing-the-control-ui) to get started. - -## Features - -- **Chat** — Send messages, stream responses with live tool-call output, view history, and abort runs. -- **Channels** — View the status of connected messaging platforms, scan QR codes for login, and edit per-channel config. -- **Sessions** — List active sessions with thinking and verbose overrides. -- **Cron Jobs** — Create, edit, enable/disable, run, and view history of scheduled tasks. -- **Skills** — View status, enable/disable, install, and manage API keys for skills. -- **Nodes** — List paired devices and their capabilities. -- **Exec Approvals** — Edit gateway or node command allowlists. See [Exec Approvals](#exec-approvals) below. -- **Config** — View and edit `openclaw.json` with schema-based form rendering and a raw JSON editor. -- **Logs** — Live tail of gateway logs with filtering and export. -- **Debug** — Status, health, model snapshots, event log, and manual RPC calls. -- **Update** — Run package updates and restart the gateway. - -For more details, please see the official [OpenClaw documentation](https://docs.openclaw.ai/web/control-ui). - -{% callout type="warning" %} -Do not use the **Update** feature in the Control UI to update KiloClaw. Use **Redeploy** from the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#redeploy) instead. Updating via the Control UI will not apply the correct KiloClaw platform image and may break your instance. -{% /callout %} - -## Changing Models - -The Control UI Chat tab doubles as a command line for model management. KiloClaw exposes 335+ models through the `kilocode` provider and you can browse and switch between them without leaving the chat. - -| Command | Description | -| ------------------------------------ | ------------------------------------------------------------------------------- | -| `/model status` | View the currently active model and provider | -| `/models kilocode` | Browse available models (paginated, 20 per page) | -| `/models kilocode ` | Jump to a specific page (e.g. `/models kilocode 2`) | -| `/model kilocode//` | Switch to a specific model (e.g. `/model kilocode/anthropic/claude-sonnet-4.6`) | -| `/models kilocode all` | List every available model at once | - -Each `/models` response includes helper text at the bottom with shortcuts for switching, paging, and listing all models. - -To change the default model for all new sessions, edit `agents.defaults.model.primary` in your `openclaw.json` via **Config** in the Control UI (or the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#changing-the-model) for a quick dropdown pick). - -For the full list of providers, advanced configuration, and CLI commands, see the [OpenClaw Model Providers documentation](https://docs.openclaw.ai/providers). - -## Authentication - -Auth is handled via token or password on the WebSocket handshake. Remote connections require one-time device pairing — the pairing request appears on the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#pairing-requests) or in the Control UI itself. - -## Exec Approvals - -Exec approvals are the safety interlock that controls which commands your agent can run on the host machine (gateway or node). By default, **all host exec requests are denied** — you must explicitly allowlist the commands you want your agent to run independently. This prevents accidental execution of destructive commands. - -{% callout type="warning" %} -The default security policy is `deny`. You must configure an allowlist before your agent can execute any host commands. -{% /callout %} - -### How It Works - -Approvals are enforced locally on the execution host and sit on top of tool policy and elevated gating. The effective policy is always the **stricter** of `tools.exec.*` and the approvals defaults. Settings are stored in `~/.openclaw/exec-approvals.json` on the host. - -### Security Policies - -| Policy | Behavior | -| ----------- | ---------------------------------------------- | -| `deny` | Block all host exec requests (default) | -| `allowlist` | Allow only commands matching the allowlist | -| `full` | Allow everything (equivalent to elevated mode) | - -### Ask Behavior - -The `ask` setting controls when the user is prompted for approval: - -| Setting | Behavior | -| --------- | ------------------------------------------------------- | -| `off` | Never prompt | -| `on-miss` | Prompt only when the allowlist does not match (default) | -| `always` | Prompt on every command | - -If a prompt is required but no UI is reachable, the `askFallback` setting decides the outcome (`deny` by default). - -### Allowlists - -Allowlists are **per agent** — each agent has its own set of allowed command patterns. Patterns are case-insensitive globs that must resolve to binary paths (basename-only entries are ignored). - -Example patterns: - -``` -~/Projects/**/bin/rg -~/.local/bin/* -/opt/homebrew/bin/rg -``` - -Each entry tracks last-used metadata (timestamp, command, resolved path) so you can audit and keep the list tidy. - -### Approval Flow - -When a command requires approval, the gateway broadcasts the request to connected operator clients. The approval dialog shows the command, arguments, working directory, agent ID, and resolved path. You can: - -- **Allow once** — run the command now -- **Allow always** — add to the allowlist and run -- **Deny** — block the request - -Approval prompts can also be forwarded to chat channels (Slack, Telegram, Discord, etc.) and resolved with `/approve`. - -### Editing in the Control UI - -Navigate to **Nodes > Exec Approvals** in the Control UI to edit defaults, per-agent overrides, and allowlists. Select a scope (Defaults or a specific agent), adjust the policy, add or remove allowlist patterns, then save. - -## Related - -- [KiloClaw Dashboard](/docs/kiloclaw/dashboard) -- [KiloClaw Overview](/docs/kiloclaw/overview) -- [Connecting Chat Platforms](/docs/kiloclaw/chat-platforms) diff --git a/packages/kilo-docs/pages/kiloclaw/pricing.md b/packages/kilo-docs/pages/kiloclaw/pricing.md deleted file mode 100644 index 2d4be00d332..00000000000 --- a/packages/kilo-docs/pages/kiloclaw/pricing.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "KiloClaw Pricing" -description: "Pricing details for KiloClaw instances and model inference" ---- - -# KiloClaw Pricing - -KiloClaw uses Kilo Gateway credits by default — if you route requests through BYOK, model usage is billed directly by your provider instead. - -### Instance Hosting - -KiloClaw hosting is **free during the beta period**. Each user gets a dedicated machine (2 shared vCPUs, 3 GB RAM, 10 GB SSD) at no cost. - -> ℹ️ **Info** -> Beta pricing is subject to change. Paid hosting tiers may be introduced after the beta period ends. Any changes will be announced in advance. - -### Model Inference - -Model usage is charged against your [Gateway credit balance](/docs/gateway/usage-and-billing). Costs vary by model — premium models like Claude Opus or GPT-5.4-pro cost more per token than smaller models. - -### Free Models - -Several models are available at **no additional cost** to your Gateway balance. These are great for getting started or for tasks that don't need the most powerful models. - -To see which models are currently free, check the [Kilo Leaderboard](https://kilo.ai/leaderboard#all-models) — free models are marked accordingly. - -### Adding Credits - -You can add Gateway credits from your [Kilo account](https://app.kilo.ai). Credits are shared across all Kilo products (VSCode extension, CLI, Cloud Agents, and KiloClaw). - -See [Adding Credits](/docs/getting-started/adding-credits) and [Gateway Usage and Billing](/docs/gateway/usage-and-billing) for details. - -## Related - -- [KiloClaw Overview](/docs/kiloclaw/overview) -- [Connecting Chat Platforms](/docs/kiloclaw/chat-platforms) -- [Gateway Usage and Billing](/docs/gateway/usage-and-billing) diff --git a/packages/kilo-docs/pages/kiloclaw/tools.md b/packages/kilo-docs/pages/kiloclaw/tools.md deleted file mode 100644 index 601e67e6dfd..00000000000 --- a/packages/kilo-docs/pages/kiloclaw/tools.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: "Tools" -description: "Third-party tool integrations for your KiloClaw agent" ---- - -# Tools - -## 1Password Integration Guide - -Connect your KiloClaw agent to 1Password to securely manage credentials. This allows your agent to fetch API keys or passwords without ever seeing them in plain text. - -### Step 1: Create a Dedicated Vault - -For maximum security, do not give the bot access to your personal vault. - -1. Log in to your 1Password account. -2. Create a **New Vault** (e.g., name it `Kilo-Agent-Vault`). -3. Move only the specific items/keys you want the bot to use into this vault. - -### Step 2: Generate a Service Account Token - -1. Go to the [1Password Developer Portal](https://developer.1password.com/). -2. Select **Service Accounts** and click **Create a Service Account**. -3. **Important:** When prompted for permissions, select only the dedicated vault you created in Step 1. -4. Copy the generated token (it will begin with `ops_`). - -### Step 3: Configure KiloClaw - -1. Navigate to your KiloClaw dashboard: [app.kilo.ai/claw](https://app.kilo.ai/claw). -2. Go to **Settings > Tools** (or **Edit Files**). -3. Paste your `ops_` token into the **1Password Setup** field. -4. Click **Save**. - -### Step 4: Activate the Integration - -To apply the changes and inject the 1Password CLI into your environment: - -1. Select **Upgrade to latest**. -2. Perform a **Redeploy** to restart the agent with the new permissions active. - ---- - -## Brave Search Integration - -Equip your KiloClaw agent with real-time web browsing capabilities by integrating the Brave Search API. This allows the agent to fetch up-to-date information, perform market research, and verify facts beyond its training data. - -### How to Generate a Brave Search API Key - -To get started, you will need to obtain a "BSA" (Brave Search API) key from the Brave developer portal. - -#### 1. Access the Brave Search Dashboard - -Go to [api.search.brave.com](https://api.search.brave.com) and sign in or create a developer account. - -#### 2. Choose a Subscription Plan - -Brave Search API requires a paid subscription. Select the plan that fits your usage volume. - -#### 3. Create an API Key - -Once your account is active, navigate to the **API Keys** section and click **"Create New Key."** - -#### 4. Copy the Key - -Your key will typically begin with the prefix `BSA`. Copy this key immediately, as it may not be displayed again for security reasons. - ---- - -## AgentCard Integration - -Enable your KiloClaw agents to perform financial transactions by creating and managing virtual debit cards. This integration allows for automated purchasing and expense management within set limits. - -> ⚠️ **Important:** This tool permits your agent to spend real money. Use extreme caution with budget limits. AgentCard is currently in Beta; card issuance may be limited or waitlisted. - -### AgentCard Setup - -#### 1. Create an AgentCard Account - -Install the AgentCard CLI and sign up via your terminal: - -```bash -agent-cards signup -``` - -#### 2. Add a Payment Method - -Link your funding source (via Stripe) to enable the creation of virtual cards: - -```bash -agent-cards payment-method -``` - -#### 3. Retrieve Your API Key - -Open your local configuration file located at `~/.agent-cards/config.json`. Copy the value assigned to the `jwt` key. - -#### 4. Configure KiloClaw - -1. Paste the **JWT** into the AgentCard setup field in your KiloClaw settings. -2. Click **Save**. -3. Use **Redeploy** to apply the new secret. Only use **Upgrade & Redeploy** if you also need the latest platform version. - -### Available Tools - -Once activated, your agent will have access to: - -- `create_card`: Generate a new virtual debit card. -- `list_cards`: View existing cards and their statuses. -- `check_balance`: Monitor available funds. diff --git a/packages/kilo-docs/pages/kiloclaw/troubleshooting.md b/packages/kilo-docs/pages/kiloclaw/troubleshooting.md deleted file mode 100644 index c3f07a9f0a0..00000000000 --- a/packages/kilo-docs/pages/kiloclaw/troubleshooting.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: "Troubleshooting" -description: "Common issues, diagnostics, and FAQ for KiloClaw instances" ---- - -# Troubleshooting - -## OpenClaw Doctor - -OpenClaw Doctor is the recommended first step when something isn't working. It runs diagnostics on your instance and automatically fixes common configuration issues. - -To use it: - -1. Make sure your instance is running -2. Click **OpenClaw Doctor** on your [dashboard](/docs/kiloclaw/dashboard) -3. Watch the output as it runs — results appear in real time - -## Common Questions - -### Does Redeploy reset my instance? - -No. Redeploy does **not** delete your files, git repos, or cron jobs. It stops the machine, applies the latest platform image and your current configuration, and starts it again with the same persistent storage. Think of it as "update and restart." - -### When should I use Restart OpenClaw vs Redeploy? - -- **Restart OpenClaw** — Restarts just the OpenClaw process. The machine stays up. Use this for quick recovery from a process-level issue or when you want to apply openclaw config changes. -- **Redeploy** — Stops and restarts the entire machine with the latest image and config. Use this when the changelog shows a redeploy hint, or after changing channel tokens or secrets. - -### My bot isn't responding on Telegram/Discord/Slack - -1. Check that the channel token is configured in [Settings](/docs/kiloclaw/dashboard#channels) -2. Make sure you **Redeployed** or **Restarted OpenClaw** after saving tokens -3. Check for pending [pairing requests](/docs/kiloclaw/chat-platforms#pairing-requests) — the user may need to be approved -4. Try running **OpenClaw Doctor** - -### Accessing and Restoring Config Files - -You can directly access the files in /root/.openclaw/ on the [KiloClaw Dashboard](https://app.kilo.ai/claw) using the file browser of the edit files dialog. This can be a useful way to examine or update the config files (especially `openclaw.json`) if you run into an issue. There may also be backups in the form of `openclaw.bak` files that you can manually restore from if needed. - -### The gateway shows "Crashed" - -The OpenClaw process is automatically restarted when it crashes. Check the Gateway Process tab on your dashboard for the exit code and restart count. If it keeps crashing: - -1. Run **OpenClaw Doctor** -2. Try a **Redeploy** to apply the latest platform image -3. If the issue persists, join the [Kilo Discord](https://kilo.ai/discord) and share details in the KiloClaw channel - -### I changed the model but the agent is still using the old one - -After selecting a new model, click **Save & Provision** to apply it. This refreshes the API key and saves the new model. You may also need to **Restart OpenClaw** for the change to take full effect. - -## Gateway Process States - -The Gateway Process tab shows the current state of the OpenClaw process inside your machine: - -- **Running** — The process is up and handling requests -- **Stopped** — The process is not running -- **Starting** — The process is booting up -- **Stopping** — The process is shutting down gracefully -- **Crashed** — The process exited unexpectedly and will be automatically restarted -- **Shutting Down** — The process is stopping as part of a machine stop or redeploy - -## FAQ - -### How can I change my model? - -You can change the model in two ways: - -- **From chat** — Type `/model` in the Chat window within the OpenClaw Control UI to switch models directly. -- **From the dashboard** — Go to [https://app.kilo.ai/claw](https://app.kilo.ai/claw), select the model you want, and click **Save**. No redeploy is needed. - -### Can I access the filesystem? - -You can access instance files in `/root/.openclaw/` directly from the [KiloClaw Dashboard](https://app.kilo.ai/claw). This is useful for examining or restoring config files — see [Accessing and Restoring Config Files](#accessing-and-restoring-config-files) above. You can also interact with files through your OpenClaw agent using its built-in file tools. - -### Can I access my KiloClaw via SSH? - -For security reasons, SSH access is currently disabled for all KiloClaw instances. Our primary goal is to provide a secure environment for all users, and restricting direct SSH access is one of the many measures we take to ensure the platform remains safe and protected for everyone. - -### How can I update my OpenClaw? - -Do **not** click **Update Now** inside the OpenClaw Control UI — this is not supported for KiloClaw instances and may break your setup. - -Updates are managed by the KiloClaw platform team to ensure stability. When a new version is available, it will be announced in the **Changelog** on your dashboard. To apply the update, click **Upgrade & Redeploy** from the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#redeploy). - -## Architecture Notes - -For advanced users — how KiloClaw instances are structured: - -- **Dedicated machine** — Each user gets their own machine and persistent volume. There is no shared infrastructure between users. -- **Region-pinned storage** — Your persistent volume stays in the region where your instance was originally created. -- **Network isolation** — OpenClaw binds to loopback only; external traffic is proxied through a Kilo controller. -- **Per-user authentication** — The gateway token is derived per-user for authenticating requests to your machine. -- **Encryption at rest** — Sensitive data (API keys, channel tokens) is encrypted at rest in the machine configuration. - -## Related - -- [KiloClaw Overview](/docs/kiloclaw/overview) -- [Dashboard Reference](/docs/kiloclaw/dashboard) -- [Connecting Chat Platforms](/docs/kiloclaw/chat-platforms) -- [KiloClaw Pricing](/docs/kiloclaw/pricing) diff --git a/packages/kilo-docs/pages/kiloclaw/version-pinning.md b/packages/kilo-docs/pages/kiloclaw/version-pinning.md deleted file mode 100644 index 5f2157e7629..00000000000 --- a/packages/kilo-docs/pages/kiloclaw/version-pinning.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "Version Pinning" -description: "Pin your KiloClaw instance to a specific OpenClaw version and variant" ---- - -# Version Pinning - -Version pinning lets you lock your KiloClaw instance to a specific OpenClaw version and variant. This gives you control over when your instance upgrades — it stays on the pinned version until you explicitly change it. - -## When to Use Version Pinning - -Version pinning is useful when: - -- A changelog entry is marked **Redeploy Required** and you're not ready to upgrade yet -- You're running a workflow that depends on specific OpenClaw behavior -- You want to test the impact of an upgrade before committing to it - -## How to Pin a Version - -1. Go to your [KiloClaw dashboard](https://app.kilo.ai/profile) -2. Open the **Settings** tab -3. Scroll to the **Version Pinning** section -4. Select a **version** and **variant** from the dropdowns -5. Click **Save** - -Your instance will stay on the selected version until you change or clear the pin. - -{% callout type="info" %} -After saving a version pin, you need to **Redeploy** for the change to take effect on your running instance. -{% /callout %} - -## Variants - -Each OpenClaw version is available in one or more variants. Variants may differ in included tools, default configuration, or base image. Select the variant that matches your use case, or use the default if unsure. - -## Clearing a Pin - -To return to automatic updates: - -1. Go to **Settings > Version Pinning** -2. Clear the version selection -3. Click **Save** -4. Use **Upgrade & Redeploy** from the dashboard to apply the latest platform version - -{% callout type="warning" %} -Clearing a pin and running **Upgrade & Redeploy** will update your instance to the latest supported platform version. Review the changelog before upgrading to check for breaking changes. -{% /callout %} - -## Related - -- [Dashboard Reference](/docs/kiloclaw/dashboard) -- [KiloClaw Overview](/docs/kiloclaw/overview) -- [Troubleshooting](/docs/kiloclaw/troubleshooting) From 560b0a13ad5dc3dd35b2fbfe288be11bfe9c8fc2 Mon Sep 17 00:00:00 2001 From: Ligia Zanchet Date: Thu, 26 Mar 2026 15:41:02 +0100 Subject: [PATCH 053/261] docs: add overview index pages for Tools, Chat Platforms, and Development Tools --- packages/kilo-docs/lib/nav/kiloclaw.ts | 9 +++++--- .../pages/kiloclaw/chat-platforms/index.md | 21 +++++++++++++++++++ .../pages/kiloclaw/development-tools/index.md | 13 ++++++++++++ .../kilo-docs/pages/kiloclaw/tools/index.md | 14 +++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 packages/kilo-docs/pages/kiloclaw/chat-platforms/index.md create mode 100644 packages/kilo-docs/pages/kiloclaw/development-tools/index.md create mode 100644 packages/kilo-docs/pages/kiloclaw/tools/index.md diff --git a/packages/kilo-docs/lib/nav/kiloclaw.ts b/packages/kilo-docs/lib/nav/kiloclaw.ts index 1aac3c672a8..90ee60a72dc 100644 --- a/packages/kilo-docs/lib/nav/kiloclaw.ts +++ b/packages/kilo-docs/lib/nav/kiloclaw.ts @@ -18,26 +18,29 @@ export const KiloClawNav: NavSection[] = [ ], }, { - href: "/kiloclaw/chat-platforms/telegram", + href: "/kiloclaw/chat-platforms", children: "Chat Platforms", subLinks: [ + { href: "/kiloclaw/chat-platforms", children: "Overview" }, { href: "/kiloclaw/chat-platforms/telegram", children: "Telegram" }, { href: "/kiloclaw/chat-platforms/discord", children: "Discord" }, { href: "/kiloclaw/chat-platforms/slack", children: "Slack" }, ], }, { - href: "/kiloclaw/development-tools/github", + href: "/kiloclaw/development-tools", children: "Development Tools", subLinks: [ + { href: "/kiloclaw/development-tools", children: "Overview" }, { href: "/kiloclaw/development-tools/github", children: "GitHub" }, { href: "/kiloclaw/development-tools/google", children: "Google Workspace" }, ], }, { - href: "/kiloclaw/tools/1password", + href: "/kiloclaw/tools", children: "Tools", subLinks: [ + { href: "/kiloclaw/tools", children: "Overview" }, { href: "/kiloclaw/tools/1password", children: "1Password" }, { href: "/kiloclaw/tools/brave-search", children: "Brave Search" }, { href: "/kiloclaw/tools/agentcard", children: "AgentCard" }, diff --git a/packages/kilo-docs/pages/kiloclaw/chat-platforms/index.md b/packages/kilo-docs/pages/kiloclaw/chat-platforms/index.md new file mode 100644 index 00000000000..69482f76a5c --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/chat-platforms/index.md @@ -0,0 +1,21 @@ +--- +title: "Chat Platforms" +description: "Connect your KiloClaw agent to Telegram, Discord, and Slack" +--- + +# Chat Platforms + +KiloClaw supports connecting your AI agent to messaging platforms so it can receive instructions and send responses directly in your chat apps. You can configure channels from the **Settings** tab on your [KiloClaw dashboard](/docs/kiloclaw/dashboard#channels), or from the OpenClaw Control UI after accessing your instance. + +The general steps to connect any chat platform are: + +1. Configure the channel token in Settings +2. Redeploy the KiloClaw instance +3. Initiate the pairing in the chat app +4. Accept the pairing request in the [KiloClaw UI](https://app.kilo.ai/claw) + +## Supported Platforms + +- [**Telegram**](/docs/kiloclaw/chat-platforms/telegram) — Connect via a BotFather bot token. +- [**Discord**](/docs/kiloclaw/chat-platforms/discord) — Connect via a Discord Developer Portal bot token. +- [**Slack**](/docs/kiloclaw/chat-platforms/slack) — Connect via a Slack app manifest with app-level and bot tokens. diff --git a/packages/kilo-docs/pages/kiloclaw/development-tools/index.md b/packages/kilo-docs/pages/kiloclaw/development-tools/index.md new file mode 100644 index 00000000000..a99a3d705de --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/development-tools/index.md @@ -0,0 +1,13 @@ +--- +title: "Development Tools" +description: "Connect your KiloClaw agent to development platforms like GitHub and Google Workspace" +--- + +# Development Tools + +KiloClaw supports integrations with popular development platforms, allowing your agent to interact with repositories, code reviews, calendars, documents, and more — all autonomously. + +## Available Integrations + +- [**GitHub**](/docs/kiloclaw/development-tools/github) — Clone repositories, push commits, open pull requests, and leave code reviews. +- [**Google Workspace**](/docs/kiloclaw/development-tools/google) — Access Gmail, Calendar, Drive, Docs, Sheets, Slides, Tasks, and more. diff --git a/packages/kilo-docs/pages/kiloclaw/tools/index.md b/packages/kilo-docs/pages/kiloclaw/tools/index.md new file mode 100644 index 00000000000..4a17e3289e7 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/tools/index.md @@ -0,0 +1,14 @@ +--- +title: "Tools" +description: "Third-party tool integrations for your KiloClaw agent" +--- + +# Tools + +KiloClaw supports integrations with third-party tools that extend your agent's capabilities — from secure credential management to web search and financial transactions. + +## Available Integrations + +- [**1Password**](/docs/kiloclaw/tools/1password) — Securely manage credentials and let your agent fetch API keys or passwords without ever seeing them in plain text. +- [**Brave Search**](/docs/kiloclaw/tools/brave-search) — Equip your agent with real-time web browsing via the Brave Search API. +- [**AgentCard**](/docs/kiloclaw/tools/agentcard) — Enable your agent to perform financial transactions using virtual debit cards. From f2dcafc2c56aad241f1ead2ac03c818ba0dffcd7 Mon Sep 17 00:00:00 2001 From: Marius Date: Thu, 26 Mar 2026 15:47:04 +0100 Subject: [PATCH 054/261] fix(cli): strip bloated file contents from tool metadata to fix session loading perf (#7706) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Edit, apply_patch, and user message summary were storing full before/after file contents in metadata — causing sessions to balloon to 90+ MB and crash the VS Code extension on load. Strip before/after from edit filediff, apply_patch files[], and summary.diffs both at write time (new data) and read time (existing data). --- .../kilo-ui/src/components/message-part.tsx | 24 ++++--- packages/opencode/src/session/message-v2.ts | 72 +++++++++++++++++-- packages/ui/src/components/message-part.tsx | 24 ++++--- 3 files changed, 93 insertions(+), 27 deletions(-) diff --git a/packages/kilo-ui/src/components/message-part.tsx b/packages/kilo-ui/src/components/message-part.tsx index ac6b5a4cf21..0ff6de64f27 100644 --- a/packages/kilo-ui/src/components/message-part.tsx +++ b/packages/kilo-ui/src/components/message-part.tsx @@ -2007,8 +2007,8 @@ interface ApplyPatchFile { relativePath: string type: "add" | "update" | "delete" | "move" diff: string - before: string - after: string + before?: string + after?: string additions: number deletions: number movePath?: string @@ -2158,7 +2158,7 @@ ToolRegistry.register({ - +
} > -
- -
+ +
+ +
+
)} diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index e468d1f2604..1e84d3433e6 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -503,6 +503,62 @@ export namespace MessageV2 { }) export type WithParts = z.infer + // kilocode_change start - strip bloated metadata fields from stored parts to prevent multi-MB payloads + // This handles both legacy data that was stored with full file contents and keeps the API response lean. + function stripPartMetadata(part: Part): Part { + if (part.type !== "tool") return part + const { state } = part + if (state.status !== "completed" && state.status !== "running") return part + const meta = state.metadata + if (!meta) return part + + let changed = false + let next = meta + + // Strip edit tool's filediff.before/after (full file contents) + if (meta.filediff && (meta.filediff.before || meta.filediff.after)) { + const { before, after, ...rest } = meta.filediff + next = { ...next, filediff: rest } + changed = true + } + + // Strip apply_patch tool's files[].before/after (full file contents per file) + if (Array.isArray(meta.files) && meta.files.length > 0 && meta.files[0]?.before !== undefined) { + next = { + ...next, + files: meta.files.map((f: Record) => { + const { before, after, ...rest } = f + return rest + }), + } + changed = true + } + + if (!changed) return part + return { ...part, state: { ...state, metadata: next } } as Part + } + + function stripMessageMetadata(info: Info): Info { + // Strip summary.diffs before/after from user messages (can be 20+ MB) + if (info.role !== "user") return info + const user = info as User + if (!user.summary?.diffs?.length) return info + const has = user.summary.diffs.some((d: Snapshot.FileDiff) => d.before || d.after) + if (!has) return info + return { + ...user, + summary: { + ...user.summary, + diffs: user.summary.diffs.map(({ before, after, ...rest }: Snapshot.FileDiff) => ({ + ...rest, + before: "", + after: "", + })), + }, + } as Info + } + // kilocode_change end + export function toModelMessages( input: WithParts[], model: Provider.Model, @@ -766,12 +822,12 @@ export namespace MessageV2 { .all(), ) for (const row of partRows) { - const part = { + const part = stripPartMetadata({ ...row.data, id: row.id, sessionID: row.session_id, messageID: row.message_id, - } as MessageV2.Part + } as MessageV2.Part) // kilocode_change - strip bloated metadata on read const list = partsByMessage.get(row.message_id) if (list) list.push(part) else partsByMessage.set(row.message_id, [part]) @@ -779,7 +835,7 @@ export namespace MessageV2 { } for (const row of rows) { - const info = { ...row.data, id: row.id, sessionID: row.session_id } as MessageV2.Info + const info = stripMessageMetadata({ ...row.data, id: row.id, sessionID: row.session_id } as MessageV2.Info) // kilocode_change yield { info, parts: partsByMessage.get(row.id) ?? [], @@ -796,7 +852,13 @@ export namespace MessageV2 { db.select().from(PartTable).where(eq(PartTable.message_id, message_id)).orderBy(PartTable.id).all(), ) return rows.map( - (row) => ({ ...row.data, id: row.id, sessionID: row.session_id, messageID: row.message_id }) as MessageV2.Part, + (row) => + stripPartMetadata({ + ...row.data, + id: row.id, + sessionID: row.session_id, + messageID: row.message_id, + } as MessageV2.Part), // kilocode_change - strip bloated metadata on read ) }) @@ -808,7 +870,7 @@ export namespace MessageV2 { async (input): Promise => { const row = Database.use((db) => db.select().from(MessageTable).where(eq(MessageTable.id, input.messageID)).get()) if (!row) throw new Error(`Message not found: ${input.messageID}`) - const info = { ...row.data, id: row.id, sessionID: row.session_id } as MessageV2.Info + const info = stripMessageMetadata({ ...row.data, id: row.id, sessionID: row.session_id } as MessageV2.Info) // kilocode_change return { info, parts: await parts(input.messageID), diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index b00e06d2886..66cdd29cc8b 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -1840,8 +1840,8 @@ interface ApplyPatchFile { relativePath: string type: "add" | "update" | "delete" | "move" diff: string - before: string - after: string + before?: string + after?: string additions: number deletions: number movePath?: string @@ -1956,7 +1956,7 @@ ToolRegistry.register({ - +
} > -
- -
+ +
+ +
+
From dcab290055e8f7cebb68f40635b0d02cdf5dce52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Thu, 26 Mar 2026 11:54:19 -0300 Subject: [PATCH 055/261] Publish release on OpenVSX (#7608) * feat: Prod Release only to OpenVSX * feat: build as a prod release * feat: dual vsx build --- packages/kilo-vscode/script/build.ts | 11 ++++++++++- packages/kilo-vscode/script/publish.ts | 11 ++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/kilo-vscode/script/build.ts b/packages/kilo-vscode/script/build.ts index cb9b162560c..86eb685dcbc 100644 --- a/packages/kilo-vscode/script/build.ts +++ b/packages/kilo-vscode/script/build.ts @@ -36,9 +36,10 @@ const targets = [ const binDir = join(import.meta.dir, "..", "bin") const distDir = join(import.meta.dir, "..", "dist") const outDir = join(import.meta.dir, "..", "out") +const outDirProd = join(import.meta.dir, "..", "out", "prod") console.log("\n🧹 Cleaning up directories...") -for (const dir of [binDir, distDir, outDir]) { +for (const dir of [binDir, distDir, outDir, outDirProd]) { if (existsSync(dir)) { rmSync(dir, { recursive: true, force: true }) console.log(` ✓ Cleaned ${dir}`) @@ -47,6 +48,7 @@ for (const dir of [binDir, distDir, outDir]) { mkdirSync(outDir, { recursive: true }) mkdirSync(distDir, { recursive: true }) +mkdirSync(outDirProd, { recursive: true }) console.log("\n🔄 Rebuilding SDK types (ensures dist/ is in sync with server API)...") await $`bun run --cwd ${join(import.meta.dir, "..", "..", "sdk", "js")} build` @@ -87,6 +89,13 @@ for (const config of targets) { npm_config_ignore_scripts: "true", }) console.log(` ✅ Created ${vsixPath}`) + + const prodVsixPath = join(outDirProd, `kilo-vscode-${config.target}.vsix`) + await $`vsce package --no-dependencies --skip-license --target ${config.target} -o ${prodVsixPath}`.env({ + ...process.env, + npm_config_ignore_scripts: "true", + }) + console.log(` ✅ Created ${prodVsixPath}`) } console.log("\n✨ All VSIX packages built successfully!") diff --git a/packages/kilo-vscode/script/publish.ts b/packages/kilo-vscode/script/publish.ts index 87ce086f029..3a526e86d5a 100755 --- a/packages/kilo-vscode/script/publish.ts +++ b/packages/kilo-vscode/script/publish.ts @@ -7,6 +7,8 @@ import { Script } from "@opencode-ai/script" console.log(`Publishing VSCode extension for release: v${Script.version}`) const outDir = process.env.VSIX_DIR || join(import.meta.dir, "..", "out") +const outDirProd = join(outDir, "prod") + console.log(`Using VSIX directory: ${outDir}`) if (!existsSync(outDir)) { @@ -37,15 +39,14 @@ console.log(`\nFound ${vsixFiles.length} VSIX files`) for (const target of targets) { const vsixPath = join(outDir, `kilo-vscode-${target}.vsix`) - console.log(`\n🚀 Publishing ${target} to VS Code Marketplace...`) await $`vsce publish --pre-release --packagePath ${vsixPath}` console.log(` ✅ Published ${target} to VS Code Marketplace`) - // Note: Open VSX publishing is commented out as it doesn't support prereleases - // console.log(`\n📤 Publishing ${target} to Open VSX...`) - // await $`npx ovsx publish ${vsixPath} --target ${target} -p ${process.env.OPENVSX_TOKEN}` - // console.log(` ✅ Published ${target} to Open VSX`) + const prodVsixPath = join(outDirProd, `kilo-vscode-${target}.vsix`) + console.log(`\n📤 Publishing ${target} to Open VSX...`) + await $`npx ovsx publish --pat ${process.env.OPENVSX_TOKEN} --packagePath ${prodVsixPath}` + console.log(` ✅ Published Prod ${target} to Open VSX`) } if (Script.release) { From 6105e356a92b32098c146a38a02a1571870a9b37 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Thu, 26 Mar 2026 17:03:39 +0200 Subject: [PATCH 056/261] fix(cli): detect nested config dirs in isRelative --- .../opencode/src/kilocode/permission/config-paths.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/kilocode/permission/config-paths.ts b/packages/opencode/src/kilocode/permission/config-paths.ts index 35b554c78b8..662851ad9d9 100644 --- a/packages/opencode/src/kilocode/permission/config-paths.ts +++ b/packages/opencode/src/kilocode/permission/config-paths.ts @@ -26,7 +26,15 @@ export namespace ConfigProtection { export function isRelative(pattern: string): boolean { const normalized = normalize(pattern) for (const dir of CONFIG_DIRS) { - if (normalized === dir.slice(0, -1) || normalized.startsWith(dir)) return true + const bare = dir.slice(0, -1) // e.g. ".kilo" + // Match at root (e.g. ".kilo/foo") or nested (e.g. "packages/sub/.kilo/foo") + if ( + normalized === bare || + normalized.startsWith(dir) || + normalized.includes("/" + dir) || + normalized.endsWith("/" + bare) + ) + return true } return CONFIG_ROOT_FILES.has(normalized) } From a2151478ee4ea39d4f20764879523a9dcd1ffada Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Thu, 26 Mar 2026 17:03:58 +0200 Subject: [PATCH 057/261] fix(cli): check movePath in apply_patch config guard --- packages/opencode/src/kilocode/permission/config-paths.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/kilocode/permission/config-paths.ts b/packages/opencode/src/kilocode/permission/config-paths.ts index 662851ad9d9..79794d11f86 100644 --- a/packages/opencode/src/kilocode/permission/config-paths.ts +++ b/packages/opencode/src/kilocode/permission/config-paths.ts @@ -82,11 +82,14 @@ export namespace ConfigProtection { } } - // Check metadata.files[] (apply_patch file objects with absolute filePath) + // Check metadata.files[] (apply_patch file objects with absolute filePath/movePath) const files = request.metadata?.files if (Array.isArray(files)) { for (const file of files) { - if (typeof file?.filePath === "string" && isAbsolute(file.filePath)) return true + for (const key of ["filePath", "movePath"] as const) { + const val = file?.[key] + if (typeof val === "string" && (path.isAbsolute(val) ? isAbsolute(val) : isRelative(val))) return true + } } } From 2dba685256394de77e80b69a9dce8a2bf12bd4e9 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Thu, 26 Mar 2026 17:13:19 +0200 Subject: [PATCH 058/261] refactor(cli): extract helpers to reduce duplication --- .../src/kilocode/permission/config-paths.ts | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/opencode/src/kilocode/permission/config-paths.ts b/packages/opencode/src/kilocode/permission/config-paths.ts index 79794d11f86..46d029567fa 100644 --- a/packages/opencode/src/kilocode/permission/config-paths.ts +++ b/packages/opencode/src/kilocode/permission/config-paths.ts @@ -39,23 +39,31 @@ export namespace ConfigProtection { return CONFIG_ROOT_FILES.has(normalized) } + /** Check if `child` is equal to or nested inside `parent`. */ + function within(child: string, parent: string): boolean { + return child === parent || child.startsWith(parent + path.sep) + } + /** Check if an absolute path is inside a known CLI config directory. */ export function isAbsolute(filepath: string): boolean { const resolved = path.resolve(filepath) // ~/.config/kilo/ (XDG config) - const xdg = path.resolve(Global.Path.config) - if (resolved === xdg || resolved.startsWith(xdg + path.sep)) return true + if (within(resolved, path.resolve(Global.Path.config))) return true // ~/.kilo/ and ~/.kilocode/ (legacy global dirs) for (const dir of KilocodePaths.globalDirs()) { - const abs = path.resolve(dir) - if (resolved === abs || resolved.startsWith(abs + path.sep)) return true + if (within(resolved, path.resolve(dir))) return true } return false } + /** Check a single path (absolute or relative) against config protection. */ + function protected_(p: string): boolean { + return path.isAbsolute(p) ? isAbsolute(p) : isRelative(p) + } + /** * Determine if a permission request targets config files. * Only checks `edit` permission — read access is not restricted. @@ -67,9 +75,9 @@ export namespace ConfigProtection { }): boolean { if (request.permission !== "edit") return false - // Check patterns — handle both relative and absolute (mirrors metadata.filepath logic) + // Check patterns — handle both relative and absolute for (const pattern of request.patterns) { - if (path.isAbsolute(pattern) ? isAbsolute(pattern) : isRelative(pattern)) return true + if (protected_(pattern)) return true } // Check metadata.filepath (absolute for edit, comma-joined relative for apply_patch) @@ -78,7 +86,7 @@ export namespace ConfigProtection { // apply_patch joins relative paths with ", " const parts = fp.includes(", ") ? fp.split(", ") : [fp] for (const part of parts) { - if (path.isAbsolute(part) ? isAbsolute(part) : isRelative(part)) return true + if (protected_(part)) return true } } @@ -88,7 +96,7 @@ export namespace ConfigProtection { for (const file of files) { for (const key of ["filePath", "movePath"] as const) { const val = file?.[key] - if (typeof val === "string" && (path.isAbsolute(val) ? isAbsolute(val) : isRelative(val))) return true + if (typeof val === "string" && protected_(val)) return true } } } From 911a32e718b12186632830035e85bc8caf9a15e1 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 25 Mar 2026 16:32:08 +0100 Subject: [PATCH 059/261] feat(vscode): add MCP server edit view in Agent Behaviour settings Add McpEditView component with editable command/args for local servers, URL for remote servers, and environment variable management. MCP server list items are now clickable, navigating to the edit view with a back button. Follows the same list-to-edit pattern as agent modes. Closes #7596 --- .../components/settings/AgentBehaviourTab.tsx | 49 +++- .../src/components/settings/McpEditView.tsx | 219 ++++++++++++++++++ .../kilo-vscode/webview-ui/src/i18n/ar.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/br.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/bs.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/da.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/de.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/en.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/es.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/fr.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/ja.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/ko.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/nl.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/no.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/pl.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/ru.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/th.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/tr.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/zh.ts | 5 + .../kilo-vscode/webview-ui/src/i18n/zht.ts | 5 + 20 files changed, 348 insertions(+), 10 deletions(-) create mode 100644 packages/kilo-vscode/webview-ui/src/components/settings/McpEditView.tsx diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index c47d739b326..0b0bf7811d6 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -13,6 +13,7 @@ import { useLanguage } from "../../context/language" import type { AgentInfo, SkillInfo } from "../../types/messages" import ModeEditView from "./ModeEditView" import ModeCreateView from "./ModeCreateView" +import McpEditView from "./McpEditView" import WorkflowsTab from "./agent-behaviour/WorkflowsTab" import { parseImport, MAX_IMPORT_SIZE } from "./mode-io" import type { ImportError } from "./mode-io" @@ -71,6 +72,9 @@ const AgentBehaviourTab: Component = () => { const [agentView, setAgentView] = createSignal("list") const [editingAgent, setEditingAgent] = createSignal("") + // MCP view state + const [editingMcp, setEditingMcp] = createSignal("") + // Fetch skills whenever the skills subtab becomes active createEffect(() => { if (activeSubtab() === "skills") { @@ -489,6 +493,19 @@ const AgentBehaviourTab: Component = () => { setExpanded((prev) => ({ ...prev, [name]: !prev[name] })) } + if (editingMcp()) { + return ( + setEditingMcp("")} + onRemove={(name) => { + confirmRemoveMcp(name) + setEditingMcp("") + }} + /> + ) + } + return (
{ {mcp.url ? "remote" : "stdio"}
- { - e.stopPropagation() - confirmRemoveMcp(name) - }} - /> +
+ { + e.stopPropagation() + confirmRemoveMcp(name) + }} + /> + { + e.stopPropagation() + setEditingMcp(name) + }} + /> +
{/* Expandable detail */} @@ -916,11 +944,12 @@ const AgentBehaviourTab: Component = () => { +
+ + + {([key, val], index) => ( +
+ + {key}={val} + + removeEnv(key)} /> +
+ )} +
+ + +
+ +
+
+ ) +} + +export default McpEditView diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index fe54704520b..baf5c7a758d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1086,6 +1086,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.title": "إزالة خادم MCP", "settings.agentBehaviour.removeMcp.confirm": 'هل تريد إزالة خادم MCP "{{name}}"؟ سيؤدي هذا إلى إزالته من الإعدادات.', "settings.agentBehaviour.removeMcp.button": "إزالة", + "settings.agentBehaviour.editMcp": "تعديل خادم MCP", + "settings.agentBehaviour.editMcp.transportLocal": "خادم محلي (نقل stdio)", + "settings.agentBehaviour.editMcp.transportRemote": "خادم بعيد (نقل SSE/HTTP)", + "settings.agentBehaviour.editMcp.env": "متغيرات البيئة", + "settings.agentBehaviour.editMcp.env.help": "المتغيرات التي يتم تمريرها إلى عملية خادم MCP.", "settings.agentBehaviour.skillPaths": "مسارات مجلدات المهارات", "settings.agentBehaviour.skillUrls": "عناوين URL للمهارات", "settings.agentBehaviour.removeSkill.title": "إزالة المهارة", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index a591304e89f..ced4b152b9e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1102,6 +1102,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.confirm": 'Remover o servidor MCP "{{name}}"? Isso o removerá da sua configuração.', "settings.agentBehaviour.removeMcp.button": "Remover", + "settings.agentBehaviour.editMcp": "Editar Servidor MCP", + "settings.agentBehaviour.editMcp.transportLocal": "Servidor local (transporte stdio)", + "settings.agentBehaviour.editMcp.transportRemote": "Servidor remoto (transporte SSE/HTTP)", + "settings.agentBehaviour.editMcp.env": "Variáveis de Ambiente", + "settings.agentBehaviour.editMcp.env.help": "Variáveis passadas para o processo do servidor MCP.", "settings.agentBehaviour.skillPaths": "Caminhos de pastas de habilidades", "settings.agentBehaviour.skillUrls": "URLs de habilidades", "settings.agentBehaviour.removeSkill.title": "Remover habilidade", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index ab1e5a84e78..40c18bb2462 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1101,6 +1101,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.confirm": 'Ukloniti MCP server "{{name}}"? Ovo će ga ukloniti iz vaše konfiguracije.', "settings.agentBehaviour.removeMcp.button": "Ukloni", + "settings.agentBehaviour.editMcp": "Uredi MCP Server", + "settings.agentBehaviour.editMcp.transportLocal": "Lokalni server (stdio transport)", + "settings.agentBehaviour.editMcp.transportRemote": "Udaljeni server (SSE/HTTP transport)", + "settings.agentBehaviour.editMcp.env": "Varijable okruženja", + "settings.agentBehaviour.editMcp.env.help": "Varijable proslijeđene procesu MCP servera.", "settings.agentBehaviour.skillPaths": "Putanje mapa vještina", "settings.agentBehaviour.skillUrls": "URL-ovi vještina", "settings.agentBehaviour.removeSkill.title": "Ukloni vještinu", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 16db57850e4..51d28865e30 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1095,6 +1095,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.confirm": 'Vil du fjerne MCP-serveren "{{name}}"? Dette vil fjerne den fra din konfiguration.', "settings.agentBehaviour.removeMcp.button": "Fjern", + "settings.agentBehaviour.editMcp": "Rediger MCP-server", + "settings.agentBehaviour.editMcp.transportLocal": "Lokal server (stdio-transport)", + "settings.agentBehaviour.editMcp.transportRemote": "Fjernserver (SSE/HTTP-transport)", + "settings.agentBehaviour.editMcp.env": "Miljøvariabler", + "settings.agentBehaviour.editMcp.env.help": "Variabler der sendes til MCP-serverprocessen.", "settings.agentBehaviour.skillPaths": "Skill-mappestier", "settings.agentBehaviour.skillUrls": "Skill-URL'er", "settings.agentBehaviour.removeSkill.title": "Fjern færdighed", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 2d845bf797a..8ae09437f07 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1115,6 +1115,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.confirm": 'MCP-Server "{{name}}" entfernen? Dadurch wird er aus Ihrer Konfiguration entfernt.', "settings.agentBehaviour.removeMcp.button": "Entfernen", + "settings.agentBehaviour.editMcp": "MCP-Server bearbeiten", + "settings.agentBehaviour.editMcp.transportLocal": "Lokaler Server (stdio-Transport)", + "settings.agentBehaviour.editMcp.transportRemote": "Remote-Server (SSE/HTTP-Transport)", + "settings.agentBehaviour.editMcp.env": "Umgebungsvariablen", + "settings.agentBehaviour.editMcp.env.help": "Variablen, die an den MCP-Serverprozess übergeben werden.", "settings.agentBehaviour.skillPaths": "Skill-Ordnerpfade", "settings.agentBehaviour.skillUrls": "Skill-URLs", "settings.agentBehaviour.removeSkill.title": "Skill entfernen", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index a7a450e5fa9..99c7054c32e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1083,6 +1083,11 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Arguments", "settings.agentBehaviour.mcpDetail.env": "Environment", "settings.agentBehaviour.mcpDetail.disabled": "This server is disabled.", + "settings.agentBehaviour.editMcp": "Edit MCP Server", + "settings.agentBehaviour.editMcp.transportLocal": "Local server (stdio transport)", + "settings.agentBehaviour.editMcp.transportRemote": "Remote server (SSE/HTTP transport)", + "settings.agentBehaviour.editMcp.env": "Environment Variables", + "settings.agentBehaviour.editMcp.env.help": "Variables passed to the MCP server process.", "settings.agentBehaviour.mcpEmpty": "No MCP servers configured. Edit the opencode config file to add MCP servers.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows are managed via workflow files in your workspace.", "settings.agentBehaviour.workflows.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 30412000091..ec7189b5038 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1106,6 +1106,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.confirm": '¿Eliminar el servidor MCP "{{name}}"? Esto lo eliminará de su configuración.', "settings.agentBehaviour.removeMcp.button": "Eliminar", + "settings.agentBehaviour.editMcp": "Editar servidor MCP", + "settings.agentBehaviour.editMcp.transportLocal": "Servidor local (transporte stdio)", + "settings.agentBehaviour.editMcp.transportRemote": "Servidor remoto (transporte SSE/HTTP)", + "settings.agentBehaviour.editMcp.env": "Variables de entorno", + "settings.agentBehaviour.editMcp.env.help": "Variables pasadas al proceso del servidor MCP.", "settings.agentBehaviour.skillPaths": "Rutas de carpetas de habilidades", "settings.agentBehaviour.skillUrls": "URLs de habilidades", "settings.agentBehaviour.removeSkill.title": "Eliminar habilidad", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index cd4da64c244..81d078d75f0 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1119,6 +1119,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.confirm": 'Supprimer le serveur MCP "{{name}}" ? Cela le supprimera de votre configuration.', "settings.agentBehaviour.removeMcp.button": "Supprimer", + "settings.agentBehaviour.editMcp": "Modifier le serveur MCP", + "settings.agentBehaviour.editMcp.transportLocal": "Serveur local (transport stdio)", + "settings.agentBehaviour.editMcp.transportRemote": "Serveur distant (transport SSE/HTTP)", + "settings.agentBehaviour.editMcp.env": "Variables d'environnement", + "settings.agentBehaviour.editMcp.env.help": "Variables transmises au processus du serveur MCP.", "settings.agentBehaviour.skillPaths": "Chemins des dossiers de compétences", "settings.agentBehaviour.skillUrls": "URLs de compétences", "settings.agentBehaviour.removeSkill.title": "Supprimer la compétence", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 86046475c55..f8203a818e8 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1096,6 +1096,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.title": "MCPサーバーを削除", "settings.agentBehaviour.removeMcp.confirm": 'MCPサーバー "{{name}}" を削除しますか?設定から削除されます。', "settings.agentBehaviour.removeMcp.button": "削除", + "settings.agentBehaviour.editMcp": "MCPサーバーを編集", + "settings.agentBehaviour.editMcp.transportLocal": "ローカルサーバー(stdio トランスポート)", + "settings.agentBehaviour.editMcp.transportRemote": "リモートサーバー(SSE/HTTP トランスポート)", + "settings.agentBehaviour.editMcp.env": "環境変数", + "settings.agentBehaviour.editMcp.env.help": "MCPサーバープロセスに渡される変数。", "settings.agentBehaviour.skillPaths": "スキルフォルダパス", "settings.agentBehaviour.skillUrls": "スキルURL", "settings.agentBehaviour.removeSkill.title": "スキルを削除", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 260c82f7c49..e1ada3b1f66 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1090,6 +1090,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.title": "MCP 서버 제거", "settings.agentBehaviour.removeMcp.confirm": 'MCP 서버 "{{name}}"을(를) 제거하시겠습니까? 구성에서 제거됩니다.', "settings.agentBehaviour.removeMcp.button": "제거", + "settings.agentBehaviour.editMcp": "MCP 서버 편집", + "settings.agentBehaviour.editMcp.transportLocal": "로컬 서버 (stdio 전송)", + "settings.agentBehaviour.editMcp.transportRemote": "원격 서버 (SSE/HTTP 전송)", + "settings.agentBehaviour.editMcp.env": "환경 변수", + "settings.agentBehaviour.editMcp.env.help": "MCP 서버 프로세스에 전달되는 변수입니다.", "settings.agentBehaviour.skillPaths": "스킬 폴더 경로", "settings.agentBehaviour.skillUrls": "스킬 URL", "settings.agentBehaviour.removeSkill.title": "스킬 제거", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 2261e058598..16089f170d8 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1097,6 +1097,11 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Argumenten", "settings.agentBehaviour.mcpDetail.env": "Omgeving", "settings.agentBehaviour.mcpDetail.disabled": "Deze server is uitgeschakeld.", + "settings.agentBehaviour.editMcp": "MCP-server bewerken", + "settings.agentBehaviour.editMcp.transportLocal": "Lokale server (stdio-transport)", + "settings.agentBehaviour.editMcp.transportRemote": "Externe server (SSE/HTTP-transport)", + "settings.agentBehaviour.editMcp.env": "Omgevingsvariabelen", + "settings.agentBehaviour.editMcp.env.help": "Variabelen die worden doorgegeven aan het MCP-serverproces.", "settings.agentBehaviour.mcpEmpty": "Geen MCP-servers geconfigureerd. Bewerk het opencode configuratiebestand om MCP-servers toe te voegen.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows worden beheerd via workflowbestanden in je workspace.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index d92b688ad78..5d30d771847 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1098,6 +1098,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.confirm": 'Vil du fjerne MCP-serveren "{{name}}"? Dette vil fjerne den fra konfigurasjonen din.', "settings.agentBehaviour.removeMcp.button": "Fjern", + "settings.agentBehaviour.editMcp": "Rediger MCP-server", + "settings.agentBehaviour.editMcp.transportLocal": "Lokal server (stdio-transport)", + "settings.agentBehaviour.editMcp.transportRemote": "Ekstern server (SSE/HTTP-transport)", + "settings.agentBehaviour.editMcp.env": "Miljøvariabler", + "settings.agentBehaviour.editMcp.env.help": "Variabler som sendes til MCP-serverprosessen.", "settings.agentBehaviour.skillPaths": "Ferdighetsmappe-stier", "settings.agentBehaviour.skillUrls": "Ferdighets-URLer", "settings.agentBehaviour.removeSkill.title": "Fjern ferdighet", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 9e3fba12eb6..d4f3e9ac4c9 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1100,6 +1100,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.confirm": 'Usunąć serwer MCP "{{name}}"? Spowoduje to usunięcie go z konfiguracji.', "settings.agentBehaviour.removeMcp.button": "Usuń", + "settings.agentBehaviour.editMcp": "Edytuj serwer MCP", + "settings.agentBehaviour.editMcp.transportLocal": "Serwer lokalny (transport stdio)", + "settings.agentBehaviour.editMcp.transportRemote": "Serwer zdalny (transport SSE/HTTP)", + "settings.agentBehaviour.editMcp.env": "Zmienne środowiskowe", + "settings.agentBehaviour.editMcp.env.help": "Zmienne przekazywane do procesu serwera MCP.", "settings.agentBehaviour.skillPaths": "Ścieżki folderów umiejętności", "settings.agentBehaviour.skillUrls": "Adresy URL umiejętności", "settings.agentBehaviour.removeSkill.title": "Usuń umiejętność", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index ee0015c90e1..14f27d7f11d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1103,6 +1103,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.title": "Удалить сервер MCP", "settings.agentBehaviour.removeMcp.confirm": 'Удалить сервер MCP "{{name}}"? Это удалит его из вашей конфигурации.', "settings.agentBehaviour.removeMcp.button": "Удалить", + "settings.agentBehaviour.editMcp": "Редактировать сервер MCP", + "settings.agentBehaviour.editMcp.transportLocal": "Локальный сервер (транспорт stdio)", + "settings.agentBehaviour.editMcp.transportRemote": "Удалённый сервер (транспорт SSE/HTTP)", + "settings.agentBehaviour.editMcp.env": "Переменные окружения", + "settings.agentBehaviour.editMcp.env.help": "Переменные, передаваемые процессу сервера MCP.", "settings.agentBehaviour.skillPaths": "Пути папок навыков", "settings.agentBehaviour.skillUrls": "URL навыков", "settings.agentBehaviour.removeSkill.title": "Удалить навык", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 07a459d75a6..e8755a307c3 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1087,6 +1087,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.confirm": 'ต้องการลบเซิร์ฟเวอร์ MCP "{{name}}" หรือไม่? การดำเนินการนี้จะลบออกจากการกำหนดค่าของคุณ', "settings.agentBehaviour.removeMcp.button": "ลบ", + "settings.agentBehaviour.editMcp": "แก้ไขเซิร์ฟเวอร์ MCP", + "settings.agentBehaviour.editMcp.transportLocal": "เซิร์ฟเวอร์ภายใน (การขนส่ง stdio)", + "settings.agentBehaviour.editMcp.transportRemote": "เซิร์ฟเวอร์ระยะไกล (การขนส่ง SSE/HTTP)", + "settings.agentBehaviour.editMcp.env": "ตัวแปรสภาพแวดล้อม", + "settings.agentBehaviour.editMcp.env.help": "ตัวแปรที่ส่งไปยังกระบวนการเซิร์ฟเวอร์ MCP", "settings.agentBehaviour.skillPaths": "เส้นทางโฟลเดอร์ทักษะ", "settings.agentBehaviour.skillUrls": "URL ทักษะ", "settings.agentBehaviour.removeSkill.title": "ลบทักษะ", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 6747676b011..1a1abd12bd7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1096,6 +1096,11 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Argümanlar", "settings.agentBehaviour.mcpDetail.env": "Ortam", "settings.agentBehaviour.mcpDetail.disabled": "Bu sunucu devre dışı.", + "settings.agentBehaviour.editMcp": "MCP Sunucusunu Düzenle", + "settings.agentBehaviour.editMcp.transportLocal": "Yerel sunucu (stdio taşıma)", + "settings.agentBehaviour.editMcp.transportRemote": "Uzak sunucu (SSE/HTTP taşıma)", + "settings.agentBehaviour.editMcp.env": "Ortam Değişkenleri", + "settings.agentBehaviour.editMcp.env.help": "MCP sunucu sürecine aktarılan değişkenler.", "settings.agentBehaviour.mcpEmpty": "Yapılandırılmış MCP sunucusu yok. MCP sunucuları eklemek için opencode yapılandırma dosyasını düzenleyin.", "settings.agentBehaviour.workflowsPlaceholder": "İş akışları çalışma alanınızdaki iş akışı dosyaları ile yönetilir.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 11fc394f20d..88a52bf9454 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1076,6 +1076,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.title": "移除 MCP 服务器", "settings.agentBehaviour.removeMcp.confirm": '移除 MCP 服务器 "{{name}}" 吗?这将从您的配置中移除它。', "settings.agentBehaviour.removeMcp.button": "移除", + "settings.agentBehaviour.editMcp": "编辑 MCP 服务器", + "settings.agentBehaviour.editMcp.transportLocal": "本地服务器(stdio 传输)", + "settings.agentBehaviour.editMcp.transportRemote": "远程服务器(SSE/HTTP 传输)", + "settings.agentBehaviour.editMcp.env": "环境变量", + "settings.agentBehaviour.editMcp.env.help": "传递给 MCP 服务器进程的变量。", "settings.agentBehaviour.skillPaths": "技能文件夹路径", "settings.agentBehaviour.skillUrls": "技能 URL", "settings.agentBehaviour.removeSkill.title": "移除技能", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index fb6d5882f3d..0381584b053 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1078,6 +1078,11 @@ export const dict = { "settings.agentBehaviour.removeMcp.title": "移除 MCP 伺服器", "settings.agentBehaviour.removeMcp.confirm": '要移除 MCP 伺服器 "{{name}}" 嗎?這將從您的設定中移除它。', "settings.agentBehaviour.removeMcp.button": "移除", + "settings.agentBehaviour.editMcp": "編輯 MCP 伺服器", + "settings.agentBehaviour.editMcp.transportLocal": "本機伺服器(stdio 傳輸)", + "settings.agentBehaviour.editMcp.transportRemote": "遠端伺服器(SSE/HTTP 傳輸)", + "settings.agentBehaviour.editMcp.env": "環境變數", + "settings.agentBehaviour.editMcp.env.help": "傳遞給 MCP 伺服器處理程序的變數。", "settings.agentBehaviour.skillPaths": "Skill 資料夾路徑", "settings.agentBehaviour.skillUrls": "Skill URL", "settings.agentBehaviour.removeSkill.title": "移除技能", From 23cfb5f81018c175ba54af8d3c68f432b67c8632 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 25 Mar 2026 16:40:32 +0100 Subject: [PATCH 060/261] fix(vscode): add missing addMcp i18n keys used by McpEditView The edit view reuses addMcp.command, addMcp.args, and addMcp.url keys from the add flow. These keys must exist in all locale files for the i18n validation tests to pass. --- packages/kilo-vscode/webview-ui/src/i18n/ar.ts | 8 ++++++++ packages/kilo-vscode/webview-ui/src/i18n/br.ts | 8 ++++++++ packages/kilo-vscode/webview-ui/src/i18n/bs.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/da.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/de.ts | 8 ++++++++ packages/kilo-vscode/webview-ui/src/i18n/en.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/es.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/fr.ts | 8 ++++++++ packages/kilo-vscode/webview-ui/src/i18n/ja.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/ko.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/nl.ts | 8 ++++++++ packages/kilo-vscode/webview-ui/src/i18n/no.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/pl.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/ru.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/th.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/tr.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/zh.ts | 7 +++++++ packages/kilo-vscode/webview-ui/src/i18n/zht.ts | 7 +++++++ 18 files changed, 131 insertions(+) diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index baf5c7a758d..e800ee5302d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1091,6 +1091,14 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "خادم بعيد (نقل SSE/HTTP)", "settings.agentBehaviour.editMcp.env": "متغيرات البيئة", "settings.agentBehaviour.editMcp.env.help": "المتغيرات التي يتم تمريرها إلى عملية خادم MCP.", + "settings.agentBehaviour.addMcp.command": "الأمر", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "الوسائط", + "settings.agentBehaviour.addMcp.args.help": + "وسيطة واحدة لكل سطر. يتم الحفاظ على المسارات التي تحتوي على مسافات كما هي.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "عنوان URL للخادم", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "مسارات مجلدات المهارات", "settings.agentBehaviour.skillUrls": "عناوين URL للمهارات", "settings.agentBehaviour.removeSkill.title": "إزالة المهارة", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index ced4b152b9e..a3650bd40db 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1107,6 +1107,14 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Servidor remoto (transporte SSE/HTTP)", "settings.agentBehaviour.editMcp.env": "Variáveis de Ambiente", "settings.agentBehaviour.editMcp.env.help": "Variáveis passadas para o processo do servidor MCP.", + "settings.agentBehaviour.addMcp.command": "Comando", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Argumentos", + "settings.agentBehaviour.addMcp.args.help": + "Um argumento por linha. Caminhos com espaços são preservados como estão.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "URL do Servidor", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "Caminhos de pastas de habilidades", "settings.agentBehaviour.skillUrls": "URLs de habilidades", "settings.agentBehaviour.removeSkill.title": "Remover habilidade", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 40c18bb2462..22c15e12565 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1106,6 +1106,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Udaljeni server (SSE/HTTP transport)", "settings.agentBehaviour.editMcp.env": "Varijable okruženja", "settings.agentBehaviour.editMcp.env.help": "Varijable proslijeđene procesu MCP servera.", + "settings.agentBehaviour.addMcp.command": "Naredba", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Argumenti", + "settings.agentBehaviour.addMcp.args.help": "Jedan argument po liniji. Putanje s razmacima se čuvaju kakve jesu.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "URL servera", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "Putanje mapa vještina", "settings.agentBehaviour.skillUrls": "URL-ovi vještina", "settings.agentBehaviour.removeSkill.title": "Ukloni vještinu", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 51d28865e30..48ffe49a53d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1100,6 +1100,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Fjernserver (SSE/HTTP-transport)", "settings.agentBehaviour.editMcp.env": "Miljøvariabler", "settings.agentBehaviour.editMcp.env.help": "Variabler der sendes til MCP-serverprocessen.", + "settings.agentBehaviour.addMcp.command": "Kommando", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Argumenter", + "settings.agentBehaviour.addMcp.args.help": "Ét argument per linje. Stier med mellemrum bevares som de er.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "Server-URL", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "Skill-mappestier", "settings.agentBehaviour.skillUrls": "Skill-URL'er", "settings.agentBehaviour.removeSkill.title": "Fjern færdighed", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 8ae09437f07..03f505dc312 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1120,6 +1120,14 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Remote-Server (SSE/HTTP-Transport)", "settings.agentBehaviour.editMcp.env": "Umgebungsvariablen", "settings.agentBehaviour.editMcp.env.help": "Variablen, die an den MCP-Serverprozess übergeben werden.", + "settings.agentBehaviour.addMcp.command": "Befehl", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Argumente", + "settings.agentBehaviour.addMcp.args.help": + "Ein Argument pro Zeile. Pfade mit Leerzeichen werden unverändert übernommen.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "Server-URL", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "Skill-Ordnerpfade", "settings.agentBehaviour.skillUrls": "Skill-URLs", "settings.agentBehaviour.removeSkill.title": "Skill entfernen", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 99c7054c32e..4298a288a4f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1088,6 +1088,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Remote server (SSE/HTTP transport)", "settings.agentBehaviour.editMcp.env": "Environment Variables", "settings.agentBehaviour.editMcp.env.help": "Variables passed to the MCP server process.", + "settings.agentBehaviour.addMcp.command": "Command", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Arguments", + "settings.agentBehaviour.addMcp.args.help": "One argument per line. Paths with spaces are preserved as-is.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "Server URL", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.mcpEmpty": "No MCP servers configured. Edit the opencode config file to add MCP servers.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows are managed via workflow files in your workspace.", "settings.agentBehaviour.workflows.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index ec7189b5038..1c36af2b40c 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1111,6 +1111,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Servidor remoto (transporte SSE/HTTP)", "settings.agentBehaviour.editMcp.env": "Variables de entorno", "settings.agentBehaviour.editMcp.env.help": "Variables pasadas al proceso del servidor MCP.", + "settings.agentBehaviour.addMcp.command": "Comando", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Argumentos", + "settings.agentBehaviour.addMcp.args.help": "Un argumento por línea. Las rutas con espacios se conservan tal cual.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "URL del servidor", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "Rutas de carpetas de habilidades", "settings.agentBehaviour.skillUrls": "URLs de habilidades", "settings.agentBehaviour.removeSkill.title": "Eliminar habilidad", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 81d078d75f0..ee037edf8bf 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1124,6 +1124,14 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Serveur distant (transport SSE/HTTP)", "settings.agentBehaviour.editMcp.env": "Variables d'environnement", "settings.agentBehaviour.editMcp.env.help": "Variables transmises au processus du serveur MCP.", + "settings.agentBehaviour.addMcp.command": "Commande", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Arguments", + "settings.agentBehaviour.addMcp.args.help": + "Un argument par ligne. Les chemins avec des espaces sont conservés tels quels.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "URL du serveur", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "Chemins des dossiers de compétences", "settings.agentBehaviour.skillUrls": "URLs de compétences", "settings.agentBehaviour.removeSkill.title": "Supprimer la compétence", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index f8203a818e8..8ea86ca573f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1101,6 +1101,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "リモートサーバー(SSE/HTTP トランスポート)", "settings.agentBehaviour.editMcp.env": "環境変数", "settings.agentBehaviour.editMcp.env.help": "MCPサーバープロセスに渡される変数。", + "settings.agentBehaviour.addMcp.command": "コマンド", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "引数", + "settings.agentBehaviour.addMcp.args.help": "1行に1つの引数。スペースを含むパスはそのまま保持されます。", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "サーバーURL", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "スキルフォルダパス", "settings.agentBehaviour.skillUrls": "スキルURL", "settings.agentBehaviour.removeSkill.title": "スキルを削除", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index e1ada3b1f66..737b6106076 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1095,6 +1095,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "원격 서버 (SSE/HTTP 전송)", "settings.agentBehaviour.editMcp.env": "환경 변수", "settings.agentBehaviour.editMcp.env.help": "MCP 서버 프로세스에 전달되는 변수입니다.", + "settings.agentBehaviour.addMcp.command": "명령어", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "인수", + "settings.agentBehaviour.addMcp.args.help": "한 줄에 하나의 인수. 공백이 포함된 경로는 그대로 유지됩니다.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "서버 URL", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "스킬 폴더 경로", "settings.agentBehaviour.skillUrls": "스킬 URL", "settings.agentBehaviour.removeSkill.title": "스킬 제거", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 16089f170d8..38c75672ff8 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1102,6 +1102,14 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Externe server (SSE/HTTP-transport)", "settings.agentBehaviour.editMcp.env": "Omgevingsvariabelen", "settings.agentBehaviour.editMcp.env.help": "Variabelen die worden doorgegeven aan het MCP-serverproces.", + "settings.agentBehaviour.addMcp.command": "Opdracht", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Argumenten", + "settings.agentBehaviour.addMcp.args.help": + "Eén argument per regel. Paden met spaties worden ongewijzigd overgenomen.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "Server-URL", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.mcpEmpty": "Geen MCP-servers geconfigureerd. Bewerk het opencode configuratiebestand om MCP-servers toe te voegen.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows worden beheerd via workflowbestanden in je workspace.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 5d30d771847..611a2f0632d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1103,6 +1103,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Ekstern server (SSE/HTTP-transport)", "settings.agentBehaviour.editMcp.env": "Miljøvariabler", "settings.agentBehaviour.editMcp.env.help": "Variabler som sendes til MCP-serverprosessen.", + "settings.agentBehaviour.addMcp.command": "Kommando", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Argumenter", + "settings.agentBehaviour.addMcp.args.help": "Ett argument per linje. Stier med mellomrom bevares som de er.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "Server-URL", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "Ferdighetsmappe-stier", "settings.agentBehaviour.skillUrls": "Ferdighets-URLer", "settings.agentBehaviour.removeSkill.title": "Fjern ferdighet", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index d4f3e9ac4c9..210f6a98009 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1105,6 +1105,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Serwer zdalny (transport SSE/HTTP)", "settings.agentBehaviour.editMcp.env": "Zmienne środowiskowe", "settings.agentBehaviour.editMcp.env.help": "Zmienne przekazywane do procesu serwera MCP.", + "settings.agentBehaviour.addMcp.command": "Polecenie", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Argumenty", + "settings.agentBehaviour.addMcp.args.help": "Jeden argument na linię. Ścieżki ze spacjami są zachowywane bez zmian.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "URL serwera", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "Ścieżki folderów umiejętności", "settings.agentBehaviour.skillUrls": "Adresy URL umiejętności", "settings.agentBehaviour.removeSkill.title": "Usuń umiejętność", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 14f27d7f11d..00f12e45506 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1108,6 +1108,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Удалённый сервер (транспорт SSE/HTTP)", "settings.agentBehaviour.editMcp.env": "Переменные окружения", "settings.agentBehaviour.editMcp.env.help": "Переменные, передаваемые процессу сервера MCP.", + "settings.agentBehaviour.addMcp.command": "Команда", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Аргументы", + "settings.agentBehaviour.addMcp.args.help": "Один аргумент на строку. Пути с пробелами сохраняются как есть.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "URL сервера", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "Пути папок навыков", "settings.agentBehaviour.skillUrls": "URL навыков", "settings.agentBehaviour.removeSkill.title": "Удалить навык", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index e8755a307c3..a8f4f7c4546 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1092,6 +1092,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "เซิร์ฟเวอร์ระยะไกล (การขนส่ง SSE/HTTP)", "settings.agentBehaviour.editMcp.env": "ตัวแปรสภาพแวดล้อม", "settings.agentBehaviour.editMcp.env.help": "ตัวแปรที่ส่งไปยังกระบวนการเซิร์ฟเวอร์ MCP", + "settings.agentBehaviour.addMcp.command": "คำสั่ง", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "อาร์กิวเมนต์", + "settings.agentBehaviour.addMcp.args.help": "หนึ่งอาร์กิวเมนต์ต่อบรรทัด เส้นทางที่มีช่องว่างจะถูกเก็บรักษาตามเดิม", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "URL เซิร์ฟเวอร์", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "เส้นทางโฟลเดอร์ทักษะ", "settings.agentBehaviour.skillUrls": "URL ทักษะ", "settings.agentBehaviour.removeSkill.title": "ลบทักษะ", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 1a1abd12bd7..9cfd8a610a3 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1101,6 +1101,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "Uzak sunucu (SSE/HTTP taşıma)", "settings.agentBehaviour.editMcp.env": "Ortam Değişkenleri", "settings.agentBehaviour.editMcp.env.help": "MCP sunucu sürecine aktarılan değişkenler.", + "settings.agentBehaviour.addMcp.command": "Komut", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "Argümanlar", + "settings.agentBehaviour.addMcp.args.help": "Satır başına bir argüman. Boşluklu yollar olduğu gibi korunur.", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "Sunucu URL'si", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.mcpEmpty": "Yapılandırılmış MCP sunucusu yok. MCP sunucuları eklemek için opencode yapılandırma dosyasını düzenleyin.", "settings.agentBehaviour.workflowsPlaceholder": "İş akışları çalışma alanınızdaki iş akışı dosyaları ile yönetilir.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 88a52bf9454..f536ae7e289 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1081,6 +1081,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "远程服务器(SSE/HTTP 传输)", "settings.agentBehaviour.editMcp.env": "环境变量", "settings.agentBehaviour.editMcp.env.help": "传递给 MCP 服务器进程的变量。", + "settings.agentBehaviour.addMcp.command": "命令", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "参数", + "settings.agentBehaviour.addMcp.args.help": "每行一个参数。包含空格的路径将按原样保留。", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "服务器 URL", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "技能文件夹路径", "settings.agentBehaviour.skillUrls": "技能 URL", "settings.agentBehaviour.removeSkill.title": "移除技能", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 0381584b053..4c9b929bde4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1083,6 +1083,13 @@ export const dict = { "settings.agentBehaviour.editMcp.transportRemote": "遠端伺服器(SSE/HTTP 傳輸)", "settings.agentBehaviour.editMcp.env": "環境變數", "settings.agentBehaviour.editMcp.env.help": "傳遞給 MCP 伺服器處理程序的變數。", + "settings.agentBehaviour.addMcp.command": "命令", + "settings.agentBehaviour.addMcp.command.placeholder": "e.g. npx", + "settings.agentBehaviour.addMcp.args": "引數", + "settings.agentBehaviour.addMcp.args.help": "每行一個引數。包含空格的路徑將按原樣保留。", + "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "伺服器 URL", + "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.skillPaths": "Skill 資料夾路徑", "settings.agentBehaviour.skillUrls": "Skill URL", "settings.agentBehaviour.removeSkill.title": "移除技能", From 97ff4dcadf3be0197f8ffe6f4d6a9f0f138d7bb5 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 25 Mar 2026 16:46:24 +0100 Subject: [PATCH 061/261] fix(vscode): use type field for transport detection and hide env for remote servers Use cfg().type instead of inferring transport from the url field, preventing invalid state when clearing a remote URL. Hide the environment variables editor for remote servers since the backend schema does not support environment on remote configs. --- .../src/components/settings/McpEditView.tsx | 112 +++++++++--------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/McpEditView.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/McpEditView.tsx index 7cd30519fa8..634794307a0 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/McpEditView.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/McpEditView.tsx @@ -32,7 +32,7 @@ const McpEditView: Component = (props) => { }) } - const transport = () => (cfg().url ? "remote" : "local") + const transport = () => cfg().type ?? (cfg().url ? "remote" : "local") const cmd = () => { const c = cfg().command @@ -146,66 +146,68 @@ const McpEditView: Component = (props) => { - {/* Environment variables */} - -
- {language.t("settings.agentBehaviour.editMcp.env")} -
-
- {language.t("settings.agentBehaviour.editMcp.env.help")} -
- -
0 ? "1px solid var(--border-weak-base)" : "none", - }} - > -
- setEnvKey(val)} /> + {/* Environment variables (local servers only) */} + + +
+ {language.t("settings.agentBehaviour.editMcp.env")}
-
- setEnvVal(val)} - onKeyDown={(e: KeyboardEvent) => { - if (e.key === "Enter") addEnv() - }} - /> +
+ {language.t("settings.agentBehaviour.editMcp.env.help")}
- -
- - {([key, val], index) => ( -
- 0 ? "1px solid var(--border-weak-base)" : "none", + }} + > +
+ setEnvKey(val)} /> +
+
+ setEnvVal(val)} + onKeyDown={(e: KeyboardEvent) => { + if (e.key === "Enter") addEnv() + }} + /> +
+ +
+ + + {([key, val], index) => ( +
- {key}={val} - - removeEnv(key)} /> -
- )} -
-
+ + {key}={val} + + removeEnv(key)} /> +
+ )} + + +
- - + + 1 ? "s" : ""} changed · +${session.worktreeStats()!.additions} -${session.worktreeStats()!.deletions}` + : "No file changes" + } + placement="top" + class="session-diff-wrapper" + > diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index de6db53320d..28201fa0610 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -154,6 +154,9 @@ interface SessionContextValue { revertedCount: Accessor summary: Accessor + // Live worktree diff stats (polled from CLI backend) + worktreeStats: Accessor<{ files: number; additions: number; deletions: number } | undefined> + // Actions revertSession: (messageID: string) => void unrevertSession: () => void @@ -266,6 +269,11 @@ export const SessionProvider: ParentComponent = (props) => { // Cloud session preview state const [cloudPreviewId, setCloudPreviewId] = createSignal(null) + // Live worktree diff stats from extension polling + const [worktreeStats, setWorktreeStats] = createSignal< + { files: number; additions: number; deletions: number } | undefined + >() + // Tracks optimistic messageIDs that haven't been confirmed by the server yet. // Prevents handleMessagesLoaded from wiping them when it replaces the array. const pendingOptimistic = new Map>() @@ -636,6 +644,10 @@ export const SessionProvider: ParentComponent = (props) => { }) console.error("[Kilo New] Cloud session import failed:", message.error) break + + case "worktreeStatsLoaded": + setWorktreeStats({ files: message.files, additions: message.additions, deletions: message.deletions }) + break } }) @@ -1650,6 +1662,7 @@ export const SessionProvider: ParentComponent = (props) => { revert, revertedCount, summary, + worktreeStats, revertSession, unrevertSession, sendMessage, diff --git a/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx b/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx index 414da2a2ac3..4c0f733837c 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx @@ -176,6 +176,7 @@ export function mockSessionValue(overrides?: { revert: () => undefined, revertedCount: () => 0, summary: () => undefined, + worktreeStats: () => undefined, revertSession: noop, unrevertSession: noop, variantList: () => [], diff --git a/packages/kilo-vscode/webview-ui/src/styles/chat.css b/packages/kilo-vscode/webview-ui/src/styles/chat.css index 46ee20a7d8e..00f13417060 100644 --- a/packages/kilo-vscode/webview-ui/src/styles/chat.css +++ b/packages/kilo-vscode/webview-ui/src/styles/chat.css @@ -174,21 +174,23 @@ /* New Task Button */ .new-task-button-wrapper { padding: 8px 12px 0; + container-type: inline-size; } .session-actions-row { display: flex; - flex-wrap: wrap; gap: 4px; align-items: center; } +/* All direct children share extra space equally, but start from their content size */ .session-actions-row > * { - flex: 1 1 0; - min-width: fit-content; + flex: 1 1 auto; + min-width: 0; + overflow: hidden; } -/* Tooltip wrapper divs must fill their flex space, and buttons inside must fill the wrapper */ +/* Tooltip wrappers fill their flex slot, buttons fill the tooltip wrapper */ .session-actions-row > [data-component="tooltip-trigger"] { display: flex; } @@ -197,15 +199,15 @@ flex: 1; } -/* Diff stats tooltip wrapper — don't grow, push right */ +/* Diff wrapper also stretches evenly (same flex as buttons) */ .session-diff-wrapper { - flex: 0 0 auto !important; - margin-left: auto; + display: flex !important; } -/* Diff stats badge — matches Agent Manager diff toggle style */ +/* Diff stats badge — fills its flex slot, content centered */ .session-diff-badge { - display: inline-flex; + display: flex; + flex: 1; align-items: center; justify-content: center; gap: 4px; @@ -219,6 +221,11 @@ font-variant-numeric: tabular-nums; cursor: pointer; white-space: nowrap; + position: relative; +} + +.session-diff-badge--empty { + opacity: 0.5; } .session-diff-badge:hover { @@ -227,10 +234,8 @@ .session-diff-badge [data-component="icon"] { opacity: 0.7; -} - -.session-diff-files { - color: var(--vscode-descriptionForeground); + position: relative; + flex-shrink: 0; } .session-diff-add { @@ -241,6 +246,31 @@ color: #f87171; } +/* Collapse diff stats to icon-only when truly narrow */ +@container (max-width: 300px) { + .session-diff-add, + .session-diff-del { + display: none; + } + + .session-diff-badge { + padding: 4px 6px; + overflow: hidden; + } + + /* Dot indicator on the icon when collapsed and there are changes */ + .session-diff-badge--has-changes [data-component="icon"]::after { + content: ""; + position: absolute; + top: -2px; + right: -2px; + width: 6px; + height: 6px; + border-radius: 50%; + background: #34d399; + } +} + /* ============================================ Message List ============================================ */ diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index e5c7a7d96a5..a7cbe68be1b 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -963,6 +963,14 @@ export interface AgentManagerLocalStatsMessage { stats: LocalGitStats } +// Sidebar: Live worktree diff stats (extension → webview) +export interface WorktreeStatsLoadedMessage { + type: "worktreeStatsLoaded" + files: number + additions: number + deletions: number +} + // Set the model for a session (extension → webview, used during multi-version creation) export interface AgentManagerSetSessionModelMessage { type: "agentManager.setSessionModel" @@ -1294,6 +1302,7 @@ export type ExtensionMessage = | RecentsLoadedMessage | LanguageChangedMessage | ContinueInWorktreeProgressMessage + | WorktreeStatsLoadedMessage // ============================================ // Messages FROM webview TO extension From 9cf83d812206e1f7a3b520a2722244b5622c9c1f Mon Sep 17 00:00:00 2001 From: Marius Date: Fri, 27 Mar 2026 17:19:30 +0100 Subject: [PATCH 103/261] fix(cli): make FreeUsageLimitError non-retryable to prevent unrecoverable backoff loop (#7809) * fix(cli): make FreeUsageLimitError non-retryable to prevent unrecoverable backoff loop When a free model hits its usage cap, the retry loop would endlessly retry with the same stale model reference. Switching models in the chat selector could not break the loop because the processor captures the model once at creation time. Making FreeUsageLimitError non-retryable surfaces the error immediately so users can switch models and continue. * chore(kilo-docs): update source links after removing FreeUsageLimitError URL --- packages/kilo-docs/source-links.md | 1 - packages/opencode/src/session/retry.ts | 7 +++++-- packages/opencode/test/session/retry.test.ts | 10 ++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/kilo-docs/source-links.md b/packages/kilo-docs/source-links.md index 0ff621242af..14b4571bff8 100644 --- a/packages/kilo-docs/source-links.md +++ b/packages/kilo-docs/source-links.md @@ -7,7 +7,6 @@ - - - - diff --git a/packages/opencode/src/session/retry.ts b/packages/opencode/src/session/retry.ts index 7eb8d2fa71f..ec27107d917 100644 --- a/packages/opencode/src/session/retry.ts +++ b/packages/opencode/src/session/retry.ts @@ -67,8 +67,11 @@ export namespace SessionRetry { if (isKiloError(error)) return undefined // kilocode_change end if (!error.data.isRetryable) return undefined - if (error.data.responseBody?.includes("FreeUsageLimitError")) - return `Free usage exceeded, add credits https://app.kilo.ai` // kilocode_change + // kilocode_change start - FreeUsageLimitError is not retryable: retrying the same + // capped model is futile and the backoff loop cannot be broken by switching + // models in the chat selector (the retry loop holds a stale model ref). + if (error.data.responseBody?.includes("FreeUsageLimitError")) return undefined + // kilocode_change end return error.data.message.includes("Overloaded") ? "Provider is overloaded" : error.data.message } diff --git a/packages/opencode/test/session/retry.test.ts b/packages/opencode/test/session/retry.test.ts index eba4a995053..551065fdd73 100644 --- a/packages/opencode/test/session/retry.test.ts +++ b/packages/opencode/test/session/retry.test.ts @@ -122,6 +122,16 @@ describe("session.retry.retryable", () => { expect(SessionRetry.retryable(error)).toBeUndefined() }) + + test("does not retry FreeUsageLimitError", () => { + const error = new MessageV2.APIError({ + message: "rate limit exceeded", + isRetryable: true, + responseBody: '{"error":{"code":"FreeUsageLimitError"}}', + }).toObject() as ReturnType + + expect(SessionRetry.retryable(error)).toBeUndefined() + }) }) describe("session.message-v2.fromError", () => { From 8102d801b9a3143783800e44f2fdcd48a022ce20 Mon Sep 17 00:00:00 2001 From: Marius Date: Fri, 27 Mar 2026 17:19:31 +0100 Subject: [PATCH 104/261] fix(cli): gate Kilo API calls behind enabled_providers to prevent data leaks (#7813) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skip Kilo provider injection, fetchDefaultModel, and ACP fallback when enabled_providers is set and doesn't include kilo. Teams using only their own models (e.g. LiteLLM) no longer make any external calls to api.kilo.ai. New users without config are unaffected — Kilo free still works by default. --- packages/opencode/src/acp/agent.ts | 12 ++++++++++-- packages/opencode/src/provider/models.ts | 11 +++++++++-- packages/opencode/src/server/routes/config.ts | 14 ++++++++++---- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index 59ecfcc6dbe..ac103a7ecfb 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -1592,8 +1592,16 @@ export namespace ACP { if (specified) return specified // kilocode_change start - const freeModel = await fetchDefaultModel() - return { providerID: "kilo", modelID: freeModel } + // Only fall back to the Kilo provider if it was present in the available + // providers list. When teams configure enabled_providers to use only their + // own models, this prevents silently routing requests to an external API. + // Note: LiteLLM / custom provider users won't reach here — the function + // returns earlier via `specified` (config.model) or the sorted providers list. + if (providers.some((p) => p.id === "kilo")) { + const freeModel = await fetchDefaultModel() + return { providerID: "kilo", modelID: freeModel } + } + throw new Error("no model available: no providers are configured and no default model is set") // kilocode_change end } diff --git a/packages/opencode/src/provider/models.ts b/packages/opencode/src/provider/models.ts index 86d5178f8d5..ceb7db4b7e6 100644 --- a/packages/opencode/src/provider/models.ts +++ b/packages/opencode/src/provider/models.ts @@ -139,8 +139,15 @@ export namespace ModelsDev { } // Inject kilo provider with dynamic model fetching - if (!providers["kilo"]) { - const config = await Config.get() + // Skip injection entirely when enabled_providers is set and doesn't include "kilo", + // or when "kilo" is in disabled_providers. This prevents unnecessary network calls + // to the Kilo API for teams using only their own providers (e.g. LiteLLM). + const config = await Config.get() + const disabled = new Set(config.disabled_providers ?? []) + const enabled = config.enabled_providers ? new Set(config.enabled_providers) : null + const kiloAllowed = (!enabled || enabled.has("kilo")) && !disabled.has("kilo") + + if (kiloAllowed && !providers["kilo"]) { const kiloOptions = config.provider?.kilo?.options // kilocode_change start - resolve org ID from auth (OAuth accountId) not just config const kiloAuth = await Auth.get("kilo") diff --git a/packages/opencode/src/server/routes/config.ts b/packages/opencode/src/server/routes/config.ts index e6ac26bb0dc..f9ac7e42976 100644 --- a/packages/opencode/src/server/routes/config.ts +++ b/packages/opencode/src/server/routes/config.ts @@ -89,10 +89,16 @@ export const ConfigRoutes = lazy(() => const providers = await Provider.list() // kilocode_change start - Fetch default model from Kilo API - const kiloAuth = await Auth.get("kilo") - const token = kiloAuth?.type === "oauth" ? kiloAuth.access : kiloAuth?.key - const organizationId = kiloAuth?.type === "oauth" ? kiloAuth.accountId : undefined - const kiloApiDefault = await fetchDefaultModel(token, organizationId) + // Only call the Kilo API when the kilo provider is actually available. + // This prevents unnecessary network calls for teams using only their + // own providers (e.g. LiteLLM) via enabled_providers config. + let kiloApiDefault: string | undefined + if (providers["kilo"]) { + const kiloAuth = await Auth.get("kilo") + const token = kiloAuth?.type === "oauth" ? kiloAuth.access : kiloAuth?.key + const organizationId = kiloAuth?.type === "oauth" ? kiloAuth.accountId : undefined + kiloApiDefault = await fetchDefaultModel(token, organizationId) + } // kilocode_change end // kilocode_change start - Use API default for Kilo provider if valid From b38aeccfa01c01921015520e4709634a43516950 Mon Sep 17 00:00:00 2001 From: Marius Date: Fri, 27 Mar 2026 17:19:58 +0100 Subject: [PATCH 105/261] feat(vscode): auto-detect models for custom OpenAI-compatible providers (#7793) * feat(vscode): auto-detect models for custom OpenAI-compatible providers Add model auto-fetching to the custom provider dialog. When a user enters a base URL and API key, available models are fetched from the server's /v1/models endpoint with a debounced request. Models are presented in a searchable selection picker with fuzzy matching, letting users choose which to register. Also adds an Edit button for existing custom providers and i18n translations for all 18 supported languages. Closes #7759 * fix(vscode): preserve auth on edit, ignore stale fetch responses Address review feedback: - Preserve existing env vars when editing a custom provider without changing the API key (prevents silent credential stripping) - Use version counter to discard stale fetch responses when the user changes inputs while a request is in-flight --- packages/kilo-vscode/src/KiloProvider.ts | 22 + .../kilo-vscode/src/shared/fetch-models.ts | 66 +++ .../settings/CustomProviderDialog.tsx | 412 +++++++++++++++++- .../src/components/settings/ProvidersTab.tsx | 26 +- .../kilo-vscode/webview-ui/src/i18n/ar.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/br.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/bs.ts | 15 + .../kilo-vscode/webview-ui/src/i18n/da.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/de.ts | 15 + .../kilo-vscode/webview-ui/src/i18n/en.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/es.ts | 15 + .../kilo-vscode/webview-ui/src/i18n/fr.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/ja.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/ko.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/nl.ts | 15 + .../kilo-vscode/webview-ui/src/i18n/no.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/pl.ts | 15 + .../kilo-vscode/webview-ui/src/i18n/ru.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/th.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/tr.ts | 15 + .../kilo-vscode/webview-ui/src/i18n/zh.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/zht.ts | 14 + .../webview-ui/src/types/messages.ts | 19 + 23 files changed, 779 insertions(+), 24 deletions(-) create mode 100644 packages/kilo-vscode/src/shared/fetch-models.ts diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index 862ee71f559..e917b82ebc5 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -80,6 +80,7 @@ import { disconnectProvider as disconnectProviderAction, saveCustomProvider as saveCustomProviderAction, } from "./provider-actions" +import { fetchOpenAIModels, FetchModelsError } from "./shared/fetch-models" type KiloProviderOptions = { projectDirectory?: string | null @@ -613,6 +614,11 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper case "saveCustomProvider": await this.handleProviderAction(message) break + case "fetchCustomProviderModels": + this.handleFetchCustomProviderModels(message).catch((e) => + console.error("[Kilo New] fetchCustomProviderModels failed:", e), + ) + break case "compact": await this.handleCompact(message.sessionID, message.providerID, message.modelID) break @@ -1439,6 +1445,22 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper return saveCustomProviderAction(ctx, rid, pid, config, key, this.cachedConfigMessage, set) } + private async handleFetchCustomProviderModels(msg: Record): Promise { + const rid = typeof msg.requestId === "string" ? msg.requestId : "" + const url = typeof msg.baseURL === "string" ? msg.baseURL : "" + if (!rid || !url) return + const key = typeof msg.apiKey === "string" ? msg.apiKey : undefined + const headers = msg.headers && typeof msg.headers === "object" ? (msg.headers as Record) : undefined + try { + const models = await fetchOpenAIModels({ baseURL: url, apiKey: key, headers }) + this.postMessage({ type: "customProviderModelsFetched", requestId: rid, models }) + } catch (err: unknown) { + const message = err instanceof Error ? err.message : "Failed to fetch models" + const auth = err instanceof FetchModelsError && err.auth + this.postMessage({ type: "customProviderModelsFetched", requestId: rid, error: message, auth }) + } + } + /** * Fetch agents (modes) from the backend and send to webview. */ diff --git a/packages/kilo-vscode/src/shared/fetch-models.ts b/packages/kilo-vscode/src/shared/fetch-models.ts new file mode 100644 index 00000000000..c8ae62260e9 --- /dev/null +++ b/packages/kilo-vscode/src/shared/fetch-models.ts @@ -0,0 +1,66 @@ +/** + * Fetch available models from an OpenAI-compatible /models endpoint. + * Runs in the extension host — no CLI backend dependency. + */ + +type Options = { + baseURL: string + apiKey?: string + headers?: Record +} + +type ModelEntry = { + id: string + name: string +} + +export class FetchModelsError extends Error { + constructor( + message: string, + public readonly status?: number, + ) { + super(message) + this.name = "FetchModelsError" + } + + get auth() { + return this.status === 401 || this.status === 403 + } +} + +export async function fetchOpenAIModels(opts: Options): Promise { + const url = opts.baseURL.replace(/\/+$/, "") + "/models" + const headers: Record = { + "Content-Type": "application/json", + ...opts.headers, + } + if (opts.apiKey) { + headers["Authorization"] = `Bearer ${opts.apiKey}` + } + + const response = await fetch(url, { + method: "GET", + headers, + signal: AbortSignal.timeout(15_000), + }) + + if (!response.ok) { + const text = await response.text().catch(() => "") + throw new FetchModelsError(`HTTP ${response.status}: ${text.slice(0, 200)}`, response.status) + } + + const body = (await response.json()) as { data?: Array<{ id?: string; name?: string }> } + const items = body?.data + if (!Array.isArray(items)) return [] + + const seen = new Set() + const result: ModelEntry[] = [] + for (const item of items) { + const id = typeof item.id === "string" ? item.id.trim() : "" + if (!id || seen.has(id)) continue + seen.add(id) + result.push({ id, name: typeof item.name === "string" ? item.name.trim() : id }) + } + result.sort((a, b) => a.id.localeCompare(b.id)) + return result +} diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/CustomProviderDialog.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/CustomProviderDialog.tsx index a1debefb010..6add99ed13f 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/CustomProviderDialog.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/CustomProviderDialog.tsx @@ -3,18 +3,33 @@ import { useDialog } from "@kilocode/kilo-ui/context/dialog" import { Dialog } from "@kilocode/kilo-ui/dialog" import { IconButton } from "@kilocode/kilo-ui/icon-button" import { ProviderIcon } from "@kilocode/kilo-ui/provider-icon" +import { Spinner } from "@kilocode/kilo-ui/spinner" import { TextField } from "@kilocode/kilo-ui/text-field" import { showToast } from "@kilocode/kilo-ui/toast" -import { For, onCleanup } from "solid-js" +import { For, Show, createEffect, createMemo, createSignal, onCleanup } from "solid-js" import { createStore } from "solid-js/store" import { useConfig } from "../../context/config" import { useLanguage } from "../../context/language" import { useProvider } from "../../context/provider" import { useVSCode } from "../../context/vscode" +import type { ExtensionMessage, ProviderConfig } from "../../types/messages" import { createProviderAction } from "../../utils/provider-action" const PROVIDER_ID = /^[a-z0-9][a-z0-9-_]*$/ const OPENAI_COMPATIBLE = "@ai-sdk/openai-compatible" +const DEBOUNCE_MS = 500 +const SEARCH_DEBOUNCE_MS = 150 + +/** Subsequence fuzzy match — "gpt4o" matches "gpt-4o-mini". */ +function fuzzy(query: string, target: string) { + const q = query.toLowerCase() + const t = target.toLowerCase() + let qi = 0 + for (let ti = 0; ti < t.length && qi < q.length; ti++) { + if (t[ti] === q[qi]) qi++ + } + return qi === q.length +} type Translator = ReturnType["t"] @@ -46,11 +61,16 @@ type FormErrors = { headers: Array<{ key?: string; value?: string }> } +type FetchedModel = { id: string; name: string } + type ValidateArgs = { form: FormState t: Translator + editing: boolean disabledProviders: string[] existingProviderIDs: Set + /** Preserved env vars from the existing provider config (edit mode only) */ + existingEnv?: string[] } function validateCustomProvider(input: ValidateArgs) { @@ -60,6 +80,8 @@ function validateCustomProvider(input: ValidateArgs) { const apiKey = input.form.apiKey.trim() const env = apiKey.match(/^\{env:([^}]+)\}$/)?.[1]?.trim() + // When editing and apiKey is empty, preserve existing env from the original config + const existingEnv = input.editing && !apiKey ? input.existingEnv : undefined const key = apiKey && !env ? apiKey : undefined const idError = !providerID @@ -78,9 +100,11 @@ function validateCustomProvider(input: ValidateArgs) { const disabled = input.disabledProviders.includes(providerID) const existsError = idError ? undefined - : input.existingProviderIDs.has(providerID) && !disabled - ? input.t("provider.custom.error.providerID.exists") - : undefined + : input.editing + ? undefined + : input.existingProviderIDs.has(providerID) && !disabled + ? input.t("provider.custom.error.providerID.exists") + : undefined const seenModels = new Set() const modelErrors = input.form.models.map((m) => { @@ -149,7 +173,7 @@ function validateCustomProvider(input: ValidateArgs) { config: { npm: OPENAI_COMPATIBLE, name, - ...(env ? { env: [env] } : {}), + ...(env ? { env: [env] } : existingEnv ? { env: existingEnv } : {}), options, models, }, @@ -157,8 +181,14 @@ function validateCustomProvider(input: ValidateArgs) { } } -interface CustomProviderDialogProps { +export interface CustomProviderDialogProps { onBack?: () => void + /** When set, the dialog opens in edit mode with pre-filled values. */ + existing?: { + providerID: string + name: string + config: ProviderConfig + } } const CustomProviderDialog = (props: CustomProviderDialogProps) => { @@ -170,13 +200,32 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { const action = createProviderAction(vscode) onCleanup(action.dispose) + const editing = () => !!props.existing + + function initModels(): ModelRow[] { + const cfg = props.existing?.config + if (!cfg?.models || typeof cfg.models !== "object") return [{ id: "", name: "" }] + const entries = Object.entries(cfg.models) + if (entries.length === 0) return [{ id: "", name: "" }] + return entries.map(([id, m]) => ({ id, name: (m as { name?: string })?.name ?? id })) + } + + function initHeaders(): HeaderRow[] { + const opts = props.existing?.config?.options as { headers?: Record } | undefined + const headers = opts?.headers + if (!headers || typeof headers !== "object") return [{ key: "", value: "" }] + const entries = Object.entries(headers) + if (entries.length === 0) return [{ key: "", value: "" }] + return entries.map(([key, value]) => ({ key, value })) + } + const [form, setForm] = createStore({ - providerID: "", - name: "", - baseURL: "", + providerID: props.existing?.providerID ?? "", + name: props.existing?.name ?? "", + baseURL: (props.existing?.config?.options as { baseURL?: string } | undefined)?.baseURL ?? "", apiKey: "", - models: [{ id: "", name: "" }], - headers: [{ key: "", value: "" }], + models: initModels(), + headers: initHeaders(), saving: false, }) @@ -184,10 +233,193 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { providerID: undefined, name: undefined, baseURL: undefined, - models: [{}], - headers: [{}], + models: form.models.map(() => ({})), + headers: form.headers.map(() => ({})), }) + // ── Fetch models state ────────────────────────────────────────────── + + const [fetching, setFetching] = createSignal(false) + const [fetchError, setFetchError] = createSignal() + const [fetchedModels, setFetchedModels] = createSignal() + const [selected, setSelected] = createSignal>(new Set()) + const [fetchStatus, setFetchStatus] = createSignal() + + // Search within fetched models + const [search, setSearch] = createSignal("") + const [debouncedSearch, setDebouncedSearch] = createSignal("") + + createEffect(() => { + const q = search() + const timer = setTimeout(() => setDebouncedSearch(q), SEARCH_DEBOUNCE_MS) + onCleanup(() => clearTimeout(timer)) + }) + + const filtered = createMemo(() => { + const models = fetchedModels() + if (!models) return [] + const q = debouncedSearch() + if (!q) return models + return models.filter((m) => fuzzy(q, m.id) || fuzzy(q, m.name)) + }) + + // ── Auto-fetch on debounce ────────────────────────────────────────── + + // Dedicated signals for the URL and API key drive the auto-fetch effect. + // We avoid reading form.baseURL / form.apiKey inside createEffect because + // SolidJS store proxies track at the property level — any store write + // (including setForm("models", ...)) invalidates effects that read from + // the same store, causing unwanted re-runs that wipe the model picker. + const [fetchURL, setFetchURL] = createSignal(form.baseURL) + const [fetchKey, setFetchKey] = createSignal(form.apiKey) + let fetchVersion = 0 + + createEffect(() => { + const url = fetchURL() + const key = fetchKey() + void key // subscribe to key changes without using the value here + + // Clear previous results whenever URL or key changes + setFetchedModels(undefined) + setFetchError(undefined) + setFetchStatus(undefined) + setSearch("") + + if (!/^https?:\/\//.test(url.trim())) return + + fetchVersion++ + const version = fetchVersion + const timer = setTimeout(() => { + if (version === fetchVersion) doFetch() + }, DEBOUNCE_MS) + onCleanup(() => clearTimeout(timer)) + }) + + // ── Core fetch logic ──────────────────────────────────────────────── + + function doFetch() { + // Snapshot all values from signals/store before entering async. + // This avoids reading the store proxy inside callbacks, which could + // subscribe to unrelated store properties and cause re-render loops. + const url = fetchURL().trim() + const raw = fetchKey().trim() + const env = raw.match(/^\{env:([^}]+)\}$/)?.[1]?.trim() + const apiKey = raw && !env ? raw : undefined + const existing = new Set(form.models.map((m) => m.id.trim()).filter(Boolean)) + + const hdrs = form.headers + .map((h) => ({ key: h.key.trim(), value: h.value.trim() })) + .filter((h) => !!h.key && !!h.value) + const headers = hdrs.length > 0 ? Object.fromEntries(hdrs.map((h) => [h.key, h.value])) : undefined + + // Bump version so any in-flight response from a previous fetch is ignored + fetchVersion++ + const version = fetchVersion + + setFetching(true) + setFetchError(undefined) + setFetchedModels(undefined) + setFetchStatus(undefined) + setSearch("") + + const rid = crypto.randomUUID() + + const unsub = vscode.onMessage((msg: ExtensionMessage) => { + if (msg.type !== "customProviderModelsFetched") return + if (!("requestId" in msg) || msg.requestId !== rid) return + unsub() + + // Stale response — a newer fetch was triggered while this one was in-flight + if (version !== fetchVersion) return + + setFetching(false) + + if (msg.error) { + setFetchError(msg.auth ? language.t("provider.custom.models.fetch.authError") : msg.error) + return + } + + const models = msg.models ?? [] + if (models.length === 0) { + setFetchError(language.t("provider.custom.models.fetch.empty")) + return + } + + // Filter using the snapshot taken at fetch time + const fresh = models.filter((m) => !existing.has(m.id)) + + if (fresh.length === 0) { + setFetchStatus(language.t("provider.custom.models.fetch.allExist")) + return + } + + // Pre-select all and show the picker + setSelected(new Set(fresh.map((m) => m.id))) + setFetchedModels(fresh) + }) + + vscode.postMessage({ + type: "fetchCustomProviderModels", + requestId: rid, + baseURL: url, + apiKey, + headers, + }) + } + + // ── Model picker actions ──────────────────────────────────────────── + + function toggleModel(id: string) { + const next = new Set(selected()) + if (next.has(id)) next.delete(id) + else next.add(id) + setSelected(next) + } + + function selectAll() { + const next = new Set(selected()) + for (const m of filtered()) next.add(m.id) + setSelected(next) + } + + function deselectAll() { + const next = new Set(selected()) + for (const m of filtered()) next.delete(m.id) + setSelected(next) + } + + function count() { + return selected().size + } + + function addSelected() { + const models = fetchedModels() + if (!models) return + const sel = selected() + const picked = models.filter((m) => sel.has(m.id)) + if (picked.length === 0) return + + // Replace the single empty row or append + const empty = form.models.length === 1 && !form.models[0].id.trim() && !form.models[0].name.trim() + const merged = empty ? picked : [...form.models, ...picked] + + setForm("models", merged) + setErrors( + "models", + merged.map(() => ({})), + ) + setFetchStatus(language.t("provider.custom.models.fetch.added", { count: String(picked.length) })) + setFetchedModels(undefined) + setSearch("") + } + + function cancelFetch() { + setFetchedModels(undefined) + setSearch("") + } + + // ── Form helpers ──────────────────────────────────────────────────── + function goBack() { if (props.onBack) { props.onBack() @@ -222,8 +454,10 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { const output = validateCustomProvider({ form, t: language.t, + editing: editing(), disabledProviders: config().disabled_providers ?? [], existingProviderIDs: new Set(Object.keys(provider.providers())), + existingEnv: props.existing?.config?.env, }) setErrors(output.errors) return output.result @@ -264,6 +498,8 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { ) } + // ── Render ────────────────────────────────────────────────────────── + return ( {
- {language.t("provider.custom.title")} + {editing() ? language.t("provider.custom.edit.title") : language.t("provider.custom.title")}
@@ -317,7 +553,7 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => {
{ onChange={(v) => setForm("providerID", v)} validationState={errors.providerID ? "invalid" : undefined} error={errors.providerID} + disabled={editing()} /> { label={language.t("provider.custom.field.baseURL.label")} placeholder={language.t("provider.custom.field.baseURL.placeholder")} value={form.baseURL} - onChange={(v) => setForm("baseURL", v)} + onChange={(v) => { + setForm("baseURL", v) + setFetchURL(v) + }} validationState={errors.baseURL ? "invalid" : undefined} error={errors.baseURL} /> @@ -348,15 +588,23 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { placeholder={language.t("provider.custom.field.apiKey.placeholder")} description={language.t("provider.custom.field.apiKey.description")} value={form.apiKey} - onChange={(v) => setForm("apiKey", v)} + onChange={(v) => { + setForm("apiKey", v) + setFetchKey(v) + }} />
{/* Models */}
- +
+ + + + +
{(m, i) => (
@@ -397,6 +645,130 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { + + {/* Fetch error */} + + {(err) => ( + {err()} + )} + + + {/* Fetch status (success/info messages) */} + + {(status) => ( + + {status()} + + )} + + + {/* Model selection picker */} + + {(models) => ( +
+ {/* Header with count + toggle */} +
+ + + {language.t("provider.custom.models.fetch.showing", { + shown: String(filtered().length), + total: String(models().length), + })} + + +
+ + +
+
+ + {/* Search */} + 10}> + + + + {/* Model list */} +
+ + {(m) => ( + + )} + +
+ + {/* Actions */} +
+ + +
+
+ )} +
{/* Headers */} diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/ProvidersTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/ProvidersTab.tsx index 4f4408b7735..53738608898 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/ProvidersTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/ProvidersTab.tsx @@ -17,7 +17,7 @@ import ProviderConnectDialog from "./ProviderConnectDialog" import ProviderSelectDialog from "./ProviderSelectDialog" import { CUSTOM_PROVIDER_ID, isPopularProvider, providerIcon, providerNoteKey, sortProviders } from "./provider-catalog" import { visibleConnectedIds } from "./provider-visibility" -import { KILO_PROVIDER_ID } from "../../../../src/shared/provider-model" +import { KILO_PROVIDER_ID, CUSTOM_PROVIDER_PACKAGE } from "../../../../src/shared/provider-model" import { createProviderAction } from "../../utils/provider-action" type ProviderSource = "env" | "api" | "config" | "custom" @@ -83,6 +83,17 @@ const ProvidersTab: Component = () => { return source(item) !== "env" } + function isCustom(item: Provider) { + const cfg = config().provider?.[item.id] + return cfg?.npm === CUSTOM_PROVIDER_PACKAGE + } + + function editProvider(item: Provider) { + const cfg = config().provider?.[item.id] + if (!cfg) return + dialog.show(() => ) + } + function disconnect(providerID: string, name: string) { action.send( { type: "disconnectProvider", providerID }, @@ -203,9 +214,16 @@ const ProvidersTab: Component = () => { } > - +
+ + + + +
)} diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index 4d54c199f78..b727ed6ae26 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -745,6 +745,20 @@ export const dict = { "provider.custom.models.name.placeholder": "الاسم المعروض", "provider.custom.models.remove": "إزالة النموذج", "provider.custom.models.add": "إضافة نموذج", + "provider.custom.models.fetch": "جلب النماذج", + "provider.custom.models.fetching": "جارٍ الجلب\u2026", + "provider.custom.models.fetch.error": "فشل جلب النماذج: {{error}}", + "provider.custom.models.fetch.authError": "فشلت المصادقة. تحقق من مفتاح API أعلاه وحاول مرة أخرى.", + "provider.custom.models.fetch.empty": "لم يتم العثور على نماذج على هذا الخادم.", + "provider.custom.models.fetch.added": "تمت إضافة {{count}} نموذج(نماذج).", + "provider.custom.models.fetch.allExist": "جميع النماذج المجلوبة مضافة بالفعل.", + "provider.custom.models.fetch.selectAll": "تحديد الكل", + "provider.custom.models.fetch.deselectAll": "إلغاء تحديد الكل", + "provider.custom.models.fetch.found": "تم العثور على {{count}} نموذج", + "provider.custom.models.fetch.showing": "عرض {{shown}} من {{total}}", + "provider.custom.models.fetch.search": "البحث في النماذج\u2026", + "provider.custom.models.fetch.add": "إضافة {{count}} نموذج(نماذج)", + "provider.custom.edit.title": "تعديل المزود", "provider.custom.headers.label": "الرؤوس (اختياري)", "provider.custom.headers.key.label": "الرأس", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 4fe778df499..719a3314cba 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -752,6 +752,20 @@ export const dict = { "provider.custom.models.name.placeholder": "Nome de Exibição", "provider.custom.models.remove": "Remover modelo", "provider.custom.models.add": "Adicionar modelo", + "provider.custom.models.fetch": "Buscar modelos", + "provider.custom.models.fetching": "Buscando\u2026", + "provider.custom.models.fetch.error": "Falha ao buscar modelos: {{error}}", + "provider.custom.models.fetch.authError": "Falha na autenticação. Verifique a chave de API acima e tente novamente.", + "provider.custom.models.fetch.empty": "Nenhum modelo encontrado neste servidor.", + "provider.custom.models.fetch.added": "{{count}} modelo(s) adicionado(s).", + "provider.custom.models.fetch.allExist": "Todos os modelos buscados já foram adicionados.", + "provider.custom.models.fetch.selectAll": "Selecionar todos", + "provider.custom.models.fetch.deselectAll": "Desmarcar todos", + "provider.custom.models.fetch.found": "{{count}} modelos encontrados", + "provider.custom.models.fetch.showing": "Mostrando {{shown}} de {{total}}", + "provider.custom.models.fetch.search": "Pesquisar modelos\u2026", + "provider.custom.models.fetch.add": "Adicionar {{count}} modelo(s)", + "provider.custom.edit.title": "Editar provedor", "provider.custom.headers.label": "Headers (opcional)", "provider.custom.headers.key.label": "Header", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 614c9d82a7c..451dd808444 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -757,6 +757,21 @@ export const dict = { "provider.custom.models.name.placeholder": "Naziv za prikaz", "provider.custom.models.remove": "Ukloni model", "provider.custom.models.add": "Dodaj model", + "provider.custom.models.fetch": "Preuzmi modele", + "provider.custom.models.fetching": "Preuzimanje\u2026", + "provider.custom.models.fetch.error": "Preuzimanje modela nije uspjelo: {{error}}", + "provider.custom.models.fetch.authError": + "Autentifikacija nije uspjela. Provjerite API ključ iznad i pokušajte ponovo.", + "provider.custom.models.fetch.empty": "Nisu pronađeni modeli na ovom serveru.", + "provider.custom.models.fetch.added": "Dodano {{count}} model(a).", + "provider.custom.models.fetch.allExist": "Svi preuzeti modeli su već dodani.", + "provider.custom.models.fetch.selectAll": "Odaberi sve", + "provider.custom.models.fetch.deselectAll": "Poništi odabir", + "provider.custom.models.fetch.found": "{{count}} modela pronađeno", + "provider.custom.models.fetch.showing": "Prikazano {{shown}} od {{total}}", + "provider.custom.models.fetch.search": "Pretraži modele\u2026", + "provider.custom.models.fetch.add": "Dodaj {{count}} model(a)", + "provider.custom.edit.title": "Uredi provajdera", "provider.custom.headers.label": "Zaglavlja (opcionalno)", "provider.custom.headers.key.label": "Zaglavlje", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 8aad7f48136..3f148b55c83 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -751,6 +751,20 @@ export const dict = { "provider.custom.models.name.placeholder": "Visningsnavn", "provider.custom.models.remove": "Fjern model", "provider.custom.models.add": "Tilføj model", + "provider.custom.models.fetch": "Hent modeller", + "provider.custom.models.fetching": "Henter\u2026", + "provider.custom.models.fetch.error": "Kunne ikke hente modeller: {{error}}", + "provider.custom.models.fetch.authError": "Godkendelse mislykkedes. Kontrollér API-nøglen ovenfor, og prøv igen.", + "provider.custom.models.fetch.empty": "Ingen modeller fundet på denne server.", + "provider.custom.models.fetch.added": "{{count}} model(ler) tilføjet.", + "provider.custom.models.fetch.allExist": "Alle hentede modeller er allerede tilføjet.", + "provider.custom.models.fetch.selectAll": "Vælg alle", + "provider.custom.models.fetch.deselectAll": "Fravælg alle", + "provider.custom.models.fetch.found": "{{count}} modeller fundet", + "provider.custom.models.fetch.showing": "Viser {{shown}} af {{total}}", + "provider.custom.models.fetch.search": "Søg modeller\u2026", + "provider.custom.models.fetch.add": "Tilføj {{count}} model(ler)", + "provider.custom.edit.title": "Rediger udbyder", "provider.custom.headers.label": "Headers (valgfrit)", "provider.custom.headers.key.label": "Header", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index ea76b3fe41d..e5d5a9fd9c7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -762,6 +762,21 @@ export const dict = { "provider.custom.models.name.placeholder": "Anzeigename", "provider.custom.models.remove": "Modell entfernen", "provider.custom.models.add": "Modell hinzufügen", + "provider.custom.models.fetch": "Modelle abrufen", + "provider.custom.models.fetching": "Abrufen\u2026", + "provider.custom.models.fetch.error": "Modelle konnten nicht abgerufen werden: {{error}}", + "provider.custom.models.fetch.authError": + "Authentifizierung fehlgeschlagen. Überprüfen Sie den API-Schlüssel oben und versuchen Sie es erneut.", + "provider.custom.models.fetch.empty": "Keine Modelle auf diesem Server gefunden.", + "provider.custom.models.fetch.added": "{{count}} Modell(e) hinzugefügt.", + "provider.custom.models.fetch.allExist": "Alle abgerufenen Modelle sind bereits hinzugefügt.", + "provider.custom.models.fetch.selectAll": "Alle auswählen", + "provider.custom.models.fetch.deselectAll": "Alle abwählen", + "provider.custom.models.fetch.found": "{{count}} Modelle gefunden", + "provider.custom.models.fetch.showing": "{{shown}} von {{total}} angezeigt", + "provider.custom.models.fetch.search": "Modelle suchen\u2026", + "provider.custom.models.fetch.add": "{{count}} Modell(e) hinzufügen", + "provider.custom.edit.title": "Anbieter bearbeiten", "provider.custom.headers.label": "Header (optional)", "provider.custom.headers.key.label": "Header", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index ad935f74487..1082423fa44 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -752,6 +752,20 @@ export const dict = { "provider.custom.models.name.placeholder": "Display Name", "provider.custom.models.remove": "Remove model", "provider.custom.models.add": "Add model", + "provider.custom.models.fetch": "Fetch models", + "provider.custom.models.fetching": "Fetching\u2026", + "provider.custom.models.fetch.error": "Failed to fetch models: {{error}}", + "provider.custom.models.fetch.authError": "Authentication failed. Check the API key above and try again.", + "provider.custom.models.fetch.empty": "No models found on this server.", + "provider.custom.models.fetch.added": "Added {{count}} model(s).", + "provider.custom.models.fetch.allExist": "All fetched models are already added.", + "provider.custom.models.fetch.selectAll": "Select all", + "provider.custom.models.fetch.deselectAll": "Deselect all", + "provider.custom.models.fetch.found": "{{count}} models found", + "provider.custom.models.fetch.showing": "Showing {{shown}} of {{total}}", + "provider.custom.models.fetch.search": "Search models\u2026", + "provider.custom.models.fetch.add": "Add {{count}} model(s)", + "provider.custom.edit.title": "Edit provider", "provider.custom.headers.label": "Headers (optional)", "provider.custom.headers.key.label": "Header", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 0db9393e06f..3c9f4c51751 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -757,6 +757,21 @@ export const dict = { "provider.custom.models.name.placeholder": "Nombre para mostrar", "provider.custom.models.remove": "Eliminar modelo", "provider.custom.models.add": "Añadir modelo", + "provider.custom.models.fetch": "Obtener modelos", + "provider.custom.models.fetching": "Obteniendo\u2026", + "provider.custom.models.fetch.error": "Error al obtener modelos: {{error}}", + "provider.custom.models.fetch.authError": + "Autenticación fallida. Verifica la clave de API arriba e intenta de nuevo.", + "provider.custom.models.fetch.empty": "No se encontraron modelos en este servidor.", + "provider.custom.models.fetch.added": "Se añadieron {{count}} modelo(s).", + "provider.custom.models.fetch.allExist": "Todos los modelos obtenidos ya están añadidos.", + "provider.custom.models.fetch.selectAll": "Seleccionar todo", + "provider.custom.models.fetch.deselectAll": "Deseleccionar todo", + "provider.custom.models.fetch.found": "{{count}} modelos encontrados", + "provider.custom.models.fetch.showing": "Mostrando {{shown}} de {{total}}", + "provider.custom.models.fetch.search": "Buscar modelos\u2026", + "provider.custom.models.fetch.add": "Añadir {{count}} modelo(s)", + "provider.custom.edit.title": "Editar proveedor", "provider.custom.headers.label": "Headers (opcional)", "provider.custom.headers.key.label": "Header", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index ca23079e040..d0d6974ca07 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -762,6 +762,20 @@ export const dict = { "provider.custom.models.name.placeholder": "Nom d'affichage", "provider.custom.models.remove": "Supprimer le modèle", "provider.custom.models.add": "Ajouter un modèle", + "provider.custom.models.fetch": "Récupérer les modèles", + "provider.custom.models.fetching": "Récupération\u2026", + "provider.custom.models.fetch.error": "Échec de la récupération des modèles : {{error}}", + "provider.custom.models.fetch.authError": "Échec de l'authentification. Vérifiez la clé API ci-dessus et réessayez.", + "provider.custom.models.fetch.empty": "Aucun modèle trouvé sur ce serveur.", + "provider.custom.models.fetch.added": "{{count}} modèle(s) ajouté(s).", + "provider.custom.models.fetch.allExist": "Tous les modèles récupérés sont déjà ajoutés.", + "provider.custom.models.fetch.selectAll": "Tout sélectionner", + "provider.custom.models.fetch.deselectAll": "Tout désélectionner", + "provider.custom.models.fetch.found": "{{count}} modèles trouvés", + "provider.custom.models.fetch.showing": "Affichage de {{shown}} sur {{total}}", + "provider.custom.models.fetch.search": "Rechercher des modèles\u2026", + "provider.custom.models.fetch.add": "Ajouter {{count}} modèle(s)", + "provider.custom.edit.title": "Modifier le fournisseur", "provider.custom.headers.label": "En-têtes (optionnel)", "provider.custom.headers.key.label": "En-tête", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index f6577aae3aa..26d49373271 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -750,6 +750,20 @@ export const dict = { "provider.custom.models.name.placeholder": "表示名", "provider.custom.models.remove": "モデルを削除", "provider.custom.models.add": "モデルを追加", + "provider.custom.models.fetch": "モデルを取得", + "provider.custom.models.fetching": "取得中\u2026", + "provider.custom.models.fetch.error": "モデルの取得に失敗しました: {{error}}", + "provider.custom.models.fetch.authError": "認証に失敗しました。上記のAPIキーを確認して再試行してください。", + "provider.custom.models.fetch.empty": "このサーバーにモデルが見つかりません。", + "provider.custom.models.fetch.added": "{{count}}個のモデルを追加しました。", + "provider.custom.models.fetch.allExist": "取得したモデルはすべて既に追加されています。", + "provider.custom.models.fetch.selectAll": "すべて選択", + "provider.custom.models.fetch.deselectAll": "すべて選択解除", + "provider.custom.models.fetch.found": "{{count}}個のモデルが見つかりました", + "provider.custom.models.fetch.showing": "{{total}}件中{{shown}}件を表示", + "provider.custom.models.fetch.search": "モデルを検索\u2026", + "provider.custom.models.fetch.add": "{{count}}個のモデルを追加", + "provider.custom.edit.title": "プロバイダーを編集", "provider.custom.headers.label": "ヘッダー(任意)", "provider.custom.headers.key.label": "ヘッダー", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index ffcbe00fedd..088d8746038 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -751,6 +751,20 @@ export const dict = { "provider.custom.models.name.placeholder": "표시 이름", "provider.custom.models.remove": "모델 제거", "provider.custom.models.add": "모델 추가", + "provider.custom.models.fetch": "모델 가져오기", + "provider.custom.models.fetching": "가져오는 중\u2026", + "provider.custom.models.fetch.error": "모델을 가져오지 못했습니다: {{error}}", + "provider.custom.models.fetch.authError": "인증에 실패했습니다. 위의 API 키를 확인하고 다시 시도하세요.", + "provider.custom.models.fetch.empty": "이 서버에서 모델을 찾을 수 없습니다.", + "provider.custom.models.fetch.added": "{{count}}개 모델이 추가되었습니다.", + "provider.custom.models.fetch.allExist": "가져온 모든 모델이 이미 추가되어 있습니다.", + "provider.custom.models.fetch.selectAll": "모두 선택", + "provider.custom.models.fetch.deselectAll": "모두 선택 해제", + "provider.custom.models.fetch.found": "{{count}}개 모델 발견", + "provider.custom.models.fetch.showing": "{{total}}개 중 {{shown}}개 표시", + "provider.custom.models.fetch.search": "모델 검색\u2026", + "provider.custom.models.fetch.add": "{{count}}개 모델 추가", + "provider.custom.edit.title": "공급자 편집", "provider.custom.headers.label": "헤더 (선택사항)", "provider.custom.headers.key.label": "헤더", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 88e91b68233..e1d5e9f4302 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -750,6 +750,21 @@ export const dict = { "provider.custom.models.name.placeholder": "Weergavenaam", "provider.custom.models.remove": "Model verwijderen", "provider.custom.models.add": "Model toevoegen", + "provider.custom.models.fetch": "Modellen ophalen", + "provider.custom.models.fetching": "Ophalen\u2026", + "provider.custom.models.fetch.error": "Kan modellen niet ophalen: {{error}}", + "provider.custom.models.fetch.authError": + "Authenticatie mislukt. Controleer de API-sleutel hierboven en probeer het opnieuw.", + "provider.custom.models.fetch.empty": "Geen modellen gevonden op deze server.", + "provider.custom.models.fetch.added": "{{count}} model(len) toegevoegd.", + "provider.custom.models.fetch.allExist": "Alle opgehaalde modellen zijn al toegevoegd.", + "provider.custom.models.fetch.selectAll": "Alles selecteren", + "provider.custom.models.fetch.deselectAll": "Alles deselecteren", + "provider.custom.models.fetch.found": "{{count}} modellen gevonden", + "provider.custom.models.fetch.showing": "{{shown}} van {{total}} weergegeven", + "provider.custom.models.fetch.search": "Modellen zoeken\u2026", + "provider.custom.models.fetch.add": "{{count}} model(len) toevoegen", + "provider.custom.edit.title": "Provider bewerken", "provider.custom.headers.label": "Headers (optioneel)", "provider.custom.headers.key.label": "Header", "provider.custom.headers.key.placeholder": "Header-Naam", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 42b0b84b621..ebde27238fa 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -755,6 +755,20 @@ export const dict = { "provider.custom.models.name.placeholder": "Visningsnavn", "provider.custom.models.remove": "Fjern modell", "provider.custom.models.add": "Legg til modell", + "provider.custom.models.fetch": "Hent modeller", + "provider.custom.models.fetching": "Henter\u2026", + "provider.custom.models.fetch.error": "Kunne ikke hente modeller: {{error}}", + "provider.custom.models.fetch.authError": "Autentisering mislyktes. Sjekk API-nøkkelen ovenfor og prøv igjen.", + "provider.custom.models.fetch.empty": "Ingen modeller funnet på denne serveren.", + "provider.custom.models.fetch.added": "{{count}} modell(er) lagt til.", + "provider.custom.models.fetch.allExist": "Alle hentede modeller er allerede lagt til.", + "provider.custom.models.fetch.selectAll": "Velg alle", + "provider.custom.models.fetch.deselectAll": "Fjern alle valg", + "provider.custom.models.fetch.found": "{{count}} modeller funnet", + "provider.custom.models.fetch.showing": "Viser {{shown}} av {{total}}", + "provider.custom.models.fetch.search": "Søk etter modeller\u2026", + "provider.custom.models.fetch.add": "Legg til {{count}} modell(er)", + "provider.custom.edit.title": "Rediger leverandør", "provider.custom.headers.label": "Headere (valgfritt)", "provider.custom.headers.key.label": "Header", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 021742cbf6f..049bec1e0d7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -755,6 +755,21 @@ export const dict = { "provider.custom.models.name.placeholder": "Nazwa wyświetlana", "provider.custom.models.remove": "Usuń model", "provider.custom.models.add": "Dodaj model", + "provider.custom.models.fetch": "Pobierz modele", + "provider.custom.models.fetching": "Pobieranie\u2026", + "provider.custom.models.fetch.error": "Nie udało się pobrać modeli: {{error}}", + "provider.custom.models.fetch.authError": + "Uwierzytelnianie nie powiodło się. Sprawdź klucz API powyżej i spróbuj ponownie.", + "provider.custom.models.fetch.empty": "Nie znaleziono modeli na tym serwerze.", + "provider.custom.models.fetch.added": "Dodano {{count}} model(i).", + "provider.custom.models.fetch.allExist": "Wszystkie pobrane modele są już dodane.", + "provider.custom.models.fetch.selectAll": "Zaznacz wszystkie", + "provider.custom.models.fetch.deselectAll": "Odznacz wszystkie", + "provider.custom.models.fetch.found": "Znaleziono {{count}} modeli", + "provider.custom.models.fetch.showing": "Wyświetlanie {{shown}} z {{total}}", + "provider.custom.models.fetch.search": "Szukaj modeli\u2026", + "provider.custom.models.fetch.add": "Dodaj {{count}} model(i)", + "provider.custom.edit.title": "Edytuj dostawcę", "provider.custom.headers.label": "Nagłówki (opcjonalnie)", "provider.custom.headers.key.label": "Nagłówek", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index af1049f31cd..128e711f201 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -758,6 +758,20 @@ export const dict = { "provider.custom.models.name.placeholder": "Отображаемое имя", "provider.custom.models.remove": "Удалить модель", "provider.custom.models.add": "Добавить модель", + "provider.custom.models.fetch": "Получить модели", + "provider.custom.models.fetching": "Загрузка\u2026", + "provider.custom.models.fetch.error": "Не удалось получить модели: {{error}}", + "provider.custom.models.fetch.authError": "Ошибка аутентификации. Проверьте API-ключ выше и попробуйте снова.", + "provider.custom.models.fetch.empty": "На этом сервере модели не найдены.", + "provider.custom.models.fetch.added": "Добавлено {{count}} модель(ей).", + "provider.custom.models.fetch.allExist": "Все полученные модели уже добавлены.", + "provider.custom.models.fetch.selectAll": "Выбрать все", + "provider.custom.models.fetch.deselectAll": "Снять выбор", + "provider.custom.models.fetch.found": "Найдено {{count}} моделей", + "provider.custom.models.fetch.showing": "Показано {{shown}} из {{total}}", + "provider.custom.models.fetch.search": "Поиск моделей\u2026", + "provider.custom.models.fetch.add": "Добавить {{count}} модель(ей)", + "provider.custom.edit.title": "Редактировать провайдера", "provider.custom.headers.label": "Заголовки (необязательно)", "provider.custom.headers.key.label": "Заголовок", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index cd9a1a67d39..3e1a51b665f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -748,6 +748,20 @@ export const dict = { "provider.custom.models.name.placeholder": "ชื่อที่แสดง", "provider.custom.models.remove": "ลบโมเดล", "provider.custom.models.add": "เพิ่มโมเดล", + "provider.custom.models.fetch": "ดึงโมเดล", + "provider.custom.models.fetching": "กำลังดึง\u2026", + "provider.custom.models.fetch.error": "ดึงโมเดลล้มเหลว: {{error}}", + "provider.custom.models.fetch.authError": "การยืนยันตัวตนล้มเหลว ตรวจสอบคีย์ API ด้านบนแล้วลองอีกครั้ง", + "provider.custom.models.fetch.empty": "ไม่พบโมเดลบนเซิร์ฟเวอร์นี้", + "provider.custom.models.fetch.added": "เพิ่มแล้ว {{count}} โมเดล", + "provider.custom.models.fetch.allExist": "โมเดลที่ดึงมาทั้งหมดถูกเพิ่มไปแล้ว", + "provider.custom.models.fetch.selectAll": "เลือกทั้งหมด", + "provider.custom.models.fetch.deselectAll": "ยกเลิกการเลือกทั้งหมด", + "provider.custom.models.fetch.found": "พบ {{count}} โมเดล", + "provider.custom.models.fetch.showing": "แสดง {{shown}} จาก {{total}}", + "provider.custom.models.fetch.search": "ค้นหาโมเดล\u2026", + "provider.custom.models.fetch.add": "เพิ่ม {{count}} โมเดล", + "provider.custom.edit.title": "แก้ไขผู้ให้บริการ", "provider.custom.headers.label": "ส่วนหัว (ไม่จำเป็น)", "provider.custom.headers.key.label": "ส่วนหัว", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index d5c216d7fbd..85cbbca10fe 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -753,6 +753,21 @@ export const dict = { "provider.custom.models.name.placeholder": "Görünen Ad", "provider.custom.models.remove": "Modeli kaldır", "provider.custom.models.add": "Model ekle", + "provider.custom.models.fetch": "Modelleri getir", + "provider.custom.models.fetching": "Getiriliyor\u2026", + "provider.custom.models.fetch.error": "Modeller getirilemedi: {{error}}", + "provider.custom.models.fetch.authError": + "Kimlik doğrulama başarısız oldu. Yukarıdaki API anahtarını kontrol edin ve tekrar deneyin.", + "provider.custom.models.fetch.empty": "Bu sunucuda model bulunamadı.", + "provider.custom.models.fetch.added": "{{count}} model eklendi.", + "provider.custom.models.fetch.allExist": "Getirilen tüm modeller zaten eklenmiş.", + "provider.custom.models.fetch.selectAll": "Tümünü seç", + "provider.custom.models.fetch.deselectAll": "Tümünün seçimini kaldır", + "provider.custom.models.fetch.found": "{{count}} model bulundu", + "provider.custom.models.fetch.showing": "{{total}} modelden {{shown}} tanesi gösteriliyor", + "provider.custom.models.fetch.search": "Model ara\u2026", + "provider.custom.models.fetch.add": "{{count}} model ekle", + "provider.custom.edit.title": "Sağlayıcıyı düzenle", "provider.custom.headers.label": "Başlıklar (isteğe bağlı)", "provider.custom.headers.key.label": "Başlık", "provider.custom.headers.key.placeholder": "Başlık-Adı", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 7fcf845a4ce..43dd9ff31ac 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -740,6 +740,20 @@ export const dict = { "provider.custom.models.name.placeholder": "显示名称", "provider.custom.models.remove": "移除模型", "provider.custom.models.add": "添加模型", + "provider.custom.models.fetch": "获取模型", + "provider.custom.models.fetching": "获取中\u2026", + "provider.custom.models.fetch.error": "获取模型失败:{{error}}", + "provider.custom.models.fetch.authError": "认证失败。请检查上方的 API 密钥后重试。", + "provider.custom.models.fetch.empty": "此服务器上未找到模型。", + "provider.custom.models.fetch.added": "已添加 {{count}} 个模型。", + "provider.custom.models.fetch.allExist": "获取的所有模型均已添加。", + "provider.custom.models.fetch.selectAll": "全选", + "provider.custom.models.fetch.deselectAll": "取消全选", + "provider.custom.models.fetch.found": "找到 {{count}} 个模型", + "provider.custom.models.fetch.showing": "显示 {{shown}}/{{total}}", + "provider.custom.models.fetch.search": "搜索模型\u2026", + "provider.custom.models.fetch.add": "添加 {{count}} 个模型", + "provider.custom.edit.title": "编辑提供商", "provider.custom.headers.label": "请求头(可选)", "provider.custom.headers.key.label": "请求头", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 2366acf5c24..b29daf739e6 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -742,6 +742,20 @@ export const dict = { "provider.custom.models.name.placeholder": "顯示名稱", "provider.custom.models.remove": "移除模型", "provider.custom.models.add": "新增模型", + "provider.custom.models.fetch": "取得模型", + "provider.custom.models.fetching": "取得中\u2026", + "provider.custom.models.fetch.error": "取得模型失敗:{{error}}", + "provider.custom.models.fetch.authError": "驗證失敗。請檢查上方的 API 金鑰後重試。", + "provider.custom.models.fetch.empty": "此伺服器上未找到模型。", + "provider.custom.models.fetch.added": "已新增 {{count}} 個模型。", + "provider.custom.models.fetch.allExist": "取得的所有模型均已新增。", + "provider.custom.models.fetch.selectAll": "全選", + "provider.custom.models.fetch.deselectAll": "取消全選", + "provider.custom.models.fetch.found": "找到 {{count}} 個模型", + "provider.custom.models.fetch.showing": "顯示 {{shown}}/{{total}}", + "provider.custom.models.fetch.search": "搜尋模型\u2026", + "provider.custom.models.fetch.add": "新增 {{count}} 個模型", + "provider.custom.edit.title": "編輯供應商", "provider.custom.headers.label": "標頭(選填)", "provider.custom.headers.key.label": "標頭", "provider.custom.headers.key.placeholder": "Header-Name", diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index a7cbe68be1b..c99670c4ea1 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -1210,6 +1210,15 @@ export interface ProviderActionErrorMessage { message: string } +export interface CustomProviderModelsFetchedMessage { + type: "customProviderModelsFetched" + requestId: string + models?: Array<{ id: string; name: string }> + error?: string + /** True when error was HTTP 401/403 — hints the user to check their API key */ + auth?: boolean +} + export type ExtensionMessage = | ReadyMessage | ConnectionStateMessage @@ -1299,6 +1308,7 @@ export type ExtensionMessage = | ProviderConnectedMessage | ProviderDisconnectedMessage | ProviderActionErrorMessage + | CustomProviderModelsFetchedMessage | RecentsLoadedMessage | LanguageChangedMessage | ContinueInWorktreeProgressMessage @@ -1905,6 +1915,14 @@ export interface SaveCustomProviderMessage { apiKey?: string } +export interface FetchCustomProviderModelsMessage { + type: "fetchCustomProviderModels" + requestId: string + baseURL: string + apiKey?: string + headers?: Record +} + export interface PersistRecentsRequest { type: "persistRecents" recents: ModelSelection[] @@ -2047,6 +2065,7 @@ export type WebviewMessage = | CompleteProviderOAuthMessage | DisconnectProviderMessage | SaveCustomProviderMessage + | FetchCustomProviderModelsMessage | PersistRecentsRequest | RequestRecentsMessage | ContinueInWorktreeRequest From 57aa3396f96df7bb0165c686e1734bfa36d4089a Mon Sep 17 00:00:00 2001 From: Marius Date: Fri, 27 Mar 2026 17:21:10 +0100 Subject: [PATCH 106/261] fix(agent-manager): align diff panel file order with file tree (#7779) buildFileTree now sorts children at every level (directories first, then files, both alphabetically). Both DiffPanel and FullScreenDiffView use a treeOrder() memo so the accordion order matches the tree sidebar. Previously the diff panel rendered files in git's flat path order with untracked files appended at the end, causing newly-added files to appear far from their directory siblings in the tree. --- .../kilo-vscode/tests/unit/file-tree.test.ts | 120 ++++++++++++++++-- .../webview-ui/agent-manager/DiffPanel.tsx | 7 +- .../agent-manager/FullScreenDiffView.tsx | 7 +- .../agent-manager/file-tree-utils.ts | 29 +++++ 4 files changed, 149 insertions(+), 14 deletions(-) diff --git a/packages/kilo-vscode/tests/unit/file-tree.test.ts b/packages/kilo-vscode/tests/unit/file-tree.test.ts index b997f86cfd4..a54908dab20 100644 --- a/packages/kilo-vscode/tests/unit/file-tree.test.ts +++ b/packages/kilo-vscode/tests/unit/file-tree.test.ts @@ -1,5 +1,11 @@ import { describe, it, expect } from "bun:test" -import { buildFileTree, flatten, flattenChain, type FileTreeNode } from "../../webview-ui/agent-manager/file-tree-utils" +import { + buildFileTree, + flatten, + flattenChain, + treeOrder, + type FileTreeNode, +} from "../../webview-ui/agent-manager/file-tree-utils" import type { WorktreeFileDiff } from "../../webview-ui/src/types/messages" function diff(file: string, status?: "added" | "deleted" | "modified"): WorktreeFileDiff { @@ -13,13 +19,13 @@ describe("buildFileTree", () => { expect(buildFileTree([])).toEqual([]) }) - it("places root-level files at the top", () => { + it("sorts root-level files alphabetically", () => { const tree = buildFileTree([diff("README.md"), diff("package.json")]) expect(tree).toHaveLength(2) - expect(tree[0]!.name).toBe("README.md") - expect(tree[0]!.path).toBe("README.md") + expect(tree[0]!.name).toBe("package.json") + expect(tree[0]!.path).toBe("package.json") expect(tree[0]!.children).toBeUndefined() - expect(tree[1]!.name).toBe("package.json") + expect(tree[1]!.name).toBe("README.md") }) it("groups files under shared directories", () => { @@ -66,15 +72,15 @@ describe("buildFileTree", () => { expect(tree[0]!.children![0]!.children![0]!.children![0]!.children![0]!.name).toBe("e.ts") }) - it("mixes root-level files with directory files", () => { + it("sorts directories before files at each level", () => { const tree = buildFileTree([diff("README.md"), diff("src/index.ts"), diff("test/index.test.ts")]) - expect(tree).toHaveLength(3) // README.md, src/, test/ - expect(tree[0]!.name).toBe("README.md") - expect(tree[0]!.children).toBeUndefined() - expect(tree[1]!.name).toBe("src") + expect(tree).toHaveLength(3) // src/, test/, README.md + expect(tree[0]!.name).toBe("src") + expect(tree[0]!.children).toHaveLength(1) + expect(tree[1]!.name).toBe("test") expect(tree[1]!.children).toHaveLength(1) - expect(tree[2]!.name).toBe("test") - expect(tree[2]!.children).toHaveLength(1) + expect(tree[2]!.name).toBe("README.md") + expect(tree[2]!.children).toBeUndefined() }) it("attaches diff data to leaf nodes", () => { @@ -89,6 +95,17 @@ describe("buildFileTree", () => { expect(tree[0]!.diff).toBeUndefined() }) + it("sorts directories before files within each level", () => { + const tree = buildFileTree([diff("src/a.ts"), diff("src/b/c.ts")]) + const src = tree[0]! + expect(src.children).toHaveLength(2) + // Directory before file + expect(src.children![0]!.name).toBe("b") + expect(src.children![0]!.children).toBeDefined() + expect(src.children![1]!.name).toBe("a.ts") + expect(src.children![1]!.children).toBeUndefined() + }) + it("separates diverging paths with common prefix", () => { const tree = buildFileTree([diff("src/a.ts"), diff("src/b/c.ts")]) const src = tree[0]! @@ -310,3 +327,82 @@ describe("flatten", () => { expect(result[0]!.children![0]!.name).toBe("index.ts") }) }) + +// ── treeOrder ────────────────────────────────────────────────────────────── + +describe("treeOrder", () => { + it("returns empty array for empty input", () => { + expect(treeOrder([])).toEqual([]) + }) + + it("returns single-element array unchanged", () => { + const input = [diff("a.ts")] + expect(treeOrder(input)).toEqual(input) + }) + + it("groups files by directory", () => { + // Git lexicographic order interleaves directories: a/x, b/y, a/z + // but buildFileTree groups by directory: a/{x,z}, b/{y} + const input = [diff("a/x.ts"), diff("b/y.ts"), diff("a/z.ts")] + const result = treeOrder(input) + expect(result.map((d) => d.file)).toEqual(["a/x.ts", "a/z.ts", "b/y.ts"]) + }) + + it("groups untracked files with their directory siblings", () => { + // The actual bug: backend appends untracked/new files AFTER all tracked + // files. settings-io.ts (untracked, added) ends up after all the tracked + // i18n modifications, but should appear with its directory siblings. + const input = [ + diff("src/components/settings/about.ts"), // tracked modification + diff("src/i18n/ar.ts"), // tracked modification + diff("src/i18n/de.ts"), // tracked modification + diff("src/i18n/en.ts"), // tracked modification + diff("src/components/settings/settings-io.ts"), // untracked, appended last + diff("tests/unit/settings-io.test.ts"), // untracked, appended last + ] + const result = treeOrder(input) + // Tree groups by directory: components/settings/ together, i18n/ together + // Directories sorted alphabetically: components/ before i18n/ before tests/ + expect(result.map((d) => d.file)).toEqual([ + "src/components/settings/about.ts", + "src/components/settings/settings-io.ts", // now grouped with about.ts! + "src/i18n/ar.ts", + "src/i18n/de.ts", + "src/i18n/en.ts", + "tests/unit/settings-io.test.ts", + ]) + }) + + it("reorders when git path sort diverges from tree grouping", () => { + // Files from the same directory are scattered in the input (e.g. because + // untracked files are appended after tracked files) + const input = [ + diff("pkg/tests/a.test.ts"), + diff("pkg/webview/src/components/x.ts"), + diff("pkg/webview/src/i18n/ar.ts"), + diff("pkg/webview/src/i18n/de.ts"), + diff("pkg/tests/b.test.ts"), + ] + const result = treeOrder(input) + // Tree groups and sorts: tests/{a,b}, webview/src/{components/x, i18n/{ar,de}} + expect(result.map((d) => d.file)).toEqual([ + "pkg/tests/a.test.ts", + "pkg/tests/b.test.ts", + "pkg/webview/src/components/x.ts", + "pkg/webview/src/i18n/ar.ts", + "pkg/webview/src/i18n/de.ts", + ]) + }) + + it("sorts root-level files alphabetically", () => { + const input = [diff("README.md"), diff("package.json"), diff("tsconfig.json")] + const result = treeOrder(input) + expect(result.map((d) => d.file)).toEqual(["package.json", "README.md", "tsconfig.json"]) + }) + + it("puts directories before files at each level", () => { + const input = [diff("README.md"), diff("src/a.ts"), diff("src/b.ts"), diff("tsconfig.json")] + const result = treeOrder(input) + expect(result.map((d) => d.file)).toEqual(["src/a.ts", "src/b.ts", "README.md", "tsconfig.json"]) + }) +}) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx b/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx index 96963fac288..3c00d20d5cd 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx @@ -22,6 +22,7 @@ import { } from "./review-annotations" import { LONG_DIFF_MARKER_FILE_COUNT, initialOpenFiles, isLargeDiffFile } from "./diff-open-policy" import { DiffEndMarker } from "./DiffEndMarker" +import { treeOrder } from "./file-tree-utils" // --- Data model --- @@ -67,6 +68,10 @@ export const DiffPanel: Component = (props) => { // only pruning happens so the user's manual collapse state is preserved. let initializedKey: string | undefined + // Reorder diffs to match the file-tree's depth-first visual order so + // scrolling through the accordion matches the tree grouping. + const sorted = createMemo(() => treeOrder(props.diffs)) + const comments = () => props.comments const setComments = (next: ReviewComment[]) => props.onCommentsChange(next) const updateComments = (updater: (prev: ReviewComment[]) => ReviewComment[]) => setComments(updater(comments())) @@ -380,7 +385,7 @@ export const DiffPanel: Component = (props) => { 0}>
- + {(diff) => { const isAdded = () => diff.status === "added" const isDeleted = () => diff.status === "deleted" diff --git a/packages/kilo-vscode/webview-ui/agent-manager/FullScreenDiffView.tsx b/packages/kilo-vscode/webview-ui/agent-manager/FullScreenDiffView.tsx index 03344ca8a11..041b1fbf142 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/FullScreenDiffView.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/FullScreenDiffView.tsx @@ -15,6 +15,7 @@ import type { DiffLineAnnotation, AnnotationSide, SelectedLineRange } from "@pie import type { WorktreeFileDiff } from "../src/types/messages" import { useLanguage } from "../src/context/language" import { FileTree } from "./FileTree" +import { treeOrder } from "./file-tree-utils" import { getDirectory, getFilename, lineCount, sanitizeReviewComments, type ReviewComment } from "./review-comments" import { buildFileAnnotations, @@ -74,6 +75,10 @@ export const FullScreenDiffView: Component = (props) => let scrollRef: HTMLDivElement | undefined let syncFrame: number | undefined + // Reorder diffs to match the file-tree's depth-first visual order so + // scrolling through the diff panel matches the tree on the left. + const sorted = createMemo(() => treeOrder(props.diffs)) + const comments = () => props.comments const setComments = (next: ReviewComment[]) => props.onCommentsChange(next) const updateComments = (updater: (prev: ReviewComment[]) => ReviewComment[]) => setComments(updater(comments())) @@ -481,7 +486,7 @@ export const FullScreenDiffView: Component = (props) => 0}>
- + {(diff) => { const isAdded = () => diff.status === "added" const isDeleted = () => diff.status === "deleted" diff --git a/packages/kilo-vscode/webview-ui/agent-manager/file-tree-utils.ts b/packages/kilo-vscode/webview-ui/agent-manager/file-tree-utils.ts index 3762d5993d4..a45c1ef9cc0 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/file-tree-utils.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/file-tree-utils.ts @@ -33,9 +33,23 @@ export function buildFileTree(diffs: WorktreeFileDiff[]): FileTreeNode[] { parent.push({ name: filename, path: diff.file, diff }) } + sortTree(root) return root } +/** Sort children at every level: directories first (alphabetically), then files (alphabetically). */ +function sortTree(nodes: FileTreeNode[]) { + nodes.sort((a, b) => { + const aDir = a.children ? 0 : 1 + const bDir = b.children ? 0 : 1 + if (aDir !== bDir) return aDir - bDir + return a.name.localeCompare(b.name) + }) + for (const node of nodes) { + if (node.children) sortTree(node.children) + } +} + // Flatten single-child directory chains: src/components/ instead of src > components export function flatten(nodes: FileTreeNode[]): FileTreeNode[] { return nodes.map((node) => { @@ -51,3 +65,18 @@ export function flattenChain(node: FileTreeNode): FileTreeNode { if (!child.children) return node return flattenChain({ name: `${node.name}/${child.name}`, path: child.path, children: child.children }) } + +/** Return diffs sorted to match the tree's depth-first visual order. */ +export function treeOrder(diffs: WorktreeFileDiff[]): WorktreeFileDiff[] { + if (diffs.length <= 1) return diffs + const tree = buildFileTree(diffs) + const result: WorktreeFileDiff[] = [] + function walk(nodes: FileTreeNode[]) { + for (const node of nodes) { + if (node.diff) result.push(node.diff) + if (node.children) walk(node.children) + } + } + walk(tree) + return result +} From a0e1fd82826b7d3c104fb3df82c30b08e5fbebd0 Mon Sep 17 00:00:00 2001 From: Marius Date: Fri, 27 Mar 2026 17:45:15 +0100 Subject: [PATCH 107/261] feat(vscode): add settings export/import to About tab (#7794) Add Export and Import buttons in the About Kilo Code settings tab so users can transfer settings between VS Code instances (closes #7755). - Export fetches global-only config (not merged/project-level) to avoid promoting project-level agent definitions to global config - All fields exported as-is including secrets for complete transfers - Import populates the draft for review before saving via existing save bar flow - KNOWN_KEYS drift guard test catches newly added Config fields - 40 unit tests covering export, import, merge, round-trip, and constants - i18n keys translated for all 17 locales --- packages/kilo-vscode/src/KiloProvider.ts | 14 + .../src/agent-manager/AgentManagerProvider.ts | 14 +- .../tests/unit/agent-manager-arch.test.ts | 9 +- .../tests/unit/settings-io.test.ts | 397 ++++++++++++++++++ .../agent-manager/AgentManagerApp.tsx | 127 +++--- .../src/components/chat/PromptInput.tsx | 2 +- .../components/settings/AboutKiloCodeTab.tsx | 119 +++++- .../src/components/settings/settings-io.ts | 130 ++++++ .../webview-ui/src/context/worktree-mode.tsx | 10 +- .../kilo-vscode/webview-ui/src/i18n/ar.ts | 10 + .../kilo-vscode/webview-ui/src/i18n/br.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/bs.ts | 12 + .../kilo-vscode/webview-ui/src/i18n/da.ts | 12 + .../kilo-vscode/webview-ui/src/i18n/de.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/en.ts | 11 + .../kilo-vscode/webview-ui/src/i18n/es.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/fr.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/ja.ts | 13 + .../kilo-vscode/webview-ui/src/i18n/ko.ts | 12 + .../kilo-vscode/webview-ui/src/i18n/nl.ts | 14 + .../kilo-vscode/webview-ui/src/i18n/no.ts | 12 + .../kilo-vscode/webview-ui/src/i18n/pl.ts | 12 + .../kilo-vscode/webview-ui/src/i18n/ru.ts | 12 + .../kilo-vscode/webview-ui/src/i18n/th.ts | 11 + .../kilo-vscode/webview-ui/src/i18n/tr.ts | 12 + .../kilo-vscode/webview-ui/src/i18n/zh.ts | 9 + .../kilo-vscode/webview-ui/src/i18n/zht.ts | 9 + .../webview-ui/src/types/messages.ts | 11 + 28 files changed, 949 insertions(+), 101 deletions(-) create mode 100644 packages/kilo-vscode/tests/unit/settings-io.test.ts create mode 100644 packages/kilo-vscode/webview-ui/src/components/settings/settings-io.ts diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index e917b82ebc5..5f30cc1f65f 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -652,6 +652,9 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper case "requestConfig": this.fetchAndSendConfig().catch((e) => console.error("[Kilo New] fetchAndSendConfig failed:", e)) break + case "requestGlobalConfig": + this.fetchAndSendGlobalConfig().catch((e) => console.error("[Kilo New] fetchAndSendGlobalConfig failed:", e)) + break case "updateConfig": await this.handleUpdateConfig(message.config) break @@ -1739,6 +1742,17 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper } } + /** Fetch global-only config (no project/managed layers) for settings export. */ + private async fetchAndSendGlobalConfig(): Promise { + if (!this.client || this.connectionState !== "connected") return + try { + const { data: config } = await this.client.global.config.get({ throwOnError: true }) + this.postMessage({ type: "globalConfigLoaded", config }) + } catch (error) { + console.error("[Kilo New] KiloProvider: Failed to fetch global config:", error) + } + } + /** * Seed sessionStatusMap with current session statuses on connect. * Without this, the Settings panel (which has no tracked sessions) would see diff --git a/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts b/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts index 43dd185ccc7..b463e7682da 100644 --- a/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts +++ b/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts @@ -276,12 +276,14 @@ export class AgentManagerProvider implements Disposable { // already emitted before the webview was ready to receive messages. if (this.cachedWorktreeStats) this.postToWebview(this.cachedWorktreeStats) if (this.cachedLocalStats) this.postToWebview(this.cachedLocalStats) - // Always refresh sessions after pushState so the webview receives - // a sessionsLoaded message. Without this unconditional call, closing - // and reopening the panel (or recovering from a backend crash) can - // leave sessionsLoaded stuck on false because the initial - // refreshSessions() in initializeState() raced ahead of mount. - this.panel?.sessions.refreshSessions() + // Refresh sessions after pushState so the webview's sessionsLoaded + // handler is guaranteed to be registered (requestState fires from + // onMount). Without this, the initial refreshSessions() in + // initializeState() can race ahead of webview mount, causing + // sessionsLoaded to never flip to true. + if (this.state.getSessions().length > 0) { + this.panel?.sessions.refreshSessions() + } }) .catch((err) => { this.log("initializeState failed, pushing partial state:", err) diff --git a/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts index 045352476c4..bf2ffcb5706 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts @@ -321,12 +321,13 @@ describe("Agent Manager Webview — non-git sessionsLoaded fix", () => { /** * Regression: when isGitRepo is false, the Kilo server never sends a * "sessionsLoaded" message, so the skeleton was stuck forever. - * The fix must set sessionsLoaded(true) from the state-application path - * when isGitRepo === false. + * The fix must set sessionsLoaded(true) when receiving a state message + * with isGitRepo === false. */ it("sets sessionsLoaded when agentManager.state arrives with isGitRepo false", () => { - const start = tsx.indexOf("const applyState =") - expect(start, "applyState helper must exist").toBeGreaterThan(-1) + // Find the agentManager.state handler block + const start = tsx.indexOf('"agentManager.state"') + expect(start, "agentManager.state handler must exist").toBeGreaterThan(-1) const snippet = tsx.slice(start, start + 800) expect(snippet, "must call setSessionsLoaded in the non-git branch").toContain("setSessionsLoaded") expect(snippet, "must check isGitRepo === false before setting sessionsLoaded").toMatch( diff --git a/packages/kilo-vscode/tests/unit/settings-io.test.ts b/packages/kilo-vscode/tests/unit/settings-io.test.ts new file mode 100644 index 00000000000..142f1e82ad1 --- /dev/null +++ b/packages/kilo-vscode/tests/unit/settings-io.test.ts @@ -0,0 +1,397 @@ +import { describe, it, expect } from "bun:test" +import { + buildExport, + parseImport, + mergeConfig, + MAX_IMPORT_SIZE, + KNOWN_KEYS, + META_VERSION, +} from "../../webview-ui/src/components/settings/settings-io" +import type { Config } from "../../webview-ui/src/types/messages" + +// --------------------------------------------------------------------------- +// buildExport +// --------------------------------------------------------------------------- +describe("buildExport", () => { + it("wraps config in _meta envelope", () => { + const cfg: Config = { model: "anthropic/claude-sonnet-4-20250514" } + const result = buildExport(cfg) + expect(result._meta).toBeDefined() + expect(result._meta.version).toBe(META_VERSION) + expect(typeof result._meta.exportedAt).toBe("string") + expect(result.model).toBe("anthropic/claude-sonnet-4-20250514") + }) + + it("preserves provider fields including secrets", () => { + const cfg: Config = { + provider: { + openai: { name: "OpenAI", api_key: "sk-secret-123" }, + custom: { name: "Custom", options: { apiKey: "secret", baseURL: "https://example.com" } }, + }, + } + const result = buildExport(cfg) + expect(result.provider.openai.api_key).toBe("sk-secret-123") + expect(result.provider.openai.name).toBe("OpenAI") + expect(result.provider.custom.options.apiKey).toBe("secret") + expect(result.provider.custom.options.baseURL).toBe("https://example.com") + }) + + it("preserves mcp fields including env and headers", () => { + const cfg: Config = { + mcp: { + github: { + type: "local" as const, + command: "npx", + env: { GITHUB_TOKEN: "ghp_secret123" }, + enabled: true, + }, + server: { + type: "local" as const, + command: "node", + environment: { SECRET: "val" }, + }, + remote: { + type: "remote" as const, + url: "https://mcp.example.com", + headers: { Authorization: "Bearer secret-token" }, + enabled: true, + }, + }, + } + const result = buildExport(cfg) + expect(result.mcp.github.env.GITHUB_TOKEN).toBe("ghp_secret123") + expect(result.mcp.github.command).toBe("npx") + expect(result.mcp.server.environment.SECRET).toBe("val") + expect(result.mcp.remote.headers.Authorization).toBe("Bearer secret-token") + expect(result.mcp.remote.url).toBe("https://mcp.example.com") + }) + + it("preserves all config fields", () => { + const cfg: Config = { + model: "test-model", + small_model: "test-small", + default_agent: "coder", + agent: { coder: { mode: "primary", prompt: "Code stuff" } }, + permission: { read: "allow" }, + instructions: ["rule1.md"], + snapshot: true, + share: "manual", + } + const result = buildExport(cfg) + expect(result.model).toBe("test-model") + expect(result.small_model).toBe("test-small") + expect(result.default_agent).toBe("coder") + expect(result.agent).toEqual({ coder: { mode: "primary", prompt: "Code stuff" } }) + expect(result.permission).toEqual({ read: "allow" }) + expect(result.instructions).toEqual(["rule1.md"]) + expect(result.snapshot).toBe(true) + expect(result.share).toBe("manual") + }) + + it("handles empty config", () => { + const result = buildExport({}) + expect(result._meta).toBeDefined() + expect(Object.keys(result).length).toBe(1) // only _meta + }) + + it("handles config with no providers or mcp", () => { + const cfg: Config = { model: "test" } + const result = buildExport(cfg) + expect(result.model).toBe("test") + expect(result.provider).toBeUndefined() + expect(result.mcp).toBeUndefined() + }) +}) + +// --------------------------------------------------------------------------- +// parseImport +// --------------------------------------------------------------------------- +describe("parseImport", () => { + it("rejects non-JSON", () => { + const result = parseImport("not json at all") + expect(result.ok).toBe(false) + if (!result.ok) expect(result.error).toBe("invalidJson") + }) + + it("rejects JSON null", () => { + const result = parseImport("null") + expect(result.ok).toBe(false) + if (!result.ok) expect(result.error).toBe("invalidJson") + }) + + it("rejects JSON array", () => { + const result = parseImport("[]") + expect(result.ok).toBe(false) + if (!result.ok) expect(result.error).toBe("invalidJson") + }) + + it("rejects JSON string", () => { + const result = parseImport('"hello"') + expect(result.ok).toBe(false) + if (!result.ok) expect(result.error).toBe("invalidJson") + }) + + it("rejects JSON number", () => { + const result = parseImport("42") + expect(result.ok).toBe(false) + if (!result.ok) expect(result.error).toBe("invalidJson") + }) + + it("rejects empty object (no known keys)", () => { + const result = parseImport("{}") + expect(result.ok).toBe(false) + if (!result.ok) expect(result.error).toBe("invalidConfig") + }) + + it("rejects object with only unknown keys", () => { + const result = parseImport(JSON.stringify({ foo: "bar", baz: 42 })) + expect(result.ok).toBe(false) + if (!result.ok) expect(result.error).toBe("invalidConfig") + }) + + it("accepts valid partial config (just agent)", () => { + const json = JSON.stringify({ + agent: { coder: { mode: "primary", prompt: "Code things" } }, + }) + const result = parseImport(json) + expect(result.ok).toBe(true) + if (result.ok) { + expect(result.config.agent).toEqual({ coder: { mode: "primary", prompt: "Code things" } }) + } + }) + + it("accepts valid partial config (just model)", () => { + const json = JSON.stringify({ model: "test-model" }) + const result = parseImport(json) + expect(result.ok).toBe(true) + if (result.ok) expect(result.config.model).toBe("test-model") + }) + + it("strips _meta before returning config", () => { + const json = JSON.stringify({ + _meta: { version: 1, exportedAt: "2026-01-01", secretsStripped: true }, + model: "test", + }) + const result = parseImport(json) + expect(result.ok).toBe(true) + if (result.ok) { + expect((result.config as Record)._meta).toBeUndefined() + expect(result.config.model).toBe("test") + } + }) + + it("strips unknown top-level keys", () => { + const json = JSON.stringify({ + model: "test", + unknownField: "should be stripped", + anotherUnknown: 42, + }) + const result = parseImport(json) + expect(result.ok).toBe(true) + if (result.ok) { + expect(result.config.model).toBe("test") + expect((result.config as Record).unknownField).toBeUndefined() + expect((result.config as Record).anotherUnknown).toBeUndefined() + } + }) + + it("returns warning when _meta.version > current", () => { + const json = JSON.stringify({ + _meta: { version: 999 }, + model: "test", + }) + const result = parseImport(json) + expect(result.ok).toBe(true) + if (result.ok) { + expect(result.warning).toBe("newerVersion") + } + }) + + it("returns no warning when _meta.version <= current", () => { + const json = JSON.stringify({ + _meta: { version: META_VERSION }, + model: "test", + }) + const result = parseImport(json) + expect(result.ok).toBe(true) + if (result.ok) { + expect(result.warning).toBeUndefined() + } + }) + + it("returns no warning when _meta is absent", () => { + const json = JSON.stringify({ model: "test" }) + const result = parseImport(json) + expect(result.ok).toBe(true) + if (result.ok) { + expect(result.warning).toBeUndefined() + } + }) + + it("accepts config with all known keys", () => { + const cfg: Record = {} + for (const key of KNOWN_KEYS) { + cfg[key] = key === "instructions" ? ["rule.md"] : key === "snapshot" ? true : "value" + } + const json = JSON.stringify(cfg) + const result = parseImport(json) + expect(result.ok).toBe(true) + }) + + it("preserves provider and mcp fields as-is (including secrets on import)", () => { + const json = JSON.stringify({ + provider: { openai: { name: "OpenAI", api_key: "sk-123" } }, + mcp: { gh: { command: "npx", env: { TOKEN: "secret" } } }, + }) + const result = parseImport(json) + expect(result.ok).toBe(true) + if (result.ok) { + expect(result.config.provider?.openai?.api_key).toBe("sk-123") + expect(result.config.mcp?.gh?.env?.TOKEN).toBe("secret") + } + }) +}) + +// --------------------------------------------------------------------------- +// mergeConfig +// --------------------------------------------------------------------------- +describe("mergeConfig", () => { + it("merges imported agents with existing agents", () => { + const existing: Config = { + agent: { + coder: { mode: "primary", prompt: "Code" }, + reviewer: { mode: "primary", prompt: "Review" }, + }, + } + const imported: Config = { + agent: { + reviewer: { mode: "primary", prompt: "Updated review" }, + planner: { mode: "primary", prompt: "Plan" }, + }, + } + const result = mergeConfig(existing, imported) + expect(result.agent?.coder?.prompt).toBe("Code") + expect(result.agent?.reviewer?.prompt).toBe("Updated review") + expect(result.agent?.planner?.prompt).toBe("Plan") + }) + + it("imported values override existing for same keys", () => { + const existing: Config = { model: "old-model", default_agent: "coder" } + const imported: Config = { model: "new-model" } + const result = mergeConfig(existing, imported) + expect(result.model).toBe("new-model") + expect(result.default_agent).toBe("coder") + }) + + it("existing values not in import are preserved", () => { + const existing: Config = { + model: "test", + permission: { read: "allow" }, + instructions: ["old.md"], + } + const imported: Config = { model: "updated" } + const result = mergeConfig(existing, imported) + expect(result.model).toBe("updated") + expect(result.permission).toEqual({ read: "allow" }) + expect(result.instructions).toEqual(["old.md"]) + }) + + it("merges providers without losing existing ones", () => { + const existing: Config = { + provider: { + openai: { name: "OpenAI", api_key: "sk-existing" }, + anthropic: { name: "Anthropic", api_key: "sk-ant" }, + }, + } + const imported: Config = { + provider: { + openai: { name: "OpenAI Updated", base_url: "https://new.api" }, + }, + } + const result = mergeConfig(existing, imported) + expect(result.provider?.openai?.name).toBe("OpenAI Updated") + expect(result.provider?.openai?.base_url).toBe("https://new.api") + expect(result.provider?.anthropic?.name).toBe("Anthropic") + expect(result.provider?.anthropic?.api_key).toBe("sk-ant") + }) + + it("handles empty existing config", () => { + const imported: Config = { model: "test", agent: { coder: { mode: "primary" } } } + const result = mergeConfig({}, imported) + expect(result.model).toBe("test") + expect(result.agent?.coder?.mode).toBe("primary") + }) + + it("handles empty imported config", () => { + const existing: Config = { model: "test" } + const result = mergeConfig(existing, {}) + expect(result.model).toBe("test") + }) +}) + +// --------------------------------------------------------------------------- +// Round-trip +// --------------------------------------------------------------------------- +describe("round-trip", () => { + it("export then import preserves all fields including secrets", () => { + const original: Config = { + model: "test-model", + agent: { coder: { mode: "primary", prompt: "Code" } }, + provider: { openai: { name: "OpenAI", api_key: "sk-secret" } }, + mcp: { gh: { command: "npx", env: { TOKEN: "secret" } } }, + permission: { read: "allow" }, + instructions: ["rules.md"], + } + const exported = buildExport(original) + const json = JSON.stringify(exported) + const result = parseImport(json) + expect(result.ok).toBe(true) + if (result.ok) { + expect(result.config.model).toBe("test-model") + expect(result.config.agent).toEqual({ coder: { mode: "primary", prompt: "Code" } }) + expect(result.config.provider?.openai?.name).toBe("OpenAI") + expect(result.config.provider?.openai?.api_key).toBe("sk-secret") + expect(result.config.mcp?.gh?.command).toBe("npx") + expect(result.config.mcp?.gh?.env?.TOKEN).toBe("secret") + expect(result.config.permission).toEqual({ read: "allow" }) + expect(result.config.instructions).toEqual(["rules.md"]) + } + }) +}) + +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- +describe("constants", () => { + it("MAX_IMPORT_SIZE is 1 MB", () => { + expect(MAX_IMPORT_SIZE).toBe(1_048_576) + }) + + it("META_VERSION is 1", () => { + expect(META_VERSION).toBe(1) + }) + + it("KNOWN_KEYS includes core config keys", () => { + expect(KNOWN_KEYS).toContain("agent") + expect(KNOWN_KEYS).toContain("provider") + expect(KNOWN_KEYS).toContain("mcp") + expect(KNOWN_KEYS).toContain("permission") + expect(KNOWN_KEYS).toContain("model") + expect(KNOWN_KEYS).toContain("instructions") + }) + + it("KNOWN_KEYS matches all keys in the Config interface (drift guard)", async () => { + // Read the Config interface from messages.ts and extract its keys. + // If someone adds a new field to Config, this test fails as a reminder + // to also add it to KNOWN_KEYS in settings-io.ts. + const src = await Bun.file(require("path").join(__dirname, "../../webview-ui/src/types/messages.ts")).text() + const match = src.match(/export interface Config \{([^}]+)\}/) + expect(match).not.toBeNull() + const body = match![1] + const keys = [...body.matchAll(/^\s+(\w+)\??:/gm)].map((m) => m[1]) + expect(keys.length).toBeGreaterThan(0) + + const sorted = (arr: readonly string[]) => [...arr].sort() + expect(sorted(KNOWN_KEYS)).toEqual(sorted(keys)) + }) +}) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx index e66f04eb737..08917a8ecc4 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx @@ -74,7 +74,7 @@ import { ProviderProvider } from "../src/context/provider" import { ConfigProvider } from "../src/context/config" import { NotificationsProvider } from "../src/context/notifications" import { SessionProvider, useSession } from "../src/context/session" -import { WorktreeModeProvider, useWorktreeMode } from "../src/context/worktree-mode" +import { WorktreeModeProvider } from "../src/context/worktree-mode" import { ChatView } from "../src/components/chat" import { NewWorktreeDialog } from "./NewWorktreeDialog" import { LanguageBridge, DataBridge } from "../src/App" @@ -312,44 +312,6 @@ const AgentManagerContent: Component = () => { const repoDefaultBranch = () => defaultBaseBranch() ?? repoDetectedBranch() ?? "main" const hasConfiguredBranch = () => !!defaultBaseBranch() - const applyState = (state: AgentManagerStateMessage) => { - setWorktrees(state.worktrees) - setManagedSessions(state.sessions) - setStaleWorktreeIds(new Set(state.staleWorktreeIds ?? [])) - if (state.isGitRepo !== undefined) setIsGitRepo(state.isGitRepo) - if (!worktreesLoaded()) setWorktreesLoaded(true) - if (state.isGitRepo === false && !sessionsLoaded()) setSessionsLoaded(true) - if (state.tabOrder) setWorktreeTabOrder(state.tabOrder) - if (state.worktreeOrder) setSidebarWorktreeOrder(state.worktreeOrder) - if (state.reviewDiffStyle === "split" || state.reviewDiffStyle === "unified") { - setReviewDiffStyle(state.reviewDiffStyle) - } - if ("defaultBaseBranch" in state) setDefaultBaseBranch(state.defaultBaseBranch || undefined) - const current = session.currentSessionID() - if (current) { - const ms = state.sessions.find((s) => s.id === current) - if (ms?.worktreeId) setSelection(ms.worktreeId) - } - const localOrder = state.tabOrder?.[LOCAL] - if (localOrder && localSessionIDs().length > 0) { - const reordered = applyTabOrder( - localSessionIDs().map((id) => ({ id })), - localOrder, - ).map((item) => item.id) - setLocalSessionIDs(reordered) - } - if (state.sessionsCollapsed !== undefined) setSessionsCollapsed(state.sessionsCollapsed) - const ids = new Set(state.worktrees.map((wt) => wt.id)) - setBusyWorktrees((prev) => { - const next = new Map([...prev].filter(([id]) => ids.has(id))) - return next.size === prev.size ? prev : next - }) - } - - const requestState = () => { - vscode.postMessage({ type: "agentManager.requestState" }) - } - const DEFAULT_SIDEBAR_WIDTH = 260 const MIN_SIDEBAR_WIDTH = 200 const MAX_SIDEBAR_WIDTH_RATIO = 0.4 @@ -397,10 +359,6 @@ const AgentManagerContent: Component = () => { const PENDING_PREFIX = "pending:" const [activePendingId, setActivePendingId] = createSignal() - // Sync activePendingId into WorktreeMode context so PromptInput can key drafts per pending tab - const worktreeCtx = useWorktreeMode() - createEffect(() => worktreeCtx?.setPendingId(activePendingId())) - // Inline delete confirmation: tracks which worktree is awaiting a second click/press const [pendingDelete, setPendingDelete] = createSignal(null) let pendingDeleteTimer: ReturnType | undefined @@ -1039,41 +997,6 @@ const AgentManagerContent: Component = () => { if (agent) session.selectAgent(agent.name) } - // Subscribe outside onMount so early sessionsLoaded messages (posted before - // the component mounts) are not missed. This matches the codebase pattern for - // loaded-message listeners and prevents the loading skeleton from persisting - // after a backend crash/restart + panel reopen. - const unsubState = vscode.onMessage((msg) => { - if (msg.type !== "agentManager.state") return - applyState(msg as AgentManagerStateMessage) - }) - onCleanup(unsubState) - - const unsubSessions = vscode.onMessage((msg) => { - if (msg.type !== "sessionsLoaded") return - if (!sessionsLoaded()) setSessionsLoaded(true) - }) - onCleanup(unsubSessions) - - // Retry state requests while the panel is bootstrapping so reopening after a - // backend restart cannot get stuck behind a missed requestState/refresh race. - const retryMs = 500 - const maxRetries = 10 - let retries = 0 - const retry = setInterval(() => { - if (worktreesLoaded() && sessionsLoaded()) { - clearInterval(retry) - return - } - retries++ - if (retries >= maxRetries) { - clearInterval(retry) - return - } - requestState() - }, retryMs) - onCleanup(() => clearInterval(retry)) - onMount(() => { const handler = (event: MessageEvent) => { const msg = event.data as ExtensionMessage @@ -1177,6 +1100,11 @@ const AgentManagerContent: Component = () => { } }) + // Mark sessions loaded as soon as the session context receives data (even if empty) + const unsubSessions = vscode.onMessage((msg) => { + if (msg.type === "sessionsLoaded" && !sessionsLoaded()) setSessionsLoaded(true) + }) + const unsub = vscode.onMessage((msg) => { if (msg.type === "agentManager.repoInfo") { const info = msg as AgentManagerRepoInfoMessage @@ -1250,6 +1178,46 @@ const AgentManagerContent: Component = () => { setKb(ev.bindings) } + if (msg.type === "agentManager.state") { + const state = msg as AgentManagerStateMessage + setWorktrees(state.worktrees) + setManagedSessions(state.sessions) + setStaleWorktreeIds(new Set(state.staleWorktreeIds ?? [])) + if (state.isGitRepo !== undefined) setIsGitRepo(state.isGitRepo) + if (!worktreesLoaded()) setWorktreesLoaded(true) + // When not a git repo, also mark sessions as loaded since the Kilo + // server won't connect to send the sessionsLoaded message. + if (state.isGitRepo === false && !sessionsLoaded()) setSessionsLoaded(true) + if (state.tabOrder) setWorktreeTabOrder(state.tabOrder) + if (state.worktreeOrder) setSidebarWorktreeOrder(state.worktreeOrder) + if (state.reviewDiffStyle === "split" || state.reviewDiffStyle === "unified") { + setReviewDiffStyle(state.reviewDiffStyle) + } + if ("defaultBaseBranch" in state) setDefaultBaseBranch(state.defaultBaseBranch || undefined) + const current = session.currentSessionID() + if (current) { + const ms = state.sessions.find((s) => s.id === current) + if (ms?.worktreeId) setSelection(ms.worktreeId) + } + // Recover local tab order from persisted state + const localOrder = state.tabOrder?.[LOCAL] + if (localOrder && localSessionIDs().length > 0) { + const reordered = applyTabOrder( + localSessionIDs().map((id) => ({ id })), + localOrder, + ).map((item) => item.id) + setLocalSessionIDs(reordered) + } + // Recover sessions collapsed state from extension-persisted state + if (state.sessionsCollapsed !== undefined) setSessionsCollapsed(state.sessionsCollapsed) + // Clear busy state for worktrees that have been removed + const ids = new Set(state.worktrees.map((wt) => wt.id)) + setBusyWorktrees((prev) => { + const next = new Map([...prev].filter(([id]) => ids.has(id))) + return next.size === prev.size ? prev : next + }) + } + // When a multi-version progress update arrives, mark newly created worktrees as loading if ((msg as { type: string }).type === "agentManager.multiVersionProgress") { const ev = msg as unknown as AgentManagerMultiVersionProgressMessage @@ -1417,6 +1385,7 @@ const AgentManagerContent: Component = () => { window.removeEventListener("keydown", deleteKeyHandler) window.removeEventListener("focus", onWindowFocus) unsubCreate() + unsubSessions() unsub() }) }) @@ -1426,7 +1395,7 @@ const AgentManagerContent: Component = () => { selectLocal() // Request worktree/session state from extension — handles race where // initializeState() pushState fires before the webview is mounted - requestState() + vscode.postMessage({ type: "agentManager.requestState" }) // Open a pending "New Session" tab if there are no persisted local sessions if (localSessionIDs().length === 0) { addPendingTab() diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx index 508ce41dde1..cf8804cff15 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx @@ -78,7 +78,7 @@ export const PromptInput: Component = (props) => { }) const history = usePromptHistory() - const sessionKey = () => session.currentSessionID() ?? worktree?.pendingId() ?? "__new__" + const sessionKey = () => session.currentSessionID() ?? "__new__" const [text, setText] = createSignal("") const [reviewComments, setReviewComments] = createSignal([]) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AboutKiloCodeTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AboutKiloCodeTab.tsx index cbf098b2a35..c531abe2de3 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AboutKiloCodeTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AboutKiloCodeTab.tsx @@ -1,7 +1,12 @@ -import { Component } from "solid-js" +import { Component, createSignal, onCleanup } from "solid-js" +import { Button } from "@kilocode/kilo-ui/button" +import { Icon } from "@kilocode/kilo-ui/icon" +import { showToast } from "@kilocode/kilo-ui/toast" import { useLanguage } from "../../context/language" import { useVSCode } from "../../context/vscode" -import type { ConnectionState } from "../../types/messages" +import { useConfig } from "../../context/config" +import type { ConnectionState, ExtensionMessage } from "../../types/messages" +import { buildExport, parseImport, MAX_IMPORT_SIZE } from "./settings-io" export interface AboutKiloCodeTabProps { port: number | null @@ -13,11 +18,96 @@ export interface AboutKiloCodeTabProps { const AboutKiloCodeTab: Component = (props) => { const language = useLanguage() const vscode = useVSCode() + const { updateConfig } = useConfig() + const [importing, setImporting] = createSignal(false) + const [exporting, setExporting] = createSignal(false) + let epoch = 0 const open = (url: string) => { vscode.postMessage({ type: "openExternal", url }) } + // Listen for globalConfigLoaded response + const handler = (event: MessageEvent) => { + const msg = event.data as ExtensionMessage + if (msg.type !== "globalConfigLoaded" || !exporting()) return + setExporting(false) + epoch++ + const payload = buildExport(msg.config) + const json = JSON.stringify(payload, null, 2) + const blob = new Blob([json], { type: "application/json" }) + const url = URL.createObjectURL(blob) + const a = document.createElement("a") + a.href = url + a.download = "kilo-settings.json" + a.click() + URL.revokeObjectURL(url) + } + window.addEventListener("message", handler) + onCleanup(() => window.removeEventListener("message", handler)) + + // ----- Export ----- + const handleExport = () => { + if (exporting()) return + setExporting(true) + const token = ++epoch + vscode.postMessage({ type: "requestGlobalConfig" }) + setTimeout(() => { + if (epoch === token) setExporting(false) + }, 5000) + } + + // ----- Import ----- + const handleImport = () => { + if (importing()) return + const input = document.createElement("input") + input.type = "file" + input.accept = ".json" + input.style.display = "none" + input.addEventListener("change", () => { + const file = input.files?.[0] + if (!file) return + if (file.size > MAX_IMPORT_SIZE) { + showToast({ variant: "error", title: language.t("settings.aboutKiloCode.importSettings.tooLarge") }) + return + } + setImporting(true) + const reader = new FileReader() + reader.onload = () => { + setImporting(false) + const text = reader.result as string + const result = parseImport(text) + if (!result.ok) { + const key = + result.error === "invalidJson" + ? "settings.aboutKiloCode.importSettings.invalidJson" + : "settings.aboutKiloCode.importSettings.invalidConfig" + showToast({ variant: "error", title: language.t(key) }) + return + } + if (result.warning === "newerVersion") { + showToast({ + variant: "default", + title: language.t("settings.aboutKiloCode.importSettings.newerVersion"), + }) + } + updateConfig(result.config) + showToast({ + variant: "success", + title: language.t("settings.aboutKiloCode.importSettings.success"), + }) + } + reader.onerror = () => { + setImporting(false) + showToast({ variant: "error", title: language.t("settings.aboutKiloCode.importSettings.invalidJson") }) + } + reader.readAsText(file) + }) + document.body.appendChild(input) + input.click() + document.body.removeChild(input) + } + const getStatusColor = () => { switch (props.connectionState) { case "connected": @@ -158,6 +248,31 @@ const AboutKiloCodeTab: Component = (props) => {
+ {/* Settings Transfer */} +
+

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

+

+ {language.t("settings.aboutKiloCode.settingsTransfer.description")} +

+
+ + +
+
+ {/* legacy-migration start */}

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

diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/settings-io.ts b/packages/kilo-vscode/webview-ui/src/components/settings/settings-io.ts new file mode 100644 index 00000000000..ea46f235d27 --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/components/settings/settings-io.ts @@ -0,0 +1,130 @@ +import type { Config } from "../../types/messages" +import { deepMerge } from "../../utils/config-utils" + +/** Maximum import file size in bytes (1 MB). */ +export const MAX_IMPORT_SIZE = 1_048_576 + +/** Current export format version. */ +export const META_VERSION = 1 + +/** Top-level keys recognised as valid Config fields. */ +export const KNOWN_KEYS: ReadonlyArray = [ + "permission", + "model", + "small_model", + "default_agent", + "agent", + "provider", + "disabled_providers", + "enabled_providers", + "mcp", + "command", + "instructions", + "skills", + "snapshot", + "share", + "username", + "watcher", + "formatter", + "lsp", + "compaction", + "tools", + "layout", + "experimental", +] + +export type ImportError = "invalidJson" | "invalidConfig" | "tooLarge" +export type ImportWarning = "newerVersion" + +export type ImportResult = { ok: true; config: Config; warning?: ImportWarning } | { ok: false; error: ImportError } + +interface ExportMeta { + version: number + exportedAt: string +} + +// --------------------------------------------------------------------------- +// Export +// --------------------------------------------------------------------------- + +/** + * Build a JSON-serialisable export payload from the current config. + * All fields are included as-is so the export is a complete snapshot + * that can be imported on another instance without re-entering secrets. + */ +export function buildExport(cfg: Config): Record { + const meta: ExportMeta = { + version: META_VERSION, + exportedAt: new Date().toISOString(), + } + + const out: Record = { _meta: meta } + + for (const [key, value] of Object.entries(cfg)) { + if (value === undefined || value === null) continue + out[key] = value + } + + return out +} + +// --------------------------------------------------------------------------- +// Import +// --------------------------------------------------------------------------- + +/** + * Parse a raw JSON string into a validated Config. + * Unknown keys and `_meta` are stripped. Returns an error tag on failure + * or a warning when the file was exported from a newer version. + */ +export function parseImport(json: string): ImportResult { + let data: unknown + try { + data = JSON.parse(json) + } catch { + return { ok: false, error: "invalidJson" } + } + + if (typeof data !== "object" || data === null || Array.isArray(data)) { + return { ok: false, error: "invalidJson" } + } + + const obj = data as Record + + // Check for newer version warning + let warning: ImportWarning | undefined + const meta = obj._meta + if (typeof meta === "object" && meta !== null && !Array.isArray(meta)) { + const version = (meta as Record).version + if (typeof version === "number" && version > META_VERSION) { + warning = "newerVersion" + } + } + + // Keep only known config keys + const config: Record = {} + for (const key of KNOWN_KEYS) { + if (key in obj && obj[key] !== undefined) { + config[key] = obj[key] + } + } + + // Must have at least one known key + if (Object.keys(config).length === 0) { + return { ok: false, error: "invalidConfig" } + } + + return warning ? { ok: true, config: config as Config, warning } : { ok: true, config: config as Config } +} + +// --------------------------------------------------------------------------- +// Merge +// --------------------------------------------------------------------------- + +/** + * Deep-merge imported config on top of existing config. + * Imported values take precedence; existing values not in import are preserved. + */ +export function mergeConfig(existing: Config, imported: Config): Config { + return deepMerge(existing, imported) +} diff --git a/packages/kilo-vscode/webview-ui/src/context/worktree-mode.tsx b/packages/kilo-vscode/webview-ui/src/context/worktree-mode.tsx index 662c5805a46..d1c9ee23b2c 100644 --- a/packages/kilo-vscode/webview-ui/src/context/worktree-mode.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/worktree-mode.tsx @@ -14,22 +14,14 @@ export type SessionMode = "local" | "worktree" interface WorktreeModeContextValue { mode: Accessor setMode: (mode: SessionMode) => void - /** Active pending tab ID (e.g. "pending:1") — set by Agent Manager so PromptInput can key drafts per tab. */ - pendingId: Accessor - setPendingId: (id: string | undefined) => void } const WorktreeModeContext = createContext() export const WorktreeModeProvider: ParentComponent = (props) => { const [mode, setMode] = createSignal("local") - const [pendingId, setPendingId] = createSignal() - return ( - - {props.children} - - ) + return {props.children} } /** diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index b727ed6ae26..ac8b73e92e1 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -968,6 +968,16 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "إعادة تعيين جميع إعدادات إضافة Kilo Code إلى قيمها الافتراضية. لا يؤثر هذا على تكوين CLI أو الواجهة الخلفية.", "settings.aboutKiloCode.resetSettings.button": "إعادة تعيين جميع الإعدادات", + "settings.aboutKiloCode.settingsTransfer.title": "نقل الإعدادات", + "settings.aboutKiloCode.settingsTransfer.description": "تصدير أو استيراد إعداداتك لنقلها بين نُسخ VS Code.", + "settings.aboutKiloCode.exportSettings": "تصدير", + "settings.aboutKiloCode.importSettings": "استيراد", + "settings.aboutKiloCode.importSettings.invalidJson": "ملف JSON غير صالح. يرجى اختيار ملف إعدادات صالح.", + "settings.aboutKiloCode.importSettings.invalidConfig": "الملف لا يحتوي على إعدادات Kilo صالحة.", + "settings.aboutKiloCode.importSettings.tooLarge": "الملف كبير جدًا. يجب أن تكون ملفات الإعدادات أقل من 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "تم تصدير هذا الملف من إصدار أحدث من Kilo. قد يتم تجاهل بعض الإعدادات.", + "settings.aboutKiloCode.importSettings.success": "تم استيراد الإعدادات. راجع التغييرات أعلاه، ثم انقر على حفظ.", "settings.agentBehaviour.subtab.modes": "الأوضاع", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 719a3314cba..b2edcbca372 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -977,6 +977,20 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Redefinir todas as configurações da extensão Kilo Code para os valores padrão. Isso não afeta a configuração do CLI ou do backend.", "settings.aboutKiloCode.resetSettings.button": "Redefinir Todas as Configurações", + "settings.aboutKiloCode.settingsTransfer.title": "Transferência de configurações", + "settings.aboutKiloCode.settingsTransfer.description": + "Exporte ou importe suas configurações para transferi-las entre instâncias do VS Code.", + "settings.aboutKiloCode.exportSettings": "Exportar", + "settings.aboutKiloCode.importSettings": "Importar", + "settings.aboutKiloCode.importSettings.invalidJson": + "Arquivo JSON inválido. Selecione um arquivo de configurações válido.", + "settings.aboutKiloCode.importSettings.invalidConfig": "O arquivo não contém configurações válidas do Kilo.", + "settings.aboutKiloCode.importSettings.tooLarge": + "O arquivo é muito grande. Arquivos de configurações devem ter menos de 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Este arquivo foi exportado de uma versão mais recente do Kilo. Algumas configurações podem ser ignoradas.", + "settings.aboutKiloCode.importSettings.success": + "Configurações importadas. Revise as alterações acima e clique em Salvar.", "settings.agentBehaviour.subtab.modes": "Modos", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 451dd808444..2f989657a50 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -981,6 +981,18 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Resetujte sve postavke Kilo Code ekstenzije na zadane vrijednosti. Ovo ne utiče na CLI ili backend konfiguraciju.", "settings.aboutKiloCode.resetSettings.button": "Resetuj sve postavke", + "settings.aboutKiloCode.settingsTransfer.title": "Prijenos postavki", + "settings.aboutKiloCode.settingsTransfer.description": + "Izvezite ili uvezite postavke za prijenos između VS Code instanci.", + "settings.aboutKiloCode.exportSettings": "Izvezi", + "settings.aboutKiloCode.importSettings": "Uvezi", + "settings.aboutKiloCode.importSettings.invalidJson": "Nevažeći JSON fajl. Odaberite važeći fajl s postavkama.", + "settings.aboutKiloCode.importSettings.invalidConfig": "Fajl ne sadrži važeće Kilo postavke.", + "settings.aboutKiloCode.importSettings.tooLarge": "Fajl je prevelik. Fajlovi s postavkama moraju biti manji od 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Ovaj fajl je izvezen iz novije verzije Kilo-a. Neke postavke mogu biti zanemarene.", + "settings.aboutKiloCode.importSettings.success": + "Postavke su uvezene. Pregledajte promjene iznad, a zatim kliknite Sačuvaj.", "settings.agentBehaviour.subtab.modes": "Modovi", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 3f148b55c83..d0cc455b133 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -975,6 +975,18 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Nulstil alle Kilo Code-udvidelsesindstillinger til standardværdierne. Dette påvirker ikke CLI- eller backend-konfiguration.", "settings.aboutKiloCode.resetSettings.button": "Nulstil alle indstillinger", + "settings.aboutKiloCode.settingsTransfer.title": "Overførsel af indstillinger", + "settings.aboutKiloCode.settingsTransfer.description": + "Eksportér eller importér dine indstillinger for at overføre dem mellem VS Code-instanser.", + "settings.aboutKiloCode.exportSettings": "Eksportér", + "settings.aboutKiloCode.importSettings": "Importér", + "settings.aboutKiloCode.importSettings.invalidJson": "Ugyldig JSON-fil. Vælg venligst en gyldig indstillingsfil.", + "settings.aboutKiloCode.importSettings.invalidConfig": "Filen indeholder ikke gyldige Kilo-indstillinger.", + "settings.aboutKiloCode.importSettings.tooLarge": "Filen er for stor. Indstillingsfiler skal være under 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Denne fil blev eksporteret fra en nyere version af Kilo. Nogle indstillinger kan blive ignoreret.", + "settings.aboutKiloCode.importSettings.success": + "Indstillinger importeret. Gennemgå ændringerne ovenfor, og klik derefter på Gem.", "settings.agentBehaviour.subtab.modes": "Tilstande", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index e5d5a9fd9c7..8ff2588e346 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -988,6 +988,20 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Alle Kilo Code-Erweiterungseinstellungen auf Standardwerte zurücksetzen. Dies hat keinen Einfluss auf die CLI- oder Backend-Konfiguration.", "settings.aboutKiloCode.resetSettings.button": "Alle Einstellungen zurücksetzen", + "settings.aboutKiloCode.settingsTransfer.title": "Einstellungen übertragen", + "settings.aboutKiloCode.settingsTransfer.description": + "Exportieren oder importieren Sie Ihre Einstellungen, um sie zwischen VS Code-Instanzen zu übertragen.", + "settings.aboutKiloCode.exportSettings": "Exportieren", + "settings.aboutKiloCode.importSettings": "Importieren", + "settings.aboutKiloCode.importSettings.invalidJson": + "Ungültige JSON-Datei. Bitte wählen Sie eine gültige Einstellungsdatei aus.", + "settings.aboutKiloCode.importSettings.invalidConfig": "Die Datei enthält keine gültigen Kilo-Einstellungen.", + "settings.aboutKiloCode.importSettings.tooLarge": + "Die Datei ist zu groß. Einstellungsdateien müssen kleiner als 1 MB sein.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Diese Datei wurde mit einer neueren Version von Kilo exportiert. Einige Einstellungen werden möglicherweise ignoriert.", + "settings.aboutKiloCode.importSettings.success": + "Einstellungen importiert. Überprüfen Sie die obigen Änderungen und klicken Sie dann auf Speichern.", "settings.agentBehaviour.subtab.modes": "Modi", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 1082423fa44..213bded0966 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -974,6 +974,17 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Reset all Kilo Code extension settings to their default values. This does not affect CLI or backend configuration.", "settings.aboutKiloCode.resetSettings.button": "Reset All Settings", + "settings.aboutKiloCode.settingsTransfer.title": "Settings Transfer", + "settings.aboutKiloCode.settingsTransfer.description": + "Export or import your settings to transfer them between VS Code instances.", + "settings.aboutKiloCode.exportSettings": "Export", + "settings.aboutKiloCode.importSettings": "Import", + "settings.aboutKiloCode.importSettings.invalidJson": "Invalid JSON file. Please select a valid settings file.", + "settings.aboutKiloCode.importSettings.invalidConfig": "File does not contain valid Kilo settings.", + "settings.aboutKiloCode.importSettings.tooLarge": "File is too large. Settings files must be under 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "This file was exported from a newer version of Kilo. Some settings may be ignored.", + "settings.aboutKiloCode.importSettings.success": "Settings imported. Review the changes above, then click Save.", "settings.agentBehaviour.subtab.modes": "Modes", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 3c9f4c51751..4302c5187b9 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -982,6 +982,20 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Restablecer todas las configuraciones de la extensión Kilo Code a sus valores predeterminados. Esto no afecta la configuración del CLI o del backend.", "settings.aboutKiloCode.resetSettings.button": "Restablecer toda la configuración", + "settings.aboutKiloCode.settingsTransfer.title": "Transferencia de ajustes", + "settings.aboutKiloCode.settingsTransfer.description": + "Exporta o importa tus ajustes para transferirlos entre instancias de VS Code.", + "settings.aboutKiloCode.exportSettings": "Exportar", + "settings.aboutKiloCode.importSettings": "Importar", + "settings.aboutKiloCode.importSettings.invalidJson": + "Archivo JSON no válido. Seleccione un archivo de ajustes válido.", + "settings.aboutKiloCode.importSettings.invalidConfig": "El archivo no contiene ajustes válidos de Kilo.", + "settings.aboutKiloCode.importSettings.tooLarge": + "El archivo es demasiado grande. Los archivos de ajustes deben ser menores de 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Este archivo fue exportado desde una versión más reciente de Kilo. Algunos ajustes podrían ignorarse.", + "settings.aboutKiloCode.importSettings.success": + "Ajustes importados. Revise los cambios anteriores y luego haga clic en Guardar.", "settings.agentBehaviour.subtab.modes": "Modos", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index d0d6974ca07..fb74537fbdb 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -990,6 +990,20 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Réinitialiser tous les paramètres de l'extension Kilo Code à leurs valeurs par défaut. Cela n'affecte pas la configuration CLI ou backend.", "settings.aboutKiloCode.resetSettings.button": "Réinitialiser tous les paramètres", + "settings.aboutKiloCode.settingsTransfer.title": "Transfert des paramètres", + "settings.aboutKiloCode.settingsTransfer.description": + "Exportez ou importez vos paramètres pour les transférer entre instances VS Code.", + "settings.aboutKiloCode.exportSettings": "Exporter", + "settings.aboutKiloCode.importSettings": "Importer", + "settings.aboutKiloCode.importSettings.invalidJson": + "Fichier JSON invalide. Veuillez sélectionner un fichier de paramètres valide.", + "settings.aboutKiloCode.importSettings.invalidConfig": "Le fichier ne contient pas de paramètres Kilo valides.", + "settings.aboutKiloCode.importSettings.tooLarge": + "Le fichier est trop volumineux. Les fichiers de paramètres doivent faire moins de 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Ce fichier a été exporté depuis une version plus récente de Kilo. Certains paramètres pourraient être ignorés.", + "settings.aboutKiloCode.importSettings.success": + "Paramètres importés. Vérifiez les modifications ci-dessus, puis cliquez sur Enregistrer.", "settings.agentBehaviour.subtab.modes": "Modes", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 26d49373271..a8e298ef97e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -974,6 +974,19 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Kilo Code拡張機能のすべての設定をデフォルト値にリセットします。CLIやバックエンドの設定には影響しません。", "settings.aboutKiloCode.resetSettings.button": "すべての設定をリセット", + "settings.aboutKiloCode.settingsTransfer.title": "設定の移行", + "settings.aboutKiloCode.settingsTransfer.description": + "VS Code インスタンス間で設定を転送するには、エクスポートまたはインポートしてください。", + "settings.aboutKiloCode.exportSettings": "エクスポート", + "settings.aboutKiloCode.importSettings": "インポート", + "settings.aboutKiloCode.importSettings.invalidJson": + "無効な JSON ファイルです。有効な設定ファイルを選択してください。", + "settings.aboutKiloCode.importSettings.invalidConfig": "ファイルに有効な Kilo の設定が含まれていません。", + "settings.aboutKiloCode.importSettings.tooLarge": "ファイルが大きすぎます。設定ファイルは 1 MB 以下にしてください。", + "settings.aboutKiloCode.importSettings.newerVersion": + "このファイルはより新しいバージョンの Kilo からエクスポートされたものです。一部の設定が無視される場合があります。", + "settings.aboutKiloCode.importSettings.success": + "設定をインポートしました。上記の変更内容を確認してから、保存をクリックしてください。", "settings.agentBehaviour.subtab.modes": "モード", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 088d8746038..31b562e318b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -973,6 +973,18 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Kilo Code 확장 프로그램의 모든 설정을 기본값으로 초기화합니다. CLI 또는 백엔드 구성에는 영향을 미치지 않습니다.", "settings.aboutKiloCode.resetSettings.button": "모든 설정 초기화", + "settings.aboutKiloCode.settingsTransfer.title": "설정 이전", + "settings.aboutKiloCode.settingsTransfer.description": + "VS Code 인스턴스 간에 설정을 전송하려면 내보내기 또는 가져오기하세요.", + "settings.aboutKiloCode.exportSettings": "내보내기", + "settings.aboutKiloCode.importSettings": "가져오기", + "settings.aboutKiloCode.importSettings.invalidJson": + "유효하지 않은 JSON 파일입니다. 올바른 설정 파일을 선택해 주세요.", + "settings.aboutKiloCode.importSettings.invalidConfig": "파일에 유효한 Kilo 설정이 포함되어 있지 않습니다.", + "settings.aboutKiloCode.importSettings.tooLarge": "파일이 너무 큽니다. 설정 파일은 1 MB 이하여야 합니다.", + "settings.aboutKiloCode.importSettings.newerVersion": + "이 파일은 더 최신 버전의 Kilo에서 내보낸 것입니다. 일부 설정이 무시될 수 있습니다.", + "settings.aboutKiloCode.importSettings.success": "설정을 가져왔습니다. 위의 변경 사항을 확인한 후 저장을 클릭하세요.", "settings.agentBehaviour.subtab.modes": "모드", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index e1d5e9f4302..f7818d373f2 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -975,6 +975,20 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Reset alle instellingen van de Kilo Code extensie naar hun standaardwaarden. Dit heeft geen invloed op CLI of backend configuratie.", "settings.aboutKiloCode.resetSettings.button": "Alle instellingen resetten", + "settings.aboutKiloCode.settingsTransfer.title": "Instellingen overdragen", + "settings.aboutKiloCode.settingsTransfer.description": + "Exporteer of importeer uw instellingen om ze tussen VS Code-instanties over te dragen.", + "settings.aboutKiloCode.exportSettings": "Exporteren", + "settings.aboutKiloCode.importSettings": "Importeren", + "settings.aboutKiloCode.importSettings.invalidJson": + "Ongeldig JSON-bestand. Selecteer een geldig instellingenbestand.", + "settings.aboutKiloCode.importSettings.invalidConfig": "Het bestand bevat geen geldige Kilo-instellingen.", + "settings.aboutKiloCode.importSettings.tooLarge": + "Het bestand is te groot. Instellingenbestanden moeten kleiner zijn dan 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Dit bestand is geëxporteerd vanuit een nieuwere versie van Kilo. Sommige instellingen worden mogelijk genegeerd.", + "settings.aboutKiloCode.importSettings.success": + "Instellingen geïmporteerd. Controleer de bovenstaande wijzigingen en klik vervolgens op Opslaan.", "settings.agentBehaviour.subtab.modes": "Modi", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index ebde27238fa..485a1d0b668 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -978,6 +978,18 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Tilbakestill alle Kilo Code-utvidelsesinnstillinger til standardverdier. Dette påvirker ikke CLI- eller backend-konfigurasjon.", "settings.aboutKiloCode.resetSettings.button": "Tilbakestill alle innstillinger", + "settings.aboutKiloCode.settingsTransfer.title": "Overføring av innstillinger", + "settings.aboutKiloCode.settingsTransfer.description": + "Eksporter eller importer innstillingene dine for å overføre dem mellom VS Code-instanser.", + "settings.aboutKiloCode.exportSettings": "Eksporter", + "settings.aboutKiloCode.importSettings": "Importer", + "settings.aboutKiloCode.importSettings.invalidJson": "Ugyldig JSON-fil. Vennligst velg en gyldig innstillingsfil.", + "settings.aboutKiloCode.importSettings.invalidConfig": "Filen inneholder ikke gyldige Kilo-innstillinger.", + "settings.aboutKiloCode.importSettings.tooLarge": "Filen er for stor. Innstillingsfiler må være under 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Denne filen ble eksportert fra en nyere versjon av Kilo. Noen innstillinger kan bli ignorert.", + "settings.aboutKiloCode.importSettings.success": + "Innstillinger importert. Gjennomgå endringene ovenfor, og klikk deretter på Lagre.", "settings.agentBehaviour.subtab.modes": "Moduser", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 049bec1e0d7..5db2913b2cf 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -979,6 +979,18 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Zresetuj wszystkie ustawienia rozszerzenia Kilo Code do wartości domyślnych. Nie wpływa to na konfigurację CLI ani backendu.", "settings.aboutKiloCode.resetSettings.button": "Resetuj wszystkie ustawienia", + "settings.aboutKiloCode.settingsTransfer.title": "Przenoszenie ustawień", + "settings.aboutKiloCode.settingsTransfer.description": + "Eksportuj lub importuj ustawienia, aby przenosić je między instancjami VS Code.", + "settings.aboutKiloCode.exportSettings": "Eksportuj", + "settings.aboutKiloCode.importSettings": "Importuj", + "settings.aboutKiloCode.importSettings.invalidJson": "Nieprawidłowy plik JSON. Wybierz prawidłowy plik ustawień.", + "settings.aboutKiloCode.importSettings.invalidConfig": "Plik nie zawiera prawidłowych ustawień Kilo.", + "settings.aboutKiloCode.importSettings.tooLarge": "Plik jest za duży. Pliki ustawień muszą mieć mniej niż 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Ten plik został wyeksportowany z nowszej wersji Kilo. Niektóre ustawienia mogą zostać zignorowane.", + "settings.aboutKiloCode.importSettings.success": + "Ustawienia zaimportowane. Przejrzyj powyższe zmiany, a następnie kliknij Zapisz.", "settings.agentBehaviour.subtab.modes": "Tryby", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 128e711f201..c9b42fbe0a4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -981,6 +981,18 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Сбросить все настройки расширения Kilo Code до значений по умолчанию. Это не влияет на конфигурацию CLI или бэкенда.", "settings.aboutKiloCode.resetSettings.button": "Сбросить все настройки", + "settings.aboutKiloCode.settingsTransfer.title": "Перенос настроек", + "settings.aboutKiloCode.settingsTransfer.description": + "Экспортируйте или импортируйте настройки для переноса между экземплярами VS Code.", + "settings.aboutKiloCode.exportSettings": "Экспорт", + "settings.aboutKiloCode.importSettings": "Импорт", + "settings.aboutKiloCode.importSettings.invalidJson": "Недопустимый файл JSON. Выберите корректный файл настроек.", + "settings.aboutKiloCode.importSettings.invalidConfig": "Файл не содержит допустимых настроек Kilo.", + "settings.aboutKiloCode.importSettings.tooLarge": "Файл слишком большой. Файлы настроек должны быть менее 1 MB.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Этот файл был экспортирован из более новой версии Kilo. Некоторые настройки могут быть проигнорированы.", + "settings.aboutKiloCode.importSettings.success": + "Настройки импортированы. Просмотрите изменения выше и нажмите «Сохранить».", "settings.agentBehaviour.subtab.modes": "Режимы", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 3e1a51b665f..7d812f4fb1a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -969,6 +969,17 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "รีเซ็ตการตั้งค่าส่วนขยาย Kilo Code ทั้งหมดเป็นค่าเริ่มต้น ไม่ส่งผลกระทบต่อการกำหนดค่า CLI หรือแบ็กเอนด์", "settings.aboutKiloCode.resetSettings.button": "รีเซ็ตการตั้งค่าทั้งหมด", + "settings.aboutKiloCode.settingsTransfer.title": "ถ่ายโอนการตั้งค่า", + "settings.aboutKiloCode.settingsTransfer.description": + "ส่งออกหรือนำเข้าการตั้งค่าเพื่อถ่ายโอนระหว่างอินสแตนซ์ VS Code", + "settings.aboutKiloCode.exportSettings": "ส่งออก", + "settings.aboutKiloCode.importSettings": "นำเข้า", + "settings.aboutKiloCode.importSettings.invalidJson": "ไฟล์ JSON ไม่ถูกต้อง กรุณาเลือกไฟล์การตั้งค่าที่ถูกต้อง", + "settings.aboutKiloCode.importSettings.invalidConfig": "ไฟล์ไม่มีการตั้งค่า Kilo ที่ถูกต้อง", + "settings.aboutKiloCode.importSettings.tooLarge": "ไฟล์มีขนาดใหญ่เกินไป ไฟล์การตั้งค่าต้องมีขนาดไม่เกิน 1 MB", + "settings.aboutKiloCode.importSettings.newerVersion": + "ไฟล์นี้ถูกส่งออกจาก Kilo เวอร์ชันใหม่กว่า การตั้งค่าบางรายการอาจถูกข้ามไป", + "settings.aboutKiloCode.importSettings.success": "นำเข้าการตั้งค่าแล้ว ตรวจสอบการเปลี่ยนแปลงด้านบน จากนั้นคลิกบันทึก", "settings.agentBehaviour.subtab.modes": "โหมด", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 85cbbca10fe..07ffb9711bd 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -978,6 +978,18 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "Tüm Kilo Code uzantı ayarlarını varsayılan değerlerine sıfırla. Bu, CLI veya arka uç yapılandırmasını etkilemez.", "settings.aboutKiloCode.resetSettings.button": "Tüm Ayarları Sıfırla", + "settings.aboutKiloCode.settingsTransfer.title": "Ayar Aktarımı", + "settings.aboutKiloCode.settingsTransfer.description": + "Ayarlarınızı VS Code örnekleri arasında aktarmak için dışa veya içe aktarın.", + "settings.aboutKiloCode.exportSettings": "Dışa Aktar", + "settings.aboutKiloCode.importSettings": "İçe Aktar", + "settings.aboutKiloCode.importSettings.invalidJson": "Geçersiz JSON dosyası. Lütfen geçerli bir ayar dosyası seçin.", + "settings.aboutKiloCode.importSettings.invalidConfig": "Dosya geçerli Kilo ayarları içermiyor.", + "settings.aboutKiloCode.importSettings.tooLarge": "Dosya çok büyük. Ayar dosyaları 1 MB altında olmalıdır.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Bu dosya Kilo'nun daha yeni bir sürümünden dışa aktarılmış. Bazı ayarlar göz ardı edilebilir.", + "settings.aboutKiloCode.importSettings.success": + "Ayarlar içe aktarıldı. Yukarıdaki değişiklikleri gözden geçirin, ardından Kaydet'e tıklayın.", "settings.agentBehaviour.subtab.modes": "Modlar", "settings.agentBehaviour.subtab.agents": "Ajanlar", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 43dd9ff31ac..ca2b27cb8ff 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -961,6 +961,15 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "将所有 Kilo Code 扩展设置重置为默认值。这不会影响 CLI 或后端配置。", "settings.aboutKiloCode.resetSettings.button": "重置所有设置", + "settings.aboutKiloCode.settingsTransfer.title": "设置迁移", + "settings.aboutKiloCode.settingsTransfer.description": "导出或导入设置,以便在 VS Code 实例之间传输。", + "settings.aboutKiloCode.exportSettings": "导出", + "settings.aboutKiloCode.importSettings": "导入", + "settings.aboutKiloCode.importSettings.invalidJson": "无效的 JSON 文件。请选择有效的设置文件。", + "settings.aboutKiloCode.importSettings.invalidConfig": "文件不包含有效的 Kilo 设置。", + "settings.aboutKiloCode.importSettings.tooLarge": "文件过大。设置文件必须小于 1 MB。", + "settings.aboutKiloCode.importSettings.newerVersion": "此文件由较新版本的 Kilo 导出。部分设置可能会被忽略。", + "settings.aboutKiloCode.importSettings.success": "设置已导入。请查看上方的更改,然后点击保存。", "settings.agentBehaviour.subtab.modes": "模式", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index b29daf739e6..635328ba589 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -963,6 +963,15 @@ export const dict = { "settings.aboutKiloCode.resetSettings.description": "將所有 Kilo Code 擴充功能設定重置為預設值。這不會影響 CLI 或後端設定。", "settings.aboutKiloCode.resetSettings.button": "重置所有設定", + "settings.aboutKiloCode.settingsTransfer.title": "設定轉移", + "settings.aboutKiloCode.settingsTransfer.description": "匯出或匯入設定,以便在 VS Code 實例之間轉移。", + "settings.aboutKiloCode.exportSettings": "匯出", + "settings.aboutKiloCode.importSettings": "匯入", + "settings.aboutKiloCode.importSettings.invalidJson": "無效的 JSON 檔案。請選擇有效的設定檔。", + "settings.aboutKiloCode.importSettings.invalidConfig": "檔案不包含有效的 Kilo 設定。", + "settings.aboutKiloCode.importSettings.tooLarge": "檔案過大。設定檔必須小於 1 MB。", + "settings.aboutKiloCode.importSettings.newerVersion": "此檔案由較新版本的 Kilo 匯出。部分設定可能會被忽略。", + "settings.aboutKiloCode.importSettings.success": "設定已匯入。請檢視上方的變更,然後點擊儲存。", "settings.agentBehaviour.subtab.modes": "模式", "settings.agentBehaviour.subtab.agents": "Agents", diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index c99670c4ea1..ccec9dd04de 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -722,6 +722,11 @@ export interface ConfigUpdatedMessage { config: Config } +export interface GlobalConfigLoadedMessage { + type: "globalConfigLoaded" + config: Config +} + export interface NotificationSettingsLoadedMessage { type: "notificationSettingsLoaded" settings: { @@ -1260,6 +1265,7 @@ export type ExtensionMessage = | BrowserSettingsLoadedMessage | ConfigLoadedMessage | ConfigUpdatedMessage + | GlobalConfigLoadedMessage | NotificationSettingsLoadedMessage | NotificationsLoadedMessage | AgentManagerSessionMetaMessage @@ -1568,6 +1574,10 @@ export interface RequestConfigMessage { type: "requestConfig" } +export interface RequestGlobalConfigMessage { + type: "requestGlobalConfig" +} + export interface UpdateConfigMessage { type: "updateConfig" config: Partial @@ -1998,6 +2008,7 @@ export type WebviewMessage = | UpdateSettingRequest | RequestBrowserSettingsMessage | RequestConfigMessage + | RequestGlobalConfigMessage | UpdateConfigMessage | RequestNotificationSettingsMessage | ResetAllSettingsRequest From b05c367fd3a0be25d8c9e47caf45736c9d7f3426 Mon Sep 17 00:00:00 2001 From: kirillk Date: Fri, 27 Mar 2026 14:12:53 -0400 Subject: [PATCH 108/261] fix(vscode): fix migration wizard race condition preventing sidebar display Replace navigation-driven migration with state-driven approach to eliminate race conditions between migration check and SettingsEditorProvider's view navigation. The wizard now renders based on a migrationNeeded flag independent of currentView, so all views (sidebar, chat tab, settings tab) show it reliably. Cross-instance broadcast ensures completing migration in any view dismisses the wizard everywhere without resetting the underlying view. Also fix sidebar-specific timing issue where the migration check never fired because sse-connected was missed and initializeConnection wasn't handled. --- packages/kilo-vscode/src/KiloProvider.ts | 22 +++- packages/kilo-vscode/src/extension.ts | 2 +- .../src/kilo-provider/handlers/migration.ts | 14 ++- .../cli-backend/connection-service.ts | 22 ++++ packages/kilo-vscode/webview-ui/src/App.tsx | 119 +++++++++--------- .../src/components/migration/migration.css | 5 +- .../webview-ui/src/types/messages.ts | 15 ++- 7 files changed, 123 insertions(+), 76 deletions(-) diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index 15883cd3e0a..7f2dda1e8e3 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -137,6 +137,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper private unsubscribeNotificationDismiss: (() => void) | null = null private unsubscribeLanguageChange: (() => void) | null = null private unsubscribeProfileChange: (() => void) | null = null + private unsubscribeMigrationComplete: (() => void) | null = null // legacy-migration private initConnectionPromise: Promise | null = null private webviewMessageDisposable: vscode.Disposable | null = null @@ -272,11 +273,13 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper } // legacy-migration start - // Only show the migration wizard once the CLI connection is established so the - // webview has finished loading providers/agents before we navigate to the wizard. - if (reason === "webviewReady" && this.connectionState === "connected") { - void checkAndShowMigrationWizard(this.migrationCtx) - } else if (reason === "sse-connected") { + // 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 @@ -972,6 +975,13 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.postMessage({ type: "profileData", data }) }) + // legacy-migration start + // Subscribe to migration-complete broadcast from any KiloProvider instance + this.unsubscribeMigrationComplete = this.connectionService.onMigrationComplete(() => { + this.postMessage({ type: "migrationState", needed: false }) + }) + // legacy-migration end + // Get current state and push to webview const serverInfo = this.connectionService.getServerInfo() this.connectionState = this.connectionService.getConnectionState() @@ -2655,6 +2665,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper self.migrationCheckInFlight = val }, disposeGlobal: () => this.disposeGlobal(), + broadcastComplete: () => this.connectionService.notifyMigrationComplete(), } } @@ -2676,6 +2687,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.unsubscribeNotificationDismiss?.() this.unsubscribeLanguageChange?.() this.unsubscribeProfileChange?.() + this.unsubscribeMigrationComplete?.() this.webviewMessageDisposable?.dispose() this.trackedSessionIds.clear() this.syncedChildSessions.clear() diff --git a/packages/kilo-vscode/src/extension.ts b/packages/kilo-vscode/src/extension.ts index f5e704bf756..f38b53b3c78 100644 --- a/packages/kilo-vscode/src/extension.ts +++ b/packages/kilo-vscode/src/extension.ts @@ -182,7 +182,7 @@ export function activate(context: vscode.ExtensionContext) { }), // legacy-migration start vscode.commands.registerCommand("kilo-code.new.openMigrationWizard", () => { - provider.postMessage({ type: "navigate", view: "migration" }) + provider.postMessage({ type: "migrationState", needed: true }) }), // legacy-migration end vscode.commands.registerCommand("kilo-code.new.generateTerminalCommand", async () => { diff --git a/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts b/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts index 2a508d4f9cc..5eb1ed51f88 100644 --- a/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts +++ b/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts @@ -31,11 +31,15 @@ export interface MigrationContext { cachedLegacyData: LegacyMigrationData | null migrationCheckInFlight: boolean disposeGlobal(): Promise + broadcastComplete(): void } /** - * Check for legacy data on first run and auto-navigate to the migration wizard + * 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 @@ -58,9 +62,9 @@ export async function checkAndShowMigrationWizard(ctx: MigrationContext): Promis ctx.cachedLegacyData = data console.log("[Kilo New] KiloProvider: 🔄 Legacy data detected, showing migration wizard") - ctx.postMessage({ type: "navigate", view: "migration" }) ctx.postMessage({ - type: "legacyMigrationData", + type: "migrationState", + needed: true, data: { providers: data.providers, mcpServers: data.mcpServers, @@ -120,6 +124,7 @@ export async function handleStartLegacyMigration( ctx.extensionContext as Parameters[0], "completed", ) + ctx.broadcastComplete() } ctx.postMessage({ type: "legacyMigrationComplete", results }) @@ -139,13 +144,14 @@ export async function handleStartLegacyMigration( } } -/** Record that the user skipped migration. */ +/** 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. */ 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 929aa1cbf9a..ff1f08409a1 100644 --- a/packages/kilo-vscode/src/services/cli-backend/connection-service.ts +++ b/packages/kilo-vscode/src/services/cli-backend/connection-service.ts @@ -12,6 +12,7 @@ type SSEEventFilter = (event: Event) => boolean type NotificationDismissListener = (notificationId: string) => void type LanguageChangeListener = (locale: string) => void type ProfileChangeListener = (data: unknown) => void +type MigrationCompleteListener = () => void // Poll /global/health at the same interval as packages/app/src/context/server.tsx. // This provides a second detection channel for server death independent of the SSE heartbeat. @@ -36,6 +37,7 @@ 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() /** * Shared mapping used to resolve session scope for events that don't reliably include a sessionID. @@ -207,6 +209,25 @@ 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 connection state changes. Returns unsubscribe function. */ @@ -228,6 +249,7 @@ export class KiloConnectionService { this.stateListeners.clear() this.notificationDismissListeners.clear() this.profileChangeListeners.clear() + this.migrationCompleteListeners.clear() this.messageSessionIdsByMessageId.clear() this.client = null this.sseClient = null diff --git a/packages/kilo-vscode/webview-ui/src/App.tsx b/packages/kilo-vscode/webview-ui/src/App.tsx index 9f535c0fcfa..8e4c2806f71 100644 --- a/packages/kilo-vscode/webview-ui/src/App.tsx +++ b/packages/kilo-vscode/webview-ui/src/App.tsx @@ -1,4 +1,4 @@ -import { Component, createSignal, createMemo, Switch, Match, onMount, onCleanup } from "solid-js" +import { Component, createSignal, createMemo, Switch, Match, Show, onMount, onCleanup } from "solid-js" import { ThemeProvider } from "@kilocode/kilo-ui/theme" import { DialogProvider } from "@kilocode/kilo-ui/context/dialog" import { MarkedProvider } from "@kilocode/kilo-ui/context/marked" @@ -34,23 +34,8 @@ import { NotificationsProvider } from "./context/notifications" import type { Message as SDKMessage, Part as SDKPart } from "@kilocode/sdk/v2" import "./styles/chat.css" -type ViewType = - | "newTask" - | "marketplace" - | "history" - | "profile" - | "settings" - | "migration" // legacy-migration - | "subAgentViewer" -const VALID_VIEWS = new Set([ - "newTask", - "marketplace", - "history", - "profile", - "settings", - "migration", // legacy-migration - "subAgentViewer", -]) +type ViewType = "newTask" | "marketplace" | "history" | "profile" | "settings" | "subAgentViewer" +const VALID_VIEWS = new Set(["newTask", "marketplace", "history", "profile", "settings", "subAgentViewer"]) /** * Bridge our session store to the DataProvider's expected Data shape. @@ -152,9 +137,12 @@ export const LanguageBridge: Component<{ children: any }> = (props) => { const AppContent: Component = () => { const [currentView, setCurrentView] = createSignal("newTask") const [settingsTab, setSettingsTab] = createSignal() - const [migrationReturnView, setMigrationReturnView] = createSignal("newTask") // legacy-migration + // legacy-migration: state-driven flag independent of currentView to avoid + // race conditions with SettingsEditorProvider's navigate messages. + const [migrationNeeded, setMigrationNeeded] = createSignal(false) const session = useSession() const server = useServer() + const vscode = useVSCode() const handleViewAction = (action: string) => { switch (action) { @@ -216,6 +204,11 @@ 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) + setMigrationNeeded(message.needed) + } } window.addEventListener("message", handler) onCleanup(() => window.removeEventListener("message", handler)) @@ -228,50 +221,50 @@ const AppContent: Component = () => { return (
- }> - - setCurrentView("history")} - continueInWorktree - /> - - - - - - setCurrentView("newTask")} /> - - - - - - { - setMigrationReturnView("settings") - setCurrentView("migration") - }} - /> - {/* legacy-migration */} - - {/* legacy-migration start */} - - setCurrentView(migrationReturnView())} - onComplete={() => setCurrentView(migrationReturnView())} - /> - - {/* legacy-migration end */} - - - - + {/* legacy-migration start — state-driven overlay, independent of currentView */} + }> + + setCurrentView("history")} + continueInWorktree + /> + + + + + + setCurrentView("newTask")} /> + + + + + + { + setMigrationNeeded(true) + vscode.postMessage({ type: "requestLegacyMigrationData" }) + }} + /> + + + + + + } + > + setMigrationNeeded(false)} onComplete={() => setMigrationNeeded(false)} /> + + {/* legacy-migration end */}
) } diff --git a/packages/kilo-vscode/webview-ui/src/components/migration/migration.css b/packages/kilo-vscode/webview-ui/src/components/migration/migration.css index 5a18f5f1477..575b1a62e14 100644 --- a/packages/kilo-vscode/webview-ui/src/components/migration/migration.css +++ b/packages/kilo-vscode/webview-ui/src/components/migration/migration.css @@ -8,12 +8,13 @@ font-size: 13px; color: var(--vscode-foreground); -webkit-font-smoothing: antialiased; - overflow: hidden; + overflow-y: auto; padding: 16px; } .migration-wizard__container { - width: 520px; + max-width: 520px; + width: 100%; } /* Screen transitions */ diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index e5c7a7d96a5..7e7e4c828e6 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -634,7 +634,7 @@ export interface DeviceAuthCancelledMessage { export interface NavigateMessage { type: "navigate" - view: "newTask" | "marketplace" | "history" | "profile" | "settings" | "migration" | "subAgentViewer" // legacy-migration: "migration" + view: "newTask" | "marketplace" | "history" | "profile" | "settings" | "subAgentViewer" tab?: string } @@ -1032,6 +1032,18 @@ export interface MigrationResultItem { message?: string } +export interface MigrationStateMessage { + type: "migrationState" + needed: boolean + data?: { + providers: MigrationProviderInfo[] + mcpServers: MigrationMcpServerInfo[] + customModes: MigrationCustomModeInfo[] + defaultModel?: { provider: string; model: string } + settings?: LegacySettings + } +} + export interface LegacyMigrationDataMessage { type: "legacyMigrationData" data: { @@ -1275,6 +1287,7 @@ export type ExtensionMessage = | AgentManagerWorktreeStatsMessage | AgentManagerLocalStatsMessage // legacy-migration start + | MigrationStateMessage | LegacyMigrationDataMessage | LegacyMigrationProgressMessage | LegacyMigrationCompleteMessage From b67e39186d0d4e9b1f6569675f5b2fe7772ef84e Mon Sep 17 00:00:00 2001 From: Ligia Zanchet Date: Fri, 27 Mar 2026 19:19:35 +0100 Subject: [PATCH 109/261] chore: trigger CI checks From 0262ab1851136adfa7bafd862ceeae3dbb43737c Mon Sep 17 00:00:00 2001 From: kirillk Date: Fri, 27 Mar 2026 14:37:27 -0400 Subject: [PATCH 110/261] fix(vscode): add onMigrationComplete to mock connectionService in test --- .../kilo-vscode/tests/unit/kilo-provider-session-refresh.test.ts | 1 + 1 file changed, 1 insertion(+) 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 4f0e44c986a..d74842073d3 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 @@ -80,6 +80,7 @@ function createConnection(client: ReturnType) { onNotificationDismissed: () => () => undefined, onLanguageChanged: () => () => undefined, onProfileChanged: () => () => undefined, + onMigrationComplete: () => () => undefined, getServerInfo: () => ({ port: 12345 }), getConnectionState: () => "connected" as const, resolveEventSessionId: () => undefined, From cdd46fe7ca118e0cd45b2e457e2ad6162c0e434c Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Fri, 27 Mar 2026 14:40:26 -0400 Subject: [PATCH 111/261] =?UTF-8?q?docs(kilo-docs):=20address=20bot=20revi?= =?UTF-8?q?ew=20=E2=80=94=20orchestrator=20deprecation=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Soften 'every agent' claim in orchestrator-mode.md: ask agent denies the task tool, so only agents with full tool access (Code, Plan, Debug) support subagent delegation - Add deprecation heading and warning callout to orchestrator sections in both VSCode and CLI tabs of using-agents.md --- .../pages/code-with-ai/agents/orchestrator-mode.md | 6 +++--- .../pages/code-with-ai/agents/using-agents.md | 14 +++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md b/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md index 73ec2bc844e..8fb065bcefa 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/orchestrator-mode.md @@ -1,19 +1,19 @@ --- title: "Orchestrator Mode" -description: "Orchestrator mode is no longer needed — all agents now support subagents" +description: "Orchestrator mode is no longer needed — agents with full tool access now support subagents natively" --- # Orchestrator Mode (Deprecated) {% callout type="warning" title="Deprecated — scheduled for removal" %} -Orchestrator mode is deprecated and will be removed in a future release. In the VSCode extension and CLI, **every agent can now delegate to subagents automatically**. You no longer need a dedicated orchestrator — just pick the agent for your task (e.g. Code, Plan, Debug) and it will coordinate subagents when helpful. +Orchestrator mode is deprecated and will be removed in a future release. In the VSCode extension and CLI, **agents with full tool access (Code, Plan, Debug) can now delegate to subagents automatically**. You no longer need a dedicated orchestrator — just pick the agent for your task and it will coordinate subagents when helpful. (Read-only agents like Ask do not support delegation.) {% /callout %} ## What Changed Previously, orchestrator mode was the only way to break complex tasks into subtasks. You had to explicitly switch to orchestrator mode, which would then delegate work to other modes like Code or Architect. -Now, **subagent support is built into every agent**. When any agent encounters a task that would benefit from delegation — like exploring a codebase, running a parallel search, or handling a subtask in isolation — it can launch a subagent directly using the `task` tool. There's no need to switch agents first. +Now, **subagent support is built into agents that have full tool access** (Code, Plan, Debug). When one of these agents encounters a task that would benefit from delegation — like exploring a codebase, running a parallel search, or handling a subtask in isolation — it can launch a subagent directly using the `task` tool. There's no need to switch agents first. ## What You Should Do diff --git a/packages/kilo-docs/pages/code-with-ai/agents/using-agents.md b/packages/kilo-docs/pages/code-with-ai/agents/using-agents.md index 71669e688ce..c03728dfbb9 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/using-agents.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/using-agents.md @@ -71,7 +71,7 @@ Users often confuse `/newtask` and `/smol`. Here's the key difference: | Windows | Ctrl + . | | Linux | Ctrl + . | -You can hold `shift` to move backwards through the list of modes, for example ⌘ + shift + on macOS. +You can hold `shift` to move backwards through the list of modes, for example ⌘ + shift + on macOS. 4. **Accept suggestions:** Click on mode switch suggestions that Kilo Code offers when appropriate @@ -121,7 +121,7 @@ You can hold `shift` to move backwards through the list of modes, for example | **Ideal For** | Tracking down bugs, diagnosing errors, and resolving complex issues | | **Special Features** | Uses a methodical approach of analyzing, narrowing possibilities, and fixing issues | -### orchestrator +### orchestrator (Deprecated) | Aspect | Details | | -------------------- | -------------------------------------------------------------------------------------------------------------------- | @@ -130,6 +130,10 @@ You can hold `shift` to move backwards through the list of modes, for example | **Ideal For** | Breaking down complex projects into manageable subtasks assigned to specialized agents | | **Special Features** | Delegates work to other agents; also has access to the **explore** subagent for codebase exploration | +{% callout type="warning" %} +Orchestrator is deprecated and will be removed in a future release. Agents with full tool access (Code, Plan, Debug) now support subagents natively — there's no need for a dedicated orchestrator. See [Orchestrator Mode (Deprecated)](/docs/code-with-ai/agents/orchestrator-mode) for migration details. +{% /callout %} + {% callout type="info" %} The VSCode extension and CLI do not include a built-in Review agent. Code review workflows can be handled by the **code** agent or via custom agent configurations. {% /callout %} @@ -173,7 +177,7 @@ The VSCode extension and CLI do not include a built-in Review agent. Code review | **Ideal For** | Tracking down bugs, diagnosing errors, and resolving complex issues | | **Special Features** | Uses a methodical approach of analyzing, narrowing possibilities, and fixing issues | -### orchestrator +### orchestrator (Deprecated) | Aspect | Details | | -------------------- | -------------------------------------------------------------------------------------------------------------------- | @@ -182,6 +186,10 @@ The VSCode extension and CLI do not include a built-in Review agent. Code review | **Ideal For** | Breaking down complex projects into manageable subtasks assigned to specialized agents | | **Special Features** | Delegates work to other agents; also has access to the **explore** subagent for codebase exploration | +{% callout type="warning" %} +Orchestrator is deprecated and will be removed in a future release. Agents with full tool access (Code, Plan, Debug) now support subagents natively — there's no need for a dedicated orchestrator. See [Orchestrator Mode (Deprecated)](/docs/code-with-ai/agents/orchestrator-mode) for migration details. +{% /callout %} + {% callout type="info" %} The VSCode extension and CLI do not include a built-in Review agent. Code review workflows can be handled by the **code** agent or via custom agent configurations. {% /callout %} From 8a2296ea4e14e2d485e06be3ec5e912c4d424509 Mon Sep 17 00:00:00 2001 From: kirillk Date: Fri, 27 Mar 2026 15:56:53 -0400 Subject: [PATCH 112/261] fix(vscode): write Kilo auth as OAuth during legacy migration The profile endpoint requires type:"oauth" but migration wrote type:"api" for personal accounts (no org ID), causing an immediate 401. Now always writes the legacy token in OAuth format matching device-auth structure. --- .../src/legacy-migration/migration-service.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/kilo-vscode/src/legacy-migration/migration-service.ts b/packages/kilo-vscode/src/legacy-migration/migration-service.ts index 1fd2b1e6d1c..c0334429415 100644 --- a/packages/kilo-vscode/src/legacy-migration/migration-service.ts +++ b/packages/kilo-vscode/src/legacy-migration/migration-service.ts @@ -374,6 +374,24 @@ async function migrateProvider( 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 From 43811bfa03a78168c87d9d131ed704feaaba1110 Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Sat, 28 Mar 2026 07:57:17 +0000 Subject: [PATCH 113/261] release: v7.1.9 --- bun.lock | 32 +++++++++++++------------- package.json | 2 +- packages/app/package.json | 2 +- packages/desktop-electron/package.json | 2 +- packages/desktop/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++----- packages/kilo-docs/package.json | 2 +- packages/kilo-gateway/package.json | 2 +- packages/kilo-i18n/package.json | 2 +- packages/kilo-telemetry/package.json | 2 +- packages/kilo-ui/package.json | 2 +- packages/kilo-vscode/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/script/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/storybook/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- script/upstream/package.json | 2 +- sdks/vscode/package.json | 2 +- 21 files changed, 41 insertions(+), 41 deletions(-) diff --git a/bun.lock b/bun.lock index 9de6aeed81e..db7e3082de2 100644 --- a/bun.lock +++ b/bun.lock @@ -27,7 +27,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "@kilocode/kilo-i18n": "workspace:*", "@kilocode/kilo-ui": "workspace:*", @@ -79,7 +79,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -112,7 +112,7 @@ }, "packages/desktop-electron": { "name": "@opencode-ai/desktop-electron", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -142,7 +142,7 @@ }, "packages/kilo-docs": { "name": "@kilocode/kilo-docs", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "@docsearch/css": "^4", "@docsearch/js": "^4", @@ -171,7 +171,7 @@ }, "packages/kilo-gateway": { "name": "@kilocode/kilo-gateway", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "@ai-sdk/anthropic": "2.0.65", "@ai-sdk/openai": "2.0.101", @@ -206,7 +206,7 @@ }, "packages/kilo-i18n": { "name": "@kilocode/kilo-i18n", - "version": "7.1.8", + "version": "7.1.9", "devDependencies": { "@tsconfig/node22": "catalog:", "@types/bun": "catalog:", @@ -216,7 +216,7 @@ }, "packages/kilo-telemetry": { "name": "@kilocode/kilo-telemetry", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "@kilocode/kilo-gateway": "workspace:*", "@opentelemetry/api": "1.9.0", @@ -236,7 +236,7 @@ }, "packages/kilo-ui": { "name": "@kilocode/kilo-ui", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "@kobalte/core": "0.13.11", "@opencode-ai/util": "workspace:*", @@ -271,7 +271,7 @@ }, "packages/kilo-vscode": { "name": "kilo-code", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "@anthropic-ai/sdk": "^0.39.0", "@kilocode/kilo-i18n": "workspace:*", @@ -324,7 +324,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "7.1.8", + "version": "7.1.9", "bin": { "kilo": "./bin/kilo", "kilocode": "./bin/kilo", @@ -446,7 +446,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "@kilocode/sdk": "workspace:*", "zod": "catalog:", @@ -460,14 +460,14 @@ }, "packages/script": { "name": "@opencode-ai/script", - "version": "7.1.8", + "version": "7.1.9", "devDependencies": { "@types/bun": "catalog:", }, }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "7.1.8", + "version": "7.1.9", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -478,7 +478,7 @@ }, "packages/storybook": { "name": "@opencode-ai/storybook", - "version": "7.1.8", + "version": "7.1.9", "devDependencies": { "@opencode-ai/ui": "workspace:*", "@solidjs/meta": "catalog:", @@ -501,7 +501,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -548,7 +548,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "7.1.8", + "version": "7.1.9", "dependencies": { "zod": "catalog:", }, diff --git a/package.json b/package.json index 963b46f01af..0ecf83a3c63 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,6 @@ "@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch", "ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch" }, - "version": "7.1.8", + "version": "7.1.9", "peerDependencies": {} } diff --git a/packages/app/package.json b/packages/app/package.json index d30c14b44a2..3a55c236177 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "7.1.8", + "version": "7.1.9", "description": "", "type": "module", "exports": { diff --git a/packages/desktop-electron/package.json b/packages/desktop-electron/package.json index f1170670d0c..37f65e4056d 100644 --- a/packages/desktop-electron/package.json +++ b/packages/desktop-electron/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop-electron", "private": true, - "version": "7.1.8", + "version": "7.1.9", "type": "module", "license": "MIT", "homepage": "https://opencode.ai", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index f21188261bb..50cb18b9d5c 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "7.1.8", + "version": "7.1.9", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 7ad7a611831..bee5ee99c13 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "kilo" name = "Kilo" description = "The open source coding agent." -version = "7.1.8" +version = "7.1.9" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/Kilo-Org/kilocode" @@ -11,26 +11,26 @@ name = "Kilo" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.8/opencode-darwin-arm64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.9/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.8/opencode-darwin-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.9/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.8/opencode-linux-arm64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.9/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.8/opencode-linux-x64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.9/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.8/opencode-windows-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.9/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/kilo-docs/package.json b/packages/kilo-docs/package.json index e72b4ef414c..6a7d7ebc766 100644 --- a/packages/kilo-docs/package.json +++ b/packages/kilo-docs/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-docs", - "version": "7.1.8", + "version": "7.1.9", "private": true, "scripts": { "dev": "next dev --webpack --port 3002", diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index 7f405db613a..f34e197bafe 100644 --- a/packages/kilo-gateway/package.json +++ b/packages/kilo-gateway/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-gateway", - "version": "7.1.8", + "version": "7.1.9", "type": "module", "license": "MIT", "description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration", diff --git a/packages/kilo-i18n/package.json b/packages/kilo-i18n/package.json index 79bd3fef8a5..07517ac4163 100644 --- a/packages/kilo-i18n/package.json +++ b/packages/kilo-i18n/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-i18n", - "version": "7.1.8", + "version": "7.1.9", "type": "module", "license": "MIT", "description": "Kilo-specific i18n translations and overrides", diff --git a/packages/kilo-telemetry/package.json b/packages/kilo-telemetry/package.json index 348c3889482..8295a09104c 100644 --- a/packages/kilo-telemetry/package.json +++ b/packages/kilo-telemetry/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-telemetry", - "version": "7.1.8", + "version": "7.1.9", "type": "module", "license": "MIT", "description": "Telemetry for Kilo CLI - PostHog analytics integration", diff --git a/packages/kilo-ui/package.json b/packages/kilo-ui/package.json index 3847808338d..9b7525e0312 100644 --- a/packages/kilo-ui/package.json +++ b/packages/kilo-ui/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-ui", - "version": "7.1.8", + "version": "7.1.9", "type": "module", "license": "MIT", "exports": { diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index a17db19551a..9f3693b5e31 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -2,7 +2,7 @@ "name": "kilo-code", "displayName": "Kilo Code: AI Coding Agent, Copilot, and Autocomplete", "description": "Open Source AI coding agent that generates code from natural language, automates tasks, and runs terminal commands. Features inline autocomplete, browser automation, automated refactoring, and custom modes for planning, coding, and debugging. Supports 500+ AI models including Claude (Anthropic), Gemini, Grok, GPT, Codex and GLM.", - "version": "7.1.8", + "version": "7.1.9", "icon": "assets/icons/logo-outline-black.png", "galleryBanner": { "color": "#FFFFFF", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index eea2feef59b..8d9afc5db37 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.1.8", + "version": "7.1.9", "name": "@kilocode/cli", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 77b0e576210..30140516b87 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/plugin", - "version": "7.1.8", + "version": "7.1.9", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/script/package.json b/packages/script/package.json index 766ac7ce6b9..cdb36ec1b58 100644 --- a/packages/script/package.json +++ b/packages/script/package.json @@ -8,7 +8,7 @@ "exports": { ".": "./src/index.ts" }, - "version": "7.1.8", + "version": "7.1.9", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 75f3d0dba9b..2a335855008 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/sdk", - "version": "7.1.8", + "version": "7.1.9", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/storybook/package.json b/packages/storybook/package.json index 6a9b097d419..567ac70798b 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -26,7 +26,7 @@ "typescript": "catalog:", "vite": "catalog:" }, - "version": "7.1.8", + "version": "7.1.9", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/ui/package.json b/packages/ui/package.json index db59f5b0409..9a1af1a1b6a 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "7.1.8", + "version": "7.1.9", "type": "module", "license": "MIT", "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index 8dde16c70d2..9011756c653 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "7.1.8", + "version": "7.1.9", "private": true, "type": "module", "license": "MIT", diff --git a/script/upstream/package.json b/script/upstream/package.json index b0148207770..34aa1e7f06e 100644 --- a/script/upstream/package.json +++ b/script/upstream/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/upstream-merge", - "version": "7.1.8", + "version": "7.1.9", "private": true, "type": "module", "description": "Scripts for automating upstream opencode merges into Kilo", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 7d864162e00..e86a8e7d2bd 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "7.1.8", + "version": "7.1.9", "publisher": "sst-dev", "repository": { "type": "git", From f4174e84a053ed0227372e2f7c4eb29b43c8ae5a Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 08:59:48 +0000 Subject: [PATCH 114/261] fix(vscode): replace opencode references with kilo.jsonc in MCP empty state i18n strings Update the mcpEmpty translation key across all 18 locale files to reference kilo.jsonc instead of "opencode config file" and mention that users can ask the agent to add MCP servers for them. --- packages/kilo-vscode/webview-ui/src/i18n/ar.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/br.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/bs.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/da.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/de.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/en.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/es.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/fr.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/ja.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/ko.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/nl.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/no.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/pl.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/ru.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/th.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/tr.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/zh.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/zht.ts | 2 +- 18 files changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index ac8b73e92e1..bca0f4ea785 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1135,7 +1135,8 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "الوسائط", "settings.agentBehaviour.mcpDetail.env": "البيئة", "settings.agentBehaviour.mcpDetail.disabled": "هذا الخادم معطّل.", - "settings.agentBehaviour.mcpEmpty": "لم يتم تهيئة خوادم MCP. قم بتحرير ملف تهيئة opencode لإضافة خوادم MCP.", + "settings.agentBehaviour.mcpEmpty": + "لم يتم تهيئة خوادم MCP. أضف خوادم MCP في kilo.jsonc، أو اطلب من الوكيل إضافتها لك.", "settings.agentBehaviour.workflowsPlaceholder": "تُدار سير العمل عبر ملفات سير العمل في مساحة العمل.", "settings.agentBehaviour.workflows.description": "سير العمل هي أوامر شرطة مائلة مخصصة محددة في التهيئة الخاصة بك. اكتب /command-name في الدردشة لتشغيلها. يتم تهيئة الأوامر في opencode.json ضمن قسم 'command'.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index b2edcbca372..1cb8a7e824f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1157,7 +1157,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "Ambiente", "settings.agentBehaviour.mcpDetail.disabled": "Este servidor está desativado.", "settings.agentBehaviour.mcpEmpty": - "Nenhum servidor MCP configurado. Edite o arquivo de configuração do opencode para adicionar servidores MCP.", + "Nenhum servidor MCP configurado. Adicione servidores MCP em kilo.jsonc ou peça ao agente para adicioná-los.", "settings.agentBehaviour.workflowsPlaceholder": "Fluxos de trabalho são gerenciados por arquivos de fluxo de trabalho no espaço de trabalho.", "settings.agentBehaviour.workflows.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 2f989657a50..cb2a7161a31 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1153,7 +1153,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "Okruženje", "settings.agentBehaviour.mcpDetail.disabled": "Ovaj server je onemogućen.", "settings.agentBehaviour.mcpEmpty": - "Nema konfiguriranih MCP servera. Uredite konfiguracijsku datoteku opencode za dodavanje MCP servera.", + "Nema konfiguriranih MCP servera. Dodajte MCP servere u kilo.jsonc ili zamolite agenta da ih doda.", "settings.agentBehaviour.workflowsPlaceholder": "Tokovi rada se upravljaju putem datoteka tokova rada.", "settings.agentBehaviour.workflows.description": "Tokovi rada su prilagođene slash komande definirane u vašoj konfiguraciji. Upišite /command-name u chat da ih pokrenete. Komande se konfiguriraju u opencode.json pod sekcijom 'command'.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index d0cc455b133..22b89abc970 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1146,7 +1146,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "Miljø", "settings.agentBehaviour.mcpDetail.disabled": "Denne server er deaktiveret.", "settings.agentBehaviour.mcpEmpty": - "Ingen MCP-servere konfigureret. Rediger opencode-konfigurationsfilen for at tilføje MCP-servere.", + "Ingen MCP-servere konfigureret. Tilføj MCP-servere i kilo.jsonc, eller bed agenten om at tilføje dem.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows administreres via workflow-filer i dit arbejdsområde.", "settings.agentBehaviour.workflows.description": "Workflows er brugerdefinerede slash-kommandoer defineret i din konfiguration. Skriv /command-name i chatten for at aktivere dem. Kommandoer konfigureres i opencode.json under sektionen 'command'.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 8ff2588e346..8b289e33340 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1169,7 +1169,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "Umgebung", "settings.agentBehaviour.mcpDetail.disabled": "Dieser Server ist deaktiviert.", "settings.agentBehaviour.mcpEmpty": - "Keine MCP-Server konfiguriert. Bearbeiten Sie die opencode-Konfigurationsdatei, um MCP-Server hinzuzufügen.", + "Keine MCP-Server konfiguriert. Fügen Sie MCP-Server in kilo.jsonc hinzu oder bitten Sie den Agenten, sie hinzuzufügen.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows werden über Workflow-Dateien in Ihrem Arbeitsbereich verwaltet.", "settings.agentBehaviour.workflows.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 213bded0966..7efa69f8b9d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1115,7 +1115,8 @@ export const dict = { "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", "settings.agentBehaviour.addMcp.url": "Server URL", "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", - "settings.agentBehaviour.mcpEmpty": "No MCP servers configured. Edit the opencode config file to add MCP servers.", + "settings.agentBehaviour.mcpEmpty": + "No MCP servers configured. Add MCP servers in kilo.jsonc, or ask the agent to add them for you.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows are managed via workflow files in your workspace.", "settings.agentBehaviour.workflows.description": "Workflows are custom slash commands defined in your config. Type /command-name in the chat to invoke them. Commands are configured in opencode.json under the 'command' section.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 4302c5187b9..8bd2ab5a197 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1161,7 +1161,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "Entorno", "settings.agentBehaviour.mcpDetail.disabled": "Este servidor está deshabilitado.", "settings.agentBehaviour.mcpEmpty": - "No hay servidores MCP configurados. Edite el archivo de configuración de opencode para añadir servidores MCP.", + "No hay servidores MCP configurados. Añada servidores MCP en kilo.jsonc o pida al agente que los añada.", "settings.agentBehaviour.workflowsPlaceholder": "Los flujos de trabajo se gestionan mediante archivos de flujo de trabajo en su espacio de trabajo.", "settings.agentBehaviour.workflows.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index fb74537fbdb..b2306632c54 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1173,7 +1173,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "Environnement", "settings.agentBehaviour.mcpDetail.disabled": "Ce serveur est désactivé.", "settings.agentBehaviour.mcpEmpty": - "Aucun serveur MCP configuré. Modifiez le fichier de configuration opencode pour ajouter des serveurs MCP.", + "Aucun serveur MCP configuré. Ajoutez des serveurs MCP dans kilo.jsonc ou demandez à l'agent de les ajouter.", "settings.agentBehaviour.workflowsPlaceholder": "Les workflows sont gérés via les fichiers de workflow dans votre espace de travail.", "settings.agentBehaviour.workflows.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index a8e298ef97e..48827875bce 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1147,7 +1147,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "環境", "settings.agentBehaviour.mcpDetail.disabled": "このサーバーは無効です。", "settings.agentBehaviour.mcpEmpty": - "MCPサーバーが設定されていません。opencode設定ファイルを編集してMCPサーバーを追加してください。", + "MCPサーバーが設定されていません。kilo.jsoncでMCPサーバーを追加するか、エージェントに追加を依頼してください。", "settings.agentBehaviour.workflowsPlaceholder": "ワークフローはワークスペース内のワークフローファイルを通じて管理されます。", "settings.agentBehaviour.workflows.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 31b562e318b..dc92fe9014a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1141,7 +1141,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "환경", "settings.agentBehaviour.mcpDetail.disabled": "이 서버는 비활성화되어 있습니다.", "settings.agentBehaviour.mcpEmpty": - "MCP 서버가 구성되지 않았습니다. opencode 구성 파일을 편집하여 MCP 서버를 추가하세요.", + "MCP 서버가 구성되지 않았습니다. kilo.jsonc에서 MCP 서버를 추가하거나 에이전트에게 추가를 요청하세요.", "settings.agentBehaviour.workflowsPlaceholder": "워크플로우는 워크스페이스의 워크플로우 파일을 통해 관리됩니다.", "settings.agentBehaviour.workflows.description": "워크플로우는 구성에서 정의된 사용자 정의 슬래시 명령입니다. 채팅에서 /command-name을 입력하여 실행합니다. 명령은 opencode.json의 'command' 섹션에서 구성됩니다.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index f7818d373f2..5380d465630 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1135,7 +1135,7 @@ export const dict = { "settings.agentBehaviour.addMcp.url": "Server-URL", "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.mcpEmpty": - "Geen MCP-servers geconfigureerd. Bewerk het opencode configuratiebestand om MCP-servers toe te voegen.", + "Geen MCP-servers geconfigureerd. Voeg MCP-servers toe in kilo.jsonc of vraag de agent om ze toe te voegen.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows worden beheerd via workflowbestanden in je workspace.", "settings.agentBehaviour.workflows.description": "Workflows zijn aangepaste slash-commando's gedefinieerd in je configuratie. Typ /command-name in de chat om ze aan te roepen. Commando's worden geconfigureerd in opencode.json onder de sectie 'command'.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 485a1d0b668..3b538326b54 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1149,7 +1149,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "Miljø", "settings.agentBehaviour.mcpDetail.disabled": "Denne serveren er deaktivert.", "settings.agentBehaviour.mcpEmpty": - "Ingen MCP-servere konfigurert. Rediger opencode-konfigurasjonsfilen for å legge til MCP-servere.", + "Ingen MCP-servere konfigurert. Legg til MCP-servere i kilo.jsonc, eller be agenten om å legge dem til.", "settings.agentBehaviour.workflowsPlaceholder": "Arbeidsflyter administreres via arbeidsflytfiler i arbeidsområdet.", "settings.agentBehaviour.workflows.description": "Arbeidsflyter er egendefinerte skråstrekkommandoer definert i konfigurasjonen din. Skriv /command-name i chatten for å kjøre dem. Kommandoer konfigureres i opencode.json under seksjonen 'command'.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 5db2913b2cf..59408be763e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1153,7 +1153,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "Środowisko", "settings.agentBehaviour.mcpDetail.disabled": "Ten serwer jest wyłączony.", "settings.agentBehaviour.mcpEmpty": - "Brak skonfigurowanych serwerów MCP. Edytuj plik konfiguracyjny opencode, aby dodać serwery MCP.", + "Brak skonfigurowanych serwerów MCP. Dodaj serwery MCP w kilo.jsonc lub poproś agenta o ich dodanie.", "settings.agentBehaviour.workflowsPlaceholder": "Przepływy pracy zarządzane są za pomocą plików przepływów pracy.", "settings.agentBehaviour.workflows.description": "Przepływy pracy to niestandardowe komendy slash zdefiniowane w konfiguracji. Wpisz /command-name na czacie, aby je uruchomić. Komendy konfiguruje się w opencode.json w sekcji 'command'.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index c9b42fbe0a4..a1a4cf56bb4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1154,7 +1154,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "Окружение", "settings.agentBehaviour.mcpDetail.disabled": "Этот сервер отключён.", "settings.agentBehaviour.mcpEmpty": - "MCP-серверы не настроены. Отредактируйте файл конфигурации opencode для добавления MCP-серверов.", + "MCP-серверы не настроены. Добавьте MCP-серверы в kilo.jsonc или попросите агента добавить их.", "settings.agentBehaviour.workflowsPlaceholder": "Рабочие процессы управляются через файлы рабочих процессов.", "settings.agentBehaviour.workflows.description": "Рабочие процессы — это пользовательские слэш-команды, определённые в вашей конфигурации. Введите /command-name в чате, чтобы вызвать их. Команды настраиваются в opencode.json в разделе 'command'.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 7d812f4fb1a..76d927ec397 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1137,7 +1137,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.env": "สภาพแวดล้อม", "settings.agentBehaviour.mcpDetail.disabled": "เซิร์ฟเวอร์นี้ถูกปิดใช้งาน", "settings.agentBehaviour.mcpEmpty": - "ไม่ได้กำหนดค่าเซิร์ฟเวอร์ MCP แก้ไขไฟล์กำหนดค่า opencode เพื่อเพิ่มเซิร์ฟเวอร์ MCP", + "ไม่ได้กำหนดค่าเซิร์ฟเวอร์ MCP เพิ่มเซิร์ฟเวอร์ MCP ใน kilo.jsonc หรือขอให้เอเจนต์เพิ่มให้คุณ", "settings.agentBehaviour.workflowsPlaceholder": "เวิร์กโฟลว์จัดการผ่านไฟล์เวิร์กโฟลว์ในพื้นที่ทำงาน", "settings.agentBehaviour.workflows.description": "เวิร์กโฟลว์คือคำสั่งสแลชแบบกำหนดเองที่กำหนดไว้ในการตั้งค่าของคุณ พิมพ์ /command-name ในแชทเพื่อเรียกใช้ คำสั่งถูกกำหนดค่าใน opencode.json ภายใต้ส่วน 'command'", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 07ffb9711bd..1028b3e6e36 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1131,7 +1131,7 @@ export const dict = { "settings.agentBehaviour.addMcp.url": "Sunucu URL'si", "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", "settings.agentBehaviour.mcpEmpty": - "Yapılandırılmış MCP sunucusu yok. MCP sunucuları eklemek için opencode yapılandırma dosyasını düzenleyin.", + "Yapılandırılmış MCP sunucusu yok. kilo.jsonc dosyasına MCP sunucuları ekleyin veya ajanın eklemesini isteyin.", "settings.agentBehaviour.workflowsPlaceholder": "İş akışları çalışma alanınızdaki iş akışı dosyaları ile yönetilir.", "settings.agentBehaviour.workflows.description": "İş akışları, yapılandırmanızda tanımlanan özel eğik çizgi komutlarıdır. Çağırmak için sohbette /command-name yazın. Komutlar opencode.json dosyasındaki 'command' bölümünde yapılandırılır.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index ca2b27cb8ff..a3d03e9d8f0 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1121,7 +1121,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "参数", "settings.agentBehaviour.mcpDetail.env": "环境", "settings.agentBehaviour.mcpDetail.disabled": "此服务器已禁用。", - "settings.agentBehaviour.mcpEmpty": "未配置 MCP 服务器。编辑 opencode 配置文件以添加 MCP 服务器。", + "settings.agentBehaviour.mcpEmpty": "未配置 MCP 服务器。在 kilo.jsonc 中添加 MCP 服务器,或让代理为您添加。", "settings.agentBehaviour.workflowsPlaceholder": "工作流通过工作区中的工作流文件管理。", "settings.agentBehaviour.workflows.description": "工作流是在配置中定义的自定义斜杠命令。在聊天中输入 /command-name 来调用它们。命令在 opencode.json 的 'command' 部分中配置。", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 635328ba589..fe15b4f6091 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1124,7 +1124,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "引數", "settings.agentBehaviour.mcpDetail.env": "環境", "settings.agentBehaviour.mcpDetail.disabled": "此伺服器已停用。", - "settings.agentBehaviour.mcpEmpty": "未設定 MCP 伺服器。編輯 opencode 設定檔以新增 MCP 伺服器。", + "settings.agentBehaviour.mcpEmpty": "未設定 MCP 伺服器。在 kilo.jsonc 中新增 MCP 伺服器,或請代理為您新增。", "settings.agentBehaviour.workflowsPlaceholder": "工作流程透過工作區中的工作流程檔案管理。", "settings.agentBehaviour.workflows.description": "工作流程是在設定中定義的自訂斜線命令。在聊天中輸入 /command-name 來呼叫它們。命令在 opencode.json 的 'command' 區段中設定。", From 4e17db82ef65303d318ffeff5e4a26857afdad37 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 15:03:50 +0000 Subject: [PATCH 115/261] fix(vscode): remove fixed width from McpEditView stories to prevent right-side crop --- .../kilo-vscode/webview-ui/src/stories/settings.stories.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx b/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx index 4e46dad733e..5563a5dfed4 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/settings.stories.tsx @@ -232,7 +232,7 @@ export const McpEditViewLocal: Story = { } as any } > -
+
@@ -255,7 +255,7 @@ export const McpEditViewLocalWithEnv: Story = { } as any } > -
+
@@ -277,7 +277,7 @@ export const McpEditViewRemote: Story = { } as any } > -
+
From be1f54ec4f240f9c76bc30b07e0808075e5920a9 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 15:04:17 +0000 Subject: [PATCH 116/261] fix(skills): prevent right-side crop in visual regression stories Do not set explicit width on story wrappers - the Playwright viewport already controls width. Use max-height instead of height to avoid forced scrollbars that eat into available horizontal space and crop screenshots. --- .kilocode/skills/vscode-visual-regression/SKILL.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.kilocode/skills/vscode-visual-regression/SKILL.md b/.kilocode/skills/vscode-visual-regression/SKILL.md index 7b2f3bc0460..35b9eda9659 100644 --- a/.kilocode/skills/vscode-visual-regression/SKILL.md +++ b/.kilocode/skills/vscode-visual-regression/SKILL.md @@ -59,7 +59,7 @@ export const MyStoryName: Story = { name: "MyComponent — description of variant", render: () => ( -
+
@@ -71,7 +71,8 @@ export const MyStoryName: Story = { - **Always start with `/** @jsxImportSource solid-js \*/`\*\* — required for SolidJS JSX compilation. - **Always wrap in ``** — provides all required contexts (VSCode, Server, Config, Provider, Session, I18n, Dialog, Marked, Data, Diff, Code). Without it, components that call `useVSCode()`, `useSession()`, etc. will throw. -- **Set explicit dimensions** on a wrapper div so the screenshot has a deterministic size. Use `width: "420px"` for sidebar-width components (the standard VS Code sidebar). Use `width: "200px"` for narrow/collapsed states. +- **Do NOT set an explicit `width` on the wrapper div.** The Playwright viewport is already 420px wide (or 200px for narrow stories). Setting `width: "420px"` leaves no room for a vertical scrollbar and causes right-side cropping in screenshots. Let the viewport control the width. +- **Use `max-height` not `height` for the wrapper div** when you need to constrain vertical size. A fixed `height` forces a scrollbar even when content is short; `max-height` avoids unnecessary scrollbars that would eat into the available horizontal space. - **Meta `title`** determines the snapshot subdirectory. Use PascalCase or slash-notation (e.g., `"Composite/Webview"`). Playwright transforms it: `"Composite/Webview"` becomes `composite-webview/` in the snapshots folder. - **Export name** determines the story ID. The Storybook ID is `{lowercase-title}--{kebab-export-name}`. For example, `title: "Chat"` + `export const ChatViewIdle` produces ID `chat--chat-view-idle`. - **Snapshot path** is derived automatically: `tests/visual-regression.spec.ts-snapshots/{title-slug}/{variant-slug}.png`. Example: `chat/chat-view-idle-chromium-linux.png`. From 3e201e4ffb2aef7ee8f69294e629704859e83a1c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 28 Mar 2026 15:07:58 +0000 Subject: [PATCH 117/261] chore: update kilo-vscode visual regression baselines --- .../settings/mcp-edit-view-local-chromium-linux.png | 4 ++-- .../settings/mcp-edit-view-local-with-env-chromium-linux.png | 4 ++-- .../settings/mcp-edit-view-remote-chromium-linux.png | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-local-chromium-linux.png b/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-local-chromium-linux.png index 366abced73e..6a0acb42d64 100644 --- a/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-local-chromium-linux.png +++ b/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-local-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:405c61afab864edcc043d8d748d3da797da834aa37dc816c076038f4b1ccdc20 -size 26879 +oid sha256:31d595b148c5efa68c023eff922e1eedf15b2d4e8af91efc18c99b7830238999 +size 26230 diff --git a/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-local-with-env-chromium-linux.png b/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-local-with-env-chromium-linux.png index cd3fbfc1b27..8f6bf7613d5 100644 --- a/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-local-with-env-chromium-linux.png +++ b/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-local-with-env-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:304b25eafdc55e17a4d0f8c310ede9d9ba0e59322ce6da3f5262613dc4300791 -size 27426 +oid sha256:220e3129994f8cb0cb0ead6fc51b9965e0e9cd2ed24269f1a65d065bea4c9d92 +size 26970 diff --git a/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-remote-chromium-linux.png b/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-remote-chromium-linux.png index ae16f78fa17..40f6ee9d981 100644 --- a/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-remote-chromium-linux.png +++ b/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/mcp-edit-view-remote-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9571ed63328ca5aa463d29c14782657a07c3fe9b44dd37c764fe28302f8bee64 -size 13977 +oid sha256:f90ee0aa1073be693836469cfd63e1bb3a2f55edcdc964dae1f68b73b12fc367 +size 12016 From 73d9fd63755049a9d838e84002b8310ce2605822 Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Sat, 28 Mar 2026 22:41:31 -0400 Subject: [PATCH 118/261] docs(kilo-docs): fix tabs, labels, and content in customize section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix mislabeled tabs: new extension content was labeled 'VSCode (Legacy)' in custom-modes.md (2 tabs) and custom-rules.md (3 tabs) - Split all 'VSCode & CLI' combined tabs into separate VSCode and CLI tabs across 7 files (18 combined tabs total) - Reorder all tabs to VSCode → CLI → VSCode (Legacy) - Fix migration skip list: add build and architect to match code - Fix docs-writer example: edit permission now allows *.md instead of denying all edits (matching the .md agent file example) - Fix skills.md: paths support ~/ and relative, name doesn't need to match directory name - Fix kilo.json → kilo.jsonc across all customize pages - Remove 'new extension' wording — just say 'the extension' - Update custom-subagents.md: remove broken new-task tool link, mark orchestrator as deprecated in Related section --- .../kilo-docs/pages/customize/agents-md.md | 72 +- .../customize/context/context-condensing.md | 195 ++- .../pages/customize/context/kilocodeignore.md | 185 ++- .../pages/customize/custom-instructions.md | 100 +- .../kilo-docs/pages/customize/custom-modes.md | 1123 +++++++++-------- .../kilo-docs/pages/customize/custom-rules.md | 366 +++--- .../pages/customize/custom-subagents.md | 9 +- packages/kilo-docs/pages/customize/skills.md | 354 ++++-- 8 files changed, 1409 insertions(+), 995 deletions(-) diff --git a/packages/kilo-docs/pages/customize/agents-md.md b/packages/kilo-docs/pages/customize/agents-md.md index ef47a81316a..a3d19b9b65a 100644 --- a/packages/kilo-docs/pages/customize/agents-md.md +++ b/packages/kilo-docs/pages/customize/agents-md.md @@ -139,6 +139,32 @@ When you start a task in Kilo Code: ### Interaction with Other Rules {% tabs %} +{% tab label="VSCode" %} + +In the new platform, AGENTS.md is loaded alongside other instruction sources. The CLI also supports `.claude/` and `.agents/` directories for compatibility with other tools. + +| Source | Scope | Location | Priority | +| ------------------------------------------------ | --------- | ------------------------------------------ | ---------------- | +| **Agent prompt** | Per-agent | `agent..prompt` in config | 1 (Highest) | +| **[Instructions](/docs/customize/custom-rules)** | Project | `instructions` key in project `kilo.jsonc` | 2 | +| **AGENTS.md** | Project | `AGENTS.md` at project root | 3 | +| **[Instructions](/docs/customize/custom-rules)** | Global | `instructions` key in global `kilo.jsonc` | 4 | +| **[Skills](/docs/customize/skills)** | Both | `.kilo/skills/`, config `skills` key | Loaded on demand | + +{% /tab %} +{% tab label="CLI" %} + +In the new platform, AGENTS.md is loaded alongside other instruction sources. The CLI also supports `.claude/` and `.agents/` directories for compatibility with other tools. + +| Source | Scope | Location | Priority | +| ------------------------------------------------ | --------- | ------------------------------------------ | ---------------- | +| **Agent prompt** | Per-agent | `agent..prompt` in config | 1 (Highest) | +| **[Instructions](/docs/customize/custom-rules)** | Project | `instructions` key in project `kilo.jsonc` | 2 | +| **AGENTS.md** | Project | `AGENTS.md` at project root | 3 | +| **[Instructions](/docs/customize/custom-rules)** | Global | `instructions` key in global `kilo.jsonc` | 4 | +| **[Skills](/docs/customize/skills)** | Both | `.kilo/skills/`, config `skills` key | Loaded on demand | + +{% /tab %} {% tab label="VSCode (Legacy)" %} AGENTS.md works alongside Kilo Code's other configuration systems: @@ -151,25 +177,34 @@ AGENTS.md works alongside Kilo Code's other configuration systems: | **[Global Custom Rules](/docs/customize/custom-rules)** | Global | `~/.kilocode/rules/` | Global Kilo Code rules | 4 | | **[Custom Instructions](/docs/customize/custom-instructions)** | Global | IDE settings | Personal preferences across all projects | 5 (Lowest) | -{% /tab %} -{% tab label="VSCode & CLI" %} - -In the new platform, AGENTS.md is loaded alongside other instruction sources. The CLI also supports `.claude/` and `.agents/` directories for compatibility with other tools. - -| Source | Scope | Location | Priority | -| ------------------------------------------------ | --------- | ----------------------------------------- | ---------------- | -| **Agent prompt** | Per-agent | `agent..prompt` in config | 1 (Highest) | -| **[Instructions](/docs/customize/custom-rules)** | Project | `instructions` key in project `kilo.json` | 2 | -| **AGENTS.md** | Project | `AGENTS.md` at project root | 3 | -| **[Instructions](/docs/customize/custom-rules)** | Global | `instructions` key in global `kilo.json` | 4 | -| **[Skills](/docs/customize/skills)** | Both | `.kilo/skills/`, config `skills` key | Loaded on demand | - {% /tab %} {% /tabs %} ### Enabling/Disabling AGENTS.md {% tabs %} +{% tab label="VSCode" %} + +AGENTS.md is loaded automatically. To disable external skill directories (`.claude/skills/`, `.agents/skills/`), set the environment variable: + +```bash +export KILO_DISABLE_EXTERNAL_SKILLS=true +``` + +AGENTS.md itself cannot be individually disabled — it is always loaded if present. To override its instructions, use higher-priority sources like the `instructions` config key or agent-specific prompts. + +{% /tab %} +{% tab label="CLI" %} + +AGENTS.md is loaded automatically. To disable external skill directories (`.claude/skills/`, `.agents/skills/`), set the environment variable: + +```bash +export KILO_DISABLE_EXTERNAL_SKILLS=true +``` + +AGENTS.md itself cannot be individually disabled — it is always loaded if present. To override its instructions, use higher-priority sources like the `instructions` config key or agent-specific prompts. + +{% /tab %} {% tab label="VSCode (Legacy)" %} AGENTS.md support is **enabled by default**. To disable it, edit `settings.json`: @@ -180,17 +215,6 @@ AGENTS.md support is **enabled by default**. To disable it, edit `settings.json` } ``` -{% /tab %} -{% tab label="VSCode & CLI" %} - -AGENTS.md is loaded automatically. To disable external skill directories (`.claude/skills/`, `.agents/skills/`), set the environment variable: - -```bash -export KILO_DISABLE_EXTERNAL_SKILLS=true -``` - -AGENTS.md itself cannot be individually disabled — it is always loaded if present. To override its instructions, use higher-priority sources like the `instructions` config key or agent-specific prompts. - {% /tab %} {% /tabs %} diff --git a/packages/kilo-docs/pages/customize/context/context-condensing.md b/packages/kilo-docs/pages/customize/context/context-condensing.md index 0dfa3136470..3d010446f35 100644 --- a/packages/kilo-docs/pages/customize/context/context-condensing.md +++ b/packages/kilo-docs/pages/customize/context/context-condensing.md @@ -18,6 +18,136 @@ Every AI model has a maximum context window - a limit on how much text it can pr - Eventually hitting the context limit and being unable to continue {% tabs %} +{% tab label="VSCode" %} + +## The Solution: Auto-Compaction + +The new platform uses a **Compaction** system to manage context automatically. When your conversation approaches the token limit, compaction kicks in and produces a structured summary that captures: + +- The overall goal of the session +- Key discoveries made along the way +- What has been accomplished so far +- Files that were modified + +This summary replaces the earlier conversation history, freeing up context window space while maintaining continuity in your work. + +## How Compaction Works + +### Automatic Compaction + +Compaction triggers automatically when the conversation reaches the `usableWindow` token threshold. The full conversation history is sent to a dedicated **compaction agent**, which produces a structured summary. This happens in the background without interrupting your workflow. + +### Context Pruning + +In addition to compaction, the system can **prune** old tool outputs to reclaim context space incrementally. Tool results older than a 40,000-token recency window are replaced with `"[Old tool result content cleared]"`. This is a lighter-weight mechanism that runs alongside full compaction. + +### Manual Compaction + +You can also trigger compaction manually: + +- **CLI TUI**: Press `c` to compact the current session +- **Extension Webview**: Send a `CompactRequest` message to trigger compaction + +{% callout type="info" %} +There is no `/condense` chat command on the new platform. Use the keybinding or message-based invocation instead. +{% /callout %} + +### The Compaction Process + +When compaction is triggered: + +1. **Threshold Check**: The system detects that context usage has reached the `usableWindow` limit +2. **Agent Summarization**: The full conversation history is sent to a dedicated compaction agent +3. **Structured Summary**: The agent produces a summary covering the goal, discoveries, accomplishments, and modified files +4. **Replacement**: The detailed history is replaced with the compacted summary +5. **Continuation**: You continue working with the freed-up context space + +## Configuration Options + +Compaction is configured in your `kilo.jsonc` file: + +```jsonc +{ + "compaction": { + "auto": true, // Enable or disable automatic compaction + "reserved": 4096, // Number of tokens to reserve (keep free) after compaction + "prune": true, // Enable pruning of old tool outputs beyond the recency window + }, +} +``` + +| Option | Type | Description | +| --------------------- | ------- | ------------------------------------------------------------------------ | +| `compaction.auto` | boolean | Enable or disable automatic compaction when the context threshold is hit | +| `compaction.reserved` | number | Number of tokens to reserve after compaction | +| `compaction.prune` | boolean | Enable pruning of old tool outputs outside the 40K token recency window | + +{% /tab %} +{% tab label="CLI" %} + +## The Solution: Auto-Compaction + +The new platform uses a **Compaction** system to manage context automatically. When your conversation approaches the token limit, compaction kicks in and produces a structured summary that captures: + +- The overall goal of the session +- Key discoveries made along the way +- What has been accomplished so far +- Files that were modified + +This summary replaces the earlier conversation history, freeing up context window space while maintaining continuity in your work. + +## How Compaction Works + +### Automatic Compaction + +Compaction triggers automatically when the conversation reaches the `usableWindow` token threshold. The full conversation history is sent to a dedicated **compaction agent**, which produces a structured summary. This happens in the background without interrupting your workflow. + +### Context Pruning + +In addition to compaction, the system can **prune** old tool outputs to reclaim context space incrementally. Tool results older than a 40,000-token recency window are replaced with `"[Old tool result content cleared]"`. This is a lighter-weight mechanism that runs alongside full compaction. + +### Manual Compaction + +You can also trigger compaction manually: + +- **CLI TUI**: Press `c` to compact the current session +- **Extension Webview**: Send a `CompactRequest` message to trigger compaction + +{% callout type="info" %} +There is no `/condense` chat command on the new platform. Use the keybinding or message-based invocation instead. +{% /callout %} + +### The Compaction Process + +When compaction is triggered: + +1. **Threshold Check**: The system detects that context usage has reached the `usableWindow` limit +2. **Agent Summarization**: The full conversation history is sent to a dedicated compaction agent +3. **Structured Summary**: The agent produces a summary covering the goal, discoveries, accomplishments, and modified files +4. **Replacement**: The detailed history is replaced with the compacted summary +5. **Continuation**: You continue working with the freed-up context space + +## Configuration Options + +Compaction is configured in your `kilo.jsonc` file: + +```jsonc +{ + "compaction": { + "auto": true, // Enable or disable automatic compaction + "reserved": 4096, // Number of tokens to reserve (keep free) after compaction + "prune": true, // Enable pruning of old tool outputs beyond the recency window + }, +} +``` + +| Option | Type | Description | +| --------------------- | ------- | ------------------------------------------------------------------------ | +| `compaction.auto` | boolean | Enable or disable automatic compaction when the context threshold is hit | +| `compaction.reserved` | number | Number of tokens to reserve after compaction | +| `compaction.prune` | boolean | Enable pruning of old tool outputs outside the 40K token recency window | + +{% /tab %} {% tab label="VSCode (Legacy)" %} ## The Solution: Intelligent Condensing @@ -84,71 +214,6 @@ If the condensed summary doesn't capture important details: - Use clear, specific language when describing your tasks - Important context can be reinforced after condensing by reminding Kilo Code of key details -{% /tab %} -{% tab label="VSCode & CLI" %} - -## The Solution: Auto-Compaction - -The new platform uses a **Compaction** system to manage context automatically. When your conversation approaches the token limit, compaction kicks in and produces a structured summary that captures: - -- The overall goal of the session -- Key discoveries made along the way -- What has been accomplished so far -- Files that were modified - -This summary replaces the earlier conversation history, freeing up context window space while maintaining continuity in your work. - -## How Compaction Works - -### Automatic Compaction - -Compaction triggers automatically when the conversation reaches the `usableWindow` token threshold. The full conversation history is sent to a dedicated **compaction agent**, which produces a structured summary. This happens in the background without interrupting your workflow. - -### Context Pruning - -In addition to compaction, the system can **prune** old tool outputs to reclaim context space incrementally. Tool results older than a 40,000-token recency window are replaced with `"[Old tool result content cleared]"`. This is a lighter-weight mechanism that runs alongside full compaction. - -### Manual Compaction - -You can also trigger compaction manually: - -- **CLI TUI**: Press `c` to compact the current session -- **Extension Webview**: Send a `CompactRequest` message to trigger compaction - -{% callout type="info" %} -There is no `/condense` chat command on the new platform. Use the keybinding or message-based invocation instead. -{% /callout %} - -### The Compaction Process - -When compaction is triggered: - -1. **Threshold Check**: The system detects that context usage has reached the `usableWindow` limit -2. **Agent Summarization**: The full conversation history is sent to a dedicated compaction agent -3. **Structured Summary**: The agent produces a summary covering the goal, discoveries, accomplishments, and modified files -4. **Replacement**: The detailed history is replaced with the compacted summary -5. **Continuation**: You continue working with the freed-up context space - -## Configuration Options - -Compaction is configured in your `kilo.json` file: - -```jsonc -{ - "compaction": { - "auto": true, // Enable or disable automatic compaction - "reserved": 4096, // Number of tokens to reserve (keep free) after compaction - "prune": true, // Enable pruning of old tool outputs beyond the recency window - }, -} -``` - -| Option | Type | Description | -| --------------------- | ------- | ------------------------------------------------------------------------ | -| `compaction.auto` | boolean | Enable or disable automatic compaction when the context threshold is hit | -| `compaction.reserved` | number | Number of tokens to reserve after compaction | -| `compaction.prune` | boolean | Enable pruning of old tool outputs outside the 40K token recency window | - {% /tab %} {% /tabs %} diff --git a/packages/kilo-docs/pages/customize/context/kilocodeignore.md b/packages/kilo-docs/pages/customize/context/kilocodeignore.md index 5000534b31e..b956db3bfb2 100644 --- a/packages/kilo-docs/pages/customize/context/kilocodeignore.md +++ b/packages/kilo-docs/pages/customize/context/kilocodeignore.md @@ -14,6 +14,58 @@ If no `.kilocodeignore` file exists, Kilo Code can access all files in the works ## Quick Start {% tabs %} +{% tab label="VSCode" %} + +The primary mechanism for controlling file access is the **permission system** in `kilo.jsonc`. You define tool-level permissions with glob patterns: + +```json +{ + "permission": { + "read": { "*.env": "deny", "*": "allow" }, + "edit": { "dist/**": "deny", "*": "allow" } + } +} +``` + +If you have an existing `.kilocodeignore` file, it is still supported. The **IgnoreMigrator** automatically converts `.kilocodeignore` patterns into permission `deny` rules on `read` and `edit` tools, so your existing rules continue to work without manual changes. + +You can also exclude paths from the file watcher separately using `config.watcher.ignore`: + +```json +{ + "watcher": { + "ignore": ["tmp/**", "logs/**"] + } +} +``` + +{% /tab %} +{% tab label="CLI" %} + +The primary mechanism for controlling file access is the **permission system** in `kilo.jsonc`. You define tool-level permissions with glob patterns: + +```json +{ + "permission": { + "read": { "*.env": "deny", "*": "allow" }, + "edit": { "dist/**": "deny", "*": "allow" } + } +} +``` + +If you have an existing `.kilocodeignore` file, it is still supported. The **IgnoreMigrator** automatically converts `.kilocodeignore` patterns into permission `deny` rules on `read` and `edit` tools, so your existing rules continue to work without manual changes. + +You can also exclude paths from the file watcher separately using `config.watcher.ignore`: + +```json +{ + "watcher": { + "ignore": ["tmp/**", "logs/**"] + } +} +``` + +{% /tab %} {% tab label="VSCode (Legacy)" %} 1. Create a `.kilocodeignore` file at the root of your project. @@ -37,32 +89,6 @@ coverage/ !secrets/README.md ``` -{% /tab %} -{% tab label="VSCode & CLI" %} - -The primary mechanism for controlling file access is the **permission system** in `kilo.json`. You define tool-level permissions with glob patterns: - -```json -{ - "permission": { - "read": { "*.env": "deny", "*": "allow" }, - "edit": { "dist/**": "deny", "*": "allow" } - } -} -``` - -If you have an existing `.kilocodeignore` file, it is still supported. The **IgnoreMigrator** automatically converts `.kilocodeignore` patterns into permission `deny` rules on `read` and `edit` tools, so your existing rules continue to work without manual changes. - -You can also exclude paths from the file watcher separately using `config.watcher.ignore`: - -```json -{ - "watcher": { - "ignore": ["tmp/**", "logs/**"] - } -} -``` - {% /tab %} {% /tabs %} @@ -80,6 +106,32 @@ Patterns are evaluated relative to the workspace root. ## What It Affects {% tabs %} +{% tab label="VSCode" %} + +File access is controlled through **permission-based access control**. Each tool (`read`, `edit`, `glob`, `grep`, `write`, `bash`, etc.) has its own permission rules evaluated against glob patterns. + +In addition to your explicit permission rules: + +- **Hardcoded directory ignores** — 27 directories are always skipped (e.g. `node_modules`, `.git`, `dist`, `build`, `.cache`, `__pycache__`, `vendor`, and others). +- **Hardcoded file pattern ignores** — 11 file patterns are always skipped (e.g. lock files, binary artifacts). +- **`.gitignore` and `.ignore` files** are also respected when listing and searching files. + +If a file is denied by a permission rule, the tool will report that access was blocked. + +{% /tab %} +{% tab label="CLI" %} + +File access is controlled through **permission-based access control**. Each tool (`read`, `edit`, `glob`, `grep`, `write`, `bash`, etc.) has its own permission rules evaluated against glob patterns. + +In addition to your explicit permission rules: + +- **Hardcoded directory ignores** — 27 directories are always skipped (e.g. `node_modules`, `.git`, `dist`, `build`, `.cache`, `__pycache__`, `vendor`, and others). +- **Hardcoded file pattern ignores** — 11 file patterns are always skipped (e.g. lock files, binary artifacts). +- **`.gitignore` and `.ignore` files** are also respected when listing and searching files. + +If a file is denied by a permission rule, the tool will report that access was blocked. + +{% /tab %} {% tab label="VSCode (Legacy)" %} Kilo Code checks `.kilocodeignore` before accessing files in tools like: @@ -93,39 +145,17 @@ Kilo Code checks `.kilocodeignore` before accessing files in tools like: If a file is blocked, Kilo Code will return an "access denied" message and suggest updating your `.kilocodeignore` rules. -{% /tab %} -{% tab label="VSCode & CLI" %} - -File access is controlled through **permission-based access control**. Each tool (`read`, `edit`, `glob`, `grep`, `write`, `bash`, etc.) has its own permission rules evaluated against glob patterns. - -In addition to your explicit permission rules: - -- **Hardcoded directory ignores** — 27 directories are always skipped (e.g. `node_modules`, `.git`, `dist`, `build`, `.cache`, `__pycache__`, `vendor`, and others). -- **Hardcoded file pattern ignores** — 11 file patterns are always skipped (e.g. lock files, binary artifacts). -- **`.gitignore` and `.ignore` files** are also respected when listing and searching files. - -If a file is denied by a permission rule, the tool will report that access was blocked. - {% /tab %} {% /tabs %} ## Configuration Details {% tabs %} -{% tab label="VSCode (Legacy)" %} - -### Visibility in Lists - -By default, ignored files are hidden from file lists. You can show them with a lock icon by enabling: - -Settings -> Context -> **Show .kilocodeignore'd files in lists and searches** - -{% /tab %} -{% tab label="VSCode & CLI" %} +{% tab label="VSCode" %} ### Permission Rules -Permission rules are defined per-tool in `kilo.json`. Patterns are evaluated in order — the last matching rule wins: +Permission rules are defined per-tool in `kilo.jsonc`. Patterns are evaluated in order — the last matching rule wins: ```json { @@ -146,7 +176,7 @@ Permission rules are defined per-tool in `kilo.json`. Patterns are evaluated in ### Migrating from .kilocodeignore -If you already have a `.kilocodeignore` file, you don't need to do anything — the IgnoreMigrator reads your existing patterns and applies them as `deny` rules on `read` and `edit` tools automatically. You can optionally move your rules into `kilo.json` for more granular control (e.g. denying edits but allowing reads). +If you already have a `.kilocodeignore` file, you don't need to do anything — the IgnoreMigrator reads your existing patterns and applies them as `deny` rules on `read` and `edit` tools automatically. You can optionally move your rules into `kilo.jsonc` for more granular control (e.g. denying edits but allowing reads). ### File Watcher Exclusions @@ -160,6 +190,55 @@ The `config.watcher.ignore` setting controls which paths the file watcher skips. } ``` +{% /tab %} +{% tab label="CLI" %} + +### Permission Rules + +Permission rules are defined per-tool in `kilo.jsonc`. Patterns are evaluated in order — the last matching rule wins: + +```json +{ + "permission": { + "read": { + "*.env": "deny", + "secrets/**": "deny", + "*": "allow" + }, + "edit": { + "dist/**": "deny", + "*.lock": "deny", + "*": "allow" + } + } +} +``` + +### Migrating from .kilocodeignore + +If you already have a `.kilocodeignore` file, you don't need to do anything — the IgnoreMigrator reads your existing patterns and applies them as `deny` rules on `read` and `edit` tools automatically. You can optionally move your rules into `kilo.jsonc` for more granular control (e.g. denying edits but allowing reads). + +### File Watcher Exclusions + +The `config.watcher.ignore` setting controls which paths the file watcher skips. This is separate from tool permissions and only affects change detection: + +```json +{ + "watcher": { + "ignore": ["tmp/**", "logs/**", ".build/**"] + } +} +``` + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +### Visibility in Lists + +By default, ignored files are hidden from file lists. You can show them with a lock icon by enabling: + +Settings -> Context -> **Show .kilocodeignore'd files in lists and searches** + {% /tab %} {% /tabs %} @@ -169,6 +248,6 @@ Checkpoint tracking is separate from file access rules. Files blocked by `.kiloc ## Troubleshooting -- **Kilo can't access a file you want:** Remove or narrow the matching rule in `.kilocodeignore` (classic) or adjust the permission rules in `kilo.json` (new extension & CLI). -- **A file still appears in lists:** In the classic extension, check the setting that shows ignored files in lists and searches. In the new extension & CLI, verify your permission and watcher ignore configuration. +- **Kilo can't access a file you want:** Remove or narrow the matching rule in `.kilocodeignore` (legacy) or adjust the permission rules in `kilo.jsonc` (VSCode extension & CLI). +- **A file still appears in lists:** In the legacy extension, check the setting that shows ignored files in lists and searches. In the extension & CLI, verify your permission and watcher ignore configuration. - **`.kilocodeignore` patterns not working in the new platform:** Ensure the file is at the workspace root. The IgnoreMigrator reads it automatically — check that your patterns use valid `.gitignore` syntax. diff --git a/packages/kilo-docs/pages/customize/custom-instructions.md b/packages/kilo-docs/pages/customize/custom-instructions.md index 4682608ba1b..88ec71ab616 100644 --- a/packages/kilo-docs/pages/customize/custom-instructions.md +++ b/packages/kilo-docs/pages/customize/custom-instructions.md @@ -5,60 +5,16 @@ description: "Provide custom instructions to guide Kilo Code" # Custom Instructions -Custom Instructions allow you to personalize how Kilo Code behaves, providing specific guidance that shapes responses, coding style, and decision-making processes. Both the **VSCode** and **VSCode & CLI** versions support custom instructions, though the mechanisms differ. +Custom Instructions allow you to personalize how Kilo Code behaves, providing specific guidance that shapes responses, coding style, and decision-making processes. Both the **VSCode** and **CLI** versions support custom instructions, though the mechanisms differ. ## What Are Custom Instructions? Custom Instructions define specific Extension behaviors, preferences, and constraints beyond Kilo's basic role definition. Examples include coding style, documentation standards, testing requirements, and workflow guidelines. {% tabs %} -{% tab label="VSCode (Legacy)" %} - -## Setting Custom Instructions - -{% callout type="info" title="Custom Instructions vs Rules" %} -Custom Instructions are IDE-wide and are applied across all workspaces and maintain your preferences regardless of which project you're working on. Unlike Instructions, [Custom Rules](/docs/customize/custom-rules) are project specific and allow you to setup workspace-based ruleset. -{% /callout %} - -**How to set them:** - -{% image src="/docs/img/custom-instructions/custom-instructions.png" alt="Kilo Code Modes tab showing global custom instructions interface" width="600" caption="Kilo Code Modes tab showing global custom instructions interface" /%} - -1. **Open Modes Tab:** Click the icon in the Kilo Code top menu bar -2. **Find Section:** Find the "Custom Instructions for All Modes" section -3. **Enter Instructions:** Enter your instructions in the text area -4. **Save Changes:** Click "Done" to save your changes - -#### Mode-Specific Instructions - -Mode-specific instructions can be set using the Modes Tab - - {% image src="/docs/img/custom-instructions/custom-instructions-3.png" alt="Kilo Code Modes tab showing mode-specific custom instructions interface" width="600" caption="Kilo Code Modes tab showing mode-specific custom instructions interface" /%} - * **Open Tab:** Click the icon in the Kilo Code top menu bar - * **Select Mode:** Under the Modes heading, click the button for the mode you want to customize - * **Enter Instructions:** Enter your instructions in the text area under "Mode-specific Custom Instructions (optional)" - * **Save Changes:** Click "Done" to save your changes - - {% callout type="info" title="Global Mode Rules" %} - -If the mode itself is global (not workspace-specific), any custom instructions you set for it will also apply globally for that mode across all workspaces. -{% /callout %} - -## Mode-Specific Instructions from Files - -For version-controlled mode instructions, use the mode rules file paths documented in [Custom Modes](/docs/customize/custom-modes#mode-specific-instructions-via-filesdirectories): - -- Preferred: `.kilo/rules-{mode-slug}/` (directory) -- Fallback: `.kilorules-{mode-slug}` (single file) - -{% callout type="info" title="Legacy Naming Note" %} -Older naming like `.clinerules-{mode-slug}` is not the recommended path for current Kilo mode-specific instructions. -{% /callout %} - -{% /tab %} {% tab label="VSCode" %} -The new extension provides multiple layers of instruction configuration — from per-agent prompts in the Settings UI to auto-discovered files in your project and global config. +The extension provides multiple layers of instruction configuration — from per-agent prompts in the Settings UI to auto-discovered files in your project and global config. ## Per-Agent Prompts @@ -123,10 +79,10 @@ The CLI provides multiple layers of instruction configuration — from per-agent ## Per-Agent Prompts -Each agent can have its own custom prompt defined in its `.md` file (the markdown body) or via the `agent..prompt` key in `kilo.json`: +Each agent can have its own custom prompt defined in its `.md` file (the markdown body) or via the `agent..prompt` key in `kilo.jsonc`: ```jsonc -// kilo.json +// kilo.jsonc { "agent": { "code": { @@ -175,10 +131,10 @@ This is useful for providing context-specific guidance for different parts of a ## Additional Instruction Sources -The `config.instructions` setting accepts an array of paths, globs, or URLs pointing to additional instruction files. Configure these in your `kilo.json`: +The `config.instructions` setting accepts an array of paths, globs, or URLs pointing to additional instruction files. Configure these in your `kilo.jsonc`: ```jsonc -// kilo.json +// kilo.jsonc { "instructions": [ "./docs/coding-standards.md", @@ -196,6 +152,50 @@ URL-based instruction sources are fetched at session start with a 5-second timeo If your project contains `.kilocoderules` files from the VSCode extension, these are still loaded via auto-migration. However, migrating to `AGENTS.md` is recommended for new projects. +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +## Setting Custom Instructions + +{% callout type="info" title="Custom Instructions vs Rules" %} +Custom Instructions are IDE-wide and are applied across all workspaces and maintain your preferences regardless of which project you're working on. Unlike Instructions, [Custom Rules](/docs/customize/custom-rules) are project specific and allow you to setup workspace-based ruleset. +{% /callout %} + +**How to set them:** + +{% image src="/docs/img/custom-instructions/custom-instructions.png" alt="Kilo Code Modes tab showing global custom instructions interface" width="600" caption="Kilo Code Modes tab showing global custom instructions interface" /%} + +1. **Open Modes Tab:** Click the icon in the Kilo Code top menu bar +2. **Find Section:** Find the "Custom Instructions for All Modes" section +3. **Enter Instructions:** Enter your instructions in the text area +4. **Save Changes:** Click "Done" to save your changes + +#### Mode-Specific Instructions + +Mode-specific instructions can be set using the Modes Tab + + {% image src="/docs/img/custom-instructions/custom-instructions-3.png" alt="Kilo Code Modes tab showing mode-specific custom instructions interface" width="600" caption="Kilo Code Modes tab showing mode-specific custom instructions interface" /%} + * **Open Tab:** Click the icon in the Kilo Code top menu bar + * **Select Mode:** Under the Modes heading, click the button for the mode you want to customize + * **Enter Instructions:** Enter your instructions in the text area under "Mode-specific Custom Instructions (optional)" + * **Save Changes:** Click "Done" to save your changes + + {% callout type="info" title="Global Mode Rules" %} + +If the mode itself is global (not workspace-specific), any custom instructions you set for it will also apply globally for that mode across all workspaces. +{% /callout %} + +## Mode-Specific Instructions from Files + +For version-controlled mode instructions, use the mode rules file paths documented in [Custom Modes](/docs/customize/custom-modes#mode-specific-instructions-via-filesdirectories): + +- Preferred: `.kilo/rules-{mode-slug}/` (directory) +- Fallback: `.kilorules-{mode-slug}` (single file) + +{% callout type="info" title="Legacy Naming Note" %} +Older naming like `.clinerules-{mode-slug}` is not the recommended path for current Kilo mode-specific instructions. +{% /callout %} + {% /tab %} {% /tabs %} diff --git a/packages/kilo-docs/pages/customize/custom-modes.md b/packages/kilo-docs/pages/customize/custom-modes.md index 7713e4e2c39..2b7ddcde043 100644 --- a/packages/kilo-docs/pages/customize/custom-modes.md +++ b/packages/kilo-docs/pages/customize/custom-modes.md @@ -15,6 +15,436 @@ Kilo Code allows you to create **custom modes** to tailor Kilo's behavior to spe - **Team Collaboration:** Share custom modes with your team to standardize workflows {% tabs %} +{% tab label="VSCode" %} + +In the VSCode extension and CLI, custom behavioral profiles are called **agents** instead of modes. Agents are defined as Markdown files with YAML frontmatter or as entries in the `agent` key of your config file. + +## What's Included in a Custom Agent? + +| Property | Description | +| --------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| **name** (filename) | The agent's identifier, derived from the `.md` filename (e.g., `docs-writer.md` creates an agent named `docs-writer`) | +| **description** | A short summary displayed in the agent picker and used by the orchestrator for delegation | +| **model** | Pin a specific model in `provider/model` format (e.g., `anthropic/claude-sonnet-4-20250514`) | +| **prompt** (markdown body) | The system prompt text — the markdown body of the file, injected into the agent's system prompt | +| **mode** | Role classification: `primary` (user-selectable), `subagent` (only invoked by other agents), or `all` (both) | +| **permission** | Per-agent permission overrides controlling which tools the agent can use (e.g., deny `edit`, `bash`) | +| **color** | Hex color (`#FF5733`) or theme keyword (`primary`, `accent`, `warning`, etc.) for the agent picker UI | +| **steps** | Maximum agentic iterations before forcing a text-only response | +| **temperature** / **top_p** | Sampling parameters for the agent's model | +| **variant** | Default model variant | +| **hidden** | If `true`, the agent is hidden from the UI (only meaningful for subagents) | +| **disable** | If `true`, removes the agent entirely | + +## Methods for Creating and Configuring Agents + +### 1. Ask Kilo! (Recommended) + +Ask Kilo to create an agent for you: + +``` +Create a new agent called "docs-writer" that can only read files and edit Markdown files. +``` + +Kilo will generate the agent definition and write it to `.kilo/agent/` in your project. + +### 2. Using the Settings UI + +You can manage agents through the **Settings → Agent Behaviour → Agents** subtab in the extension. This lets you view, create, and edit agent configurations — including the agent's prompt, model, permissions, and other properties. + +### 3. Markdown Files with YAML Frontmatter + +Create `.md` files in any of these directories: + +``` +.kilo/agents/my-agent.md +.kilo/agent/my-agent.md +.opencode/agents/my-agent.md +``` + +For global agents, place files in your global config directory: + +``` +~/.config/kilo/agent/my-agent.md +``` + +The **filename** (minus `.md`) becomes the agent name. Nested directories create namespaced names (e.g., `agents/backend/sql.md` becomes agent `backend/sql`). + +**Example agent file** (`.kilo/agents/docs-writer.md`): + +```markdown +--- +description: Specialized for writing and editing technical documentation +mode: primary +color: "#10B981" +permission: + edit: + "*.md": "allow" + "*": "deny" + bash: deny +--- + +You are a technical documentation specialist. Your expertise includes: + +- Writing clear, well-structured documentation +- Following markdown best practices +- Creating helpful code examples + +Focus on clarity and completeness. Only edit Markdown files. +``` + +### 4. Config File (`kilo.jsonc`) + +Define agents under the `agent` key in your project's `kilo.jsonc`: + +```jsonc +{ + "agent": { + "docs-writer": { + "description": "Specialized for writing and editing technical documentation", + "mode": "primary", + "color": "#10B981", + "prompt": "You are a technical documentation specialist...", + "permission": { + "edit": { + "*.md": "allow", + "*": "deny", + }, + "bash": "deny", + }, + }, + // Override a built-in agent + "code": { + "model": "anthropic/claude-sonnet-4-20250514", + "temperature": 0.3, + }, + }, +} +``` + +## Agent Property Reference + +### `mode` + +Controls where the agent appears: + +| Value | Behavior | +| ---------- | -------------------------------------------------------------------------------------- | +| `primary` | Shown in the agent picker — the user can select it directly | +| `subagent` | Only invokable by other agents via the `task` tool | +| `all` | Available both as a top-level pick and as a subagent (default for user-defined agents) | + +### `permission` + +An ordered set of rules controlling tool access. Permissions support three actions: `allow`, `deny`, and `ask` (prompt the user). You can use glob patterns to scope rules to specific files or commands: + +```yaml +permission: + edit: + "*.md": "allow" + "*": "deny" + bash: deny + read: allow +``` + +Known permission types include: `read`, `edit`, `bash`, `glob`, `grep`, `list`, `task`, `webfetch`, `websearch`, `codesearch`, `todowrite`, `todoread`, and more. + +### `model` + +Pin a specific model using the `provider/model` format: + +```yaml +model: anthropic/claude-sonnet-4-20250514 +``` + +### `steps` + +Limits the number of agentic iterations (tool call rounds) before the agent is forced to respond with text only. Useful for preventing runaway agents: + +```yaml +steps: 25 +``` + +## Configuration Precedence + +Agent configurations merge from lowest to highest priority: + +1. Built-in (native) agent defaults +2. Global config (`~/.config/kilo/kilo.jsonc`) +3. Project config (`kilo.jsonc` at project root) +4. `.kilo/` / `.opencode/` directory configs and agent `.md` files +5. Environment variable overrides (`KILO_CONFIG_CONTENT`) + +When the same agent name appears at multiple levels, properties are merged (not replaced wholesale), so you can override just a model or temperature without redefining the entire agent. + +## Overriding Built-in Agents + +Override any built-in agent (**code**, **plan**, **debug**, **ask**, **orchestrator**, **explore**, **general**) by defining an agent with the same name: + +```jsonc +// kilo.jsonc — override the built-in "code" agent +{ + "agent": { + "code": { + "model": "openai/gpt-4o", + "temperature": 0.2, + "permission": { + "edit": { + "*.py": "allow", + "*": "deny", + }, + }, + }, + }, +} +``` + +Or as a `.md` file (`.kilo/agents/code.md`): + +```markdown +--- +model: openai/gpt-4o +temperature: 0.2 +permission: + edit: + "*.py": "allow" + "*": "deny" +--- + +You are a Python specialist. Only edit Python files. +``` + +## Migration from VSCode Extension Modes + +If you have existing `.kilocodemodes` or `custom_modes.yaml` files from the VSCode extension, the extension automatically migrates them on startup. The migration converts: + +- `slug` to the agent name (key) +- `roleDefinition` + `customInstructions` to `prompt` +- `groups` (e.g., `["read", "edit", "browser"]`) to `permission` rules +- `whenToUse` / `description` to `description` +- Mode is set to `primary` + +Built-in mode slugs (`code`, `build`, `architect`, `ask`, `debug`, `orchestrator`) are skipped since they have native agent equivalents. + +{% /tab %} +{% tab label="CLI" %} + +In the CLI, custom behavioral profiles are called **agents** instead of modes. Agents are defined as Markdown files with YAML frontmatter or as entries in the `agent` key of your config file. + +## What's Included in a Custom Agent? + +| Property | Description | +| --------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| **name** (filename) | The agent's identifier, derived from the `.md` filename (e.g., `docs-writer.md` creates an agent named `docs-writer`) | +| **description** | A short summary displayed in the agent picker and used by the orchestrator for delegation | +| **model** | Pin a specific model in `provider/model` format (e.g., `anthropic/claude-sonnet-4-20250514`) | +| **prompt** (markdown body) | The system prompt text — the markdown body of the file, injected into the agent's system prompt | +| **mode** | Role classification: `primary` (user-selectable), `subagent` (only invoked by other agents), or `all` (both) | +| **permission** | Per-agent permission overrides controlling which tools the agent can use (e.g., deny `edit`, `bash`) | +| **color** | Hex color (`#FF5733`) or theme keyword (`primary`, `accent`, `warning`, etc.) for the agent picker UI | +| **steps** | Maximum agentic iterations before forcing a text-only response | +| **temperature** / **top_p** | Sampling parameters for the agent's model | +| **variant** | Default model variant | +| **hidden** | If `true`, the agent is hidden from the UI (only meaningful for subagents) | +| **disable** | If `true`, removes the agent entirely | + +## Methods for Creating and Configuring Agents + +### 1. Ask Kilo! (Recommended) + +Ask Kilo to create an agent for you: + +``` +Create a new agent called "docs-writer" that can only read files and edit Markdown files. +``` + +Kilo will generate the agent definition and write it to `.kilo/agent/` in your project. + +### 2. Using `kilo agent create` + +The CLI provides an interactive command: + +```bash +kilo agent create +``` + +This walks you through selecting a description, mode, and tools, then uses an LLM to generate the agent's system prompt and writes a `.md` file with YAML frontmatter. + +### 3. Markdown Files with YAML Frontmatter + +Create `.md` files in any of these directories: + +``` +.kilo/agents/my-agent.md +.kilo/agent/my-agent.md +.opencode/agents/my-agent.md +``` + +For global agents, place files in your global config directory: + +``` +~/.config/kilo/agent/my-agent.md +``` + +The **filename** (minus `.md`) becomes the agent name. Nested directories create namespaced names (e.g., `agents/backend/sql.md` becomes agent `backend/sql`). + +**Example agent file** (`.kilo/agents/docs-writer.md`): + +```markdown +--- +description: Specialized for writing and editing technical documentation +mode: primary +color: "#10B981" +permission: + edit: + "*.md": "allow" + "*": "deny" + bash: deny +--- + +You are a technical documentation specialist. Your expertise includes: + +- Writing clear, well-structured documentation +- Following markdown best practices +- Creating helpful code examples + +Focus on clarity and completeness. Only edit Markdown files. +``` + +### 4. Config File (`kilo.jsonc`) + +Define agents under the `agent` key in your project's `kilo.jsonc`: + +```jsonc +{ + "agent": { + "docs-writer": { + "description": "Specialized for writing and editing technical documentation", + "mode": "primary", + "color": "#10B981", + "prompt": "You are a technical documentation specialist...", + "permission": { + "edit": { + "*.md": "allow", + "*": "deny", + }, + "bash": "deny", + }, + }, + // Override a built-in agent + "code": { + "model": "anthropic/claude-sonnet-4-20250514", + "temperature": 0.3, + }, + }, +} +``` + +## Agent Property Reference + +### `mode` + +Controls where the agent appears: + +| Value | Behavior | +| ---------- | -------------------------------------------------------------------------------------- | +| `primary` | Shown in the agent picker — the user can select it directly | +| `subagent` | Only invokable by other agents via the `task` tool | +| `all` | Available both as a top-level pick and as a subagent (default for user-defined agents) | + +### `permission` + +An ordered set of rules controlling tool access. Permissions support three actions: `allow`, `deny`, and `ask` (prompt the user). You can use glob patterns to scope rules to specific files or commands: + +```yaml +permission: + edit: + "*.md": "allow" + "*": "deny" + bash: deny + read: allow +``` + +Known permission types include: `read`, `edit`, `bash`, `glob`, `grep`, `list`, `task`, `webfetch`, `websearch`, `codesearch`, `todowrite`, `todoread`, and more. + +### `model` + +Pin a specific model using the `provider/model` format: + +```yaml +model: anthropic/claude-sonnet-4-20250514 +``` + +### `steps` + +Limits the number of agentic iterations (tool call rounds) before the agent is forced to respond with text only. Useful for preventing runaway agents: + +```yaml +steps: 25 +``` + +## Configuration Precedence + +Agent configurations merge from lowest to highest priority: + +1. Built-in (native) agent defaults +2. Global config (`~/.config/kilo/kilo.jsonc`) +3. Project config (`kilo.jsonc` at project root) +4. `.kilo/` / `.opencode/` directory configs and agent `.md` files +5. Environment variable overrides (`KILO_CONFIG_CONTENT`) + +When the same agent name appears at multiple levels, properties are merged (not replaced wholesale), so you can override just a model or temperature without redefining the entire agent. + +## Overriding Built-in Agents + +Override any built-in agent (**code**, **plan**, **debug**, **ask**, **orchestrator**, **explore**, **general**) by defining an agent with the same name: + +```jsonc +// kilo.jsonc — override the built-in "code" agent +{ + "agent": { + "code": { + "model": "openai/gpt-4o", + "temperature": 0.2, + "permission": { + "edit": { + "*.py": "allow", + "*": "deny", + }, + }, + }, + }, +} +``` + +Or as a `.md` file (`.kilo/agents/code.md`): + +```markdown +--- +model: openai/gpt-4o +temperature: 0.2 +permission: + edit: + "*.py": "allow" + "*": "deny" +--- + +You are a Python specialist. Only edit Python files. +``` + +## Migration from VSCode Extension Modes + +If you have existing `.kilocodemodes` or `custom_modes.yaml` files from the VSCode extension, the CLI automatically migrates them on startup. The migration converts: + +- `slug` to the agent name (key) +- `roleDefinition` + `customInstructions` to `prompt` +- `groups` (e.g., `["read", "edit", "browser"]`) to `permission` rules +- `whenToUse` / `description` to `description` +- Mode is set to `primary` + +Built-in mode slugs (`code`, `build`, `architect`, `ask`, `debug`, `orchestrator`) are skipped since they have native agent equivalents. + +{% /tab %} {% tab label="VSCode (Legacy)" %} ## Sticky Models for Efficient Workflow @@ -389,444 +819,15 @@ customModes: - command ``` -{% /tab %} -{% tab label="VSCode (Legacy)" %} - -In the new extension, custom behavioral profiles are called **agents** instead of modes. Agents are defined as Markdown files with YAML frontmatter or as entries in the `agent` key of your config file. - -## What's Included in a Custom Agent? - -| Property | Description | -| --------------------------- | --------------------------------------------------------------------------------------------------------------------- | -| **name** (filename) | The agent's identifier, derived from the `.md` filename (e.g., `docs-writer.md` creates an agent named `docs-writer`) | -| **description** | A short summary displayed in the agent picker and used by the orchestrator for delegation | -| **model** | Pin a specific model in `provider/model` format (e.g., `anthropic/claude-sonnet-4-20250514`) | -| **prompt** (markdown body) | The system prompt text — the markdown body of the file, injected into the agent's system prompt | -| **mode** | Role classification: `primary` (user-selectable), `subagent` (only invoked by other agents), or `all` (both) | -| **permission** | Per-agent permission overrides controlling which tools the agent can use (e.g., deny `edit`, `bash`) | -| **color** | Hex color (`#FF5733`) or theme keyword (`primary`, `accent`, `warning`, etc.) for the agent picker UI | -| **steps** | Maximum agentic iterations before forcing a text-only response | -| **temperature** / **top_p** | Sampling parameters for the agent's model | -| **variant** | Default model variant | -| **hidden** | If `true`, the agent is hidden from the UI (only meaningful for subagents) | -| **disable** | If `true`, removes the agent entirely | - -## Methods for Creating and Configuring Agents - -### 1. Ask Kilo! (Recommended) - -Ask Kilo to create an agent for you: - -``` -Create a new agent called "docs-writer" that can only read files and edit Markdown files. -``` - -Kilo will generate the agent definition and write it to `.kilo/agent/` in your project. - -### 2. Using the Settings UI - -You can manage agents through the **Settings → Agent Behaviour → Agents** subtab in the extension. This lets you view, create, and edit agent configurations — including the agent's prompt, model, permissions, and other properties. - -### 3. Markdown Files with YAML Frontmatter - -Create `.md` files in any of these directories: - -``` -.kilo/agents/my-agent.md -.kilo/agent/my-agent.md -.opencode/agents/my-agent.md -``` - -For global agents, place files in your global config directory: - -``` -~/.config/kilo/agent/my-agent.md -``` - -The **filename** (minus `.md`) becomes the agent name. Nested directories create namespaced names (e.g., `agents/backend/sql.md` becomes agent `backend/sql`). - -**Example agent file** (`.kilo/agents/docs-writer.md`): - -```markdown ---- -description: Specialized for writing and editing technical documentation -mode: primary -color: "#10B981" -permission: - edit: - "*.md": "allow" - "*": "deny" - bash: deny ---- - -You are a technical documentation specialist. Your expertise includes: - -- Writing clear, well-structured documentation -- Following markdown best practices -- Creating helpful code examples - -Focus on clarity and completeness. Only edit Markdown files. -``` - -### 4. Config File (`kilo.json`) - -Define agents under the `agent` key in your project's `kilo.json` (or `opencode.jsonc`): - -```jsonc -{ - "agent": { - "docs-writer": { - "description": "Specialized for writing and editing technical documentation", - "mode": "primary", - "color": "#10B981", - "prompt": "You are a technical documentation specialist...", - "permission": { - "edit": "deny", - "bash": "deny", - }, - }, - // Override a built-in agent - "code": { - "model": "anthropic/claude-sonnet-4-20250514", - "temperature": 0.3, - }, - }, -} -``` - -## Agent Property Reference - -### `mode` - -Controls where the agent appears: - -| Value | Behavior | -| ---------- | -------------------------------------------------------------------------------------- | -| `primary` | Shown in the agent picker — the user can select it directly | -| `subagent` | Only invokable by other agents via the `task` tool | -| `all` | Available both as a top-level pick and as a subagent (default for user-defined agents) | - -### `permission` - -An ordered set of rules controlling tool access. Permissions support three actions: `allow`, `deny`, and `ask` (prompt the user). You can use glob patterns to scope rules to specific files or commands: - -```yaml -permission: - edit: - "*.md": "allow" - "*": "deny" - bash: deny - read: allow -``` - -Known permission types include: `read`, `edit`, `bash`, `glob`, `grep`, `list`, `task`, `webfetch`, `websearch`, `codesearch`, `todowrite`, `todoread`, and more. - -### `model` - -Pin a specific model using the `provider/model` format: - -```yaml -model: anthropic/claude-sonnet-4-20250514 -``` - -### `steps` - -Limits the number of agentic iterations (tool call rounds) before the agent is forced to respond with text only. Useful for preventing runaway agents: - -```yaml -steps: 25 -``` - -## Configuration Precedence - -Agent configurations merge from lowest to highest priority: - -1. Built-in (native) agent defaults -2. Global config (`~/.config/kilo/kilo.json`) -3. Project config (`kilo.json` at project root) -4. `.kilo/` / `.opencode/` directory configs and agent `.md` files -5. Environment variable overrides (`KILO_CONFIG_CONTENT`) - -When the same agent name appears at multiple levels, properties are merged (not replaced wholesale), so you can override just a model or temperature without redefining the entire agent. - -## Overriding Built-in Agents - -Override any built-in agent (**code**, **plan**, **debug**, **ask**, **orchestrator**, **explore**, **general**) by defining an agent with the same name: - -```jsonc -// kilo.json — override the built-in "code" agent -{ - "agent": { - "code": { - "model": "openai/gpt-4o", - "temperature": 0.2, - "permission": { - "edit": { - "*.py": "allow", - "*": "deny", - }, - }, - }, - }, -} -``` - -Or as a `.md` file (`.kilo/agents/code.md`): - -```markdown ---- -model: openai/gpt-4o -temperature: 0.2 -permission: - edit: - "*.py": "allow" - "*": "deny" ---- - -You are a Python specialist. Only edit Python files. -``` - -## Migration from VSCode Extension Modes - -If you have existing `.kilocodemodes` or `custom_modes.yaml` files from the VSCode extension, the new extension automatically migrates them on startup. The migration converts: - -- `slug` to the agent name (key) -- `roleDefinition` + `customInstructions` to `prompt` -- `groups` (e.g., `["read", "edit", "browser"]`) to `permission` rules -- `whenToUse` / `description` to `description` -- Mode is set to `primary` - -Built-in mode slugs (`code`, `ask`, `debug`, `orchestrator`) are skipped since they have native agent equivalents. - -{% /tab %} -{% tab label="CLI" %} - -In the CLI, custom behavioral profiles are called **agents** instead of modes. Agents are defined as Markdown files with YAML frontmatter or as entries in the `agent` key of your config file. - -## What's Included in a Custom Agent? - -| Property | Description | -| --------------------------- | --------------------------------------------------------------------------------------------------------------------- | -| **name** (filename) | The agent's identifier, derived from the `.md` filename (e.g., `docs-writer.md` creates an agent named `docs-writer`) | -| **description** | A short summary displayed in the agent picker and used by the orchestrator for delegation | -| **model** | Pin a specific model in `provider/model` format (e.g., `anthropic/claude-sonnet-4-20250514`) | -| **prompt** (markdown body) | The system prompt text — the markdown body of the file, injected into the agent's system prompt | -| **mode** | Role classification: `primary` (user-selectable), `subagent` (only invoked by other agents), or `all` (both) | -| **permission** | Per-agent permission overrides controlling which tools the agent can use (e.g., deny `edit`, `bash`) | -| **color** | Hex color (`#FF5733`) or theme keyword (`primary`, `accent`, `warning`, etc.) for the agent picker UI | -| **steps** | Maximum agentic iterations before forcing a text-only response | -| **temperature** / **top_p** | Sampling parameters for the agent's model | -| **variant** | Default model variant | -| **hidden** | If `true`, the agent is hidden from the UI (only meaningful for subagents) | -| **disable** | If `true`, removes the agent entirely | - -## Methods for Creating and Configuring Agents - -### 1. Ask Kilo! (Recommended) - -Ask Kilo to create an agent for you: - -``` -Create a new agent called "docs-writer" that can only read files and edit Markdown files. -``` - -Kilo will generate the agent definition and write it to `.kilo/agent/` in your project. - -### 2. Using `kilo agent create` - -The CLI provides an interactive command: - -```bash -kilo agent create -``` - -This walks you through selecting a description, mode, and tools, then uses an LLM to generate the agent's system prompt and writes a `.md` file with YAML frontmatter. - -### 3. Markdown Files with YAML Frontmatter - -Create `.md` files in any of these directories: - -``` -.kilo/agents/my-agent.md -.kilo/agent/my-agent.md -.opencode/agents/my-agent.md -``` - -For global agents, place files in your global config directory: - -``` -~/.config/kilo/agent/my-agent.md -``` - -The **filename** (minus `.md`) becomes the agent name. Nested directories create namespaced names (e.g., `agents/backend/sql.md` becomes agent `backend/sql`). - -**Example agent file** (`.kilo/agents/docs-writer.md`): - -```markdown ---- -description: Specialized for writing and editing technical documentation -mode: primary -color: "#10B981" -permission: - edit: - "*.md": "allow" - "*": "deny" - bash: deny ---- - -You are a technical documentation specialist. Your expertise includes: - -- Writing clear, well-structured documentation -- Following markdown best practices -- Creating helpful code examples - -Focus on clarity and completeness. Only edit Markdown files. -``` - -### 4. Config File (`kilo.json`) - -Define agents under the `agent` key in your project's `kilo.json` (or `opencode.jsonc`): - -```jsonc -{ - "agent": { - "docs-writer": { - "description": "Specialized for writing and editing technical documentation", - "mode": "primary", - "color": "#10B981", - "prompt": "You are a technical documentation specialist...", - "permission": { - "edit": "deny", - "bash": "deny", - }, - }, - // Override a built-in agent - "code": { - "model": "anthropic/claude-sonnet-4-20250514", - "temperature": 0.3, - }, - }, -} -``` - -## Agent Property Reference - -### `mode` - -Controls where the agent appears: - -| Value | Behavior | -| ---------- | -------------------------------------------------------------------------------------- | -| `primary` | Shown in the agent picker — the user can select it directly | -| `subagent` | Only invokable by other agents via the `task` tool | -| `all` | Available both as a top-level pick and as a subagent (default for user-defined agents) | - -### `permission` - -An ordered set of rules controlling tool access. Permissions support three actions: `allow`, `deny`, and `ask` (prompt the user). You can use glob patterns to scope rules to specific files or commands: - -```yaml -permission: - edit: - "*.md": "allow" - "*": "deny" - bash: deny - read: allow -``` - -Known permission types include: `read`, `edit`, `bash`, `glob`, `grep`, `list`, `task`, `webfetch`, `websearch`, `codesearch`, `todowrite`, `todoread`, and more. - -### `model` - -Pin a specific model using the `provider/model` format: - -```yaml -model: anthropic/claude-sonnet-4-20250514 -``` - -### `steps` - -Limits the number of agentic iterations (tool call rounds) before the agent is forced to respond with text only. Useful for preventing runaway agents: - -```yaml -steps: 25 -``` - -## Configuration Precedence - -Agent configurations merge from lowest to highest priority: - -1. Built-in (native) agent defaults -2. Global config (`~/.config/kilo/kilo.json`) -3. Project config (`kilo.json` at project root) -4. `.kilo/` / `.opencode/` directory configs and agent `.md` files -5. Environment variable overrides (`KILO_CONFIG_CONTENT`) - -When the same agent name appears at multiple levels, properties are merged (not replaced wholesale), so you can override just a model or temperature without redefining the entire agent. - -## Overriding Built-in Agents - -Override any built-in agent (**code**, **plan**, **debug**, **ask**, **orchestrator**, **explore**, **general**) by defining an agent with the same name: - -```jsonc -// kilo.json — override the built-in "code" agent -{ - "agent": { - "code": { - "model": "openai/gpt-4o", - "temperature": 0.2, - "permission": { - "edit": { - "*.py": "allow", - "*": "deny", - }, - }, - }, - }, -} -``` - -Or as a `.md` file (`.kilo/agents/code.md`): - -```markdown ---- -model: openai/gpt-4o -temperature: 0.2 -permission: - edit: - "*.py": "allow" - "*": "deny" ---- - -You are a Python specialist. Only edit Python files. -``` - -## Migration from VSCode Extension Modes - -If you have existing `.kilocodemodes` or `custom_modes.yaml` files from the VSCode extension, the CLI automatically migrates them on startup. The migration converts: - -- `slug` to the agent name (key) -- `roleDefinition` + `customInstructions` to `prompt` -- `groups` (e.g., `["read", "edit", "browser"]`) to `permission` rules -- `whenToUse` / `description` to `description` -- Mode is set to `primary` - -Built-in mode slugs (`code`, `ask`, `debug`, `orchestrator`) are skipped since they have native agent equivalents. - {% /tab %} {% /tabs %} ## Understanding Regex in Custom Modes {% tabs %} -{% tab label="VSCode (Legacy)" %} +{% tab label="VSCode" %} -Regular expressions (`fileRegex`) in the **VSCode** version offer fine-grained control over file editing permissions within tool groups. - -{% /tab %} -{% tab label="VSCode & CLI" %} - -The new extension and CLI use **permission rules with glob patterns** instead of regex. Permissions are defined per-tool (e.g., `edit`, `bash`, `read`) and support `allow`, `deny`, and `ask` actions with glob matching: +The extension uses **permission rules with glob patterns** instead of regex. Permissions are defined per-tool (e.g., `edit`, `bash`, `read`) and support `allow`, `deny`, and `ask` actions with glob matching: ```yaml permission: @@ -835,7 +836,26 @@ permission: "*": "deny" ``` -The **VSCode** version's `fileRegex` approach is automatically converted to permission rules during migration. +The **VSCode (Legacy)** version's `fileRegex` approach is automatically converted to permission rules during migration. + +{% /tab %} +{% tab label="CLI" %} + +The CLI uses **permission rules with glob patterns** instead of regex. Permissions are defined per-tool (e.g., `edit`, `bash`, `read`) and support `allow`, `deny`, and `ask` actions with glob matching: + +```yaml +permission: + edit: + "*.md": "allow" + "*": "deny" +``` + +The **VSCode (Legacy)** version's `fileRegex` approach is automatically converted to permission rules during migration. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +Regular expressions (`fileRegex`) in the **VSCode** version offer fine-grained control over file editing permissions within tool groups. {% /tab %} {% /tabs %} @@ -894,63 +914,7 @@ When a mode attempts to edit a file that doesn't match its `fileRegex` pattern, ## Example Configurations {% tabs %} -{% tab label="VSCode (Legacy)" %} - -### Basic Documentation Writer (YAML) - -```yaml -customModes: - - slug: docs-writer - name: 📝 Documentation Writer - description: Specialized for writing and editing technical documentation - roleDefinition: You are a technical writer specializing in clear documentation - groups: - - read - - - edit - - fileRegex: \.md$ - description: Markdown files only - customInstructions: Focus on clear explanations and examples -``` - -### Test Engineer with File Restrictions (YAML) - -```yaml -customModes: - - slug: test-engineer - name: 🧪 Test Engineer - description: Focused on writing and maintaining test suites - roleDefinition: You are a test engineer focused on code quality - whenToUse: Use for writing tests, debugging test failures, and improving test coverage - groups: - - read - - - edit - - fileRegex: \.(test|spec)\.(js|ts)$ - description: Test files only - - command -``` - -### Security Review Mode (YAML) - -```yaml -customModes: - - slug: security-review - name: 🔒 Security Reviewer - description: Read-only security analysis and vulnerability assessment - roleDefinition: You are a security specialist reviewing code for vulnerabilities - whenToUse: Use for security reviews and vulnerability assessments - customInstructions: |- - Focus on: - - Input validation issues - - Authentication and authorization flaws - - Data exposure risks - - Injection vulnerabilities - groups: - - read - - browser -``` - -{% /tab %} -{% tab label="VSCode & CLI" %} +{% tab label="VSCode" %} ### Basic Documentation Writer (`.kilo/agents/docs-writer.md`) @@ -1009,7 +973,7 @@ Focus on: - Injection vulnerabilities ``` -### Config File Example (`kilo.json`) +### Config File Example (`kilo.jsonc`) ```jsonc { @@ -1036,30 +1000,156 @@ Focus on: } ``` +{% /tab %} +{% tab label="CLI" %} + +### Basic Documentation Writer (`.kilo/agents/docs-writer.md`) + +```markdown +--- +description: Specialized for writing and editing technical documentation +mode: primary +color: "#10B981" +permission: + edit: + "*.md": "allow" + "*": "deny" + bash: deny +--- + +You are a technical writer specializing in clear documentation. +Focus on clear explanations and examples. +``` + +### Test Engineer (`.kilo/agents/test-engineer.md`) + +```markdown +--- +description: Focused on writing and maintaining test suites +mode: primary +color: "#F59E0B" +permission: + edit: + "*.{test,spec}.{js,ts}": "allow" + "*": "deny" +--- + +You are a test engineer focused on code quality. +Use for writing tests, debugging test failures, and improving test coverage. +``` + +### Security Reviewer (`.kilo/agents/security-review.md`) + +```markdown +--- +description: Read-only security analysis and vulnerability assessment +mode: primary +color: "#EF4444" +permission: + edit: deny + bash: deny +--- + +You are a security specialist reviewing code for vulnerabilities. + +Focus on: + +- Input validation issues +- Authentication and authorization flaws +- Data exposure risks +- Injection vulnerabilities +``` + +### Config File Example (`kilo.jsonc`) + +```jsonc +{ + "agent": { + "docs-writer": { + "description": "Specialized for writing and editing technical documentation", + "mode": "primary", + "color": "#10B981", + "prompt": "You are a technical writer specializing in clear documentation.", + "permission": { + "edit": { "*.md": "allow", "*": "deny" }, + "bash": "deny", + }, + }, + "test-engineer": { + "description": "Focused on writing and maintaining test suites", + "mode": "primary", + "prompt": "You are a test engineer focused on code quality.", + "permission": { + "edit": { "*.{test,spec}.{js,ts}": "allow", "*": "deny" }, + }, + }, + }, +} +``` + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +### Basic Documentation Writer (YAML) + +```yaml +customModes: + - slug: docs-writer + name: 📝 Documentation Writer + description: Specialized for writing and editing technical documentation + roleDefinition: You are a technical writer specializing in clear documentation + groups: + - read + - - edit + - fileRegex: \.md$ + description: Markdown files only + customInstructions: Focus on clear explanations and examples +``` + +### Test Engineer with File Restrictions (YAML) + +```yaml +customModes: + - slug: test-engineer + name: 🧪 Test Engineer + description: Focused on writing and maintaining test suites + roleDefinition: You are a test engineer focused on code quality + whenToUse: Use for writing tests, debugging test failures, and improving test coverage + groups: + - read + - - edit + - fileRegex: \.(test|spec)\.(js|ts)$ + description: Test files only + - command +``` + +### Security Review Mode (YAML) + +```yaml +customModes: + - slug: security-review + name: 🔒 Security Reviewer + description: Read-only security analysis and vulnerability assessment + roleDefinition: You are a security specialist reviewing code for vulnerabilities + whenToUse: Use for security reviews and vulnerability assessments + customInstructions: |- + Focus on: + - Input validation issues + - Authentication and authorization flaws + - Data exposure risks + - Injection vulnerabilities + groups: + - read + - browser +``` + {% /tab %} {% /tabs %} ## Troubleshooting {% tabs %} -{% tab label="VSCode (Legacy)" %} - -### Common Issues - -- **Mode not appearing:** After creating or importing a mode, you may need to reload the VS Code window -- **Invalid regex patterns:** Test your patterns using online regex testers before applying them -- **Precedence confusion:** Remember that project modes completely override global modes with the same slug -- **YAML syntax errors:** Use proper indentation (spaces, not tabs) and validate your YAML - -### Tips for Working with YAML - -- **Indentation is Key:** YAML uses indentation (spaces, not tabs) to define structure -- **Colons for Key-Value Pairs:** Keys must be followed by a colon and a space (e.g., `slug: my-mode`) -- **Hyphens for List Items:** List items start with a hyphen and a space (e.g., `- read`) -- **Validate Your YAML:** Use online YAML validators or your editor's built-in validation - -{% /tab %} -{% tab label="VSCode (Legacy)" %} +{% tab label="VSCode" %} ### Common Issues @@ -1092,6 +1182,23 @@ Focus on: - **Test with `kilo agent create`** to see how the CLI generates agent definitions, then customize from there - **Legacy modes are auto-migrated:** If you have `.kilocodemodes` files, they'll be converted on startup — no manual migration needed +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +### Common Issues + +- **Mode not appearing:** After creating or importing a mode, you may need to reload the VS Code window +- **Invalid regex patterns:** Test your patterns using online regex testers before applying them +- **Precedence confusion:** Remember that project modes completely override global modes with the same slug +- **YAML syntax errors:** Use proper indentation (spaces, not tabs) and validate your YAML + +### Tips for Working with YAML + +- **Indentation is Key:** YAML uses indentation (spaces, not tabs) to define structure +- **Colons for Key-Value Pairs:** Keys must be followed by a colon and a space (e.g., `slug: my-mode`) +- **Hyphens for List Items:** List items start with a hyphen and a space (e.g., `- read`) +- **Validate Your YAML:** Use online YAML validators or your editor's built-in validation + {% /tab %} {% /tabs %} diff --git a/packages/kilo-docs/pages/customize/custom-rules.md b/packages/kilo-docs/pages/customize/custom-rules.md index d89be15ed5e..5aa86a9a11b 100644 --- a/packages/kilo-docs/pages/customize/custom-rules.md +++ b/packages/kilo-docs/pages/customize/custom-rules.md @@ -29,6 +29,78 @@ Kilo Code supports two types of custom rules: ## Rule Location {% tabs %} +{% tab label="VSCode" %} + +### Project Rules + +Project rules are configured via the `instructions` key in your project's `kilo.jsonc` file. You can edit this file directly or use the **Settings** webview to manage the `instructions` configuration. Each entry points to a file path or glob pattern: + +```jsonc +// kilo.jsonc +{ + "instructions": [".kilo/rules/formatting.md", ".kilo/rules/*.md"], +} +``` + +You can also place rule files in the **`.kilo/`** directory structure: + +``` +project/ +├── .kilo/ +│ ├── rules/ +│ │ ├── formatting.md +│ │ ├── restricted_files.md +│ │ └── naming_conventions.md +├── kilo.json +├── src/ +└── ... +``` + +### Global Rules + +Global rules are configured via the `instructions` key in your global `kilo.jsonc` config file (typically at `~/.config/kilo/kilo.jsonc`). + +{% callout type="note" title="Migration" %} +The extension is backward compatible with `.kilocode/rules/` directories. Existing rules will continue to work, but migrating to `kilo.jsonc` is recommended. +{% /callout %} + +{% /tab %} +{% tab label="CLI" %} + +### Project Rules + +Project rules are configured via the `instructions` key in your project's `kilo.jsonc` file. Each entry points to a file path or glob pattern: + +```jsonc +// kilo.jsonc +{ + "instructions": [".kilo/rules/formatting.md", ".kilo/rules/*.md"], +} +``` + +You can also place rule files in the **`.kilo/`** directory structure: + +``` +project/ +├── .kilo/ +│ ├── rules/ +│ │ ├── formatting.md +│ │ ├── restricted_files.md +│ │ └── naming_conventions.md +├── kilo.json +├── src/ +└── ... +``` + +### Global Rules + +Global rules are configured via the `instructions` key in your global `kilo.jsonc` config file (typically at `~/.config/kilo/kilo.jsonc`). + +{% callout type="note" title="Migration" %} +The CLI is backward compatible with `.kilocode/rules/` directories. Existing rules will continue to work, but migrating to `kilo.jsonc` is recommended. +{% /callout %} + +{% /tab %} {% tab label="VSCode (Legacy)" %} ### Project Rules @@ -58,84 +130,52 @@ Global rules are stored in your home directory and apply to all projects: │ └── documentation_style.md ``` -{% /tab %} -{% tab label="VSCode (Legacy)" %} - -### Project Rules - -Project rules are configured via the `instructions` key in your project's `kilo.json` file. You can edit this file directly or use the **Settings** webview to manage the `instructions` configuration. Each entry points to a file path or glob pattern: - -```jsonc -// kilo.json -{ - "instructions": [".kilo/rules/formatting.md", ".kilo/rules/*.md"], -} -``` - -You can also place rule files in the **`.kilo/`** directory structure: - -``` -project/ -├── .kilo/ -│ ├── rules/ -│ │ ├── formatting.md -│ │ ├── restricted_files.md -│ │ └── naming_conventions.md -├── kilo.json -├── src/ -└── ... -``` - -### Global Rules - -Global rules are configured via the `instructions` key in your global `kilo.json` config file (typically at `~/.config/kilo/kilo.json`). - -{% callout type="note" title="Migration" %} -The new extension is backward compatible with `.kilocode/rules/` directories. Existing rules will continue to work, but migrating to `kilo.json` is recommended. -{% /callout %} - -{% /tab %} -{% tab label="CLI" %} - -### Project Rules - -Project rules are configured via the `instructions` key in your project's `kilo.json` file. Each entry points to a file path or glob pattern: - -```jsonc -// kilo.json -{ - "instructions": [".kilo/rules/formatting.md", ".kilo/rules/*.md"], -} -``` - -You can also place rule files in the **`.kilo/`** directory structure: - -``` -project/ -├── .kilo/ -│ ├── rules/ -│ │ ├── formatting.md -│ │ ├── restricted_files.md -│ │ └── naming_conventions.md -├── kilo.json -├── src/ -└── ... -``` - -### Global Rules - -Global rules are configured via the `instructions` key in your global `kilo.json` config file (typically at `~/.config/kilo/kilo.json`). - -{% callout type="note" title="Migration" %} -The CLI is backward compatible with `.kilocode/rules/` directories. Existing rules will continue to work, but migrating to `kilo.json` is recommended. -{% /callout %} - {% /tab %} {% /tabs %} ## Managing Rules Through the UI {% tabs %} +{% tab label="VSCode" %} + +Rules are managed by editing the `instructions` array in your `kilo.jsonc` config file. You can also use the **Settings** webview in VS Code to edit the configuration. + +- **Add a rule**: Add a file path or glob pattern to the `instructions` array +- **Remove a rule**: Remove the entry from the array +- **Disable a rule temporarily**: Comment out the line in `kilo.jsonc` (JSONC supports `//` comments) + +```jsonc +// kilo.jsonc +{ + "instructions": [ + ".kilo/rules/formatting.md", + // ".kilo/rules/experimental.md" -- temporarily disabled + ".kilo/rules/naming_conventions.md", + ], +} +``` + +{% /tab %} +{% tab label="CLI" %} + +Rules are managed by editing the `instructions` array in your `kilo.jsonc` config file directly. + +- **Add a rule**: Add a file path or glob pattern to the `instructions` array +- **Remove a rule**: Remove the entry from the array +- **Disable a rule temporarily**: Comment out the line in `kilo.jsonc` (JSONC supports `//` comments) + +```jsonc +// kilo.jsonc +{ + "instructions": [ + ".kilo/rules/formatting.md", + // ".kilo/rules/experimental.md" -- temporarily disabled + ".kilo/rules/naming_conventions.md", + ], +} +``` + +{% /tab %} {% tab label="VSCode (Legacy)" %} Kilo Code provides a built-in interface for managing your custom rules without manually editing files in the `.kilocode/rules/` directories. To access the UI, click on the icon in the **bottom right corner** of the Kilo Code window. @@ -151,52 +191,40 @@ You can access the rules management UI to: The built-in rules management UI is available for general rules only. Mode-specific rules must be managed through the file system. {% /callout %} -{% /tab %} -{% tab label="VSCode (Legacy)" %} - -Rules are managed by editing the `instructions` array in your `kilo.json` config file. You can also use the **Settings** webview in VS Code to edit the configuration. - -- **Add a rule**: Add a file path or glob pattern to the `instructions` array -- **Remove a rule**: Remove the entry from the array -- **Disable a rule temporarily**: Comment out the line in `kilo.json` (JSONC supports `//` comments) - -```jsonc -// kilo.json -{ - "instructions": [ - ".kilo/rules/formatting.md", - // ".kilo/rules/experimental.md" -- temporarily disabled - ".kilo/rules/naming_conventions.md", - ], -} -``` - -{% /tab %} -{% tab label="CLI" %} - -Rules are managed by editing the `instructions` array in your `kilo.json` config file directly. - -- **Add a rule**: Add a file path or glob pattern to the `instructions` array -- **Remove a rule**: Remove the entry from the array -- **Disable a rule temporarily**: Comment out the line in `kilo.json` (JSONC supports `//` comments) - -```jsonc -// kilo.json -{ - "instructions": [ - ".kilo/rules/formatting.md", - // ".kilo/rules/experimental.md" -- temporarily disabled - ".kilo/rules/naming_conventions.md", - ], -} -``` - {% /tab %} {% /tabs %} ## Rule Loading Order {% tabs %} +{% tab label="VSCode" %} + +Rules are loaded in the order they appear in the `instructions` array in `kilo.jsonc`: + +1. **Global instructions** from the global `kilo.jsonc` config +2. **Project instructions** from the project's `kilo.jsonc` + +Files matched by glob patterns are loaded in filesystem order. Project-level instructions take precedence over global instructions for conflicting directives. + +{% callout type="note" title="Backward Compatibility" %} +If `.kilocode/rules/` directories exist in your project, their contents are automatically included for backward compatibility. To fully migrate, move your rule files and reference them in `kilo.jsonc`. +{% /callout %} + +{% /tab %} +{% tab label="CLI" %} + +Rules are loaded in the order they appear in the `instructions` array in `kilo.jsonc`: + +1. **Global instructions** from the global `kilo.jsonc` config +2. **Project instructions** from the project's `kilo.jsonc` + +Files matched by glob patterns are loaded in filesystem order. Project-level instructions take precedence over global instructions for conflicting directives. + +{% callout type="note" title="Backward Compatibility" %} +If `.kilocode/rules/` directories exist in your project, their contents are automatically included for backward compatibility. To fully migrate, move your rule files and reference them in `kilo.jsonc`. +{% /callout %} + +{% /tab %} {% tab label="VSCode (Legacy)" %} ### General Rules (Any Mode) @@ -225,26 +253,50 @@ The system also supports mode-specific rules with their own priority order: Mode-specific rules are only supported at the project level. When both generic and mode-specific rules exist, mode-specific rules take priority. -{% /tab %} -{% tab label="VSCode & CLI" %} - -Rules are loaded in the order they appear in the `instructions` array in `kilo.json`: - -1. **Global instructions** from the global `kilo.json` config -2. **Project instructions** from the project's `kilo.json` - -Files matched by glob patterns are loaded in filesystem order. Project-level instructions take precedence over global instructions for conflicting directives. - -{% callout type="note" title="Backward Compatibility" %} -If `.kilocode/rules/` directories exist in your project, their contents are automatically included for backward compatibility. To fully migrate, move your rule files and reference them in `kilo.json`. -{% /callout %} - {% /tab %} {% /tabs %} ## Creating Custom Rules {% tabs %} +{% tab label="VSCode" %} + +### Using the Settings UI or Config File + +1. Create a `kilo.jsonc` file in your project root (if it doesn't exist) +2. Create a `.kilo/rules/` directory (or any directory you prefer) +3. Write your rule as a Markdown file in that directory +4. Add the file path or a glob pattern to the `instructions` array in `kilo.jsonc` + +```jsonc +// kilo.jsonc +{ + "instructions": [".kilo/rules/my-new-rule.md"], +} +``` + +Rules are applied on the next interaction. You can also edit `kilo.jsonc` through the **Settings** webview in VS Code. + +{% /tab %} +{% tab label="CLI" %} + +### Using the Config File + +1. Create a `kilo.jsonc` file in your project root (if it doesn't exist) +2. Create a `.kilo/rules/` directory (or any directory you prefer) +3. Write your rule as a Markdown file in that directory +4. Add the file path or a glob pattern to the `instructions` array in `kilo.jsonc` + +```jsonc +// kilo.jsonc +{ + "instructions": [".kilo/rules/my-new-rule.md"], +} +``` + +Rules are applied on the next interaction. + +{% /tab %} {% tab label="VSCode (Legacy)" %} ### Using the UI Interface @@ -278,44 +330,6 @@ To create rules manually: Rules will be automatically applied to all future Kilo Code interactions. Any new changes will be applied immediately. -{% /tab %} -{% tab label="VSCode (Legacy)" %} - -### Using the Settings UI or Config File - -1. Create a `kilo.json` file in your project root (if it doesn't exist) -2. Create a `.kilo/rules/` directory (or any directory you prefer) -3. Write your rule as a Markdown file in that directory -4. Add the file path or a glob pattern to the `instructions` array in `kilo.json` - -```jsonc -// kilo.json -{ - "instructions": [".kilo/rules/my-new-rule.md"], -} -``` - -Rules are applied on the next interaction. You can also edit `kilo.json` through the **Settings** webview in VS Code. - -{% /tab %} -{% tab label="CLI" %} - -### Using the Config File - -1. Create a `kilo.json` file in your project root (if it doesn't exist) -2. Create a `.kilo/rules/` directory (or any directory you prefer) -3. Write your rule as a Markdown file in that directory -4. Add the file path or a glob pattern to the `instructions` array in `kilo.json` - -```jsonc -// kilo.json -{ - "instructions": [".kilo/rules/my-new-rule.md"], -} -``` - -Rules are applied on the next interaction. - {% /tab %} {% /tabs %} @@ -399,6 +413,22 @@ If your custom rules aren't being properly followed: 3. **Check rule locations**: {% tabs %} +{% tab label="VSCode" %} + +- Verify that your `kilo.jsonc` file is valid JSON (with comments) +- Ensure the `instructions` paths resolve to existing files +- Check that glob patterns match the intended files +- Run `kilo` to see if rules are loaded in the output + +{% /tab %} +{% tab label="CLI" %} + +- Verify that your `kilo.jsonc` file is valid JSON (with comments) +- Ensure the `instructions` paths resolve to existing files +- Check that glob patterns match the intended files +- Run `kilo` to see if rules are loaded in the output + +{% /tab %} {% tab label="VSCode (Legacy)" %} - **Check rule status in the UI**: Use the rules management interface to verify that your rules are active and properly loaded @@ -408,14 +438,6 @@ If your custom rules aren't being properly followed: - Legacy files: `.kilocoderules`, `.roorules`, or `.clinerules` - **Restart VS Code** to ensure the rules are properly loaded -{% /tab %} -{% tab label="VSCode & CLI" %} - -- Verify that your `kilo.json` file is valid JSON (with comments) -- Ensure the `instructions` paths resolve to existing files -- Check that glob patterns match the intended files -- Run `kilo` to see if rules are loaded in the output - {% /tab %} {% /tabs %} diff --git a/packages/kilo-docs/pages/customize/custom-subagents.md b/packages/kilo-docs/pages/customize/custom-subagents.md index 7fa87c195af..e2c2dc6e379 100644 --- a/packages/kilo-docs/pages/customize/custom-subagents.md +++ b/packages/kilo-docs/pages/customize/custom-subagents.md @@ -9,7 +9,7 @@ platform: new Kilo Code's CLI supports **custom subagents** — specialized AI assistants that can be invoked by primary agents or manually via `@` mentions. Subagents run in their own isolated sessions with tailored prompts, models, tool access, and permissions, enabling you to build purpose-built workflows for tasks like code review, documentation, security audits, and more. {% callout type="info" %} -Custom subagents are currently configured through the config file (`kilo.json`) or via markdown agent files. UI-based configuration is not yet available. +Custom subagents are currently configured through the config file (`kilo.jsonc`) or via markdown agent files. UI-based configuration is not yet available. {% /callout %} ## What Are Subagents? @@ -48,7 +48,7 @@ There are two ways to define custom subagents: through JSON configuration or mar ### Method 1: JSON Configuration -Add agents to the `agent` section of your `kilo.json` config file. Any key that doesn't match a built-in agent name creates a new custom agent. +Add agents to the `agent` section of your `kilo.jsonc` config file. Any key that doesn't match a built-in agent name creates a new custom agent. ```json { @@ -247,7 +247,7 @@ Agent configurations are merged from multiple sources. Later sources override ea 1. **Built-in agent defaults** (native agents defined in the codebase) 2. **Global config** (`~/.config/kilo/config.json`) 3. **Global agent markdown files** (`~/.config/kilo/agents/*.md`) -4. **Project config** (`kilo.json` in the project root) +4. **Project config** (`kilo.jsonc` in the project root) 5. **Project agent markdown files** (`.kilo/agents/*.md`) When overriding a built-in agent, properties are merged — only the fields you specify are overridden. When creating a new custom agent, unspecified fields use sensible defaults (`mode: "all"`, full permissions inherited from global config). @@ -374,5 +374,4 @@ To disable a built-in agent entirely: - [Custom Modes](/docs/customize/custom-modes) — Create specialized primary agents with tool restrictions - [Custom Rules](/docs/customize/custom-rules) — Define rules that apply to specific file types or situations -- [Orchestrator Mode](/docs/code-with-ai/agents/orchestrator-mode) — Coordinate complex tasks by delegating to subagents -- [Task Tool](/docs/automate/tools/new-task) — The tool used to invoke subagents +- [Orchestrator Mode (Deprecated)](/docs/code-with-ai/agents/orchestrator-mode) — Legacy orchestration approach, now replaced by native subagent support diff --git a/packages/kilo-docs/pages/customize/skills.md b/packages/kilo-docs/pages/customize/skills.md index 8d49fbb7e64..cc180e4df6a 100644 --- a/packages/kilo-docs/pages/customize/skills.md +++ b/packages/kilo-docs/pages/customize/skills.md @@ -48,6 +48,112 @@ This means: Skills are loaded from multiple locations, allowing both personal skills and project-specific instructions. {% tabs %} +{% tab label="VSCode" %} + +### Global Skills (User-Level) + +Global skills are located in the `.kilo` directory within your Home directory: + +- Mac and Linux: `~/.kilo/skills/` +- Windows: `\Users\\.kilo\skills\` + +``` +~/.kilo/ +└── skills/ # Generic skills (all modes) + ├── my-skill/ + │ └── SKILL.md + └── another-skill/ + └── SKILL.md +``` + +### Project Skills (Workspace-Level) + +Located in `.kilo/skills/` within your project: + +``` +your-project/ +└── .kilo/ + └── skills/ # Generic skills for this project + └── project-conventions/ + └── SKILL.md +``` + +### Compatibility Directories + +For interoperability with other tools, the CLI also loads skills from: + +- `.claude/skills/` — Claude Code compatibility +- `.agents/skills/` — Open agent standard + +### Additional Skill Paths and Remote URLs + +You can configure extra skill locations and remote skill URLs in your `kilo.jsonc` config (project or global): + +```jsonc +{ + "skills": { + "paths": ["/path/to/shared/skills", "~/my-skills", "relative/skills"], + "urls": ["https://example.com/skills/my-skill/SKILL.md"], + }, +} +``` + +The `skills.paths` key accepts absolute paths, `~/` home-relative paths, or paths relative to the project root. The `skills.urls` key accepts URLs pointing to remote `SKILL.md` files that are fetched on demand. + +{% /tab %} +{% tab label="CLI" %} + +### Global Skills (User-Level) + +Global skills are located in the `.kilo` directory within your Home directory: + +- Mac and Linux: `~/.kilo/skills/` +- Windows: `\Users\\.kilo\skills\` + +``` +~/.kilo/ +└── skills/ # Generic skills (all modes) + ├── my-skill/ + │ └── SKILL.md + └── another-skill/ + └── SKILL.md +``` + +### Project Skills (Workspace-Level) + +Located in `.kilo/skills/` within your project: + +``` +your-project/ +└── .kilo/ + └── skills/ # Generic skills for this project + └── project-conventions/ + └── SKILL.md +``` + +### Compatibility Directories + +For interoperability with other tools, the CLI also loads skills from: + +- `.claude/skills/` — Claude Code compatibility +- `.agents/skills/` — Open agent standard + +### Additional Skill Paths and Remote URLs + +You can configure extra skill locations and remote skill URLs in your `kilo.jsonc` config (project or global): + +```jsonc +{ + "skills": { + "paths": ["/path/to/shared/skills", "~/my-skills", "relative/skills"], + "urls": ["https://example.com/skills/my-skill/SKILL.md"], + }, +} +``` + +The `skills.paths` key accepts absolute paths, `~/` home-relative paths, or paths relative to the project root. The `skills.urls` key accepts URLs pointing to remote `SKILL.md` files that are fetched on demand. + +{% /tab %} {% tab label="VSCode (Legacy)" %} ### Global Skills (User-Level) @@ -87,65 +193,26 @@ your-project/ └── SKILL.md ``` -{% /tab %} -{% tab label="VSCode & CLI" %} - -### Global Skills (User-Level) - -Global skills are located in the `.kilo` directory within your Home directory: - -- Mac and Linux: `~/.kilo/skills/` -- Windows: `\Users\\.kilo\skills\` - -``` -~/.kilo/ -└── skills/ # Generic skills (all modes) - ├── my-skill/ - │ └── SKILL.md - └── another-skill/ - └── SKILL.md -``` - -### Project Skills (Workspace-Level) - -Located in `.kilo/skills/` within your project: - -``` -your-project/ -└── .kilo/ - └── skills/ # Generic skills for this project - └── project-conventions/ - └── SKILL.md -``` - -### Compatibility Directories - -For interoperability with other tools, the CLI also loads skills from: - -- `.claude/skills/` — Claude Code compatibility -- `.agents/skills/` — Open agent standard - -### Additional Skill Paths and Remote URLs - -You can configure extra skill locations and remote skill URLs in your `kilo.json` config (project or global): - -```jsonc -{ - "skills": { - "paths": ["/path/to/shared/skills"], - "urls": ["https://example.com/skills/my-skill/SKILL.md"], - }, -} -``` - -The `skills.paths` key accepts absolute paths to additional skill directories. The `skills.urls` key accepts URLs pointing to remote `SKILL.md` files that are fetched on demand. - {% /tab %} {% /tabs %} ## Mode-Specific Skills {% tabs %} +{% tab label="VSCode" %} + +The new platform does not use mode-specific skill directories. All skills are loaded into a shared pool and the agent decides which skill to invoke based on the skill's `description` field and the current task context. + +If you need a skill to only apply in certain situations, write a clear and specific `description` in the SKILL.md frontmatter so the agent knows when to use it. + +{% /tab %} +{% tab label="CLI" %} + +The new platform does not use mode-specific skill directories. All skills are loaded into a shared pool and the agent decides which skill to invoke based on the skill's `description` field and the current task context. + +If you need a skill to only apply in certain situations, write a clear and specific `description` in the SKILL.md frontmatter so the agent knows when to use it. + +{% /tab %} {% tab label="VSCode (Legacy)" %} To create a skill that only appears in a specific mode, place it in a `skills-{mode-slug}` directory: @@ -160,19 +227,22 @@ mkdir -p ~/.kilocode/skills-architect/microservices The directory naming pattern is `skills-{mode-slug}` where `{mode-slug}` matches the mode's identifier (e.g., `code`, `architect`, `ask`, `debug`). -{% /tab %} -{% tab label="VSCode & CLI" %} - -The new platform does not use mode-specific skill directories. All skills are loaded into a shared pool and the agent decides which skill to invoke based on the skill's `description` field and the current task context. - -If you need a skill to only apply in certain situations, write a clear and specific `description` in the SKILL.md frontmatter so the agent knows when to use it. - {% /tab %} {% /tabs %} ## Priority and Overrides {% tabs %} +{% tab label="VSCode" %} + +When multiple skills share the same name, project-level skills (`.kilo/skills/`) take precedence over global skills (`~/.kilo/skills/`). Skills from compatibility directories (`.claude/skills/`, `.agents/skills/`) and additional configured paths are loaded alongside project and global skills. + +{% /tab %} +{% tab label="CLI" %} + +When multiple skills share the same name, project-level skills (`.kilo/skills/`) take precedence over global skills (`~/.kilo/skills/`). Skills from compatibility directories (`.claude/skills/`, `.agents/skills/`) and additional configured paths are loaded alongside project and global skills. + +{% /tab %} {% tab label="VSCode (Legacy)" %} When multiple skills share the same name, Kilo Code uses these priority rules: @@ -186,17 +256,32 @@ This allows you to: - Override them per-project when needed - Customize behavior for specific modes -{% /tab %} -{% tab label="VSCode & CLI" %} - -When multiple skills share the same name, project-level skills (`.kilo/skills/`) take precedence over global skills (`~/.kilo/skills/`). Skills from compatibility directories (`.claude/skills/`, `.agents/skills/`) and additional configured paths are loaded alongside project and global skills. - {% /tab %} {% /tabs %} ## When Skills Are Loaded {% tabs %} +{% tab label="VSCode" %} + +Skills are discovered when a session starts. The CLI scans all configured skill directories and reads metadata (name, description, file path) for each skill. + +- In the **CLI**: Skills are loaded when you start a new session or run `kilo run` +- In the **VS Code extension**: Skills are loaded when the extension connects to the CLI server + +Skills are re-scanned at the start of each new session. To pick up newly added or modified skills, start a new session. + +{% /tab %} +{% tab label="CLI" %} + +Skills are discovered when a session starts. The CLI scans all configured skill directories and reads metadata (name, description, file path) for each skill. + +- In the **CLI**: Skills are loaded when you start a new session or run `kilo run` +- In the **VS Code extension**: Skills are loaded when the extension connects to the CLI server + +Skills are re-scanned at the start of each new session. To pick up newly added or modified skills, start a new session. + +{% /tab %} {% tab label="VSCode (Legacy)" %} Skills are discovered when Kilo Code initializes: @@ -212,16 +297,6 @@ Skills directories are monitored for changes to `SKILL.md` files. However, the m You can symlink skills directories to share skills across machines or from a central repository. When using symlinks, the skill's `name` field must match the **symlink name**, not the target directory name. -{% /tab %} -{% tab label="VSCode & CLI" %} - -Skills are discovered when a session starts. The CLI scans all configured skill directories and reads metadata (name, description, file path) for each skill. - -- In the **CLI**: Skills are loaded when you start a new session or run `kilo run` -- In the **VS Code extension**: Skills are loaded when the extension connects to the CLI server - -Skills are re-scanned at the start of each new session. To pick up newly added or modified skills, start a new session. - {% /tab %} {% /tabs %} @@ -313,6 +388,32 @@ These additional files can be referenced from your skill's instructions, allowin ## Example: Creating a Skill {% tabs %} +{% tab label="VSCode" %} + +1. Create the skill directory: + + ```bash + mkdir -p ~/.kilo/skills/api-design + ``` + +2. Create `SKILL.md` (see content below) + +3. Start a new session to pick up the skill + +{% /tab %} +{% tab label="CLI" %} + +1. Create the skill directory: + + ```bash + mkdir -p ~/.kilo/skills/api-design + ``` + +2. Create `SKILL.md` (see content below) + +3. Start a new session to pick up the skill + +{% /tab %} {% tab label="VSCode (Legacy)" %} 1. Create the skill directory: @@ -327,19 +428,6 @@ These additional files can be referenced from your skill's instructions, allowin 4. The skill will now be available in all modes -{% /tab %} -{% tab label="VSCode & CLI" %} - -1. Create the skill directory: - - ```bash - mkdir -p ~/.kilo/skills/api-design - ``` - -2. Create `SKILL.md` (see content below) - -3. Start a new session to pick up the skill - {% /tab %} {% /tabs %} @@ -381,15 +469,7 @@ When designing REST APIs, follow these conventions: ## Finding Skills {% tabs %} -{% tab label="VSCode (Legacy)" %} - -You can discover and install community-created skills through: - -- **Kilo Marketplace** — Browse skills directly in the Kilo Code extension via the Marketplace tab, or explore the [Kilo Marketplace repository](https://github.com/Kilo-Org/kilo-marketplace) on GitHub -- [Agent Skills Specification](https://agentskills.io/home) — The open specification that skills follow, enabling interoperability across different AI agents - -{% /tab %} -{% tab label="VSCode & CLI" %} +{% tab label="VSCode" %} The new platform does not have a marketplace UI yet. You can find and share skills through: @@ -397,6 +477,23 @@ The new platform does not have a marketplace UI yet. You can find and share skil - **[Agent Skills Specification](https://agentskills.io/home)** — The open specification that skills follow, enabling interoperability across different AI agents - **Remote URLs** — Use the `skills.urls` config key to load skills directly from URLs without manually downloading them +{% /tab %} +{% tab label="CLI" %} + +The new platform does not have a marketplace UI yet. You can find and share skills through: + +- **[Kilo Marketplace repository](https://github.com/Kilo-Org/kilo-marketplace)** — Browse community skills on GitHub and manually download them into your skills directory +- **[Agent Skills Specification](https://agentskills.io/home)** — The open specification that skills follow, enabling interoperability across different AI agents +- **Remote URLs** — Use the `skills.urls` config key to load skills directly from URLs without manually downloading them + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +You can discover and install community-created skills through: + +- **Kilo Marketplace** — Browse skills directly in the Kilo Code extension via the Marketplace tab, or explore the [Kilo Marketplace repository](https://github.com/Kilo-Org/kilo-marketplace) on GitHub +- [Agent Skills Specification](https://agentskills.io/home) — The open specification that skills follow, enabling interoperability across different AI agents + {% /tab %} {% /tabs %} @@ -405,6 +502,28 @@ The new platform does not have a marketplace UI yet. You can find and share skil ### Skill Not Loading? {% tabs %} +{% tab label="VSCode" %} + +1. **Verify frontmatter**: Ensure `name` and `description` are present in the YAML frontmatter. The `name` does not need to match the directory name but should be unique across all loaded skills. + +2. **Start a new session**: Skills are scanned at session start. Begin a new session to pick up changes. + +3. **Check file location**: Ensure `SKILL.md` is directly inside the skill directory (e.g., `.kilo/skills/my-skill/SKILL.md`), not nested further. + +4. **Check config paths**: If using `skills.paths` or `skills.urls`, verify the paths and URLs are correct in your `kilo.jsonc`. + +{% /tab %} +{% tab label="CLI" %} + +1. **Verify frontmatter**: Ensure `name` and `description` are present in the YAML frontmatter. The `name` does not need to match the directory name but should be unique across all loaded skills. + +2. **Start a new session**: Skills are scanned at session start. Begin a new session to pick up changes. + +3. **Check file location**: Ensure `SKILL.md` is directly inside the skill directory (e.g., `.kilo/skills/my-skill/SKILL.md`), not nested further. + +4. **Check config paths**: If using `skills.paths` or `skills.urls`, verify the paths and URLs are correct in your `kilo.jsonc`. + +{% /tab %} {% tab label="VSCode (Legacy)" %} 1. **Check the Output panel**: Open `View` → `Output` → Select "Kilo Code" from dropdown. Look for skill-related errors. @@ -415,17 +534,6 @@ The new platform does not have a marketplace UI yet. You can find and share skil 4. **Check file location**: Ensure `SKILL.md` is directly inside the skill directory, not nested further. -{% /tab %} -{% tab label="VSCode & CLI" %} - -1. **Verify frontmatter**: Ensure `name` exactly matches the directory name and `description` is present. - -2. **Start a new session**: Skills are scanned at session start. Begin a new session to pick up changes. - -3. **Check file location**: Ensure `SKILL.md` is directly inside the skill directory (e.g., `.kilo/skills/my-skill/SKILL.md`), not nested further. - -4. **Check config paths**: If using `skills.paths` or `skills.urls`, verify the paths and URLs are correct in your `kilo.json`. - {% /tab %} {% /tabs %} @@ -444,17 +552,22 @@ If the agent confirms the skill is available, you're ready to use it. If not, ch ### Checking if a Skill Was Used {% tabs %} +{% tab label="VSCode" %} + +When the agent uses a skill, it invokes the `skill` tool with the skill's name. Look for a `skill` tool call in the conversation to confirm a skill was loaded. The tool output includes the full skill content injected into context. + +{% /tab %} +{% tab label="CLI" %} + +When the agent uses a skill, it invokes the `skill` tool with the skill's name. Look for a `skill` tool call in the conversation to confirm a skill was loaded. The tool output includes the full skill content injected into context. + +{% /tab %} {% tab label="VSCode (Legacy)" %} To see if a skill was actually used during a conversation, look for a `read_file` tool call in the chat that targets a `SKILL.md` file. When the agent decides to use a skill, it reads the full skill file into context—this appears as a file read operation in the conversation. There's currently no dedicated UI indicator showing "Skill X was activated." The `read_file` call is the most reliable way to confirm a skill was used. -{% /tab %} -{% tab label="VSCode & CLI" %} - -When the agent uses a skill, it invokes the `skill` tool with the skill's name. Look for a `skill` tool call in the conversation to confirm a skill was loaded. The tool output includes the full skill content injected into context. - {% /tab %} {% /tabs %} @@ -471,15 +584,20 @@ When the agent uses a skill, it invokes the `skill` tool with the skill's name. Have you created a skill that others might find useful? Share it with the community by contributing to the [Kilo Marketplace](https://github.com/Kilo-Org/kilo-marketplace)! {% tabs %} +{% tab label="VSCode" %} + +While the new platform does not yet have a built-in marketplace UI, skills from the [Kilo Marketplace repository](https://github.com/Kilo-Org/kilo-marketplace) can be manually downloaded into your `.kilo/skills/` directory or loaded via `skills.urls` in config. + +{% /tab %} +{% tab label="CLI" %} + +While the new platform does not yet have a built-in marketplace UI, skills from the [Kilo Marketplace repository](https://github.com/Kilo-Org/kilo-marketplace) can be manually downloaded into your `.kilo/skills/` directory or loaded via `skills.urls` in config. + +{% /tab %} {% tab label="VSCode (Legacy)" %} Skills submitted to the marketplace are browsable and installable directly from the Marketplace tab in the **VSCode** version. -{% /tab %} -{% tab label="VSCode & CLI" %} - -While the new platform does not yet have a built-in marketplace UI, skills from the [Kilo Marketplace repository](https://github.com/Kilo-Org/kilo-marketplace) can be manually downloaded into your `.kilo/skills/` directory or loaded via `skills.urls` in config. - {% /tab %} {% /tabs %} From 100a1fdd2c5939e01103681da24bf982efdae954 Mon Sep 17 00:00:00 2001 From: Aarav Sharma Date: Sun, 29 Mar 2026 08:45:36 -0600 Subject: [PATCH 119/261] fix(vscode): enable scrolling in local session history list The .session-list wrapper was missing flex: 1 and min-height: 0, causing the list to size to its content instead of being constrained by the parent flex container. Without a constrained height, the overflow-y: auto on the inner list-scroll element never triggered, making the session list unscrollable. The cloud session list already had these properties (.cloud-session-list). --- packages/kilo-vscode/webview-ui/src/styles/chat.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/kilo-vscode/webview-ui/src/styles/chat.css b/packages/kilo-vscode/webview-ui/src/styles/chat.css index 00f13417060..c27b21154f9 100644 --- a/packages/kilo-vscode/webview-ui/src/styles/chat.css +++ b/packages/kilo-vscode/webview-ui/src/styles/chat.css @@ -2200,6 +2200,14 @@ opacity: 0.7; } +/* Session List (inside History View) */ +.session-list { + display: flex; + flex-direction: column; + flex: 1; + min-height: 0; +} + /* Session List Items */ .session-list [data-slot="list-item-title"], .cloud-session-list [data-slot="list-item-title"] { From e9060468a1f1d11b06aa69e57645d3843c05edee Mon Sep 17 00:00:00 2001 From: Aarav Sharma Date: Sun, 29 Mar 2026 17:11:27 -0600 Subject: [PATCH 120/261] core: deprecate orchestrator agent with visual badge across UI Mark the orchestrator agent as deprecated so users see a warning badge in the mode switcher and agent settings, signaling they should migrate to other agent configurations for task delegation. --- packages/kilo-vscode/src/KiloProvider.ts | 1 + .../components/settings/AgentBehaviourTab.tsx | 14 ++++++++++++++ .../src/components/shared/ModeSwitcher.tsx | 19 ++++++++++++++++++- .../kilo-vscode/webview-ui/src/i18n/ar.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/br.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/bs.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/da.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/de.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/en.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/es.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/fr.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/ja.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/ko.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/nl.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/no.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/pl.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/ru.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/th.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/tr.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/zh.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/zht.ts | 1 + .../webview-ui/src/types/messages.ts | 1 + packages/opencode/src/agent/agent.ts | 4 +++- .../cli/cmd/tui/component/dialog-agent.tsx | 3 ++- packages/sdk/js/src/v2/gen/types.gen.ts | 1 + packages/sdk/openapi.json | 3 +++ 26 files changed, 61 insertions(+), 3 deletions(-) diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index ba24906f0f9..9ce3ae749bf 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -1500,6 +1500,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper mode: a.mode, native: a.native, color: a.color, + deprecated: a.deprecated, })), defaultAgent, } diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index 9245f7bd014..ec039f1d37d 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -342,6 +342,7 @@ const AgentBehaviourTab: Component = () => { const agentCfg = () => config().agent?.[name] ?? {} const disabled = () => agentCfg().disable ?? false const hidden = () => agentCfg().hidden ?? false + const deprecated = () => agent()?.deprecated ?? false return (
{ {language.t("settings.agentBehaviour.badge.disabled")} + + + {language.t("settings.agentBehaviour.badge.deprecated")} + +
= (props) => { const [open, setOpen] = createSignal(false) const [focused, setFocused] = createSignal(-1) + const language = useLanguage() let listRef: HTMLDivElement | undefined // Listen for slash command trigger @@ -132,7 +134,22 @@ export const ModeSwitcherBase: Component = (props) => { onClick={() => pick(agent.name)} onFocus={() => setFocused(i())} > - {formatAgentLabel(agent)} +
+ {formatAgentLabel(agent)} + + + {language.t("settings.agentBehaviour.badge.deprecated")} + + +
{agent.description} diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index ac8b73e92e1..26a797b8ae7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1065,6 +1065,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "تعطيل هذا الوكيل بالكامل — لن يظهر في أي مكان", "settings.agentBehaviour.badge.hidden": "مخفي", "settings.agentBehaviour.badge.disabled": "معطل", + "settings.agentBehaviour.badge.deprecated": "مُهمَل", "settings.agentBehaviour.discoveredSkills": "المهارات المكتشفة", "settings.agentBehaviour.noSkillsFound": "لم يتم العثور على مهارات. أضف مسارات مجلدات أو عناوين URL أدناه لإتاحة المهارات.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index b2edcbca372..5c221c581a8 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1083,6 +1083,7 @@ export const dict = { "Desativar completamente este agente — ele não aparecerá em nenhum lugar", "settings.agentBehaviour.badge.hidden": "oculto", "settings.agentBehaviour.badge.disabled": "desativado", + "settings.agentBehaviour.badge.deprecated": "Descontinuado", "settings.agentBehaviour.discoveredSkills": "Habilidades descobertas", "settings.agentBehaviour.noSkillsFound": "Nenhuma habilidade encontrada. Adicione caminhos de pastas ou URLs abaixo para disponibilizar habilidades.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 2f989657a50..176a16e9255 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1081,6 +1081,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Potpuno onemogući ovog agenta — neće se pojaviti nigdje", "settings.agentBehaviour.badge.hidden": "skriveno", "settings.agentBehaviour.badge.disabled": "onemogućeno", + "settings.agentBehaviour.badge.deprecated": "Zastarjelo", "settings.agentBehaviour.discoveredSkills": "Otkrivene vještine", "settings.agentBehaviour.noSkillsFound": "Nisu pronađene vještine. Dodajte putanje mapa ili URL-ove ispod kako biste učinili vještine dostupnim.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index d0cc455b133..a1b480586d9 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1075,6 +1075,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Deaktiver denne agent fuldstændigt — den vises ingen steder", "settings.agentBehaviour.badge.hidden": "skjult", "settings.agentBehaviour.badge.disabled": "deaktiveret", + "settings.agentBehaviour.badge.deprecated": "Udfaset", "settings.agentBehaviour.discoveredSkills": "Opdagede skills", "settings.agentBehaviour.noSkillsFound": "Ingen skills fundet. Tilføj skill-mappestier eller URL'er nedenfor for at gøre skills tilgængelige.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 8ff2588e346..db80f651478 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1095,6 +1095,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Diesen Agent vollständig deaktivieren — er wird nirgends angezeigt", "settings.agentBehaviour.badge.hidden": "versteckt", "settings.agentBehaviour.badge.disabled": "deaktiviert", + "settings.agentBehaviour.badge.deprecated": "Veraltet", "settings.agentBehaviour.discoveredSkills": "Erkannte Skills", "settings.agentBehaviour.noSkillsFound": "Keine Skills gefunden. Fügen Sie unten Skill-Ordnerpfade oder URLs hinzu, um Skills verfügbar zu machen.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 213bded0966..60bfc371722 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1077,6 +1077,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Fully disable this agent — it will not appear anywhere", "settings.agentBehaviour.badge.hidden": "hidden", "settings.agentBehaviour.badge.disabled": "disabled", + "settings.agentBehaviour.badge.deprecated": "deprecated", "settings.agentBehaviour.discoveredSkills": "Discovered Skills", "settings.agentBehaviour.noSkillsFound": "No skills discovered. Add skill folder paths or URLs below to make skills available.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 4302c5187b9..6d83e805e41 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1086,6 +1086,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Desactivar completamente este agente — no aparecerá en ningún lugar", "settings.agentBehaviour.badge.hidden": "oculto", "settings.agentBehaviour.badge.disabled": "desactivado", + "settings.agentBehaviour.badge.deprecated": "Obsoleto", "settings.agentBehaviour.discoveredSkills": "Habilidades descubiertas", "settings.agentBehaviour.noSkillsFound": "No se encontraron habilidades. Agregue rutas de carpetas o URLs abajo para hacer disponibles las habilidades.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index fb74537fbdb..c5f351ba1d6 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1097,6 +1097,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Désactiver complètement cet agent — il n'apparaîtra nulle part", "settings.agentBehaviour.badge.hidden": "masqué", "settings.agentBehaviour.badge.disabled": "désactivé", + "settings.agentBehaviour.badge.deprecated": "Déprécié", "settings.agentBehaviour.discoveredSkills": "Compétences découvertes", "settings.agentBehaviour.noSkillsFound": "Aucune compétence découverte. Ajoutez des chemins de dossiers ou des URLs ci-dessous pour rendre les compétences disponibles.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index a8e298ef97e..028d0364c30 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1075,6 +1075,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "このエージェントを完全に無効にする — どこにも表示されなくなります", "settings.agentBehaviour.badge.hidden": "非表示", "settings.agentBehaviour.badge.disabled": "無効", + "settings.agentBehaviour.badge.deprecated": "非推奨", "settings.agentBehaviour.discoveredSkills": "検出されたスキル", "settings.agentBehaviour.noSkillsFound": "スキルが見つかりません。スキルを利用可能にするには、以下にスキルフォルダパスまたはURLを追加してください。", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 31b562e318b..09c03950f3c 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1072,6 +1072,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "이 에이전트를 완전히 비활성화 — 어디에도 표시되지 않습니다", "settings.agentBehaviour.badge.hidden": "숨김", "settings.agentBehaviour.badge.disabled": "비활성화됨", + "settings.agentBehaviour.badge.deprecated": "비권장", "settings.agentBehaviour.discoveredSkills": "검색된 스킬", "settings.agentBehaviour.noSkillsFound": "스킬을 찾을 수 없습니다. 스킬을 사용하려면 아래에 스킬 폴더 경로 또는 URL을 추가하세요.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index f7818d373f2..a4ae0ad6f45 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1085,6 +1085,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Schakel deze agent volledig uit — deze verschijnt nergens", "settings.agentBehaviour.badge.hidden": "verborgen", "settings.agentBehaviour.badge.disabled": "uitgeschakeld", + "settings.agentBehaviour.badge.deprecated": "Verouderd", "settings.agentBehaviour.discoveredSkills": "Ontdekte Skills", "settings.agentBehaviour.noSkillsFound": "Geen skills ontdekt. Voeg hieronder skill mappaden of URL's toe om skills beschikbaar te maken.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 485a1d0b668..c1152d9ba34 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1078,6 +1078,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Deaktiver denne agenten fullstendig — den vises ikke noe sted", "settings.agentBehaviour.badge.hidden": "skjult", "settings.agentBehaviour.badge.disabled": "deaktivert", + "settings.agentBehaviour.badge.deprecated": "Utdatert", "settings.agentBehaviour.discoveredSkills": "Oppdagede ferdigheter", "settings.agentBehaviour.noSkillsFound": "Ingen ferdigheter funnet. Legg til ferdighetsmappestier eller URLer nedenfor for å gjøre ferdigheter tilgjengelige.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 5db2913b2cf..9eaf50713cf 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1079,6 +1079,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Całkowicie wyłącz tego agenta — nie pojawi się nigdzie", "settings.agentBehaviour.badge.hidden": "ukryty", "settings.agentBehaviour.badge.disabled": "wyłączony", + "settings.agentBehaviour.badge.deprecated": "Przestarzały", "settings.agentBehaviour.discoveredSkills": "Wykryte umiejętności", "settings.agentBehaviour.noSkillsFound": "Nie znaleziono umiejętności. Dodaj ścieżki folderów lub adresy URL poniżej, aby udostępnić umiejętności.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index c9b42fbe0a4..0a2ca396fd8 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1081,6 +1081,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Полностью отключить этого агента — он не будет отображаться нигде", "settings.agentBehaviour.badge.hidden": "скрытый", "settings.agentBehaviour.badge.disabled": "отключён", + "settings.agentBehaviour.badge.deprecated": "Устаревший", "settings.agentBehaviour.discoveredSkills": "Обнаруженные навыки", "settings.agentBehaviour.noSkillsFound": "Навыки не обнаружены. Добавьте пути к папкам навыков или URL-адреса ниже, чтобы сделать навыки доступными.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 7d812f4fb1a..2b1be15ed01 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1067,6 +1067,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "ปิดใช้งานเอเจนต์นี้อย่างสมบูรณ์ — จะไม่ปรากฏที่ใดเลย", "settings.agentBehaviour.badge.hidden": "ซ่อน", "settings.agentBehaviour.badge.disabled": "ปิดใช้งาน", + "settings.agentBehaviour.badge.deprecated": "เลิกใช้", "settings.agentBehaviour.discoveredSkills": "ทักษะที่ค้นพบ", "settings.agentBehaviour.noSkillsFound": "ไม่พบทักษะ เพิ่มเส้นทางโฟลเดอร์หรือ URL ด้านล่างเพื่อทำให้ทักษะพร้อมใช้งาน", "settings.agentBehaviour.availableModes": "โหมดกำหนดเองที่ใช้ได้", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 07ffb9711bd..041985a6d51 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1082,6 +1082,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "Bu ajanı tamamen devre dışı bırak — hiçbir yerde görünmeyecek", "settings.agentBehaviour.badge.hidden": "gizli", "settings.agentBehaviour.badge.disabled": "devre dışı", + "settings.agentBehaviour.badge.deprecated": "Kullanımdan kaldırılmış", "settings.agentBehaviour.discoveredSkills": "Keşfedilen Beceriler", "settings.agentBehaviour.noSkillsFound": "Keşfedilen beceri yok. Becerileri kullanılabilir kılmak için aşağıya beceri klasör yolları veya URL'ler ekleyin.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index ca2b27cb8ff..252e943497d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1057,6 +1057,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "完全禁用此智能体 — 它将不会出现在任何地方", "settings.agentBehaviour.badge.hidden": "隐藏", "settings.agentBehaviour.badge.disabled": "已禁用", + "settings.agentBehaviour.badge.deprecated": "弃用", "settings.agentBehaviour.discoveredSkills": "已发现的技能", "settings.agentBehaviour.noSkillsFound": "未发现任何技能。请在下方添加技能文件夹路径或 URL 以使技能可用。", "settings.agentBehaviour.availableModes": "可用自定义模式", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 635328ba589..3a3eaf67e37 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1059,6 +1059,7 @@ export const dict = { "settings.agentBehaviour.disable.description": "完全停用此 Agent — 它將不會出現在任何地方", "settings.agentBehaviour.badge.hidden": "隱藏", "settings.agentBehaviour.badge.disabled": "已停用", + "settings.agentBehaviour.badge.deprecated": "棄用", "settings.agentBehaviour.discoveredSkills": "已發現的 Skill", "settings.agentBehaviour.noSkillsFound": "未發現任何 Skill。請在下方新增 Skill 資料夾路徑或 URL 以使 Skill 可用。", "settings.agentBehaviour.availableModes": "可用自訂模式", diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index 63e633994e0..1734a94395d 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -219,6 +219,7 @@ export interface AgentInfo { mode: "subagent" | "primary" | "all" native?: boolean hidden?: boolean + deprecated?: boolean color?: string } diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 16305db1286..7886a5ee534 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -37,6 +37,7 @@ export namespace Agent { mode: z.enum(["subagent", "primary", "all"]), native: z.boolean().optional(), hidden: z.boolean().optional(), + deprecated: z.boolean().optional(), topP: z.number().optional(), temperature: z.number().optional(), color: z.string().optional(), @@ -193,7 +194,7 @@ export namespace Agent { }, orchestrator: { name: "orchestrator", - description: "Coordinate complex tasks by delegating to specialized agents in parallel.", + description: "Deprecated. Coordinate complex tasks by delegating to specialized agents in parallel.", prompt: PROMPT_ORCHESTRATOR, options: {}, permission: PermissionNext.merge( @@ -226,6 +227,7 @@ export namespace Agent { ), mode: "primary", native: true, + deprecated: true, }, ask: { name: "ask", diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx index 24be2167d2b..6a8aa1f3f62 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx @@ -12,7 +12,8 @@ export function DialogAgent() { return { value: item.name, title: item.displayName ?? item.name, // kilocode_change - description: item.native ? "native" : item.description, + description: + [item.deprecated && "deprecated", item.native && "native"].filter(Boolean).join(", ") || item.description, } }), ) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index af5ae1d6b6d..be71a41d7c8 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -1940,6 +1940,7 @@ export type Agent = { mode: "subagent" | "primary" | "all" native?: boolean hidden?: boolean + deprecated?: boolean topP?: number temperature?: number color?: string diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 8393d52605d..3f4f142364e 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -14773,6 +14773,9 @@ "hidden": { "type": "boolean" }, + "deprecated": { + "type": "boolean" + }, "topP": { "type": "number" }, From d2a86f6f9d67e38c06f69c7bdf979671f2424156 Mon Sep 17 00:00:00 2001 From: Yasuhiro ARAKI Date: Mon, 30 Mar 2026 09:26:49 +0900 Subject: [PATCH 121/261] fix: prevent Enter from sending message during IME composition When using IME (e.g. Chinese, Japanese) input methods, pressing Enter to confirm a candidate was also triggering message send. Check `e.isComposing` in the keydown handler and in the slash/file-mention dropdown hooks so that composition-confirmation Enter events are ignored. Fixes #7659 --- .../kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx | 2 +- packages/kilo-vscode/webview-ui/src/hooks/useFileMention.ts | 1 + packages/kilo-vscode/webview-ui/src/hooks/useSlashCommand.ts | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx index cf8804cff15..67157664e3b 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx @@ -482,7 +482,7 @@ export const PromptInput: Component = (props) => { session.abort() return } - if (e.key === "Enter" && !e.shiftKey) { + if (e.key === "Enter" && !e.shiftKey && !e.isComposing) { e.preventDefault() handleSend() } diff --git a/packages/kilo-vscode/webview-ui/src/hooks/useFileMention.ts b/packages/kilo-vscode/webview-ui/src/hooks/useFileMention.ts index f87a9567441..79f5d697f3a 100644 --- a/packages/kilo-vscode/webview-ui/src/hooks/useFileMention.ts +++ b/packages/kilo-vscode/webview-ui/src/hooks/useFileMention.ts @@ -132,6 +132,7 @@ export function useFileMention(vscode: VSCodeContext): FileMention { onSelect?: () => void, ): boolean => { if (!showMention()) return false + if (e.isComposing) return false if (e.key === "ArrowDown") { e.preventDefault() diff --git a/packages/kilo-vscode/webview-ui/src/hooks/useSlashCommand.ts b/packages/kilo-vscode/webview-ui/src/hooks/useSlashCommand.ts index 4835b6e1757..b546cadfce2 100644 --- a/packages/kilo-vscode/webview-ui/src/hooks/useSlashCommand.ts +++ b/packages/kilo-vscode/webview-ui/src/hooks/useSlashCommand.ts @@ -183,6 +183,7 @@ export function useSlashCommand(vscode: VSCodeContext, exclude?: Set): S onSelect?: () => void, ): boolean => { if (!show()) return false + if (e.isComposing) return false const filtered = results() From 482bf89b6905c16ebc85bc53871b1884e00f4349 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 07:03:58 +0000 Subject: [PATCH 122/261] fix: add windowsHide:true to remaining spawn/exec calls to prevent CMD flash on Windows Previous fixes in #6813 and subsequent PRs added windowsHide:true to most spawn sites, but several call sites were missed or regressed: - SDK server.ts (v1 + v2): kilo serve and TUI spawn - ts-check.ts: Bun.spawn for tsc invocation - github.ts: exec for browser open - desktop-electron cli.ts: install script spawn and version check - desktop-electron ipc.ts: open-path execFile - desktop-electron apps.ts: wsl/where execFileSync calls Without windowsHide:true, each of these subprocess invocations causes a visible cmd.exe console window to briefly flash on Windows. Closes #7896 --- packages/desktop-electron/src/main/apps.ts | 6 +++--- packages/desktop-electron/src/main/cli.ts | 4 ++-- packages/desktop-electron/src/main/ipc.ts | 2 +- packages/opencode/src/cli/cmd/github.ts | 2 +- packages/opencode/src/kilocode/ts-check.ts | 1 + packages/sdk/js/src/server.ts | 2 ++ packages/sdk/js/src/v2/server.ts | 2 ++ 7 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/desktop-electron/src/main/apps.ts b/packages/desktop-electron/src/main/apps.ts index 2b460378948..16a0783067c 100644 --- a/packages/desktop-electron/src/main/apps.ts +++ b/packages/desktop-electron/src/main/apps.ts @@ -21,11 +21,11 @@ export function wslPath(path: string, mode: "windows" | "linux" | null): string if (path.startsWith("~")) { const suffix = path.slice(1) const cmd = `wslpath ${flag} \"$HOME${suffix.replace(/\"/g, '\\"')}\"` - const output = execFileSync("wsl", ["-e", "sh", "-lc", cmd]) + const output = execFileSync("wsl", ["-e", "sh", "-lc", cmd], { windowsHide: true }) return output.toString().trim() } - const output = execFileSync("wsl", ["-e", "wslpath", flag, path]) + const output = execFileSync("wsl", ["-e", "wslpath", flag, path], { windowsHide: true }) return output.toString().trim() } catch (error) { throw new Error(`Failed to run wslpath: ${String(error)}`) @@ -51,7 +51,7 @@ function checkMacosApp(appName: string) { function resolveWindowsAppPath(appName: string): string | null { let output: string try { - output = execFileSync("where", [appName]).toString() + output = execFileSync("where", [appName], { windowsHide: true }).toString() } catch { return null } diff --git a/packages/desktop-electron/src/main/cli.ts b/packages/desktop-electron/src/main/cli.ts index e338d39138e..4b2d9447175 100644 --- a/packages/desktop-electron/src/main/cli.ts +++ b/packages/desktop-electron/src/main/cli.ts @@ -84,7 +84,7 @@ export async function installCli(): Promise { writeFileSync(tempScript, script, "utf8") chmodSync(tempScript, 0o755) - const cmd = spawn(tempScript, ["--binary", sidecar], { stdio: "pipe" }) + const cmd = spawn(tempScript, ["--binary", sidecar], { stdio: "pipe", windowsHide: true }) return await new Promise((resolve, reject) => { cmd.on("exit", (code: number | null) => { try { @@ -107,7 +107,7 @@ export function syncCli() { let version = "" try { - version = execFileSync(installPath, ["--version"]).toString().trim() + version = execFileSync(installPath, ["--version"], { windowsHide: true }).toString().trim() } catch { return } diff --git a/packages/desktop-electron/src/main/ipc.ts b/packages/desktop-electron/src/main/ipc.ts index bbb5379bb7a..a27302e4b73 100644 --- a/packages/desktop-electron/src/main/ipc.ts +++ b/packages/desktop-electron/src/main/ipc.ts @@ -123,7 +123,7 @@ export function registerIpcHandlers(deps: Deps) { await new Promise((resolve, reject) => { const [cmd, args] = process.platform === "darwin" ? (["open", ["-a", app, path]] as const) : ([app, [path]] as const) - execFile(cmd, args, (err) => (err ? reject(err) : resolve())) + execFile(cmd, args, { windowsHide: true }, (err) => (err ? reject(err) : resolve())) }) }) diff --git a/packages/opencode/src/cli/cmd/github.ts b/packages/opencode/src/cli/cmd/github.ts index df03d61b91a..bc0d83e9532 100644 --- a/packages/opencode/src/cli/cmd/github.ts +++ b/packages/opencode/src/cli/cmd/github.ts @@ -330,7 +330,7 @@ export const GithubInstallCommand = cmd({ ? `start "" "${url}"` : `xdg-open "${url}"` - exec(command, (error) => { + exec(command, { windowsHide: true }, (error) => { if (error) { prompts.log.warn(`Could not open browser. Please visit: ${url}`) } diff --git a/packages/opencode/src/kilocode/ts-check.ts b/packages/opencode/src/kilocode/ts-check.ts index 449609df830..9deb9506929 100644 --- a/packages/opencode/src/kilocode/ts-check.ts +++ b/packages/opencode/src/kilocode/ts-check.ts @@ -29,6 +29,7 @@ export namespace TsCheck { cwd: root, stdout: "pipe", stderr: "pipe", + windowsHide: true, env: { ...process.env }, }) diff --git a/packages/sdk/js/src/server.ts b/packages/sdk/js/src/server.ts index f878f832f9f..bace9a3b05d 100644 --- a/packages/sdk/js/src/server.ts +++ b/packages/sdk/js/src/server.ts @@ -68,6 +68,7 @@ export async function createKiloServer(options?: ServerOptions) { const proc = spawn(`kilo`, args, { // kilocode_change end signal: options.signal, + windowsHide: true, env: { ...process.env, KILO_CONFIG_CONTENT: buildConfigEnv(options.config), // kilocode_change @@ -148,6 +149,7 @@ export function createKiloTui(options?: TuiOptions) { // kilocode_change end signal: options?.signal, stdio: "inherit", + windowsHide: true, env: { ...process.env, KILO_CONFIG_CONTENT: buildConfigEnv(options?.config), // kilocode_change diff --git a/packages/sdk/js/src/v2/server.ts b/packages/sdk/js/src/v2/server.ts index f878f832f9f..bace9a3b05d 100644 --- a/packages/sdk/js/src/v2/server.ts +++ b/packages/sdk/js/src/v2/server.ts @@ -68,6 +68,7 @@ export async function createKiloServer(options?: ServerOptions) { const proc = spawn(`kilo`, args, { // kilocode_change end signal: options.signal, + windowsHide: true, env: { ...process.env, KILO_CONFIG_CONTENT: buildConfigEnv(options.config), // kilocode_change @@ -148,6 +149,7 @@ export function createKiloTui(options?: TuiOptions) { // kilocode_change end signal: options?.signal, stdio: "inherit", + windowsHide: true, env: { ...process.env, KILO_CONFIG_CONTENT: buildConfigEnv(options?.config), // kilocode_change From 43bfeef8d845b691c305323be2dbbe0e45bf6381 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Mon, 30 Mar 2026 09:17:34 +0200 Subject: [PATCH 123/261] fix(ui): open Exa search result links via openUrl in VS Code webview ExaOutput links used target="_blank" with only stopPropagation, which doesn't work in VS Code webviews. Apply the same openUrl pattern already used by WebfetchMeta so links route through vscode.env.openExternal. --- .../kilo-ui/src/components/message-part.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/kilo-ui/src/components/message-part.tsx b/packages/kilo-ui/src/components/message-part.tsx index e4b6351e429..187a6a2df21 100644 --- a/packages/kilo-ui/src/components/message-part.tsx +++ b/packages/kilo-ui/src/components/message-part.tsx @@ -669,6 +669,15 @@ function isContextGroupTool(part: PartType): part is ToolPart { function ExaOutput(props: { output?: string }) { const links = createMemo(() => urls(props.output)) + const data = useData() + + const open = (url: string, event: MouseEvent) => { + event.stopPropagation() + event.preventDefault() + const handler = data.openUrl + if (handler) return handler(url) + window.open(url, "_blank", "noopener,noreferrer") + } return ( 0}> @@ -676,13 +685,7 @@ function ExaOutput(props: { output?: string }) {
{(url) => ( - event.stopPropagation()} - > + {url} )} From 6e8da6ead4ca952a28d20729123ea99bcff5cbfa Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 07:48:34 +0000 Subject: [PATCH 124/261] revert: restore desktop-electron spawn calls to upstream state desktop-electron is not actively maintained and is synced from upstream. Reverting windowsHide changes in apps.ts, cli.ts, and ipc.ts to keep the diff from upstream minimal and avoid merge conflicts. --- packages/desktop-electron/src/main/apps.ts | 6 +++--- packages/desktop-electron/src/main/cli.ts | 4 ++-- packages/desktop-electron/src/main/ipc.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/desktop-electron/src/main/apps.ts b/packages/desktop-electron/src/main/apps.ts index 16a0783067c..2b460378948 100644 --- a/packages/desktop-electron/src/main/apps.ts +++ b/packages/desktop-electron/src/main/apps.ts @@ -21,11 +21,11 @@ export function wslPath(path: string, mode: "windows" | "linux" | null): string if (path.startsWith("~")) { const suffix = path.slice(1) const cmd = `wslpath ${flag} \"$HOME${suffix.replace(/\"/g, '\\"')}\"` - const output = execFileSync("wsl", ["-e", "sh", "-lc", cmd], { windowsHide: true }) + const output = execFileSync("wsl", ["-e", "sh", "-lc", cmd]) return output.toString().trim() } - const output = execFileSync("wsl", ["-e", "wslpath", flag, path], { windowsHide: true }) + const output = execFileSync("wsl", ["-e", "wslpath", flag, path]) return output.toString().trim() } catch (error) { throw new Error(`Failed to run wslpath: ${String(error)}`) @@ -51,7 +51,7 @@ function checkMacosApp(appName: string) { function resolveWindowsAppPath(appName: string): string | null { let output: string try { - output = execFileSync("where", [appName], { windowsHide: true }).toString() + output = execFileSync("where", [appName]).toString() } catch { return null } diff --git a/packages/desktop-electron/src/main/cli.ts b/packages/desktop-electron/src/main/cli.ts index 4b2d9447175..e338d39138e 100644 --- a/packages/desktop-electron/src/main/cli.ts +++ b/packages/desktop-electron/src/main/cli.ts @@ -84,7 +84,7 @@ export async function installCli(): Promise { writeFileSync(tempScript, script, "utf8") chmodSync(tempScript, 0o755) - const cmd = spawn(tempScript, ["--binary", sidecar], { stdio: "pipe", windowsHide: true }) + const cmd = spawn(tempScript, ["--binary", sidecar], { stdio: "pipe" }) return await new Promise((resolve, reject) => { cmd.on("exit", (code: number | null) => { try { @@ -107,7 +107,7 @@ export function syncCli() { let version = "" try { - version = execFileSync(installPath, ["--version"], { windowsHide: true }).toString().trim() + version = execFileSync(installPath, ["--version"]).toString().trim() } catch { return } diff --git a/packages/desktop-electron/src/main/ipc.ts b/packages/desktop-electron/src/main/ipc.ts index a27302e4b73..bbb5379bb7a 100644 --- a/packages/desktop-electron/src/main/ipc.ts +++ b/packages/desktop-electron/src/main/ipc.ts @@ -123,7 +123,7 @@ export function registerIpcHandlers(deps: Deps) { await new Promise((resolve, reject) => { const [cmd, args] = process.platform === "darwin" ? (["open", ["-a", app, path]] as const) : ([app, [path]] as const) - execFile(cmd, args, { windowsHide: true }, (err) => (err ? reject(err) : resolve())) + execFile(cmd, args, (err) => (err ? reject(err) : resolve())) }) }) From 6b7a403cb030367b2a43f756266d947df9298cd7 Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 30 Mar 2026 10:02:19 +0200 Subject: [PATCH 125/261] feat(vscode): add MCP server connect/disconnect toggle and status display (#7810) Wire the existing CLI MCP APIs (status, connect, disconnect) into the extension webview so users can toggle MCP servers on/off and see live connection status without editing config files. - Add message types for MCP status flow (request/connect/disconnect/loaded) - Add KiloProvider handlers that call SDK client.mcp.status/connect/disconnect - Add mcpStatus signal + subscription to session context with retry on init - Enhance MCP settings subtab with status dots, status labels, error display, and Switch toggle per server row Closes #7806 --- packages/kilo-vscode/src/KiloProvider.ts | 58 +++++++++++++ .../components/settings/AgentBehaviourTab.tsx | 86 ++++++++++++++++--- .../webview-ui/src/context/session.tsx | 57 ++++++++++++ .../kilo-vscode/webview-ui/src/i18n/ar.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/br.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/bs.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/da.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/de.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/en.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/es.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/fr.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/ja.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/ko.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/nl.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/no.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/pl.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/ru.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/th.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/tr.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/zh.ts | 1 + .../kilo-vscode/webview-ui/src/i18n/zht.ts | 1 + .../webview-ui/src/types/messages.ts | 28 ++++++ 22 files changed, 235 insertions(+), 12 deletions(-) diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index ba24906f0f9..a113794e254 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -113,6 +113,8 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper private cachedCommandsMessage: unknown = null /** Cached configLoaded payload so requestConfig can be served before client is ready */ private cachedConfigMessage: unknown = null + /** Cached mcpStatusLoaded payload so requestMcpStatus can be served before client is ready */ + private cachedMcpStatusMessage: unknown = null /** Ref-count of in-flight handleUpdateConfig calls; prevents fetchAndSendConfig from sending stale data */ private pending = 0 /** Cached notificationsLoaded payload */ @@ -645,6 +647,17 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper case "removeMcp": this.handleRemoveMcp(message.name).catch((e) => console.error("[Kilo New] handleRemoveMcp failed:", e)) break + case "requestMcpStatus": + this.fetchAndSendMcpStatus().catch((e) => console.error("[Kilo New] fetchAndSendMcpStatus failed:", e)) + break + case "connectMcp": + this.handleConnectMcp(message.name).catch((e) => console.error("[Kilo New] handleConnectMcp failed:", e)) + break + case "disconnectMcp": + this.handleDisconnectMcp(message.name).catch((e) => + console.error("[Kilo New] handleDisconnectMcp failed:", e), + ) + break case "questionReply": await handleQuestionReply(this.questionCtx, message.requestID, message.answers) @@ -1663,6 +1676,51 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper } } + private async fetchAndSendMcpStatus(): Promise { + if (!this.client) { + if (this.cachedMcpStatusMessage) { + this.postMessage(this.cachedMcpStatusMessage) + } + return + } + + try { + const directory = this.getWorkspaceDirectory() + const { data } = await this.client.mcp.status({ directory }) + if (data) { + const message = { type: "mcpStatusLoaded", status: data } + this.cachedMcpStatusMessage = message + this.postMessage(message) + } + } catch (error) { + console.error("[Kilo New] KiloProvider: Failed to fetch MCP status:", error) + } + } + + private async handleConnectMcp(name: string): Promise { + if (!this.client) return + try { + const directory = this.getWorkspaceDirectory() + await this.client.mcp.connect({ name, directory }) + await this.fetchAndSendMcpStatus() + } catch (error) { + console.error("[Kilo New] KiloProvider: Failed to connect MCP:", name, error) + await this.fetchAndSendMcpStatus() + } + } + + private async handleDisconnectMcp(name: string): Promise { + if (!this.client) return + try { + const directory = this.getWorkspaceDirectory() + await this.client.mcp.disconnect({ name, directory }) + await this.fetchAndSendMcpStatus() + } catch (error) { + console.error("[Kilo New] KiloProvider: Failed to disconnect MCP:", name, error) + await this.fetchAndSendMcpStatus() + } + } + /** * Dispose the CLI backend instance so it re-reads config from disk. * Call after any marketplace install/remove that writes config files directly. diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index 9245f7bd014..181dd855cea 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -6,6 +6,7 @@ import { Button } from "@kilocode/kilo-ui/button" import { IconButton } from "@kilocode/kilo-ui/icon-button" import { Dialog } from "@kilocode/kilo-ui/dialog" import { useDialog } from "@kilocode/kilo-ui/context/dialog" +import { Switch } from "@kilocode/kilo-ui/switch" import { useConfig } from "../../context/config" import { useSession } from "../../context/session" @@ -478,6 +479,31 @@ const AgentBehaviourTab: Component = () => { setExpanded((prev) => ({ ...prev, [name]: !prev[name] })) } + const statusColor = (name: string) => { + const s = session.mcpStatus()[name]?.status + if (s === "connected") return "var(--vscode-testing-iconPassed, #4caf50)" + if (s === "failed") return "var(--vscode-testing-iconFailed, #f44336)" + if (s === "needs_auth" || s === "needs_client_registration") + return "var(--vscode-editorWarning-foreground, #ff9800)" + if (s === "disabled") return "var(--vscode-disabledForeground, #888)" + return "var(--vscode-disabledForeground, #888)" + } + + const statusLabel = (name: string) => { + const s = session.mcpStatus()[name]?.status + if (!s) return "" + const key = { + connected: "mcp.status.connected", + failed: "mcp.status.failed", + needs_auth: "mcp.status.needs_auth", + disabled: "mcp.status.disabled", + needs_client_registration: "mcp.status.needs_registration", + }[s] + return key ? language.t(key) : s + } + + const isConnected = (name: string) => session.mcpStatus()[name]?.status === "connected" + if (editingMcp()) { return ( { {([name, mcp], index) => { const open = () => expanded()[name] ?? false const env = () => Object.entries(mcp.environment ?? mcp.env ?? {}) + const error = () => { + const s = session.mcpStatus()[name] + if (s?.status === "failed") return s.error + if (s?.status === "needs_client_registration") return s.error + return undefined + } return (
{ toggle(name) }} /> + {/* Status dot */} +
{name}
{ color: "var(--text-weak-base, var(--vscode-descriptionForeground))", }} > - {mcp.url ? "remote" : "stdio"} + {statusLabel(name) || (mcp.url ? "remote" : "stdio")}
-
+
+
e.stopPropagation()}> + { + if (isConnected(name)) { + session.disconnectMcp(name) + } else { + session.connectMcp(name) + } + }} + hideLabel + > + {name} + +
{
+ {/* Error message */} + +
+ {error()} +
+
+ {/* Expandable detail */}
{ )} - -
- {language.t("settings.agentBehaviour.mcpDetail.disabled")} -
-
diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index 28201fa0610..6bd771ab7ec 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -40,6 +40,7 @@ import type { ExtensionMessage, FileAttachment, SendMessageFailedMessage, + McpStatusEntry, } from "../types/messages" import { removeSessionPermissions, upsertPermission } from "./permission-queue" import { computeStatus, calcTotalCost, calcContextUsage } from "./session-utils" @@ -137,6 +138,13 @@ interface SessionContextValue { agents: Accessor removeMode: (name: string) => void removeMcp: (name: string) => void + + // MCP server status (runtime connect/disconnect) + mcpStatus: Accessor> + mcpLoading: Accessor + connectMcp: (name: string) => void + disconnectMcp: (name: string) => void + refreshMcpStatus: () => void selectedAgent: Accessor selectAgent: (name: string) => void getSessionAgent: (sessionID: string) => string @@ -263,6 +271,28 @@ export const SessionProvider: ParentComponent = (props) => { vscode.postMessage({ type: "removeMcp", name }) } + // MCP runtime status + const [mcpStatus, setMcpStatus] = createSignal>({}) + const [mcpLoading, setMcpLoading] = createSignal(null) + + const connectMcp = (name: string) => { + if (mcpLoading()) return + if (!server.isConnected()) return + setMcpLoading(name) + vscode.postMessage({ type: "connectMcp", name }) + } + + const disconnectMcp = (name: string) => { + if (mcpLoading()) return + if (!server.isConnected()) return + setMcpLoading(name) + vscode.postMessage({ type: "disconnectMcp", name }) + } + + const refreshMcpStatus = () => { + vscode.postMessage({ type: "requestMcpStatus" }) + } + // Pending agent selection for before a session exists const [pendingAgentSelection, setPendingAgentSelection] = createSignal(null) @@ -474,10 +504,32 @@ export const SessionProvider: ParentComponent = (props) => { vscode.postMessage({ type: "removeSkill", location }) } + // MCP status loaded from CLI backend + const unsubMcpStatus = vscode.onMessage((message: ExtensionMessage) => { + if (message.type === "mcpStatusLoaded") { + setMcpStatus(message.status) + setMcpLoading(null) + } + }) + + // Request MCP status on init with retry (same pattern as agents) + let mcpRetries = 0 + vscode.postMessage({ type: "requestMcpStatus" }) + const mcpRetryTimer = setInterval(() => { + mcpRetries++ + if (Object.keys(mcpStatus()).length > 0 || mcpRetries >= 5) { + clearInterval(mcpRetryTimer) + return + } + vscode.postMessage({ type: "requestMcpStatus" }) + }, 500) + onCleanup(() => { unsubAgents() unsubSkills() + unsubMcpStatus() clearInterval(agentRetryTimer) + clearInterval(mcpRetryTimer) }) // Variant (thinking effort) selection — keyed by "providerID/modelID" @@ -1631,6 +1683,11 @@ export const SessionProvider: ParentComponent = (props) => { removeSkill, removeMode, removeMcp, + mcpStatus, + mcpLoading, + connectMcp, + disconnectMcp, + refreshMcpStatus, selectedAgent: selectedAgentName, selectAgent, getSessionAgent: (sessionID: string) => store.agentSelections[sessionID] ?? defaultAgent(), diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index bca0f4ea785..550ceae34de 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -266,6 +266,7 @@ export const dict = { "mcp.status.connected": "متصل", "mcp.status.failed": "فشل", "mcp.status.needs_auth": "يحتاج إلى مصادقة", + "mcp.status.needs_registration": "يحتاج إلى تسجيل العميل", "mcp.status.disabled": "معطل", "dialog.fork.empty": "لا توجد رسائل للتفرع منها", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 1cb8a7e824f..933ef32d636 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -266,6 +266,7 @@ export const dict = { "mcp.status.connected": "conectado", "mcp.status.failed": "falhou", "mcp.status.needs_auth": "precisa de autenticação", + "mcp.status.needs_registration": "precisa de registro do cliente", "mcp.status.disabled": "desabilitado", "dialog.fork.empty": "Nenhuma mensagem para bifurcar", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index cb2a7161a31..7fa352473fd 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -268,6 +268,7 @@ export const dict = { "mcp.status.connected": "povezano", "mcp.status.failed": "neuspjelo", "mcp.status.needs_auth": "potrebna autentifikacija", + "mcp.status.needs_registration": "potrebna registracija klijenta", "mcp.status.disabled": "onemogućeno", "dialog.fork.empty": "Nema poruka za fork", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 22b89abc970..2fad5ccb451 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -267,6 +267,7 @@ export const dict = { "mcp.status.connected": "forbundet", "mcp.status.failed": "mislykkedes", "mcp.status.needs_auth": "kræver godkendelse", + "mcp.status.needs_registration": "kræver klientregistrering", "mcp.status.disabled": "deaktiveret", "dialog.fork.empty": "Ingen beskeder at forgrene fra", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 8b289e33340..115a4125129 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -272,6 +272,7 @@ export const dict = { "mcp.status.connected": "verbunden", "mcp.status.failed": "fehlgeschlagen", "mcp.status.needs_auth": "benötigt Authentifizierung", + "mcp.status.needs_registration": "Client-Registrierung erforderlich", "mcp.status.disabled": "deaktiviert", "dialog.fork.empty": "Keine Nachrichten zum Abzweigen vorhanden", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 7efa69f8b9d..05b2040b3ce 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -268,6 +268,7 @@ export const dict = { "mcp.status.connected": "connected", "mcp.status.failed": "failed", "mcp.status.needs_auth": "needs auth", + "mcp.status.needs_registration": "needs client registration", "mcp.status.disabled": "disabled", "dialog.fork.empty": "No messages to fork from", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 8bd2ab5a197..ea73828f217 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -267,6 +267,7 @@ export const dict = { "mcp.status.connected": "conectado", "mcp.status.failed": "fallido", "mcp.status.needs_auth": "necesita auth", + "mcp.status.needs_registration": "necesita registro de cliente", "mcp.status.disabled": "deshabilitado", "dialog.fork.empty": "No hay mensajes desde donde bifurcar", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index b2306632c54..0ffc850e1dc 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -268,6 +268,7 @@ export const dict = { "mcp.status.connected": "connecté", "mcp.status.failed": "échoué", "mcp.status.needs_auth": "nécessite auth", + "mcp.status.needs_registration": "nécessite enregistrement client", "mcp.status.disabled": "désactivé", "dialog.fork.empty": "Aucun message à partir duquel bifurquer", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 48827875bce..17857037d91 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -266,6 +266,7 @@ export const dict = { "mcp.status.connected": "接続済み", "mcp.status.failed": "失敗", "mcp.status.needs_auth": "認証が必要", + "mcp.status.needs_registration": "クライアント登録が必要", "mcp.status.disabled": "無効", "dialog.fork.empty": "フォーク元のメッセージがありません", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index dc92fe9014a..16dfd140665 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -270,6 +270,7 @@ export const dict = { "mcp.status.connected": "연결됨", "mcp.status.failed": "실패", "mcp.status.needs_auth": "인증 필요", + "mcp.status.needs_registration": "클라이언트 등록 필요", "mcp.status.disabled": "비활성화됨", "dialog.fork.empty": "분기할 메시지 없음", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 5380d465630..12b3e8a3a5e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -268,6 +268,7 @@ export const dict = { "mcp.status.connected": "verbonden", "mcp.status.failed": "mislukt", "mcp.status.needs_auth": "authenticatie vereist", + "mcp.status.needs_registration": "clientregistratie vereist", "mcp.status.disabled": "uitgeschakeld", "dialog.fork.empty": "Geen berichten om van af te splitsen", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 3b538326b54..d02b1280d5d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -270,6 +270,7 @@ export const dict = { "mcp.status.connected": "tilkoblet", "mcp.status.failed": "mislyktes", "mcp.status.needs_auth": "trenger autentisering", + "mcp.status.needs_registration": "trenger klientregistrering", "mcp.status.disabled": "deaktivert", "dialog.fork.empty": "Ingen meldinger å forgrene fra", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 59408be763e..27a18dd978a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -267,6 +267,7 @@ export const dict = { "mcp.status.connected": "połączono", "mcp.status.failed": "niepowodzenie", "mcp.status.needs_auth": "wymaga autoryzacji", + "mcp.status.needs_registration": "wymaga rejestracji klienta", "mcp.status.disabled": "wyłączone", "dialog.fork.empty": "Brak wiadomości do rozwidlenia", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index a1a4cf56bb4..a0a494ac760 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -267,6 +267,7 @@ export const dict = { "mcp.status.connected": "подключено", "mcp.status.failed": "ошибка", "mcp.status.needs_auth": "требуется авторизация", + "mcp.status.needs_registration": "требуется регистрация клиента", "mcp.status.disabled": "отключено", "dialog.fork.empty": "Нет сообщений для ответвления", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 76d927ec397..000c8d7cb02 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -267,6 +267,7 @@ export const dict = { "mcp.status.connected": "เชื่อมต่อแล้ว", "mcp.status.failed": "ล้มเหลว", "mcp.status.needs_auth": "ต้องการการตรวจสอบสิทธิ์", + "mcp.status.needs_registration": "ต้องการลงทะเบียนไคลเอนต์", "mcp.status.disabled": "ปิดใช้งาน", "dialog.fork.empty": "ไม่มีข้อความให้แตกแขนง", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 1028b3e6e36..0a6efea37fe 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -267,6 +267,7 @@ export const dict = { "mcp.status.connected": "bağlı", "mcp.status.failed": "başarısız", "mcp.status.needs_auth": "kimlik doğrulama gerekli", + "mcp.status.needs_registration": "istemci kaydı gerekli", "mcp.status.disabled": "devre dışı", "dialog.fork.empty": "Dallandırılacak mesaj yok", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index a3d03e9d8f0..ecaebfb8448 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -267,6 +267,7 @@ export const dict = { "mcp.status.connected": "已连接", "mcp.status.failed": "失败", "mcp.status.needs_auth": "需要授权", + "mcp.status.needs_registration": "需要客户端注册", "mcp.status.disabled": "已禁用", "dialog.fork.empty": "没有可用于分叉的消息", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index fe15b4f6091..2dffda1cad9 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -267,6 +267,7 @@ export const dict = { "mcp.status.connected": "已連線", "mcp.status.failed": "失敗", "mcp.status.needs_auth": "需要授權", + "mcp.status.needs_registration": "需要客戶端註冊", "mcp.status.disabled": "已停用", "dialog.fork.empty": "沒有可用於分支的訊息", diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index 63e633994e0..7e7f7e03777 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -1332,6 +1332,7 @@ export type ExtensionMessage = | LanguageChangedMessage | ContinueInWorktreeProgressMessage | WorktreeStatsLoadedMessage + | McpStatusLoadedMessage // ============================================ // Messages FROM webview TO extension @@ -1520,6 +1521,30 @@ export interface RemoveMcpMessage { name: string } +export interface RequestMcpStatusMessage { + type: "requestMcpStatus" +} + +export interface ConnectMcpMessage { + type: "connectMcp" + name: string +} + +export interface DisconnectMcpMessage { + type: "disconnectMcp" + name: string +} + +export interface McpStatusEntry { + status: "connected" | "disabled" | "failed" | "needs_auth" | "needs_client_registration" + error?: string +} + +export interface McpStatusLoadedMessage { + type: "mcpStatusLoaded" + status: Record +} + export interface SetLanguageRequest { type: "setLanguage" locale: string @@ -2008,6 +2033,9 @@ export type WebviewMessage = | RemoveSkillMessage | RemoveModeMessage | RemoveMcpMessage + | RequestMcpStatusMessage + | ConnectMcpMessage + | DisconnectMcpMessage | SetLanguageRequest | QuestionReplyRequest | QuestionRejectRequest From e6d75b19805a7b9db9d455f6f5d9ee87f11f56b3 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 08:45:38 +0000 Subject: [PATCH 126/261] fix(vscode): clarify reset settings button only affects extension-specific settings Update the description above the 'Reset All Settings' button to make clear that it only resets VS Code extension-specific settings and not settings shared with the CLI (such as modes and auto-approve rules). Translations updated in all 18 supported languages. Fixes #7727 --- packages/kilo-vscode/webview-ui/src/i18n/ar.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/br.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/bs.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/da.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/de.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/en.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/es.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/fr.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/ja.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/ko.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/nl.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/no.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/pl.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/ru.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/th.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/tr.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/zh.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/zht.ts | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index 550ceae34de..8ac9723457a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -967,7 +967,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "لأسئلة الفوترة أو الحساب، تواصل مع دعم العملاء على", "settings.aboutKiloCode.resetSettings.title": "إعادة تعيين الإعدادات", "settings.aboutKiloCode.resetSettings.description": - "إعادة تعيين جميع إعدادات إضافة Kilo Code إلى قيمها الافتراضية. لا يؤثر هذا على تكوين CLI أو الواجهة الخلفية.", + "يؤدي هذا إلى إعادة تعيين الإعدادات الخاصة بامتداد VS Code فقط إلى قيمها الافتراضية. الإعدادات المشتركة مع CLI، مثل الأوضاع وقواعد الموافقة التلقائية، مخزّنة في تكوين CLI ولن تتأثر.", "settings.aboutKiloCode.resetSettings.button": "إعادة تعيين جميع الإعدادات", "settings.aboutKiloCode.settingsTransfer.title": "نقل الإعدادات", "settings.aboutKiloCode.settingsTransfer.description": "تصدير أو استيراد إعداداتك لنقلها بين نُسخ VS Code.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 933ef32d636..ae3354126f7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -976,7 +976,7 @@ export const dict = { "Para questões de cobrança ou conta, entre em contato com o Suporte ao Cliente em", "settings.aboutKiloCode.resetSettings.title": "Redefinir Configurações", "settings.aboutKiloCode.resetSettings.description": - "Redefinir todas as configurações da extensão Kilo Code para os valores padrão. Isso não afeta a configuração do CLI ou do backend.", + "Isso redefine apenas as configurações específicas da extensão VS Code para seus valores padrão. As configurações compartilhadas com o CLI, como modos e regras de aprovação automática, são armazenadas na configuração do CLI e não serão redefinidas.", "settings.aboutKiloCode.resetSettings.button": "Redefinir Todas as Configurações", "settings.aboutKiloCode.settingsTransfer.title": "Transferência de configurações", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 7fa352473fd..d64c14baf07 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -980,7 +980,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "Za pitanja o naplati ili računu, kontaktirajte korisničku podršku na", "settings.aboutKiloCode.resetSettings.title": "Resetovanje postavki", "settings.aboutKiloCode.resetSettings.description": - "Resetujte sve postavke Kilo Code ekstenzije na zadane vrijednosti. Ovo ne utiče na CLI ili backend konfiguraciju.", + "Ovo resetuje samo postavke specifične za VS Code ekstenziju na njihove zadane vrijednosti. Postavke koje se dijele s CLI-jem, kao što su načini rada i pravila automatskog odobravanja, pohranjene su u CLI konfiguraciji i neće biti resetovane.", "settings.aboutKiloCode.resetSettings.button": "Resetuj sve postavke", "settings.aboutKiloCode.settingsTransfer.title": "Prijenos postavki", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 2fad5ccb451..a8eeecae1f4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -974,7 +974,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "For fakturerings- eller kontospørgsmål, kontakt kundesupport på", "settings.aboutKiloCode.resetSettings.title": "Nulstil indstillinger", "settings.aboutKiloCode.resetSettings.description": - "Nulstil alle Kilo Code-udvidelsesindstillinger til standardværdierne. Dette påvirker ikke CLI- eller backend-konfiguration.", + "Dette nulstiller kun VS Code-udvidelsesspecifikke indstillinger til deres standardværdier. Indstillinger der deles med CLI, såsom tilstande og regler for automatisk godkendelse, er gemt i CLI-konfigurationen og vil ikke blive nulstillet.", "settings.aboutKiloCode.resetSettings.button": "Nulstil alle indstillinger", "settings.aboutKiloCode.settingsTransfer.title": "Overførsel af indstillinger", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 115a4125129..8f7c6805178 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -987,7 +987,7 @@ export const dict = { "Bei Abrechnungs- oder Kontofragen wenden Sie sich an den Kundensupport unter", "settings.aboutKiloCode.resetSettings.title": "Einstellungen zurücksetzen", "settings.aboutKiloCode.resetSettings.description": - "Alle Kilo Code-Erweiterungseinstellungen auf Standardwerte zurücksetzen. Dies hat keinen Einfluss auf die CLI- oder Backend-Konfiguration.", + "Dies setzt nur VS Code-erweiterungsspezifische Einstellungen auf ihre Standardwerte zurück. Einstellungen, die mit der CLI geteilt werden, wie Modi und Regeln für die automatische Genehmigung, werden in der CLI-Konfiguration gespeichert und nicht zurückgesetzt.", "settings.aboutKiloCode.resetSettings.button": "Alle Einstellungen zurücksetzen", "settings.aboutKiloCode.settingsTransfer.title": "Einstellungen übertragen", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 05b2040b3ce..fbb8f1191b9 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -973,7 +973,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "For billing or account questions, contact Customer Support at", "settings.aboutKiloCode.resetSettings.title": "Reset Settings", "settings.aboutKiloCode.resetSettings.description": - "Reset all Kilo Code extension settings to their default values. This does not affect CLI or backend configuration.", + "This resets only VS Code extension-specific settings to their default values. Settings shared with the CLI, such as modes and auto-approve rules, are stored in the CLI configuration and will not be reset.", "settings.aboutKiloCode.resetSettings.button": "Reset All Settings", "settings.aboutKiloCode.settingsTransfer.title": "Settings Transfer", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index ea73828f217..d83c3168d3e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -981,7 +981,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "Para preguntas de facturación o cuenta, contacta al Soporte al Cliente en", "settings.aboutKiloCode.resetSettings.title": "Restablecer configuración", "settings.aboutKiloCode.resetSettings.description": - "Restablecer todas las configuraciones de la extensión Kilo Code a sus valores predeterminados. Esto no afecta la configuración del CLI o del backend.", + "Esto restablece únicamente las configuraciones específicas de la extensión VS Code a sus valores predeterminados. Las configuraciones compartidas con el CLI, como los modos y las reglas de aprobación automática, se almacenan en la configuración del CLI y no serán restablecidas.", "settings.aboutKiloCode.resetSettings.button": "Restablecer toda la configuración", "settings.aboutKiloCode.settingsTransfer.title": "Transferencia de ajustes", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 0ffc850e1dc..051bab83981 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -989,7 +989,7 @@ export const dict = { "Pour les questions de facturation ou de compte, contactez le support client à", "settings.aboutKiloCode.resetSettings.title": "Réinitialiser les paramètres", "settings.aboutKiloCode.resetSettings.description": - "Réinitialiser tous les paramètres de l'extension Kilo Code à leurs valeurs par défaut. Cela n'affecte pas la configuration CLI ou backend.", + "Ceci réinitialise uniquement les paramètres spécifiques à l'extension VS Code à leurs valeurs par défaut. Les paramètres partagés avec le CLI, tels que les modes et les règles d'approbation automatique, sont stockés dans la configuration du CLI et ne seront pas réinitialisés.", "settings.aboutKiloCode.resetSettings.button": "Réinitialiser tous les paramètres", "settings.aboutKiloCode.settingsTransfer.title": "Transfert des paramètres", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 17857037d91..f65245c19d9 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -973,7 +973,7 @@ export const dict = { "請求やアカウントに関するご質問は、カスタマーサポートまでお問い合わせください", "settings.aboutKiloCode.resetSettings.title": "設定をリセット", "settings.aboutKiloCode.resetSettings.description": - "Kilo Code拡張機能のすべての設定をデフォルト値にリセットします。CLIやバックエンドの設定には影響しません。", + "これはVS Code拡張機能固有の設定のみをデフォルト値にリセットします。モードや自動承認ルールなど、CLIと共有される設定はCLI設定ファイルに保存されており、リセットされません。", "settings.aboutKiloCode.resetSettings.button": "すべての設定をリセット", "settings.aboutKiloCode.settingsTransfer.title": "設定の移行", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 16dfd140665..4e9f93ba204 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -972,7 +972,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "결제 또는 계정 관련 문의는 고객 지원팀에 문의하세요", "settings.aboutKiloCode.resetSettings.title": "설정 초기화", "settings.aboutKiloCode.resetSettings.description": - "Kilo Code 확장 프로그램의 모든 설정을 기본값으로 초기화합니다. CLI 또는 백엔드 구성에는 영향을 미치지 않습니다.", + "이 기능은 VS Code 확장 프로그램 전용 설정만 기본값으로 초기화합니다. 모드 및 자동 승인 규칙과 같이 CLI와 공유되는 설정은 CLI 구성에 저장되며 초기화되지 않습니다.", "settings.aboutKiloCode.resetSettings.button": "모든 설정 초기화", "settings.aboutKiloCode.settingsTransfer.title": "설정 이전", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 12b3e8a3a5e..87cbe8ef733 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -974,7 +974,7 @@ export const dict = { "Voor vragen over facturering of je account, neem contact op met Klantenservice op", "settings.aboutKiloCode.resetSettings.title": "Instellingen resetten", "settings.aboutKiloCode.resetSettings.description": - "Reset alle instellingen van de Kilo Code extensie naar hun standaardwaarden. Dit heeft geen invloed op CLI of backend configuratie.", + "Dit reset alleen VS Code-extensiespecifieke instellingen naar hun standaardwaarden. Instellingen die gedeeld worden met de CLI, zoals modi en regels voor automatisch goedkeuren, worden opgeslagen in de CLI-configuratie en worden niet gereset.", "settings.aboutKiloCode.resetSettings.button": "Alle instellingen resetten", "settings.aboutKiloCode.settingsTransfer.title": "Instellingen overdragen", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index d02b1280d5d..ce43e675979 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -977,7 +977,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "For fakturerings- eller kontospørsmål, kontakt kundestøtte på", "settings.aboutKiloCode.resetSettings.title": "Tilbakestill innstillinger", "settings.aboutKiloCode.resetSettings.description": - "Tilbakestill alle Kilo Code-utvidelsesinnstillinger til standardverdier. Dette påvirker ikke CLI- eller backend-konfigurasjon.", + "Dette tilbakestiller kun VS Code-utvidelsesspecifikke innstillinger til standardverdiene. Innstillinger som deles med CLI, som modi og regler for automatisk godkjenning, lagres i CLI-konfigurasjonen og vil ikke tilbakestilles.", "settings.aboutKiloCode.resetSettings.button": "Tilbakestill alle innstillinger", "settings.aboutKiloCode.settingsTransfer.title": "Overføring av innstillinger", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 27a18dd978a..6d79e1c6205 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -978,7 +978,7 @@ export const dict = { "W sprawach rozliczeń lub konta skontaktuj się z obsługą klienta pod adresem", "settings.aboutKiloCode.resetSettings.title": "Resetuj ustawienia", "settings.aboutKiloCode.resetSettings.description": - "Zresetuj wszystkie ustawienia rozszerzenia Kilo Code do wartości domyślnych. Nie wpływa to na konfigurację CLI ani backendu.", + "To resetuje tylko ustawienia specyficzne dla rozszerzenia VS Code do ich domyślnych wartości. Ustawienia współdzielone z CLI, takie jak tryby i reguły automatycznego zatwierdzania, są przechowywane w konfiguracji CLI i nie zostaną zresetowane.", "settings.aboutKiloCode.resetSettings.button": "Resetuj wszystkie ustawienia", "settings.aboutKiloCode.settingsTransfer.title": "Przenoszenie ustawień", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index a0a494ac760..293dfb78577 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -980,7 +980,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "По вопросам оплаты или аккаунта обращайтесь в службу поддержки по адресу", "settings.aboutKiloCode.resetSettings.title": "Сброс настроек", "settings.aboutKiloCode.resetSettings.description": - "Сбросить все настройки расширения Kilo Code до значений по умолчанию. Это не влияет на конфигурацию CLI или бэкенда.", + "Это сбрасывает только настройки, специфичные для расширения VS Code, до значений по умолчанию. Настройки, общие с CLI, такие как режимы и правила автоматического утверждения, хранятся в конфигурации CLI и не будут сброшены.", "settings.aboutKiloCode.resetSettings.button": "Сбросить все настройки", "settings.aboutKiloCode.settingsTransfer.title": "Перенос настроек", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 000c8d7cb02..4b826b3317a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -968,7 +968,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "สำหรับคำถามเกี่ยวกับการเรียกเก็บเงินหรือบัญชี ติดต่อฝ่ายสนับสนุนลูกค้าที่", "settings.aboutKiloCode.resetSettings.title": "รีเซ็ตการตั้งค่า", "settings.aboutKiloCode.resetSettings.description": - "รีเซ็ตการตั้งค่าส่วนขยาย Kilo Code ทั้งหมดเป็นค่าเริ่มต้น ไม่ส่งผลกระทบต่อการกำหนดค่า CLI หรือแบ็กเอนด์", + "การดำเนินการนี้จะรีเซ็ตเฉพาะการตั้งค่าเฉพาะของส่วนขยาย VS Code กลับเป็นค่าเริ่มต้นเท่านั้น การตั้งค่าที่ใช้ร่วมกับ CLI เช่น โหมดและกฎการอนุมัติอัตโนมัติ จะถูกเก็บไว้ในการกำหนดค่า CLI และจะไม่ถูกรีเซ็ต", "settings.aboutKiloCode.resetSettings.button": "รีเซ็ตการตั้งค่าทั้งหมด", "settings.aboutKiloCode.settingsTransfer.title": "ถ่ายโอนการตั้งค่า", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 0a6efea37fe..ae0fe2fa314 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -977,7 +977,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "Faturalama veya hesap soruları için Müşteri Desteği ile iletişime geçin:", "settings.aboutKiloCode.resetSettings.title": "Ayarları Sıfırla", "settings.aboutKiloCode.resetSettings.description": - "Tüm Kilo Code uzantı ayarlarını varsayılan değerlerine sıfırla. Bu, CLI veya arka uç yapılandırmasını etkilemez.", + "Bu, yalnızca VS Code uzantısına özgü ayarları varsayılan değerlerine sıfırlar. Modlar ve otomatik onay kuralları gibi CLI ile paylaşılan ayarlar, CLI yapılandırmasında depolanır ve sıfırlanmaz.", "settings.aboutKiloCode.resetSettings.button": "Tüm Ayarları Sıfırla", "settings.aboutKiloCode.settingsTransfer.title": "Ayar Aktarımı", "settings.aboutKiloCode.settingsTransfer.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index ecaebfb8448..91e2e50edd7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -960,7 +960,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "如有账单或账户问题,请联系客户支持", "settings.aboutKiloCode.resetSettings.title": "重置设置", "settings.aboutKiloCode.resetSettings.description": - "将所有 Kilo Code 扩展设置重置为默认值。这不会影响 CLI 或后端配置。", + "此操作仅将 VS Code 扩展专属设置重置为默认值。与 CLI 共享的设置(如模式和自动审批规则)存储在 CLI 配置中,不会被重置。", "settings.aboutKiloCode.resetSettings.button": "重置所有设置", "settings.aboutKiloCode.settingsTransfer.title": "设置迁移", "settings.aboutKiloCode.settingsTransfer.description": "导出或导入设置,以便在 VS Code 实例之间传输。", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 2dffda1cad9..58cc5597892 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -962,7 +962,7 @@ export const dict = { "settings.aboutKiloCode.support.prefix": "如有帳單或帳戶問題,請聯繫客戶支援", "settings.aboutKiloCode.resetSettings.title": "重置設定", "settings.aboutKiloCode.resetSettings.description": - "將所有 Kilo Code 擴充功能設定重置為預設值。這不會影響 CLI 或後端設定。", + "此操作僅將 VS Code 擴充功能專屬設定重置為預設值。與 CLI 共享的設定(例如模式和自動核准規則)儲存在 CLI 設定中,不會被重置。", "settings.aboutKiloCode.resetSettings.button": "重置所有設定", "settings.aboutKiloCode.settingsTransfer.title": "設定轉移", "settings.aboutKiloCode.settingsTransfer.description": "匯出或匯入設定,以便在 VS Code 實例之間轉移。", From 2e6e99187648528328845e403b4a4e49dd3b5252 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:09:32 +0000 Subject: [PATCH 127/261] fix(vscode): correctly map zh-TW/zh-HK/zh-MO to Traditional Chinese locale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #7914 — normalizeLocale and resolveLocale only checked for the explicit 'hant' script subtag. zh-TW (Taiwan), zh-HK (Hong Kong), and zh-MO (Macau) use region-based codes to denote Traditional Chinese, so they were incorrectly mapped to Simplified Chinese (zh). Add region checks for -tw, -hk, and -mo so VS Code's 'zh-tw' display language correctly resolves to the 'zht' locale. --- packages/kilo-vscode/src/services/cli-backend/i18n/index.ts | 6 +++++- packages/kilo-vscode/tests/unit/language-utils.test.ts | 4 +++- .../kilo-vscode/webview-ui/src/context/language-utils.ts | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts b/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts index 88163caafbc..8d271c036d7 100644 --- a/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts +++ b/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts @@ -41,7 +41,11 @@ const bundles: Record> = { function resolveLocale(lang: string): string { const lower = lang.toLowerCase() - if (lower.startsWith("zh")) return lower.includes("hant") ? "zht" : "zh" + if (lower.startsWith("zh")) { + const traditional = + lower.includes("hant") || lower.includes("-tw") || lower.includes("-hk") || lower.includes("-mo") + return traditional ? "zht" : "zh" + } if (lower.startsWith("nb") || lower.startsWith("nn")) return "no" if (lower.startsWith("pt")) return "br" for (const key of Object.keys(bundles)) { diff --git a/packages/kilo-vscode/tests/unit/language-utils.test.ts b/packages/kilo-vscode/tests/unit/language-utils.test.ts index 75ad9bd5f8c..8226e58d85e 100644 --- a/packages/kilo-vscode/tests/unit/language-utils.test.ts +++ b/packages/kilo-vscode/tests/unit/language-utils.test.ts @@ -16,7 +16,9 @@ describe("normalizeLocale", () => { it("returns 'zht' for Traditional Chinese", () => { expect(normalizeLocale("zh-Hant")).toBe("zht") - expect(normalizeLocale("zh-TW")).toBe("zh") + expect(normalizeLocale("zh-TW")).toBe("zht") + expect(normalizeLocale("zh-HK")).toBe("zht") + expect(normalizeLocale("zh-MO")).toBe("zht") expect(normalizeLocale("zh-hant-TW")).toBe("zht") }) diff --git a/packages/kilo-vscode/webview-ui/src/context/language-utils.ts b/packages/kilo-vscode/webview-ui/src/context/language-utils.ts index f3f989e220a..8ab09e7a726 100644 --- a/packages/kilo-vscode/webview-ui/src/context/language-utils.ts +++ b/packages/kilo-vscode/webview-ui/src/context/language-utils.ts @@ -46,7 +46,9 @@ export const LOCALES: readonly Locale[] = [ export function normalizeLocale(lang: string): Locale { const lower = lang.toLowerCase() if (lower.startsWith("zh")) { - return lower.includes("hant") ? "zht" : "zh" + const traditional = + lower.includes("hant") || lower.includes("-tw") || lower.includes("-hk") || lower.includes("-mo") + return traditional ? "zht" : "zh" } for (const loc of LOCALES) { if (lower.startsWith(loc)) { From 356ed5df27bdd322f8081c1cd0972867bb0997ca Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Mon, 30 Mar 2026 11:23:52 +0200 Subject: [PATCH 128/261] fix(vscode): handle bare "zht" locale in normalizeLocale and resolveLocale When user selects Traditional Chinese from the settings dropdown, the bare string "zht" is passed through normalizeLocale. Since "zht" starts with "zh", it entered the Chinese branch but matched none of the BCP 47 traditional markers (hant, -tw, -hk, -mo), incorrectly returning "zh". --- packages/kilo-vscode/src/services/cli-backend/i18n/index.ts | 1 + packages/kilo-vscode/tests/unit/language-utils.test.ts | 1 + packages/kilo-vscode/webview-ui/src/context/language-utils.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts b/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts index 8d271c036d7..b758b4ba105 100644 --- a/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts +++ b/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts @@ -42,6 +42,7 @@ const bundles: Record> = { function resolveLocale(lang: string): string { const lower = lang.toLowerCase() if (lower.startsWith("zh")) { + if (lower === "zht") return "zht" const traditional = lower.includes("hant") || lower.includes("-tw") || lower.includes("-hk") || lower.includes("-mo") return traditional ? "zht" : "zh" diff --git a/packages/kilo-vscode/tests/unit/language-utils.test.ts b/packages/kilo-vscode/tests/unit/language-utils.test.ts index 8226e58d85e..cc1a8c286bd 100644 --- a/packages/kilo-vscode/tests/unit/language-utils.test.ts +++ b/packages/kilo-vscode/tests/unit/language-utils.test.ts @@ -15,6 +15,7 @@ describe("normalizeLocale", () => { }) it("returns 'zht' for Traditional Chinese", () => { + expect(normalizeLocale("zht")).toBe("zht") expect(normalizeLocale("zh-Hant")).toBe("zht") expect(normalizeLocale("zh-TW")).toBe("zht") expect(normalizeLocale("zh-HK")).toBe("zht") diff --git a/packages/kilo-vscode/webview-ui/src/context/language-utils.ts b/packages/kilo-vscode/webview-ui/src/context/language-utils.ts index 8ab09e7a726..5ea74bca858 100644 --- a/packages/kilo-vscode/webview-ui/src/context/language-utils.ts +++ b/packages/kilo-vscode/webview-ui/src/context/language-utils.ts @@ -46,6 +46,7 @@ export const LOCALES: readonly Locale[] = [ export function normalizeLocale(lang: string): Locale { const lower = lang.toLowerCase() if (lower.startsWith("zh")) { + if (lower === "zht") return "zht" const traditional = lower.includes("hant") || lower.includes("-tw") || lower.includes("-hk") || lower.includes("-mo") return traditional ? "zht" : "zh" From dba6fe46f6cb028575b29a2e2313475bc4273360 Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 30 Mar 2026 12:20:07 +0200 Subject: [PATCH 129/261] fix(vscode): fix health check permanently killing SSE connection (#7920) --- .../cli-backend/connection-service.ts | 2 +- .../services/cli-backend/sdk-sse-adapter.ts | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) 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 ff1f08409a1..abee02099a5 100644 --- a/packages/kilo-vscode/src/services/cli-backend/connection-service.ts +++ b/packages/kilo-vscode/src/services/cli-backend/connection-service.ts @@ -282,7 +282,7 @@ export class KiloConnectionService { const healthy = await this.checkHealth(baseUrl, password) if (!healthy && this.state === "connected") { console.warn("[Kilo New] ConnectionService: ❤️‍🩹 Health check failed — forcing SSE reconnect") - this.sseClient?.disconnect() + this.sseClient?.reconnect() } }, HEALTH_POLL_INTERVAL_MS) diff --git a/packages/kilo-vscode/src/services/cli-backend/sdk-sse-adapter.ts b/packages/kilo-vscode/src/services/cli-backend/sdk-sse-adapter.ts index 967b86fa5c5..260ca663262 100644 --- a/packages/kilo-vscode/src/services/cli-backend/sdk-sse-adapter.ts +++ b/packages/kilo-vscode/src/services/cli-backend/sdk-sse-adapter.ts @@ -32,6 +32,7 @@ export class SdkSSEAdapter { private readonly stateHandlers = new Set() private abortController: AbortController | null = null + private attemptController: AbortController | null = null private heartbeatTimer: ReturnType | null = null // 15s matches packages/app/src/context/global-sdk.tsx — server sends heartbeats @@ -71,9 +72,24 @@ export class SdkSSEAdapter { console.log("[Kilo New] SSE: 🔌 disconnect() called") this.abortController?.abort() this.abortController = null + this.attemptController = null this.clearHeartbeat() } + /** + * Force the current SSE attempt to reconnect without killing the outer loop. + * Aborts only the per-attempt controller so `consumeLoop` re-enters its + * reconnection path instead of terminating permanently. + */ + reconnect(): void { + if (!this.attemptController) { + console.log("[Kilo New] SSE: ⚠️ reconnect() called but no active attempt") + return + } + console.log("[Kilo New] SSE: 🔄 reconnect() — aborting current attempt") + this.attemptController.abort() + } + /** * Disconnect and clear all registered handlers. */ @@ -121,6 +137,8 @@ export class SdkSSEAdapter { const onAbort = () => attempt.abort() signal.addEventListener("abort", onAbort) + this.attemptController = attempt + try { console.log("[Kilo New] SSE: 🎬 Calling SDK global.event()...") const events = await this.client.global.event({ @@ -159,6 +177,7 @@ export class SdkSSEAdapter { } } finally { signal.removeEventListener("abort", onAbort) + this.attemptController = null this.clearHeartbeat() } From 4a6899fafd085134d1e5209c4cffd82feba8fa19 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 11:17:36 +0000 Subject: [PATCH 130/261] feat(vscode): add Browse Marketplace button to MCP settings Add a "Browse Marketplace" button to the MCP Servers subtab in Agent Behaviour settings, guiding users to discover and install MCPs from the marketplace rather than only configuring them manually. - Add button above the MCP server list that opens the Marketplace panel - Add openMarketplacePanel webview message type and handler - Add translations for all 18 supported languages --- packages/kilo-vscode/src/KiloProvider.ts | 3 +++ .../components/settings/AgentBehaviourTab.tsx | 16 ++++++++++++++++ packages/kilo-vscode/webview-ui/src/i18n/ar.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/br.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/bs.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/da.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/de.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/en.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/es.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/fr.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/ja.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/ko.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/nl.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/no.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/pl.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/ru.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/th.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/tr.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/zh.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/zht.ts | 1 + .../kilo-vscode/webview-ui/src/types/messages.ts | 5 +++++ 21 files changed, 42 insertions(+) diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index 8378c5629b8..bffed832744 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -575,6 +575,9 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper case "openSettingsPanel": vscode.commands.executeCommand("kilo-code.new.settingsButtonClicked", message.tab) break + case "openMarketplacePanel": + vscode.commands.executeCommand("kilo-code.new.marketplaceButtonClicked") + break case "openChanges": vscode.commands.executeCommand("kilo-code.new.showChanges") break diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index 181dd855cea..52357b9ee58 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -11,6 +11,7 @@ import { Switch } from "@kilocode/kilo-ui/switch" import { useConfig } from "../../context/config" import { useSession } from "../../context/session" import { useLanguage } from "../../context/language" +import { useVSCode } from "../../context/vscode" import type { AgentInfo, SkillInfo } from "../../types/messages" import ModeEditView from "./ModeEditView" import ModeCreateView from "./ModeCreateView" @@ -49,6 +50,7 @@ const AgentBehaviourTab: Component = () => { const { config, updateConfig } = useConfig() const session = useSession() const dialog = useDialog() + const vscode = useVSCode() const [activeSubtab, setActiveSubtab] = createSignal("agents") const [newSkillPath, setNewSkillPath] = createSignal("") const [newSkillUrl, setNewSkillUrl] = createSignal("") @@ -517,8 +519,22 @@ const AgentBehaviourTab: Component = () => { ) } + const browse = () => vscode.postMessage({ type: "openMarketplacePanel" }) + return (
+
+ +
0} fallback={ diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index 8ac9723457a..83240e59ea4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1136,6 +1136,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "الوسائط", "settings.agentBehaviour.mcpDetail.env": "البيئة", "settings.agentBehaviour.mcpDetail.disabled": "هذا الخادم معطّل.", + "settings.agentBehaviour.mcpBrowseMarketplace": "تصفح Marketplace", "settings.agentBehaviour.mcpEmpty": "لم يتم تهيئة خوادم MCP. أضف خوادم MCP في kilo.jsonc، أو اطلب من الوكيل إضافتها لك.", "settings.agentBehaviour.workflowsPlaceholder": "تُدار سير العمل عبر ملفات سير العمل في مساحة العمل.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index ae3354126f7..cc975752e65 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1157,6 +1157,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Argumentos", "settings.agentBehaviour.mcpDetail.env": "Ambiente", "settings.agentBehaviour.mcpDetail.disabled": "Este servidor está desativado.", + "settings.agentBehaviour.mcpBrowseMarketplace": "Explorar Marketplace", "settings.agentBehaviour.mcpEmpty": "Nenhum servidor MCP configurado. Adicione servidores MCP em kilo.jsonc ou peça ao agente para adicioná-los.", "settings.agentBehaviour.workflowsPlaceholder": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index d64c14baf07..666211c6a12 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1153,6 +1153,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Argumenti", "settings.agentBehaviour.mcpDetail.env": "Okruženje", "settings.agentBehaviour.mcpDetail.disabled": "Ovaj server je onemogućen.", + "settings.agentBehaviour.mcpBrowseMarketplace": "Pregledaj Marketplace", "settings.agentBehaviour.mcpEmpty": "Nema konfiguriranih MCP servera. Dodajte MCP servere u kilo.jsonc ili zamolite agenta da ih doda.", "settings.agentBehaviour.workflowsPlaceholder": "Tokovi rada se upravljaju putem datoteka tokova rada.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index a8eeecae1f4..949c5715424 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1146,6 +1146,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Argumenter", "settings.agentBehaviour.mcpDetail.env": "Miljø", "settings.agentBehaviour.mcpDetail.disabled": "Denne server er deaktiveret.", + "settings.agentBehaviour.mcpBrowseMarketplace": "Gennemse Marketplace", "settings.agentBehaviour.mcpEmpty": "Ingen MCP-servere konfigureret. Tilføj MCP-servere i kilo.jsonc, eller bed agenten om at tilføje dem.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows administreres via workflow-filer i dit arbejdsområde.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 8f7c6805178..ece4dbdc7a6 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1169,6 +1169,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Argumente", "settings.agentBehaviour.mcpDetail.env": "Umgebung", "settings.agentBehaviour.mcpDetail.disabled": "Dieser Server ist deaktiviert.", + "settings.agentBehaviour.mcpBrowseMarketplace": "Marketplace durchsuchen", "settings.agentBehaviour.mcpEmpty": "Keine MCP-Server konfiguriert. Fügen Sie MCP-Server in kilo.jsonc hinzu oder bitten Sie den Agenten, sie hinzuzufügen.", "settings.agentBehaviour.workflowsPlaceholder": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index fbb8f1191b9..0fe710232eb 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1116,6 +1116,7 @@ export const dict = { "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", "settings.agentBehaviour.addMcp.url": "Server URL", "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", + "settings.agentBehaviour.mcpBrowseMarketplace": "Browse Marketplace", "settings.agentBehaviour.mcpEmpty": "No MCP servers configured. Add MCP servers in kilo.jsonc, or ask the agent to add them for you.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows are managed via workflow files in your workspace.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index d83c3168d3e..42370d43476 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1161,6 +1161,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Argumentos", "settings.agentBehaviour.mcpDetail.env": "Entorno", "settings.agentBehaviour.mcpDetail.disabled": "Este servidor está deshabilitado.", + "settings.agentBehaviour.mcpBrowseMarketplace": "Explorar Marketplace", "settings.agentBehaviour.mcpEmpty": "No hay servidores MCP configurados. Añada servidores MCP en kilo.jsonc o pida al agente que los añada.", "settings.agentBehaviour.workflowsPlaceholder": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 051bab83981..bc2413d7f58 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1173,6 +1173,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Arguments", "settings.agentBehaviour.mcpDetail.env": "Environnement", "settings.agentBehaviour.mcpDetail.disabled": "Ce serveur est désactivé.", + "settings.agentBehaviour.mcpBrowseMarketplace": "Parcourir le Marketplace", "settings.agentBehaviour.mcpEmpty": "Aucun serveur MCP configuré. Ajoutez des serveurs MCP dans kilo.jsonc ou demandez à l'agent de les ajouter.", "settings.agentBehaviour.workflowsPlaceholder": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index f65245c19d9..b1e949f6d4f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1147,6 +1147,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "引数", "settings.agentBehaviour.mcpDetail.env": "環境", "settings.agentBehaviour.mcpDetail.disabled": "このサーバーは無効です。", + "settings.agentBehaviour.mcpBrowseMarketplace": "マーケットプレイスを閲覧", "settings.agentBehaviour.mcpEmpty": "MCPサーバーが設定されていません。kilo.jsoncでMCPサーバーを追加するか、エージェントに追加を依頼してください。", "settings.agentBehaviour.workflowsPlaceholder": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 4e9f93ba204..35dabf797ad 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1141,6 +1141,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "인수", "settings.agentBehaviour.mcpDetail.env": "환경", "settings.agentBehaviour.mcpDetail.disabled": "이 서버는 비활성화되어 있습니다.", + "settings.agentBehaviour.mcpBrowseMarketplace": "마켓플레이스 둘러보기", "settings.agentBehaviour.mcpEmpty": "MCP 서버가 구성되지 않았습니다. kilo.jsonc에서 MCP 서버를 추가하거나 에이전트에게 추가를 요청하세요.", "settings.agentBehaviour.workflowsPlaceholder": "워크플로우는 워크스페이스의 워크플로우 파일을 통해 관리됩니다.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 87cbe8ef733..3c5d0562fe1 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1135,6 +1135,7 @@ export const dict = { "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", "settings.agentBehaviour.addMcp.url": "Server-URL", "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", + "settings.agentBehaviour.mcpBrowseMarketplace": "Bladeren door Marketplace", "settings.agentBehaviour.mcpEmpty": "Geen MCP-servers geconfigureerd. Voeg MCP-servers toe in kilo.jsonc of vraag de agent om ze toe te voegen.", "settings.agentBehaviour.workflowsPlaceholder": "Workflows worden beheerd via workflowbestanden in je workspace.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index ce43e675979..aa28b1c76a4 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1149,6 +1149,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Argumenter", "settings.agentBehaviour.mcpDetail.env": "Miljø", "settings.agentBehaviour.mcpDetail.disabled": "Denne serveren er deaktivert.", + "settings.agentBehaviour.mcpBrowseMarketplace": "Bla gjennom Marketplace", "settings.agentBehaviour.mcpEmpty": "Ingen MCP-servere konfigurert. Legg til MCP-servere i kilo.jsonc, eller be agenten om å legge dem til.", "settings.agentBehaviour.workflowsPlaceholder": "Arbeidsflyter administreres via arbeidsflytfiler i arbeidsområdet.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 6d79e1c6205..3d57852a8e5 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1153,6 +1153,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Argumenty", "settings.agentBehaviour.mcpDetail.env": "Środowisko", "settings.agentBehaviour.mcpDetail.disabled": "Ten serwer jest wyłączony.", + "settings.agentBehaviour.mcpBrowseMarketplace": "Przeglądaj Marketplace", "settings.agentBehaviour.mcpEmpty": "Brak skonfigurowanych serwerów MCP. Dodaj serwery MCP w kilo.jsonc lub poproś agenta o ich dodanie.", "settings.agentBehaviour.workflowsPlaceholder": "Przepływy pracy zarządzane są za pomocą plików przepływów pracy.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 293dfb78577..c0ceeeb856a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1154,6 +1154,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "Аргументы", "settings.agentBehaviour.mcpDetail.env": "Окружение", "settings.agentBehaviour.mcpDetail.disabled": "Этот сервер отключён.", + "settings.agentBehaviour.mcpBrowseMarketplace": "Обзор Marketplace", "settings.agentBehaviour.mcpEmpty": "MCP-серверы не настроены. Добавьте MCP-серверы в kilo.jsonc или попросите агента добавить их.", "settings.agentBehaviour.workflowsPlaceholder": "Рабочие процессы управляются через файлы рабочих процессов.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 4b826b3317a..e1fe89d4951 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1137,6 +1137,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "อาร์กิวเมนต์", "settings.agentBehaviour.mcpDetail.env": "สภาพแวดล้อม", "settings.agentBehaviour.mcpDetail.disabled": "เซิร์ฟเวอร์นี้ถูกปิดใช้งาน", + "settings.agentBehaviour.mcpBrowseMarketplace": "เรียกดู Marketplace", "settings.agentBehaviour.mcpEmpty": "ไม่ได้กำหนดค่าเซิร์ฟเวอร์ MCP เพิ่มเซิร์ฟเวอร์ MCP ใน kilo.jsonc หรือขอให้เอเจนต์เพิ่มให้คุณ", "settings.agentBehaviour.workflowsPlaceholder": "เวิร์กโฟลว์จัดการผ่านไฟล์เวิร์กโฟลว์ในพื้นที่ทำงาน", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index ae0fe2fa314..7f2715f36dd 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1131,6 +1131,7 @@ export const dict = { "settings.agentBehaviour.addMcp.args.placeholder": "e.g.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", "settings.agentBehaviour.addMcp.url": "Sunucu URL'si", "settings.agentBehaviour.addMcp.url.placeholder": "e.g. http://localhost:3000/sse", + "settings.agentBehaviour.mcpBrowseMarketplace": "Marketplace'e Göz At", "settings.agentBehaviour.mcpEmpty": "Yapılandırılmış MCP sunucusu yok. kilo.jsonc dosyasına MCP sunucuları ekleyin veya ajanın eklemesini isteyin.", "settings.agentBehaviour.workflowsPlaceholder": "İş akışları çalışma alanınızdaki iş akışı dosyaları ile yönetilir.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 91e2e50edd7..c3f3ccd169c 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1122,6 +1122,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "参数", "settings.agentBehaviour.mcpDetail.env": "环境", "settings.agentBehaviour.mcpDetail.disabled": "此服务器已禁用。", + "settings.agentBehaviour.mcpBrowseMarketplace": "浏览市场", "settings.agentBehaviour.mcpEmpty": "未配置 MCP 服务器。在 kilo.jsonc 中添加 MCP 服务器,或让代理为您添加。", "settings.agentBehaviour.workflowsPlaceholder": "工作流通过工作区中的工作流文件管理。", "settings.agentBehaviour.workflows.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 58cc5597892..bee77c353c2 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1125,6 +1125,7 @@ export const dict = { "settings.agentBehaviour.mcpDetail.args": "引數", "settings.agentBehaviour.mcpDetail.env": "環境", "settings.agentBehaviour.mcpDetail.disabled": "此伺服器已停用。", + "settings.agentBehaviour.mcpBrowseMarketplace": "瀏覽市場", "settings.agentBehaviour.mcpEmpty": "未設定 MCP 伺服器。在 kilo.jsonc 中新增 MCP 伺服器,或請代理為您新增。", "settings.agentBehaviour.workflowsPlaceholder": "工作流程透過工作區中的工作流程檔案管理。", "settings.agentBehaviour.workflows.description": diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index 7e7f7e03777..2069404932b 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -1481,6 +1481,10 @@ export interface OpenSettingsPanelRequest { tab?: string } +export interface OpenMarketplacePanelRequest { + type: "openMarketplacePanel" +} + export interface RequestAgentsMessage { type: "requestAgents" } @@ -2020,6 +2024,7 @@ export type WebviewMessage = | RefreshProfileRequest | OpenExternalRequest | OpenSettingsPanelRequest + | OpenMarketplacePanelRequest | OpenFileRequest | CancelLoginRequest | SetOrganizationRequest From 25a8c9320e1800d5d6f4b6d0a9c92fd591b7db89 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 11:26:54 +0000 Subject: [PATCH 131/261] fix(vscode): preserve project directory when opening marketplace from settings Pass the current panel's project directory through to the marketplace panel so project-scoped MCP installs work correctly in multi-root workspaces. Without this, the marketplace panel would fall back to null project directory since there is no active text editor when clicking from a webview. --- packages/kilo-vscode/src/KiloProvider.ts | 2 +- packages/kilo-vscode/src/SettingsEditorProvider.ts | 4 ++-- packages/kilo-vscode/src/extension.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index bffed832744..af04b501103 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -576,7 +576,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper vscode.commands.executeCommand("kilo-code.new.settingsButtonClicked", message.tab) break case "openMarketplacePanel": - vscode.commands.executeCommand("kilo-code.new.marketplaceButtonClicked") + vscode.commands.executeCommand("kilo-code.new.marketplaceButtonClicked", this.projectDirectory) break case "openChanges": vscode.commands.executeCommand("kilo-code.new.showChanges") diff --git a/packages/kilo-vscode/src/SettingsEditorProvider.ts b/packages/kilo-vscode/src/SettingsEditorProvider.ts index afaa819944b..922754e319f 100644 --- a/packages/kilo-vscode/src/SettingsEditorProvider.ts +++ b/packages/kilo-vscode/src/SettingsEditorProvider.ts @@ -51,10 +51,10 @@ export class SettingsEditorProvider implements vscode.Disposable { return view } - openPanel(view: PanelView, tab?: string): void { + openPanel(view: PanelView, tab?: string, directory?: string | null): void { if (tab) this.tabs.set(view, tab) - const projectDirectory = this.getProjectDirectory() + const projectDirectory = directory ?? this.getProjectDirectory() const existing = this.panels.get(view) if (existing) { this.providers.get(view)?.setProjectDirectory(projectDirectory) diff --git a/packages/kilo-vscode/src/extension.ts b/packages/kilo-vscode/src/extension.ts index f38b53b3c78..56d8124d8f6 100644 --- a/packages/kilo-vscode/src/extension.ts +++ b/packages/kilo-vscode/src/extension.ts @@ -160,8 +160,8 @@ export function activate(context: vscode.ExtensionContext) { vscode.commands.registerCommand("kilo-code.new.agentManagerOpen", () => { agentManagerProvider.openPanel() }), - vscode.commands.registerCommand("kilo-code.new.marketplaceButtonClicked", () => { - settingsEditorProvider.openPanel("marketplace") + vscode.commands.registerCommand("kilo-code.new.marketplaceButtonClicked", (directory?: string) => { + settingsEditorProvider.openPanel("marketplace", undefined, directory) }), vscode.commands.registerCommand("kilo-code.new.historyButtonClicked", () => { provider.postMessage({ type: "action", action: "historyButtonClicked" }) From ad8681e96f40bbd547bba70dfc5a962b55f6a661 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Mon, 30 Mar 2026 13:48:42 +0200 Subject: [PATCH 132/261] feat(vscode): add Browse Marketplace button to agents and skills tabs Add the Browse Marketplace button to the Agents and Skills subtabs in Agent Behaviour settings, matching the existing button in the MCP Servers subtab. This lets users discover marketplace items from any of the three configuration tabs. - Agents tab: added as a ghost button in the header row alongside Import and Create Mode buttons - Skills tab: added as a secondary button at the top-right, matching the MCP tab layout - Extracted the browse handler to the component scope for reuse --- .../components/settings/AgentBehaviourTab.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index 52357b9ee58..859eee8d15b 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -55,6 +55,7 @@ const AgentBehaviourTab: Component = () => { const [newSkillPath, setNewSkillPath] = createSignal("") const [newSkillUrl, setNewSkillUrl] = createSignal("") const [newInstruction, setNewInstruction] = createSignal("") + const browse = () => vscode.postMessage({ type: "openMarketplacePanel" }) // Agent view state const [agentView, setAgentView] = createSignal("list") @@ -303,6 +304,9 @@ const AgentBehaviourTab: Component = () => { + @@ -519,8 +523,6 @@ const AgentBehaviourTab: Component = () => { ) } - const browse = () => vscode.postMessage({ type: "openMarketplacePanel" }) - return (
{ const renderSkillsSubtab = () => (
+
+ +
{/* Discovered skills */}

{language.t("settings.agentBehaviour.discoveredSkills")} From ad816eee2a248b3f08bef478895a6c9959cfc8de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 30 Mar 2026 11:50:48 +0000 Subject: [PATCH 133/261] chore: update kilo-vscode visual regression baselines --- .../settings/agent-behaviour-agents-chromium-linux.png | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/agent-behaviour-agents-chromium-linux.png b/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/agent-behaviour-agents-chromium-linux.png index b4a57e37a4a..795674c1ad6 100644 --- a/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/agent-behaviour-agents-chromium-linux.png +++ b/packages/kilo-vscode/tests/visual-regression.spec.ts-snapshots/settings/agent-behaviour-agents-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:41df17f60c5361a230839c07a9bd29d9dbf645a9750db6fa00e37c0bd06eff11 -size 25424 +oid sha256:8e9f04f72f6227b08bff321ab4af7a794fa754dc58bd504eb88259cd244ba51b +size 27146 From 15ac71c5f07676583db7f3015fabdeb970ce635f Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Mon, 30 Mar 2026 15:02:23 +0300 Subject: [PATCH 134/261] feat(cli): add read-only bash commands to Ask agent Define a readOnlyBash allowlist with deny-by-default semantics so the Ask agent can run safe information-gathering commands (ls, cat, grep, git log, find, jq, etc.) while blocking all write operations. Git write subcommands (commit, push, merge, reset, etc.) are explicitly denied. gh commands require user approval. --- packages/opencode/src/agent/agent.ts | 65 ++++++++++++++++++++++ packages/opencode/src/agent/prompt/ask.txt | 3 +- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 16305db1286..c5eef1a51ab 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -111,6 +111,70 @@ export namespace Agent { "gunzip *": "allow", } // kilocode_change end + + // kilocode_change start — read-only bash commands for the ask agent. + // Unlike the default bash allowlist, unknown commands are DENIED (not "ask") + // because the ask agent must never modify the filesystem. + const readOnlyBash: Record = { + "*": "deny", + // read-only / informational + "cat *": "allow", + "head *": "allow", + "tail *": "allow", + "less *": "allow", + "ls *": "allow", + "tree *": "allow", + "pwd *": "allow", + "echo *": "allow", + "wc *": "allow", + "which *": "allow", + "type *": "allow", + "file *": "allow", + "diff *": "allow", + "du *": "allow", + "df *": "allow", + "date *": "allow", + "uname *": "allow", + "whoami *": "allow", + "printenv *": "allow", + "man *": "allow", + // file discovery + "find *": "allow", + // text processing (stdout only, no file modification) + "grep *": "allow", + "rg *": "allow", + "ag *": "allow", + "sort *": "allow", + "uniq *": "allow", + "cut *": "allow", + "tr *": "allow", + "jq *": "allow", + // git — allow read operations, deny all write operations + "git *": "allow", + "git add *": "deny", + "git commit *": "deny", + "git push *": "deny", + "git merge *": "deny", + "git rebase *": "deny", + "git cherry-pick *": "deny", + "git reset *": "deny", + "git checkout *": "deny", + "git switch *": "deny", + "git stash *": "deny", + "git tag *": "deny", + "git am *": "deny", + "git apply *": "deny", + "git remote set-url *": "deny", + "git remote add *": "deny", + "git remote remove *": "deny", + "git clean *": "deny", + "git mv *": "deny", + "git rm *": "deny", + // gh — require user approval since commands vary widely + "gh *": "ask", + } + // kilocode_change end + const defaults = PermissionNext.fromConfig({ "*": "allow", bash, // kilocode_change @@ -237,6 +301,7 @@ export namespace Agent { user, // kilocode_change: user before ask-specific so ask's deny+allowlist wins PermissionNext.fromConfig({ "*": "deny", + bash: readOnlyBash, read: { "*": "allow", "*.env": "ask", diff --git a/packages/opencode/src/agent/prompt/ask.txt b/packages/opencode/src/agent/prompt/ask.txt index 32f9e74e3ef..28e9a04e98c 100644 --- a/packages/opencode/src/agent/prompt/ask.txt +++ b/packages/opencode/src/agent/prompt/ask.txt @@ -4,5 +4,6 @@ Guidelines: - Answer questions thoroughly with clear explanations and relevant examples - Analyze code, explain concepts, and provide recommendations without making changes - Use Mermaid diagrams when they help clarify your response -- Do not edit files or execute commands; this agent is read-only +- You may run read-only bash commands (ls, cat, grep, git log, git diff, find, etc.) to gather information +- You must NOT modify files, run write commands, or execute code — this agent is read-only - If a question requires implementation, suggest switching to a different agent From 2cdf6b61c7441089678897dea181878b2cd716be Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 30 Mar 2026 14:02:57 +0200 Subject: [PATCH 135/261] perf(cli): cache MCP listTools results to avoid redundant RPCs per loop step (#7922) MCP.tools() called client.listTools() for every connected server on every agent loop iteration. With multiple servers this added hundreds of milliseconds of overhead per step (measured ~300-750ms for remote servers like Vercel). Cache listTools results in a module-level Map and return them on subsequent calls. The cache is invalidated on: - ToolListChangedNotification from the MCP server - Server add/connect/disconnect - Instance dispose (config change, project switch, shutdown) --- packages/opencode/src/mcp/index.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/opencode/src/mcp/index.ts b/packages/opencode/src/mcp/index.ts index 9ffbce1a0ba..a828bdaa59d 100644 --- a/packages/opencode/src/mcp/index.ts +++ b/packages/opencode/src/mcp/index.ts @@ -121,6 +121,7 @@ export namespace MCP { function registerNotificationHandlers(client: MCPClient, serverName: string) { client.setNotificationHandler(ToolListChangedNotificationSchema, async () => { log.info("tools list changed notification received", { server: serverName }) + ;(await state()).toolsCache.delete(serverName) // kilocode_change Bus.publish(ToolsChanged, { server: serverName }) }) } @@ -224,6 +225,7 @@ export namespace MCP { return { status, clients, + toolsCache: new Map(), // kilocode_change — per-server listTools cache } }, async (state) => { @@ -302,6 +304,7 @@ export namespace MCP { export async function add(name: string, mcp: Config.Mcp) { const s = await state() + s.toolsCache.delete(name) // kilocode_change const result = await create(name, mcp) if (!result) { const status = { @@ -559,6 +562,7 @@ export namespace MCP { } export async function connect(name: string) { + ;(await state()).toolsCache.delete(name) // kilocode_change const cfg = await Config.get() const config = cfg.mcp ?? {} const mcp = config[name] @@ -599,6 +603,7 @@ export namespace MCP { export async function disconnect(name: string) { const s = await state() + s.toolsCache.delete(name) // kilocode_change const client = s.clients[name] if (client) { await client.close().catch((error) => { @@ -623,6 +628,12 @@ export namespace MCP { const toolsResults = await Promise.all( connectedClients.map(async ([clientName, client]) => { + // kilocode_change start — use cached listTools when available + const cached = s.toolsCache.get(clientName) + if (cached) { + return { clientName, client, toolsResult: { tools: cached } } + } + // kilocode_change end const toolsResult = await client.listTools().catch((e) => { log.error("failed to get tools", { clientName, error: e.message }) const failedStatus = { @@ -633,6 +644,7 @@ export namespace MCP { delete s.clients[clientName] return undefined }) + if (toolsResult) s.toolsCache.set(clientName, toolsResult.tools) // kilocode_change return { clientName, client, toolsResult } }), ) From 1d7bc418418c6440d71a04c1e492f9d44d3e5483 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Mon, 30 Mar 2026 15:03:40 +0300 Subject: [PATCH 136/261] feat(cli): add MCP tool support to Ask agent Dynamically build per-server permission rules from cfg.mcp at agent init time using the same sanitization as mcp/index.ts. MCP tools get "ask" permission so every call requires user approval. Rules are spread after "*": "deny" to override via findLast() semantics. --- packages/opencode/src/agent/agent.ts | 9 +++++++++ packages/opencode/src/agent/prompt/ask.txt | 1 + 2 files changed, 10 insertions(+) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index c5eef1a51ab..5590cc8abc4 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -173,6 +173,14 @@ export namespace Agent { // gh — require user approval since commands vary widely "gh *": "ask", } + + // kilocode_change start — allow MCP tools in ask agent with user approval. + // Generates per-server wildcard rules that override "*": "deny". + const mcpRules: Record = {} + for (const key of Object.keys(cfg.mcp ?? {})) { + const sanitized = key.replace(/[^a-zA-Z0-9_-]/g, "_") + mcpRules[sanitized + "_*"] = "ask" + } // kilocode_change end const defaults = PermissionNext.fromConfig({ @@ -319,6 +327,7 @@ export namespace Agent { external_directory: { [Truncate.GLOB]: "allow", }, + ...mcpRules, }), ), mode: "primary", diff --git a/packages/opencode/src/agent/prompt/ask.txt b/packages/opencode/src/agent/prompt/ask.txt index 28e9a04e98c..e324b0df985 100644 --- a/packages/opencode/src/agent/prompt/ask.txt +++ b/packages/opencode/src/agent/prompt/ask.txt @@ -6,4 +6,5 @@ Guidelines: - Use Mermaid diagrams when they help clarify your response - You may run read-only bash commands (ls, cat, grep, git log, git diff, find, etc.) to gather information - You must NOT modify files, run write commands, or execute code — this agent is read-only +- MCP tools are available if configured — each call requires user approval - If a question requires implementation, suggest switching to a different agent From 75dacd050da01658859b4e1e62f4d1be150e8edf Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 30 Mar 2026 14:04:41 +0200 Subject: [PATCH 137/261] fix(agent-manager): add retries to worktree cleanup for macOS .app bundles (#7921) --- .../kilo-vscode/src/agent-manager/WorktreeManager.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts b/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts index a95226ffdab..899d7471c94 100644 --- a/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts +++ b/packages/kilo-vscode/src/agent-manager/WorktreeManager.ts @@ -10,8 +10,6 @@ import * as path from "path" import * as fs from "fs" import { randomUUID } from "crypto" import simpleGit, { type SimpleGit } from "simple-git" - -const TEMP_PREFIX = ".kilo-delete-" import { generateBranchName, sanitizeBranchName } from "./branch-name" import type { GitOps } from "./GitOps" import { execWithShellEnv } from "./shell-env" @@ -29,6 +27,9 @@ import { type BranchListItem, } from "./git-import" +const TEMP_PREFIX = ".kilo-delete-" +const RM_OPTS: fs.RmOptions = { recursive: true, force: true, maxRetries: 3, retryDelay: 200 } + interface WorktreeInfo { branch: string path: string @@ -388,7 +389,7 @@ export class WorktreeManager { if (branch) await this.deleteBranch(branch) // 4. Background delete — fire-and-forget, cross-platform - fs.promises.rm(temp, { recursive: true, force: true }).catch((err) => { + fs.promises.rm(temp, RM_OPTS).catch((err) => { this.log(`Background cleanup failed for ${temp}: ${err}`) }) } @@ -411,7 +412,7 @@ export class WorktreeManager { for (const e of entries) { if (e.isDirectory() && e.name.startsWith(TEMP_PREFIX)) { const stale = path.join(this.dir, e.name) - fs.promises.rm(stale, { recursive: true, force: true }).catch((err) => { + fs.promises.rm(stale, RM_OPTS).catch((err) => { this.log(`Failed to clean orphaned temp dir ${stale}: ${err}`) }) } From e64aba0b239bccd457e191c47d59926e1d28599c Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Mon, 30 Mar 2026 15:06:36 +0300 Subject: [PATCH 138/261] test(cli): add Ask agent permission tests Verify readOnlyBash allowlist, git write denials, gh ask rules, disabled() behavior for edit/task/bash tools, and dynamic MCP permission generation with server name sanitization. --- .../kilocode/ask-agent-permissions.test.ts | 300 ++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 packages/opencode/test/kilocode/ask-agent-permissions.test.ts diff --git a/packages/opencode/test/kilocode/ask-agent-permissions.test.ts b/packages/opencode/test/kilocode/ask-agent-permissions.test.ts new file mode 100644 index 00000000000..a727b014a00 --- /dev/null +++ b/packages/opencode/test/kilocode/ask-agent-permissions.test.ts @@ -0,0 +1,300 @@ +import { test, expect, describe } from "bun:test" +import { PermissionNext } from "../../src/permission/next" + +// Reconstruct the Ask agent's readOnlyBash allowlist (mirrors agent.ts) +const readOnlyBash: Record = { + "*": "deny", + "cat *": "allow", + "head *": "allow", + "tail *": "allow", + "less *": "allow", + "ls *": "allow", + "tree *": "allow", + "pwd *": "allow", + "echo *": "allow", + "wc *": "allow", + "which *": "allow", + "type *": "allow", + "file *": "allow", + "diff *": "allow", + "du *": "allow", + "df *": "allow", + "date *": "allow", + "uname *": "allow", + "whoami *": "allow", + "printenv *": "allow", + "man *": "allow", + "find *": "allow", + "grep *": "allow", + "rg *": "allow", + "ag *": "allow", + "sort *": "allow", + "uniq *": "allow", + "cut *": "allow", + "tr *": "allow", + "jq *": "allow", + "git *": "allow", + "git add *": "deny", + "git commit *": "deny", + "git push *": "deny", + "git merge *": "deny", + "git rebase *": "deny", + "git cherry-pick *": "deny", + "git reset *": "deny", + "git checkout *": "deny", + "git switch *": "deny", + "git stash *": "deny", + "git tag *": "deny", + "git am *": "deny", + "git apply *": "deny", + "git remote set-url *": "deny", + "git remote add *": "deny", + "git remote remove *": "deny", + "git clean *": "deny", + "git mv *": "deny", + "git rm *": "deny", + "gh *": "ask", +} + +/** Build the Ask agent ruleset without MCP servers */ +function askRuleset() { + return PermissionNext.fromConfig({ + "*": "deny", + bash: readOnlyBash, + read: { + "*": "allow", + "*.env": "ask", + "*.env.*": "ask", + "*.env.example": "allow", + }, + grep: "allow", + glob: "allow", + list: "allow", + question: "allow", + webfetch: "allow", + websearch: "allow", + codesearch: "allow", + codebase_search: "allow", + }) +} + +/** Build the Ask agent ruleset WITH MCP servers */ +function askRulesetWithMcp(servers: string[]) { + const mcpRules: Record = {} + for (const key of servers) { + const sanitized = key.replace(/[^a-zA-Z0-9_-]/g, "_") + mcpRules[sanitized + "_*"] = "ask" + } + return PermissionNext.fromConfig({ + "*": "deny", + bash: readOnlyBash, + read: { + "*": "allow", + "*.env": "ask", + "*.env.*": "ask", + "*.env.example": "allow", + }, + grep: "allow", + glob: "allow", + list: "allow", + question: "allow", + webfetch: "allow", + websearch: "allow", + codesearch: "allow", + codebase_search: "allow", + ...mcpRules, + }) +} + +describe("Ask agent bash permissions", () => { + const ruleset = askRuleset() + + describe("allowed read-only commands", () => { + const allowed: [string, string][] = [ + ["cat", "cat README.md"], + ["ls", "ls -la"], + ["grep", "grep -r TODO src/"], + ["rg", "rg pattern"], + ["find", "find . -name '*.ts'"], + ["jq", "jq '.name' package.json"], + ["head", "head -n 10 file.txt"], + ["tail", "tail -f log.txt"], + ["wc", "wc -l src/index.ts"], + ["diff", "diff a.txt b.txt"], + ["sort", "sort names.txt"], + ["tree", "tree src/"], + ["echo", "echo hello"], + ["pwd", "pwd"], + ["date", "date"], + ["whoami", "whoami"], + ] + + for (const [name, cmd] of allowed) { + test(`${name}: "${cmd}" → allow`, () => { + const result = PermissionNext.evaluate("bash", cmd, ruleset) + expect(result.action).toBe("allow") + }) + } + }) + + describe("allowed git read commands", () => { + const allowed = [ + "git log --oneline -10", + "git diff HEAD~1", + "git show HEAD:src/index.ts", + "git status", + "git branch -a", + "git log --graph", + "git blame src/index.ts", + "git rev-parse HEAD", + ] + + for (const cmd of allowed) { + test(`"${cmd}" → allow`, () => { + const result = PermissionNext.evaluate("bash", cmd, ruleset) + expect(result.action).toBe("allow") + }) + } + }) + + describe("denied git write commands", () => { + const denied = [ + "git commit -m 'test'", + "git push origin main", + "git merge feature", + "git rebase main", + "git reset --hard HEAD~1", + "git checkout -b new-branch", + "git switch main", + "git stash", + "git tag v1.0", + "git cherry-pick abc123", + "git am patch.diff", + "git apply changes.patch", + "git clean -fd", + "git mv old.ts new.ts", + "git rm file.ts", + "git add .", + "git remote add origin url", + "git remote remove upstream", + "git remote set-url origin url", + ] + + for (const cmd of denied) { + test(`"${cmd}" → deny`, () => { + const result = PermissionNext.evaluate("bash", cmd, ruleset) + expect(result.action).toBe("deny") + }) + } + }) + + describe("denied write/execute commands", () => { + const denied = [ + "touch newfile.ts", + "mkdir src/new", + "cp a.ts b.ts", + "mv old.ts new.ts", + "tsc --noEmit", + "tar xzf archive.tar.gz", + "npm install", + "python3 script.py", + "rm -rf /", + "node server.js", + "bun run dev", + "curl http://example.com", + ] + + for (const cmd of denied) { + test(`"${cmd}" → deny`, () => { + const result = PermissionNext.evaluate("bash", cmd, ruleset) + expect(result.action).toBe("deny") + }) + } + }) + + test("gh commands → ask", () => { + expect(PermissionNext.evaluate("bash", "gh pr view 123", ruleset).action).toBe("ask") + expect(PermissionNext.evaluate("bash", "gh issue list", ruleset).action).toBe("ask") + expect(PermissionNext.evaluate("bash", "gh api repos/org/repo", ruleset).action).toBe("ask") + }) +}) + +describe("Ask agent tool disabled checks", () => { + const ruleset = askRuleset() + + test("bash tool is NOT disabled (has specific allow rules after deny)", () => { + const result = PermissionNext.disabled(["bash"], ruleset) + expect(result.has("bash")).toBe(false) + }) + + test("allowed tools are not disabled", () => { + const tools = ["read", "grep", "glob", "list", "question", "webfetch", "websearch", "codesearch", "codebase_search"] + const result = PermissionNext.disabled(tools, ruleset) + for (const tool of tools) { + expect(result.has(tool)).toBe(false) + } + }) + + test("edit tools are disabled", () => { + const tools = ["edit", "write", "patch", "multiedit"] + const result = PermissionNext.disabled(tools, ruleset) + for (const tool of tools) { + expect(result.has(tool)).toBe(true) + } + }) + + test("task tool is disabled", () => { + const result = PermissionNext.disabled(["task"], ruleset) + expect(result.has("task")).toBe(true) + }) + + test("todowrite and todoread are disabled", () => { + const result = PermissionNext.disabled(["todowrite", "todoread"], ruleset) + expect(result.has("todowrite")).toBe(true) + expect(result.has("todoread")).toBe(true) + }) +}) + +describe("Ask agent MCP permissions", () => { + test("MCP tools not disabled when servers configured", () => { + const ruleset = askRulesetWithMcp(["my-server", "another_server"]) + const result = PermissionNext.disabled(["my-server_sometool", "another_server_listthing"], ruleset) + expect(result.has("my-server_sometool")).toBe(false) + expect(result.has("another_server_listthing")).toBe(false) + }) + + test("MCP tools evaluate to ask", () => { + const ruleset = askRulesetWithMcp(["my-server"]) + const result = PermissionNext.evaluate("my-server_read_file", "*", ruleset) + expect(result.action).toBe("ask") + }) + + test("MCP tools disabled without server config", () => { + const ruleset = askRuleset() + const result = PermissionNext.disabled(["my-server_sometool"], ruleset) + expect(result.has("my-server_sometool")).toBe(true) + }) + + test("server names with special characters are sanitized", () => { + const ruleset = askRulesetWithMcp(["my.special server!"]) + // "my.special server!" → "my_special_server_" + const result = PermissionNext.disabled(["my_special_server__sometool"], ruleset) + expect(result.has("my_special_server__sometool")).toBe(false) + + const eval_ = PermissionNext.evaluate("my_special_server__sometool", "*", ruleset) + expect(eval_.action).toBe("ask") + }) + + test("MCP rules don't interfere with built-in tool permissions", () => { + const ruleset = askRulesetWithMcp(["server1"]) + // Built-in tools should still work normally + expect(PermissionNext.evaluate("read", "src/index.ts", ruleset).action).toBe("allow") + expect(PermissionNext.evaluate("bash", "ls -la", ruleset).action).toBe("allow") + expect(PermissionNext.evaluate("bash", "git commit -m test", ruleset).action).toBe("deny") + + // Edit tools should still be disabled + const disabled = PermissionNext.disabled(["edit", "write"], ruleset) + expect(disabled.has("edit")).toBe(true) + expect(disabled.has("write")).toBe(true) + }) +}) From 19467461dec3f3320456a22a2c8872f95500a6ac Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 30 Mar 2026 14:16:27 +0200 Subject: [PATCH 139/261] perf(agent-manager): extend slimPart to strip heavy tool metadata for faster session switching (#7927) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend slim-metadata.ts to handle apply_patch, multiedit, write, and bash tools in addition to edit. Previously only edit tool parts had their heavy metadata stripped before IPC serialization. apply_patch parts carried full file before/after contents per file, write parts carried the entire written file, and bash parts carried up to 30KB of output — all serialized on every session switch. This reduces session-switch time by ~2x for sessions with many tool calls. --- .../src/kilo-provider/slim-metadata.ts | 183 ++++++++++++++---- 1 file changed, 149 insertions(+), 34 deletions(-) diff --git a/packages/kilo-vscode/src/kilo-provider/slim-metadata.ts b/packages/kilo-vscode/src/kilo-provider/slim-metadata.ts index d81b70045d4..3ec760d7c4a 100644 --- a/packages/kilo-vscode/src/kilo-provider/slim-metadata.ts +++ b/packages/kilo-vscode/src/kilo-provider/slim-metadata.ts @@ -1,54 +1,169 @@ /** - * Pure data-transform helpers that strip heavy edit-tool metadata from + * Pure data-transform helpers that strip heavy tool metadata from * message parts before sending them to the webview via postMessage. * + * The webview communicates with the extension over VS Code's IPC bridge. + * Every message is JSON-serialised → deserialised on each side. Tool parts + * from edit, apply_patch, multiedit and write often carry full file contents + * (before/after snapshots, patch text, written content). Sending those on + * every session switch makes serialisation the dominant bottleneck. + * + * This module strips fields the webview never (or rarely) needs while keeping + * everything required to render collapsed tool-part headers and diagnostics. + * * No vscode dependency — safe to unit-test in isolation. */ -/** Strip a filediff down to path + addition/deletion counts. */ -function slimEditMeta(meta: unknown): Record | undefined { - if (!meta || typeof meta !== "object") return undefined +// Max chars to keep for truncated output fields (bash metadata.output etc.) +const OUTPUT_CAP = 4000 - const obj = meta as Record - const filediff = obj.filediff - if (!filediff || typeof filediff !== "object") return undefined +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- - const diff = filediff as Record - const file = typeof diff.file === "string" ? diff.file : undefined - const additions = typeof diff.additions === "number" ? diff.additions : 0 - const deletions = typeof diff.deletions === "number" ? diff.deletions : 0 - - const result: Record = { - filediff: { - ...(file ? { file } : {}), - additions, - deletions, - }, - } - // Preserve diagnostics so post-edit LSP errors still render - if (obj.diagnostics) result.diagnostics = obj.diagnostics - return result +function isObj(v: unknown): v is Record { + return !!v && typeof v === "object" && !Array.isArray(v) } -/** Strip heavy metadata from a single edit tool part; pass-through for everything else. */ +/** Truncate a string value to cap, appending a marker when trimmed. */ +function cap(v: unknown, limit = OUTPUT_CAP): string | undefined { + if (typeof v !== "string") return undefined + if (v.length <= limit) return v + return v.slice(0, limit) + `\n… (truncated, ${v.length - limit} chars omitted)` +} + +// --------------------------------------------------------------------------- +// Per-tool slimmers +// --------------------------------------------------------------------------- + +/** edit: strip filediff.before/after (webview falls back to input.oldString/newString). */ +function slimEdit(state: Record): Record { + const next = { ...state } + const meta = state.metadata + if (!isObj(meta)) { + delete next.metadata + return next + } + + const result: Record = {} + const fd = meta.filediff + if (isObj(fd)) { + result.filediff = { + ...(typeof fd.file === "string" ? { file: fd.file } : {}), + additions: typeof fd.additions === "number" ? fd.additions : 0, + deletions: typeof fd.deletions === "number" ? fd.deletions : 0, + } + } + if (meta.diagnostics) result.diagnostics = meta.diagnostics + next.metadata = result + return next +} + +/** apply_patch: strip files[].before/after/diff + input.patchText. */ +function slimPatch(state: Record): Record { + const next = { ...state } + const meta = state.metadata + if (isObj(meta) && Array.isArray(meta.files)) { + next.metadata = { + ...meta, + files: (meta.files as Record[]).map((f) => ({ + filePath: f.filePath, + relativePath: f.relativePath, + type: f.type, + additions: f.additions, + deletions: f.deletions, + movePath: f.movePath, + })), + } + if (isObj(meta) && meta.diagnostics) { + ;(next.metadata as Record).diagnostics = meta.diagnostics + } + } + // Strip the full patch text from input — only keep files count for title + const input = state.input + if (isObj(input) && typeof input.patchText === "string") { + next.input = { ...input, patchText: undefined } + } + return next +} + +/** multiedit: strip nested results (each is a full edit metadata object). */ +function slimMultiedit(state: Record): Record { + const next = { ...state } + const meta = state.metadata + if (isObj(meta) && Array.isArray(meta.results)) { + next.metadata = { + ...meta, + results: (meta.results as Record[]).map((r) => { + const slim: Record = {} + if (r.diagnostics) slim.diagnostics = r.diagnostics + const fd = r.filediff + if (isObj(fd)) { + slim.filediff = { + ...(typeof fd.file === "string" ? { file: fd.file } : {}), + additions: typeof fd.additions === "number" ? fd.additions : 0, + deletions: typeof fd.deletions === "number" ? fd.deletions : 0, + } + } + return slim + }), + } + } + return next +} + +/** write: strip input.content (entire file). Keep filePath + diagnostics. */ +function slimWrite(state: Record): Record { + const next = { ...state } + const input = state.input + if (isObj(input) && typeof input.content === "string") { + next.input = { ...input, content: undefined } + } + return next +} + +/** bash: truncate metadata.output (up to 30KB) and state.output (up to 50KB). */ +function slimBash(state: Record): Record { + const next = { ...state } + const meta = state.metadata + if (isObj(meta) && typeof meta.output === "string" && meta.output.length > OUTPUT_CAP) { + next.metadata = { ...meta, output: cap(meta.output) } + } + if (typeof state.output === "string" && (state.output as string).length > OUTPUT_CAP) { + next.output = cap(state.output) + } + return next +} + +// --------------------------------------------------------------------------- +// Public API +// --------------------------------------------------------------------------- + +const slimmers: Record) => Record> = { + edit: slimEdit, + apply_patch: slimPatch, + multiedit: slimMultiedit, + write: slimWrite, + bash: slimBash, +} + +/** Strip heavy metadata from a single tool part; pass-through for non-tool parts. */ export function slimPart(part: T): T { if (!part || typeof part !== "object") return part const obj = part as Record - if (obj.type !== "tool" || obj.tool !== "edit") return part + if (obj.type !== "tool") return part + + const tool = obj.tool + if (typeof tool !== "string") return part + + const fn = slimmers[tool] + if (!fn) return part const state = obj.state - if (!state || typeof state !== "object") return part + if (!isObj(state)) return part - const next = { ...(state as Record) } - const meta = slimEditMeta(next.metadata) - if (meta) next.metadata = meta - else delete next.metadata - - return { - ...obj, - state: next, - } as T + return { ...obj, state: fn(state) } as T } /** Slim every part in an array. */ From a68cf47dacc02c3f91574c76f886feb543d198ee Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Mon, 30 Mar 2026 15:21:55 +0300 Subject: [PATCH 140/261] fix(cli): remove find from Ask allowlist, add git write denials find has -exec/-execdir/-delete flags that execute arbitrary commands or delete files, bypassing the prefix-based permission check. Also add missing git write subcommand denials: config, clone, pull, init, worktree, submodule, revert, bisect, filter-branch, fetch, restore. --- packages/opencode/src/agent/agent.ts | 13 ++++++++-- packages/opencode/src/agent/prompt/ask.txt | 2 +- .../kilocode/ask-agent-permissions.test.ts | 25 +++++++++++++++++-- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 5590cc8abc4..fc99fd690ee 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -138,8 +138,6 @@ export namespace Agent { "whoami *": "allow", "printenv *": "allow", "man *": "allow", - // file discovery - "find *": "allow", // text processing (stdout only, no file modification) "grep *": "allow", "rg *": "allow", @@ -170,6 +168,17 @@ export namespace Agent { "git clean *": "deny", "git mv *": "deny", "git rm *": "deny", + "git config *": "deny", + "git clone *": "deny", + "git pull *": "deny", + "git init *": "deny", + "git worktree *": "deny", + "git submodule *": "deny", + "git revert *": "deny", + "git bisect *": "deny", + "git filter-branch *": "deny", + "git fetch *": "deny", + "git restore *": "deny", // gh — require user approval since commands vary widely "gh *": "ask", } diff --git a/packages/opencode/src/agent/prompt/ask.txt b/packages/opencode/src/agent/prompt/ask.txt index e324b0df985..40b5f9cf4aa 100644 --- a/packages/opencode/src/agent/prompt/ask.txt +++ b/packages/opencode/src/agent/prompt/ask.txt @@ -4,7 +4,7 @@ Guidelines: - Answer questions thoroughly with clear explanations and relevant examples - Analyze code, explain concepts, and provide recommendations without making changes - Use Mermaid diagrams when they help clarify your response -- You may run read-only bash commands (ls, cat, grep, git log, git diff, find, etc.) to gather information +- You may run read-only bash commands (ls, cat, grep, git log, git diff, etc.) to gather information - You must NOT modify files, run write commands, or execute code — this agent is read-only - MCP tools are available if configured — each call requires user approval - If a question requires implementation, suggest switching to a different agent diff --git a/packages/opencode/test/kilocode/ask-agent-permissions.test.ts b/packages/opencode/test/kilocode/ask-agent-permissions.test.ts index a727b014a00..50c31b1d116 100644 --- a/packages/opencode/test/kilocode/ask-agent-permissions.test.ts +++ b/packages/opencode/test/kilocode/ask-agent-permissions.test.ts @@ -24,7 +24,6 @@ const readOnlyBash: Record = { "whoami *": "allow", "printenv *": "allow", "man *": "allow", - "find *": "allow", "grep *": "allow", "rg *": "allow", "ag *": "allow", @@ -53,6 +52,17 @@ const readOnlyBash: Record = { "git clean *": "deny", "git mv *": "deny", "git rm *": "deny", + "git config *": "deny", + "git clone *": "deny", + "git pull *": "deny", + "git init *": "deny", + "git worktree *": "deny", + "git submodule *": "deny", + "git revert *": "deny", + "git bisect *": "deny", + "git filter-branch *": "deny", + "git fetch *": "deny", + "git restore *": "deny", "gh *": "ask", } @@ -115,7 +125,6 @@ describe("Ask agent bash permissions", () => { ["ls", "ls -la"], ["grep", "grep -r TODO src/"], ["rg", "rg pattern"], - ["find", "find . -name '*.ts'"], ["jq", "jq '.name' package.json"], ["head", "head -n 10 file.txt"], ["tail", "tail -f log.txt"], @@ -178,6 +187,17 @@ describe("Ask agent bash permissions", () => { "git remote add origin url", "git remote remove upstream", "git remote set-url origin url", + "git config user.name test", + "git clone https://example.com/repo", + "git pull origin main", + "git init", + "git worktree add ../branch", + "git submodule update --init", + "git revert HEAD", + "git bisect start", + "git filter-branch --all", + "git fetch origin", + "git restore src/index.ts", ] for (const cmd of denied) { @@ -190,6 +210,7 @@ describe("Ask agent bash permissions", () => { describe("denied write/execute commands", () => { const denied = [ + "find . -exec rm {} \\;", "touch newfile.ts", "mkdir src/new", "cp a.ts b.ts", From 6fadd9de994d22e3ee4ca706952b636447c658d1 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Mon, 30 Mar 2026 15:31:47 +0300 Subject: [PATCH 141/261] fix(cli): user denies override MCP ask rules Re-apply user deny rules after the ask-specific config so explicit user denies for MCP servers are not overridden by the generated mcpRules 'ask' defaults. --- packages/opencode/src/agent/agent.ts | 1 + .../kilocode/ask-agent-permissions.test.ts | 55 ++++++++++++------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index fc99fd690ee..5b1cb2bdcb1 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -338,6 +338,7 @@ export namespace Agent { }, ...mcpRules, }), + user.filter((r) => r.action === "deny"), // kilocode_change: re-apply user denies so explicit MCP blocks win over mcpRules ), mode: "primary", native: true, diff --git a/packages/opencode/test/kilocode/ask-agent-permissions.test.ts b/packages/opencode/test/kilocode/ask-agent-permissions.test.ts index 50c31b1d116..31bd7f3d796 100644 --- a/packages/opencode/test/kilocode/ask-agent-permissions.test.ts +++ b/packages/opencode/test/kilocode/ask-agent-permissions.test.ts @@ -88,32 +88,37 @@ function askRuleset() { }) } -/** Build the Ask agent ruleset WITH MCP servers */ -function askRulesetWithMcp(servers: string[]) { +/** Build the Ask agent ruleset WITH MCP servers and optional user config */ +function askRulesetWithMcp(servers: string[], user: PermissionNext.Ruleset = []) { const mcpRules: Record = {} for (const key of servers) { const sanitized = key.replace(/[^a-zA-Z0-9_-]/g, "_") mcpRules[sanitized + "_*"] = "ask" } - return PermissionNext.fromConfig({ - "*": "deny", - bash: readOnlyBash, - read: { - "*": "allow", - "*.env": "ask", - "*.env.*": "ask", - "*.env.example": "allow", - }, - grep: "allow", - glob: "allow", - list: "allow", - question: "allow", - webfetch: "allow", - websearch: "allow", - codesearch: "allow", - codebase_search: "allow", - ...mcpRules, - }) + // Mirrors agent.ts merge order: user, ask-specific (with mcpRules), user denies last + return PermissionNext.merge( + user, + PermissionNext.fromConfig({ + "*": "deny", + bash: readOnlyBash, + read: { + "*": "allow", + "*.env": "ask", + "*.env.*": "ask", + "*.env.example": "allow", + }, + grep: "allow", + glob: "allow", + list: "allow", + question: "allow", + webfetch: "allow", + websearch: "allow", + codesearch: "allow", + codebase_search: "allow", + ...mcpRules, + }), + user.filter((r) => r.action === "deny"), + ) } describe("Ask agent bash permissions", () => { @@ -318,4 +323,12 @@ describe("Ask agent MCP permissions", () => { expect(disabled.has("edit")).toBe(true) expect(disabled.has("write")).toBe(true) }) + + test("user config deny overrides MCP ask rules", () => { + const deny = PermissionNext.fromConfig({ "my-server_*": "deny" }) + const ruleset = askRulesetWithMcp(["my-server"], deny) + // User explicitly denied this server — should stay denied + const result = PermissionNext.disabled(["my-server_sometool"], ruleset) + expect(result.has("my-server_sometool")).toBe(true) + }) }) From 7376d2131a50e2b1d524892821a67590d4fe8de7 Mon Sep 17 00:00:00 2001 From: nivin karthick <107146054+so-nerdyy@users.noreply.github.com> Date: Mon, 30 Mar 2026 07:49:29 -0500 Subject: [PATCH 142/261] fix: preserve separator style when migrating .kilocode to .kilo paths (#7562) * fix: preserve separator style when migrating .kilocode to .kilo paths Fixes path corruption on Windows when stored paths used Unix slashes. Previously forced OS separator which created mixed-separator paths like: /repo\.kilo\worktrees/fix Now preserves original separator style from stored path. Closes: [issue reference if any] * test: update Windows test to match separator-preserving migration The test previously used path.sep which doesn't match the new behavior of preserving the separator style from the stored path. --------- Co-authored-by: marius-kilocode --- .../kilo-vscode/src/agent-manager/WorktreeStateManager.ts | 7 +++++-- .../kilo-vscode/tests/unit/worktree-state-manager.test.ts | 5 ++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/kilo-vscode/src/agent-manager/WorktreeStateManager.ts b/packages/kilo-vscode/src/agent-manager/WorktreeStateManager.ts index 695af8899b3..6dbaee91edb 100644 --- a/packages/kilo-vscode/src/agent-manager/WorktreeStateManager.ts +++ b/packages/kilo-vscode/src/agent-manager/WorktreeStateManager.ts @@ -318,8 +318,11 @@ export class WorktreeStateManager { this.reviewDiffStyle = "unified" for (const [id, wt] of Object.entries(data.worktrees ?? {})) { - // Rewrite stale .kilocode/ paths (handles both Unix / and Windows \ separators) - const fixed = wt.path?.replace(/[/\\]\.kilocode[/\\]/g, `${path.sep}.kilo${path.sep}`) ?? wt.path + // Rewrite stale .kilocode paths while preserving the separator style already stored. + const fixed = + wt.path?.replace(/([/\\])\.kilocode([/\\])/g, (_match, leadingSep, trailingSep) => { + return `${leadingSep}.kilo${trailingSep}` + }) ?? wt.path this.worktrees.set(id, { id, ...wt, path: fixed }) } for (const [id, s] of Object.entries(data.sessions ?? {})) { diff --git a/packages/kilo-vscode/tests/unit/worktree-state-manager.test.ts b/packages/kilo-vscode/tests/unit/worktree-state-manager.test.ts index 8e0a18a7066..5b0c2af1be2 100644 --- a/packages/kilo-vscode/tests/unit/worktree-state-manager.test.ts +++ b/packages/kilo-vscode/tests/unit/worktree-state-manager.test.ts @@ -548,9 +548,8 @@ describe("WorktreeStateManager", () => { await manager.load() - // path.sep is / on unix, \ on windows — the rewrite uses path.sep - const expected = `C:${path.sep}.kilo${path.sep}worktrees\\fix` - expect(manager.getWorktrees()[0].path).toBe(expected) + // Separator style from the stored path is preserved (backslashes stay as backslashes) + expect(manager.getWorktrees()[0].path).toBe("C:\\.kilo\\worktrees\\fix") }) }) }) From 5385dab21ae94af384af8c5fde99b806be7f9f97 Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 30 Mar 2026 14:59:04 +0200 Subject: [PATCH 143/261] fix(vscode): prevent spinner from disappearing during webview recreation (#7931) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When VS Code recreates a sidebar webview (e.g. switching panels and back), syncWebviewState re-seeds session statuses via HTTP. The reconciliation logic was resetting busy sessions to idle when they were absent from the HTTP response, causing a brief spinner gap before the next SSE event restored the busy state. Only reconcile (reset missing busy→idle) on the very first seed before any SSE events have populated the status map. After that, live SSE events are authoritative. Also adds defensive SSE improvements matching the app's behavior: - Disable SDK internal retry loop (sseMaxRetryAttempts: 1) - Filter AbortErrors in onSseError callback and catch block --- packages/kilo-vscode/src/KiloProvider.ts | 15 ++++-- .../services/cli-backend/sdk-sse-adapter.ts | 15 +++++- packages/kilo-vscode/src/session-status.ts | 18 +++++-- .../tests/unit/session-status.test.ts | 48 +++++++++++++++++++ 4 files changed, 88 insertions(+), 8 deletions(-) diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index af04b501103..8f72a833dd4 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -281,7 +281,12 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper // Seed session status map so the Settings panel knows about already-running sessions. // Must run after webview is ready (postMessage is a no-op before that). - void this.seedSessionStatusMap() + // Only reconcile (reset missing busy→idle) when the map is empty, i.e. + // on the very first seed before any real-time SSE events have arrived. + // On SSE reconnects or webview recreations the live SSE data is + // authoritative and reconciliation risks race-resetting busy sessions. + const reconcile = this.sessionStatusMap.size === 0 + void this.seedSessionStatusMap(reconcile) } // legacy-migration start @@ -1828,11 +1833,15 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper * Seed sessionStatusMap with current session statuses on connect. * Without this, the Settings panel (which has no tracked sessions) would see * busyCount() = 0 for sessions that were already running before it opened. + * + * @param reconcile When true, reset locally-busy sessions absent from the + * server response to idle (crash recovery). Set to false on SSE reconnects + * to avoid a race where a brief HTTP fetch gap causes the spinner to vanish. */ - private async seedSessionStatusMap(): Promise { + private async seedSessionStatusMap(reconcile = true): Promise { if (!this.client || this.connectionState !== "connected") return const dir = this.getWorkspaceDirectory() - await seedSessionStatuses(this.client, dir, this.sessionStatusMap, (msg) => this.postMessage(msg)) + await seedSessionStatuses(this.client, dir, this.sessionStatusMap, (msg) => this.postMessage(msg), reconcile) } /** diff --git a/packages/kilo-vscode/src/services/cli-backend/sdk-sse-adapter.ts b/packages/kilo-vscode/src/services/cli-backend/sdk-sse-adapter.ts index 260ca663262..0021e4e7a9a 100644 --- a/packages/kilo-vscode/src/services/cli-backend/sdk-sse-adapter.ts +++ b/packages/kilo-vscode/src/services/cli-backend/sdk-sse-adapter.ts @@ -143,10 +143,20 @@ export class SdkSSEAdapter { console.log("[Kilo New] SSE: 🎬 Calling SDK global.event()...") const events = await this.client.global.event({ signal: attempt.signal, + // Disable SDK-internal retries — consumeLoop handles reconnection + // with its own outer while-loop. Without this the SDK's infinite + // retry loop with exponential backoff runs in parallel, causing + // duplicate connections and "error" state flicker. + sseMaxRetryAttempts: 1, onSseError: (error) => { if (signal.aborted) { return } + // Filter AbortErrors — they are expected during heartbeat timeout + // or manual reconnect() calls, not real connection failures. + if (error instanceof DOMException && error.name === "AbortError") { + return + } console.error("[Kilo New] SSE: ❌ SDK SSE error callback:", error) this.notifyError(error instanceof Error ? error : new Error(String(error))) }, @@ -171,7 +181,10 @@ export class SdkSSEAdapter { console.log("[Kilo New] SSE: 📭 Stream ended normally") } catch (error) { - if (!signal.aborted) { + // Suppress AbortErrors — they are expected when the heartbeat timer + // or reconnect() aborts the per-attempt controller. + const aborted = signal.aborted || (error instanceof DOMException && error.name === "AbortError") + if (!aborted) { console.error("[Kilo New] SSE: ❌ Stream error:", error) this.notifyError(error instanceof Error ? error : new Error(String(error))) } diff --git a/packages/kilo-vscode/src/session-status.ts b/packages/kilo-vscode/src/session-status.ts index de476537f31..e596603e704 100644 --- a/packages/kilo-vscode/src/session-status.ts +++ b/packages/kilo-vscode/src/session-status.ts @@ -16,12 +16,18 @@ export function getBusySessionCount(map: Map): nu * Fetch all current session statuses and seed the provided map + webview. * Called on connect so the Settings panel knows about already-running sessions * without waiting for the next session.status SSE event. + * + * When `reconcile` is true (default: first seed), locally-busy sessions absent + * from the server response are reset to idle — covering server crash/restart. + * On SSE reconnects set `reconcile: false` to avoid a race where the HTTP + * fetch briefly returns stale data and the spinner disappears mid-stream. */ export async function seedSessionStatuses( client: KiloClient, dir: string, map: Map, post: (msg: unknown) => void, + reconcile = true, ): Promise { try { const result = await client.session.status({ directory: dir }) @@ -41,10 +47,14 @@ export async function seedSessionStatuses( // Reconcile: any locally non-idle session absent from the server response // means the server lost its in-memory state (crash/restart). Reset to idle. - for (const [sid, status] of map) { - if (status !== "idle" && !active[sid]) { - map.set(sid, "idle") - post({ type: "sessionStatus", sessionID: sid, status: "idle" }) + // Skipped on SSE reconnects — the real-time SSE events are authoritative + // for status transitions and the brief HTTP fetch can race with them. + if (reconcile) { + for (const [sid, status] of map) { + if (status !== "idle" && !active[sid]) { + map.set(sid, "idle") + post({ type: "sessionStatus", sessionID: sid, status: "idle" }) + } } } } catch (error) { diff --git a/packages/kilo-vscode/tests/unit/session-status.test.ts b/packages/kilo-vscode/tests/unit/session-status.test.ts index 2b9355c99fb..62478587521 100644 --- a/packages/kilo-vscode/tests/unit/session-status.test.ts +++ b/packages/kilo-vscode/tests/unit/session-status.test.ts @@ -147,6 +147,54 @@ describe("seedSessionStatuses", () => { expect(map.get("s1")).toBe("busy") expect(msgs).toEqual([]) }) + + // ---- reconcile=false (SSE reconnect) ---- + + it("skips reconciliation when reconcile=false", async () => { + const client = createClient({ data: {} }) + const map = new Map([["s1", "busy"]]) + const { msgs, post } = collect() + + await seedSessionStatuses(client, "/repo", map, post, false) + + // Session stays busy — reconciliation skipped on SSE reconnect + expect(map.get("s1")).toBe("busy") + expect(msgs).toEqual([]) + }) + + it("still seeds server entries when reconcile=false", async () => { + const client = createClient({ + data: { s1: { type: "busy" }, s2: { type: "retry", attempt: 1, message: "err", next: 1000 } }, + }) + const map = new Map() + const { msgs, post } = collect() + + await seedSessionStatuses(client, "/repo", map, post, false) + + expect(map.get("s1")).toBe("busy") + expect(map.get("s2")).toBe("retry") + expect(msgs).toEqual([ + { type: "sessionStatus", sessionID: "s1", status: "busy" }, + { type: "sessionStatus", sessionID: "s2", status: "retry", attempt: 1, message: "err", next: 1000 }, + ]) + }) + + it("does not reset stale entries when reconcile=false but updates confirmed ones", async () => { + const client = createClient({ data: { confirmed: { type: "busy" } } }) + const map = new Map([ + ["stale", "busy"], + ["confirmed", "retry"], + ]) + const { msgs, post } = collect() + + await seedSessionStatuses(client, "/repo", map, post, false) + + // stale: stays busy (no reconciliation) + expect(map.get("stale")).toBe("busy") + // confirmed: updated to busy from server + expect(map.get("confirmed")).toBe("busy") + expect(msgs).toEqual([{ type: "sessionStatus", sessionID: "confirmed", status: "busy" }]) + }) }) // --------------------------------------------------------------------------- From ca92e63b0f3efa3ee12666084e011c3b7dd9e982 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Mon, 30 Mar 2026 16:28:53 +0300 Subject: [PATCH 144/261] fix(cli): use allowlist for read-only git cmds --- packages/opencode/src/agent/agent.ts | 52 +++++++++++----------------- 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 5b1cb2bdcb1..175de2079f3 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -147,38 +147,26 @@ export namespace Agent { "cut *": "allow", "tr *": "allow", "jq *": "allow", - // git — allow read operations, deny all write operations - "git *": "allow", - "git add *": "deny", - "git commit *": "deny", - "git push *": "deny", - "git merge *": "deny", - "git rebase *": "deny", - "git cherry-pick *": "deny", - "git reset *": "deny", - "git checkout *": "deny", - "git switch *": "deny", - "git stash *": "deny", - "git tag *": "deny", - "git am *": "deny", - "git apply *": "deny", - "git remote set-url *": "deny", - "git remote add *": "deny", - "git remote remove *": "deny", - "git clean *": "deny", - "git mv *": "deny", - "git rm *": "deny", - "git config *": "deny", - "git clone *": "deny", - "git pull *": "deny", - "git init *": "deny", - "git worktree *": "deny", - "git submodule *": "deny", - "git revert *": "deny", - "git bisect *": "deny", - "git filter-branch *": "deny", - "git fetch *": "deny", - "git restore *": "deny", + // git — allowlist of read-only subcommands, deny everything else + "git *": "deny", + "git log *": "allow", + "git show *": "allow", + "git diff *": "allow", + "git status *": "allow", + "git branch *": "allow", + "git blame *": "allow", + "git rev-parse *": "allow", + "git rev-list *": "allow", + "git ls-files *": "allow", + "git ls-tree *": "allow", + "git ls-remote *": "allow", + "git shortlog *": "allow", + "git describe *": "allow", + "git cat-file *": "allow", + "git name-rev *": "allow", + "git remote *": "allow", + "git tag *": "allow", + "git stash list *": "allow", // gh — require user approval since commands vary widely "gh *": "ask", } From b007fa2d92f52637d4d82044c9d2e8fc449c88c0 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Mon, 30 Mar 2026 16:39:13 +0300 Subject: [PATCH 145/261] fix(cli): restrict git branch/tag/remote to read-only flags --- packages/opencode/src/agent/agent.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 175de2079f3..833aea650c5 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -153,7 +153,6 @@ export namespace Agent { "git show *": "allow", "git diff *": "allow", "git status *": "allow", - "git branch *": "allow", "git blame *": "allow", "git rev-parse *": "allow", "git rev-list *": "allow", @@ -164,9 +163,12 @@ export namespace Agent { "git describe *": "allow", "git cat-file *": "allow", "git name-rev *": "allow", - "git remote *": "allow", - "git tag *": "allow", "git stash list *": "allow", + "git tag -l *": "allow", + "git branch -l *": "allow", + "git branch -a *": "allow", + "git branch -r *": "allow", + "git remote -v *": "allow", // gh — require user approval since commands vary widely "gh *": "ask", } From 657296a08b268d9a6a7209cdc4d98543eda9572f Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Mon, 30 Mar 2026 16:39:48 +0300 Subject: [PATCH 146/261] fix(cli): clarify read-only wording in ask prompt --- packages/opencode/src/agent/prompt/ask.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/agent/prompt/ask.txt b/packages/opencode/src/agent/prompt/ask.txt index 40b5f9cf4aa..fc96b149ab1 100644 --- a/packages/opencode/src/agent/prompt/ask.txt +++ b/packages/opencode/src/agent/prompt/ask.txt @@ -5,6 +5,6 @@ Guidelines: - Analyze code, explain concepts, and provide recommendations without making changes - Use Mermaid diagrams when they help clarify your response - You may run read-only bash commands (ls, cat, grep, git log, git diff, etc.) to gather information -- You must NOT modify files, run write commands, or execute code — this agent is read-only +- You must NOT modify files, run write commands, or execute code — you are read-only - MCP tools are available if configured — each call requires user approval - If a question requires implementation, suggest switching to a different agent From a5c3a9567810268246608cea394ec343202104e3 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 13:46:10 +0000 Subject: [PATCH 147/261] feat(vscode): center profile screen with max-width --- .../webview-ui/src/components/profile/ProfileView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/profile/ProfileView.tsx b/packages/kilo-vscode/webview-ui/src/components/profile/ProfileView.tsx index f1f29cade1b..56a0cecb27f 100644 --- a/packages/kilo-vscode/webview-ui/src/components/profile/ProfileView.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/profile/ProfileView.tsx @@ -110,7 +110,7 @@ const ProfileView: Component = (props) => { >

{language.t("profile.title")}

-
+
Date: Mon, 30 Mar 2026 13:53:19 +0000 Subject: [PATCH 148/261] fix(vscode): add box-sizing border-box to prevent overflow on narrow panels --- .../webview-ui/src/components/profile/ProfileView.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/profile/ProfileView.tsx b/packages/kilo-vscode/webview-ui/src/components/profile/ProfileView.tsx index 56a0cecb27f..83f55ca0fbf 100644 --- a/packages/kilo-vscode/webview-ui/src/components/profile/ProfileView.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/profile/ProfileView.tsx @@ -110,7 +110,9 @@ const ProfileView: Component = (props) => { >

{language.t("profile.title")}

-
+
Date: Mon, 30 Mar 2026 13:56:56 +0000 Subject: [PATCH 149/261] docs: remove cline-to-kilo-migration page and add redirect --- packages/kilo-docs/lib/nav/contributing.ts | 4 - .../contributing/cline-to-kilo-migration.md | 180 ------------------ packages/kilo-docs/previous-docs-redirects.js | 6 + 3 files changed, 6 insertions(+), 184 deletions(-) delete mode 100644 packages/kilo-docs/pages/contributing/cline-to-kilo-migration.md diff --git a/packages/kilo-docs/lib/nav/contributing.ts b/packages/kilo-docs/lib/nav/contributing.ts index e02eb80fdaa..34fb344f30f 100644 --- a/packages/kilo-docs/lib/nav/contributing.ts +++ b/packages/kilo-docs/lib/nav/contributing.ts @@ -13,10 +13,6 @@ export const ContributingNav: NavSection[] = [ href: "/contributing/ecosystem", children: "Ecosystem", }, - { - href: "/contributing/cline-to-kilo-migration", - children: "Cline to Kilo Migration", - }, ], }, { diff --git a/packages/kilo-docs/pages/contributing/cline-to-kilo-migration.md b/packages/kilo-docs/pages/contributing/cline-to-kilo-migration.md deleted file mode 100644 index 4e4d399fc7f..00000000000 --- a/packages/kilo-docs/pages/contributing/cline-to-kilo-migration.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: "Cline to Kilo: Contributor Migration Guide" -description: "A guide for Cline contributors who want to start contributing to Kilo Code" ---- - -# Cline to Kilo: Contributor Migration Guide - -If you've been contributing to Cline and you're ready to bring those skills over to Kilo Code, you're in the right place. This guide will walk you through what's different, what's the same, and how to get up and running as a Kilo contributor. - -The good news: if you've been contributing to Cline, you already have most of the skills you need. The workflows are similar, but there are some differences worth knowing about before you dive in. - -## The Quick Version - -| What You Know from Cline | What's Different in Kilo | -| -------------------------------------------- | ------------------------ | -| `npm run install:all` | `pnpm install` | -| `npm run protos` required before first build | Not required | -| F5 to launch dev extension | Same — F5 to launch | -| Changesets for versioning | Same — `pnpm changeset` | - -## Setting Up Your Environment - -### What Stays the Same - -- Git, Node.js (v20.18.1+), and VS Code are still your core tools -- F5 still launches the extension in debug mode -- The project structure follows similar patterns (`src/`, `webview-ui/`, `e2e/`) - -### What's Changed - -**Package Manager: pnpm instead of npm** - -Kilo uses pnpm for dependency management. If you don't have it installed: - -```bash -npm install -g pnpm -``` - -Then instead of: - -```bash -# Cline -npm run install:all -``` - -You'll run: - -```bash -# Kilo -pnpm install -``` - -This single command handles everything — the main extension, webview UI, and e2e tests. - -**No Protocol Buffer Generation** - -In Cline, you needed to run `npm run protos` before your first build. Kilo doesn't require this step. Just install dependencies and you're ready to go. - -**Building the Extension** - -```bash -pnpm build -``` - -This builds the webview UI, compiles TypeScript, bundles everything, and drops a `.vsix` file in `bin/`. - -## Development Workflow Differences - -### Hot Reloading - -Kilo has improved hot reloading in development mode: - -- **Webview UI changes:** Apply immediately without restart (same as Cline) -- **Core extension changes:** In dev mode (`NODE_ENV="development"`), Kilo automatically triggers `workbench.action.reloadWindow` — no manual debugger restarts needed - -In Cline, you had to manually stop debugging, kill background tasks, and restart. Kilo handles this for you during development. - -**Note:** Production builds still require the manual stop/restart cycle. - -### Git Hooks - -Kilo uses Husky for git hooks, which run automatically: - -**Pre-commit:** - -- Blocks commits directly to main -- Runs type generation (`pnpm generate-types`) -- Checks for type file changes -- Runs lint-staged - -**Pre-push:** - -- Blocks pushes directly to main -- Compiles the project -- Reminds you to create a changeset if needed - -These hooks catch issues early. If a commit or push fails, check the hook output for details. - -## Testing - -### Running Tests - -```bash -# All tests -pnpm test - -# Extension tests only -pnpm test:extension - -# Webview tests only -pnpm test:webview - -# E2E / Integration tests -pnpm test:integration -``` - -### E2E Test Setup - -For integration tests, create a `.env.local` file in the project root: - -``` -OPENROUTER_API_KEY=sk-or-v1-... -``` - -Check `e2e/VSCODE_INTEGRATION_TESTS.md` for full details. - -## Contributing Code - -### Creating a Pull Request - -The changeset workflow is identical to Cline: - -```bash -pnpm changeset -``` - -Choose your version bump: - -- **major** — breaking changes -- **minor** — new features -- **patch** — bug fixes - -Commit the generated `.changeset` file with your changes. - -### Code Quality Checks - -```bash -pnpm lint # ESLint -pnpm check-types # TypeScript type checking -``` - -## What's New in Kilo - -Beyond the workflow changes, Kilo has expanded significantly as a platform. As a contributor, you might find opportunities to work on: - -- **Multiple interfaces:** VS Code, JetBrains, CLI, and web (Cloud Agents, App Builder) -- **Specialized Agent modes:** Code, Ask, Debug, Architect, Orchestrator -- **Custom Modes:** A system for creating and sharing specialized agent configurations -- **Platform features:** Sessions, Parallel Agents, Deploy, Code Reviews, Managed Indexing -- **Kilo Marketplace:** A community-driven repository where you can contribute Skills (modular workflows), MCP Servers (tool integrations), and Modes (custom agent behaviors) - -Check the [Architecture Overview](architecture) to understand how these pieces fit together. - -## Getting Help - -- **Discord:** Real-time support from the community -- **GitHub Discussions:** For questions and feature ideas -- **Reddit:** Community discussions - -## TL;DR Checklist - -- ✅ Install pnpm globally -- ✅ Fork and clone the Kilo repo -- ✅ Run `pnpm install` (not `npm run install:all`) -- ✅ Skip the protos step — it's not needed -- ✅ Press F5 to launch the dev extension -- ✅ Create a changeset before your PR (`pnpm changeset`) -- ✅ Let the git hooks do their thing - -Welcome to Kilo. We're glad you're here. diff --git a/packages/kilo-docs/previous-docs-redirects.js b/packages/kilo-docs/previous-docs-redirects.js index 0b163d427ae..c6d3804f430 100644 --- a/packages/kilo-docs/previous-docs-redirects.js +++ b/packages/kilo-docs/previous-docs-redirects.js @@ -1,4 +1,10 @@ module.exports = [ + { + source: "/docs/contributing/cline-to-kilo-migration", + destination: "/docs/contributing", + basePath: false, + permanent: true, + }, { source: "/docs/contributing/architecture/model-provider-blocklist", destination: "/docs/collaborate/enterprise/model-access-controls", From af6328aeccb9a0f9029d9a90f1340b31461ca45e Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 13:58:12 +0000 Subject: [PATCH 150/261] fix: update Kilo-Org/kilo references to Kilo-Org/kilocode --- .opencode/command/issues.md | 2 +- packages/kilo-docs/pages/contributing/index.md | 2 +- script/upstream/transforms/transform-take-theirs.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.opencode/command/issues.md b/.opencode/command/issues.md index d1e37d4a7df..224f22e3035 100644 --- a/.opencode/command/issues.md +++ b/.opencode/command/issues.md @@ -3,7 +3,7 @@ description: "find issue(s) on github" model: opencode/claude-haiku-4-5 --- -Search through existing issues in Kilo-Org/kilo using the gh cli to find issues matching this query: +Search through existing issues in Kilo-Org/kilocode using the gh cli to find issues matching this query: $ARGUMENTS diff --git a/packages/kilo-docs/pages/contributing/index.md b/packages/kilo-docs/pages/contributing/index.md index ba8960f7be3..1b8fa9e8604 100644 --- a/packages/kilo-docs/pages/contributing/index.md +++ b/packages/kilo-docs/pages/contributing/index.md @@ -6,7 +6,7 @@ description: "Contribute to Kilo Code" # Contributing Overview {% callout type="info" %} -**New versions of the VS Code extension and CLI are being developed in [Kilo-Org/Kilo](https://github.com/Kilo-Org/Kilo)** (extension at `packages/kilo-vscode`, CLI at `packages/opencode`). If you're looking to contribute to the extension or CLI, please head over to that repository. +**New versions of the VS Code extension and CLI are being developed in [Kilo-Org/kilocode](https://github.com/Kilo-Org/kilocode)** (extension at `packages/kilo-vscode`, CLI at `packages/opencode`). If you're looking to contribute to the extension or CLI, please head over to that repository. {% /callout %} Kilo Code is an open-source project that welcomes contributions from developers of all skill levels. This guide will help you get started with contributing to Kilo Code, whether you're fixing bugs, adding features, improving documentation, or sharing custom modes. diff --git a/script/upstream/transforms/transform-take-theirs.ts b/script/upstream/transforms/transform-take-theirs.ts index 0420d5074f3..0fd39f9c41a 100644 --- a/script/upstream/transforms/transform-take-theirs.ts +++ b/script/upstream/transforms/transform-take-theirs.ts @@ -45,7 +45,7 @@ const BRANDING_REPLACEMENTS: BrandingReplacement[] = [ }, { pattern: /anomalyco\/opencode/g, - replacement: "Kilo-Org/kilo", + replacement: "Kilo-Org/kilocode", description: "GitHub repo reference", }, From 598a2656b7b2f68b7c15c5bb55d5f21b971ded06 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Mon, 30 Mar 2026 16:07:56 +0200 Subject: [PATCH 151/261] fix(vscode): track leading-edge FIM requests as pending to enable reuse The leading-edge (first) call in debouncedFetchAndCacheSuggestion was not added to pendingRequests, making it invisible to findCoveringPendingRequest. When a user typed quickly while a leading-edge FIM request was still in-flight, subsequent calls could not reuse it and would create new debounced requests instead. Now the leading-edge request is tracked with a .finally() cleanup, so subsequent keystrokes that extend the prefix can piggyback on the in-flight request instead of issuing a redundant FIM call. --- .../AutocompleteInlineCompletionProvider.ts | 12 ++++- ...tocompleteInlineCompletionProvider.test.ts | 51 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider.ts b/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider.ts index 73fe0cdf10c..3783decc361 100644 --- a/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider.ts +++ b/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider.ts @@ -500,9 +500,19 @@ export class AutocompleteInlineCompletionProvider implements vscode.InlineComple } // If this is the first call (no pending debounce), execute immediately + // but still track it as a pending request so subsequent calls can reuse it if (this.isFirstCall && this.debounceTimer === null) { this.isFirstCall = false - return this.fetchAndCacheSuggestion(prompt, prefix, suffix, languageId) + const leading: PendingRequest = { + prefix, + suffix, + promise: null!, + } + leading.promise = this.fetchAndCacheSuggestion(prompt, prefix, suffix, languageId).finally(() => { + this.removePendingRequest(leading) + }) + this.pendingRequests.push(leading) + return leading.promise } // Clear any existing timer (reset the debounce) diff --git a/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/__tests__/AutocompleteInlineCompletionProvider.test.ts b/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/__tests__/AutocompleteInlineCompletionProvider.test.ts index 77a9297f640..65d709f7232 100644 --- a/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/__tests__/AutocompleteInlineCompletionProvider.test.ts +++ b/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/__tests__/AutocompleteInlineCompletionProvider.test.ts @@ -1973,6 +1973,57 @@ describe("AutocompleteInlineCompletionProvider", () => { expect(callCount).toBe(1) }) + it("should reuse slow leading-edge request when user types forward before it completes", async () => { + // Mock the model with a slow response that takes 500ms + let callCount = 0 + let resolvers: Array<() => void> = [] + vi.mocked(mockModel.generateFimResponse).mockImplementation(async (_prefix, _suffix, onChunk) => { + callCount++ + // Simulate a slow FIM response — wait for manual resolution + await new Promise((resolve) => { + resolvers.push(resolve) + }) + if (onChunk) { + onChunk("console.log('test');") + } + return { + cost: 0.01, + inputTokens: 100, + outputTokens: 50, + cacheWriteTokens: 0, + cacheReadTokens: 0, + } + }) + + // First request: leading edge fires immediately for "const x = 1" + const doc1 = new MockTextDocument(vscode.Uri.file("/test.ts"), "const x = 1\nconst y = 2") + const pos1 = new vscode.Position(0, 11) + const promise1 = provider.provideInlineCompletionItems(doc1, pos1, mockContext, mockToken) + + // Leading edge should have started the request immediately + expect(callCount).toBe(1) + + // User types "c" while the leading-edge request is still in-flight + const doc2 = new MockTextDocument(vscode.Uri.file("/test.ts"), "const x = 1c\nconst y = 2") + const pos2 = new vscode.Position(0, 12) + const promise2 = provider.provideInlineCompletionItems(doc2, pos2, mockContext, mockToken) + + // The second request should NOT have triggered a new FIM call — + // it should reuse the leading-edge pending request since the prefix + // extends and the suffix is unchanged + expect(callCount).toBe(1) + + // Now resolve the FIM response + resolvers[0]() + await vi.advanceTimersByTimeAsync(500) + + await promise1 + await promise2 + + // Only one FIM request should have been made total + expect(callCount).toBe(1) + }) + it("should NOT reuse pending request when suffix changes", async () => { // Mock the model to track call count let callCount = 0 From 6a6372f100e7fcb42ef498ecc34cbc7a4b29eaf5 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 13:59:09 +0000 Subject: [PATCH 152/261] docs: add Secondary Side Bar tip to VSCode tab in chat-interface --- .../kilo-docs/pages/code-with-ai/agents/chat-interface.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md index 490a1aa978b..7ae2bc19c1d 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/chat-interface.md @@ -188,6 +188,12 @@ This feature streamlines the interaction when Kilo Code requires clarification, **Pop out to an editor tab.** If the sidebar feels cramped, pop the chat into a full editor tab for more room. {% /callout %} +{% callout type="tip" %} +**Move Kilo Code to the Secondary Side Bar** for a better layout. Right-click on the Kilo Code icon in the Activity Bar and select **Move To → Secondary Side Bar**. This lets you see the Explorer, Search, Source Control, etc. alongside Kilo Code. + +{% image src="/docs/img/move-to-secondary.png" alt="Move to Secondary Side Bar" width="600" caption="Move Kilo Code to the Secondary Side Bar for better workspace organization" /%} +{% /callout %} + {% /tab %} {% tab label="CLI" %} From 81222b1474bf845402ecc4878cbc896646d3c02d Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 30 Mar 2026 16:10:00 +0200 Subject: [PATCH 153/261] fix(vscode): enable sub-agent open-in-tab button in Agent Manager (#7937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The button was hidden in the Agent Manager since the feature was new. The message routing already works — AgentManagerProvider passes openSubAgentViewer through to KiloProvider which opens the panel. --- .../webview-ui/src/components/chat/TaskToolExpanded.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/TaskToolExpanded.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/TaskToolExpanded.tsx index 1ac0d388f64..e9cfd8b3078 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/TaskToolExpanded.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/TaskToolExpanded.tsx @@ -17,7 +17,6 @@ import { useI18n } from "@kilocode/kilo-ui/context/i18n" import { createAutoScroll } from "@kilocode/kilo-ui/hooks" import { useSession } from "../../context/session" import { useVSCode } from "../../context/vscode" -import { useWorktreeMode } from "../../context/worktree-mode" import type { ToolPart, Message as SDKMessage } from "@kilocode/sdk/v2" /** Collect all tool parts from all assistant messages in a given session. */ @@ -41,9 +40,6 @@ const TaskToolRenderer: Component = (props) => { const i18n = useI18n() const session = useSession() const vscode = useVSCode() - const worktreeMode = useWorktreeMode() - // Hide the open-in-tab button inside the Agent Manager - const inAgentManager = worktreeMode !== undefined const childSessionId = () => props.metadata.sessionId as string | undefined @@ -97,7 +93,7 @@ const TaskToolRenderer: Component = (props) => {
- + Date: Mon, 30 Mar 2026 14:11:04 +0000 Subject: [PATCH 154/261] fix(kilo-docs): fix broken kiloclaw links for pricing and version-pinning --- packages/kilo-docs/pages/kiloclaw/dashboard.md | 4 ++-- packages/kilo-docs/pages/kiloclaw/overview.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/kilo-docs/pages/kiloclaw/dashboard.md b/packages/kilo-docs/pages/kiloclaw/dashboard.md index 9e75225fdd0..ae04957539f 100644 --- a/packages/kilo-docs/pages/kiloclaw/dashboard.md +++ b/packages/kilo-docs/pages/kiloclaw/dashboard.md @@ -100,7 +100,7 @@ You can pin your instance to a specific OpenClaw version and variant from the Se Select a version and variant from the dropdowns and click **Save**. To return to automatic updates, clear the version pin and save. -See [Version Pinning](/docs/kiloclaw/version-pinning) for details. +See [Version Pinning](/docs/kiloclaw/control-ui/version-pinning) for details. ### Version Status Indicators @@ -199,4 +199,4 @@ These are the beta specifications for machines and subject to change without not - [OpenClaw Control UI](/docs/kiloclaw/control-ui) - [Connecting Chat Platforms](/docs/kiloclaw/chat-platforms) - [Troubleshooting](/docs/kiloclaw/troubleshooting) -- [KiloClaw Pricing](/docs/kiloclaw/pricing) +- [KiloClaw Pricing](/docs/kiloclaw/faq/pricing) diff --git a/packages/kilo-docs/pages/kiloclaw/overview.md b/packages/kilo-docs/pages/kiloclaw/overview.md index 713fa0e6cb3..40624dd2f6c 100644 --- a/packages/kilo-docs/pages/kiloclaw/overview.md +++ b/packages/kilo-docs/pages/kiloclaw/overview.md @@ -96,7 +96,7 @@ For more information on use cases: - [Dashboard Reference](/docs/kiloclaw/dashboard) - [Connecting Chat Platforms](/docs/kiloclaw/chat-platforms) - [Troubleshooting](/docs/kiloclaw/troubleshooting) -- [KiloClaw Pricing](/docs/kiloclaw/pricing) +- [KiloClaw Pricing](/docs/kiloclaw/faq/pricing) - [Gateway Usage and Billing](/docs/gateway/usage-and-billing) - [Agent Manager](/docs/automate/agent-manager) - [OpenClaw Documentation](https://docs.openclaw.ai) From bfb80d1918484ef61401d89996522d91c0e14f81 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:16:34 +0000 Subject: [PATCH 155/261] docs: update legacy-only pages with VSCode/VSCode (Legacy) tabs for new CLI extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds VSCode tabs to 10 documentation pages that previously described only the legacy extension's behaviour. Each affected page now uses the same VSCode / VSCode (Legacy) tab pattern used elsewhere in the docs. Pages updated: - automate/how-tools-work: new tool names (read/glob/grep/edit/bash/task…) - automate/tools/index: new tool groups and names for the CLI-based extension - automate/mcp/using-in-kilo-code: new config format (opencode.json mcp key) - customize/custom-rules: new instructions[] config, .kilo/ directories - customize/custom-modes: new agent Markdown file format in .kilo/agents/ - customize/custom-instructions: config-file based instructions, no Modes Tab - customize/workflows: slash commands in .kilo/commands/, /name syntax - code-with-ai/features/checkpoints: snapshot: true config, revert UI - automate/agent-manager: full new Agent Manager feature set documented - getting-started/settings: fix Experimental tab (extension does expose toggles) Closes #7938 --- .../kilo-docs/pages/automate/agent-manager.md | 111 ++++++++++- .../pages/automate/how-tools-work.md | 84 +++++++++ .../pages/automate/mcp/using-in-kilo-code.md | 176 +++++++++++++++++- .../kilo-docs/pages/automate/tools/index.md | 76 ++++++++ .../code-with-ai/features/checkpoints.md | 89 +++++++-- .../pages/customize/custom-instructions.md | 50 +++++ .../kilo-docs/pages/customize/custom-modes.md | 65 ++++++- .../kilo-docs/pages/customize/custom-rules.md | 118 ++++++++++-- .../kilo-docs/pages/customize/workflows.md | 95 +++++++++- .../pages/getting-started/settings/index.md | 25 ++- 10 files changed, 847 insertions(+), 42 deletions(-) diff --git a/packages/kilo-docs/pages/automate/agent-manager.md b/packages/kilo-docs/pages/automate/agent-manager.md index 5f47025343d..17162a67172 100644 --- a/packages/kilo-docs/pages/automate/agent-manager.md +++ b/packages/kilo-docs/pages/automate/agent-manager.md @@ -5,6 +5,108 @@ description: "Manage and orchestrate multiple AI agents" # Agent Manager +The Agent Manager is a control panel for running and orchestrating multiple Kilo Code agents, with support for parallel worktree-isolated sessions. + +{% tabs %} +{% tab label="VSCode" %} + +The Agent Manager is a **full-panel editor tab** built directly into the extension. All sessions share the single `kilo serve` backend process. It supports: + +- Multiple parallel sessions, each in its own git worktree +- A diff/review panel showing changes vs. the parent branch +- Dedicated VS Code integrated terminals per session +- Setup scripts and `.env` auto-copy on worktree creation +- Session import from existing branches, external worktrees, or GitHub PR URLs +- "Continue in Worktree" to promote a sidebar session to the Agent Manager + +## Opening the Agent Manager + +- Keyboard shortcut: `Cmd+Shift+M` (macOS) / `Ctrl+Shift+M` (Windows/Linux) +- Command Palette: "Kilo Code: Open Agent Manager" +- Click the Agent Manager icon in the sidebar toolbar + +The panel opens as an editor tab and stays active across focus changes. + +## Working with Worktrees + +Each Agent Manager session runs in an isolated git worktree on a separate branch, keeping your main branch clean. + +### Creating a New Worktree Session + +1. Click **New Worktree** or press `Cmd+Shift+W` to create a new worktree +2. Enter a branch name (or let Kilo generate one) +3. Type your first message to start the agent + +A new git worktree is created from your current branch. The agent works in isolation — your main branch is unaffected. + +### Multi-Version Mode + +You can run up to 4 parallel implementations of the same prompt across separate worktrees: + +1. Click the multi-version button and enter a prompt +2. Optionally assign different models to each version +3. Kilo creates one worktree + session per version and runs them in parallel + +### Importing Existing Work + +- **From a branch:** Import an existing git branch as a worktree +- **From a GitHub PR URL:** Paste a PR URL to import it as a worktree +- **From an external worktree:** Import a worktree that already exists on disk +- **Continue in Worktree:** From the sidebar chat, promote the current session to a new Agent Manager worktree + +## Sending Messages, Approvals, and Control + +- **Continue the conversation:** Send a follow-up message to the running agent +- **Approvals:** The Permission Dock shows tool approval prompts — approve once, approve always, or deny +- **Cancel:** Sends a cooperative stop signal to the agent +- **Stop:** Force-terminates the session and marks it as stopped + +## Diff / Review Panel + +Press `Cmd+Alt+D` to toggle the diff panel. It shows a live-updating diff between the worktree and its parent branch. + +- Select files and click **Apply to Main Branch** to merge changes +- Conflicts are surfaced with a resolution dialog +- Supports unified and split diff views + +## Terminals + +Each session has a dedicated integrated terminal. Press `Cmd+Alt+T` to focus the terminal for the active session. + +## Setup Scripts + +Place an executable script at `.kilo/setup-script` in your project root. It runs automatically whenever a new worktree is created (useful for `npm install`, env setup, etc.). `.env` files are also auto-copied from the main repo. + +## Session State and Persistence + +Agent Manager state is persisted in `.kilo/agent-manager.json`. Sessions, worktrees, and their order are restored on reload. + +## Keyboard Shortcuts (Agent Manager Panel) + +| Shortcut | Action | +| ----------------- | --------------------------------- | +| `Cmd+Shift+M` | Open Agent Manager | +| `Cmd+Shift+W` | New worktree | +| `Cmd+Shift+O` | Import/open worktree | +| `Cmd+Shift+X` | Close current worktree | +| `Cmd+N` | New tab (session) in worktree | +| `Cmd+W` | Close current tab | +| `Cmd+Alt+[` / `]` | Previous / next worktree | +| `Cmd+Alt+,` / `.` | Previous / next tab in worktree | +| `Cmd+Alt+T` | Show terminal for current session | +| `Cmd+Alt+D` | Toggle diff panel | +| `Cmd+Alt+?` | Show keyboard shortcuts | +| `Cmd+1` … `Cmd+9` | Jump to worktree/session by index | + +## Troubleshooting + +- **"Please open a folder…" error** — the Agent Manager requires a VS Code workspace folder +- **"Cannot use parallel mode from within a git worktree"** — open the main repository (where `.git` is a directory), not a worktree checkout +- **Worktree creation fails** — ensure Git is installed and the workspace is a valid git repository + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + The Agent Manager is a dedicated control panel for running and supervising Kilo Code agents as interactive CLI processes. It supports: - Local sessions @@ -22,7 +124,7 @@ This page reflects the actual implementation in the extension. ## Opening the Agent Manager -- Command Palette: “Kilo Code: Open Agent Manager” +- Command Palette: "Kilo Code: Open Agent Manager" - Or use the title/menu entry if available in your Kilo Code UI The panel opens as a webview and stays active across focus changes. @@ -34,13 +136,13 @@ The panel opens as a webview and stays active across focus changes. - Approve or reject, optionally adding a short note - Cancel vs Stop - Cancel sends a structured cancel message to the running process (clean cooperative stop) - - Stop force-terminates the underlying CLI process, updating status to “stopped” + - Stop force-terminates the underlying CLI process, updating status to "stopped" ## Resuming an existing session You can continue a session later (local or remote): -- If a session is not currently running, the Agent Manager will spawn a new CLI process attached to that session’s ID +- If a session is not currently running, the Agent Manager will spawn a new CLI process attached to that session's ID - Labels from the original session are preserved whenever possible - Your first follow-up message becomes the continuation input @@ -144,6 +246,9 @@ Message transcripts are fetched from a signed blob and exclude internal checkpoi - Verify you're logged in via extension settings or using CLI with kilocode provider - BYOK configurations do not support Agent Manager authentication +{% /tab %} +{% /tabs %} + ## Related features - [Sessions](/docs/collaborate/sessions-sharing) diff --git a/packages/kilo-docs/pages/automate/how-tools-work.md b/packages/kilo-docs/pages/automate/how-tools-work.md index ea7d88abe47..6cc0d01be56 100644 --- a/packages/kilo-docs/pages/automate/how-tools-work.md +++ b/packages/kilo-docs/pages/automate/how-tools-work.md @@ -18,6 +18,20 @@ Describe what you want to accomplish in natural language, and Kilo Code will: ## Tool Categories +{% tabs %} +{% tab label="VSCode" %} + +| Category | Purpose | Tool Names | +| :------- | :----------------------------------------- | :----------------------------------------------------------- | +| Read | Access file content and code structure | `read`, `glob`, `grep` | +| Edit | Create or modify files and code | `edit`, `multiedit`, `write`, `apply_patch` | +| Execute | Run commands and perform system operations | `bash` | +| Web | Fetch and search web content | `webfetch`, `websearch`, `codesearch` | +| Workflow | Manage task flow and sub-agents | `question`, `task`, `todowrite`, `todoread`, `plan`, `skill` | + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + | Category | Purpose | Tool Names | | :------- | :----------------------------------------- | :----------------------------------------------------------------------- | | Read | Access file content and code structure | `read_file`, `search_files`, `list_files`, `list_code_definition_names` | @@ -26,10 +40,29 @@ Describe what you want to accomplish in natural language, and Kilo Code will: | Browser | Interact with web content | `browser_action` | | Workflow | Manage task flow and context | `ask_followup_question`, `attempt_completion`, `switch_mode`, `new_task` | +{% /tab %} +{% /tabs %} + ## Example: Using Tools Here's how a typical tool interaction works: +{% tabs %} +{% tab label="VSCode" %} + +{% callout type="info" title="Tool Approval UI" %} +When a tool is proposed, you'll see an approval prompt in the **Permission Dock** at the bottom of the chat. You can approve once, approve always (saves to config), or deny. +{% /callout %} + +**User:** Create a file named `greeting.js` that logs a greeting message + +**Kilo Code:** (Proposes the `write` tool) + +The extension shows the file path and proposed content for review. Click **Approve** to execute or **Deny** to cancel. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + {% callout type="info" title="Tool Approval UI" %} When a tool is proposed, you'll see Save and Reject buttons along with an optional Auto-approve checkbox for trusted operations. {% /callout %} @@ -56,8 +89,27 @@ greet('World'); **Kilo Code:** (Confirms file creation) +{% /tab %} +{% /tabs %} + ## Tool Safety and Approval +{% tabs %} +{% tab label="VSCode" %} + +Every tool use requires your explicit approval via the **Permission Dock** floating UI in the chat panel. For each tool call you can: + +- **Approve** — execute the tool once +- **Approve Always** — add this tool/pattern to your config so future calls are auto-approved +- **Deny** — decline the proposed tool call + +You can also toggle **Auto-approve** for all tools for the current session using `Ctrl+Alt+A` / `Cmd+Alt+A`. + +This safety mechanism ensures you maintain control over which files are modified, what commands are executed, and how your codebase is changed. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + Every tool use requires your explicit approval. When Kilo proposes a tool, you'll see: - A "Save" button to approve and execute the tool @@ -66,8 +118,37 @@ Every tool use requires your explicit approval. When Kilo proposes a tool, you'l This safety mechanism ensures you maintain control over which files are modified, what commands are executed, and how your codebase is changed. Always review tool proposals carefully before saving them. +{% /tab %} +{% /tabs %} + ## Core Tools Reference +{% tabs %} +{% tab label="VSCode" %} + +| Tool Name | Description | Category | +| :------------ | :----------------------------------------------------- | :------- | +| `read` | Reads file contents with line numbers | Read | +| `glob` | Finds files by glob pattern | Read | +| `grep` | Searches file contents with regex | Read | +| `edit` | Makes precise text replacements in a file | Edit | +| `multiedit` | Multiple edits in a single call | Edit | +| `write` | Creates new files or overwrites existing ones | Edit | +| `apply_patch` | Applies unified diffs (used with certain models) | Edit | +| `bash` | Runs shell commands | Execute | +| `webfetch` | Fetches a URL | Web | +| `websearch` | Searches the web (Kilo/OpenRouter users) | Web | +| `codesearch` | Semantic code search (Kilo/OpenRouter users) | Web | +| `question` | Asks you a clarifying question with selectable options | Workflow | +| `task` | Spawns a sub-agent session | Workflow | +| `todowrite` | Creates and updates a session TODO list | Workflow | +| `todoread` | Reads the current session TODO list | Workflow | +| `plan` | Enters structured planning mode | Workflow | +| `skill` | Invokes a reusable skill (Markdown instruction module) | Workflow | + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + | Tool Name | Description | Category | | :--------------------------- | :-------------------------------------------------- | :------- | | `read_file` | Reads the content of a file with line numbers | Read | @@ -84,6 +165,9 @@ This safety mechanism ensures you maintain control over which files are modified | `switch_mode` | Changes to a different operational mode | Workflow | | `new_task` | Creates a new subtask with a specific starting mode | Workflow | +{% /tab %} +{% /tabs %} + ## Learn More About Tools For more detailed information about each tool, including complete parameter references and advanced usage patterns, see the [Tool Use Overview](/docs/automate/tools) documentation. diff --git a/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md b/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md index 43dd907c755..219fc8cc364 100644 --- a/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md +++ b/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md @@ -11,10 +11,75 @@ Model Context Protocol (MCP) extends Kilo Code's capabilities by connecting to e ## Configuring MCP Servers +{% tabs %} +{% tab label="VSCode" %} + +MCP server configurations are stored inside the main Kilo config file. There are two levels: + +1. **Global Configuration**: `~/.config/kilo/opencode.json` — applies to all projects. +2. **Project-level Configuration**: `kilo.json` or `.kilo/kilo.jsonc` in your project root. + +**Precedence**: Project-level configuration takes precedence over global configuration. + +### Editing MCP Settings + +You can edit MCP settings from the Kilo Code settings UI: + +1. Click the {% codicon name="gear" /%} icon in the sidebar toolbar to open Settings. +2. Click the `Agent Behaviour` tab on the left side. +3. Select the `MCP Servers` sub-tab. + +From here you can add, edit, enable/disable, and delete MCP servers. Changes are written directly to the appropriate config file. + +### Config Format + +MCP servers are configured under the `mcp` key in `opencode.json` / `kilo.jsonc`: + +**Local (STDIO) server:** + +```json +{ + "mcp": { + "my-local-server": { + "type": "local", + "command": ["node", "/path/to/server.js"], + "environment": { + "API_KEY": "your_api_key" + }, + "enabled": true, + "timeout": 10000 + } + } +} +``` + +**Remote (HTTP/SSE) server:** + +```json +{ + "mcp": { + "my-remote-server": { + "type": "remote", + "url": "https://your-server-url.com/mcp", + "headers": { + "Authorization": "Bearer your-token" + }, + "enabled": true, + "timeout": 15000 + } + } +} +``` + +Remote servers support OAuth 2.0 authentication. If the server supports it, Kilo Code will automatically start the OAuth flow when you connect. You can also disable OAuth with `"oauth": false`. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + MCP server configurations can be managed at two levels: -1. **Global Configuration**: Stored in the `mcp_settings.json` file, accessible via VS Code settings (see below). These settings apply across all your workspaces unless overridden by a project-level configuration. -2. **Project-level Configuration**: Defined in a `.kilocode/mcp.json` file within your project's root directory. This allows you to set up project-specific servers and share configurations with your team by committing the file to version control. Kilo Code automatically detects and loads this file if it exists. +1. **Global Configuration**: Stored in the `mcp_settings.json` file, accessible via VS Code settings (see below). These settings apply across all your workspaces unless overridden by a project-level configuration. +2. **Project-level Configuration**: Defined in a `.kilocode/mcp.json` file within your project's root directory. This allows you to set up project-specific servers and share configurations with your team by committing the file to version control. Kilo Code automatically detects and loads this file if it exists. **Precedence**: If a server name exists in both global and project configurations, the **project-level configuration takes precedence**. @@ -51,7 +116,39 @@ Both files use a JSON format with a `mcpServers` object containing named server _Example of MCP Server config in Kilo Code (STDIO Transport)_ -### Understanding Transport Types +{% /tab %} +{% /tabs %} + +## Understanding Transport Types + +{% tabs %} +{% tab label="VSCode" %} + +MCP supports two transport types: + +#### Local (STDIO) Transport + +Used for servers running on your machine as a child process: + +- Communicates via standard input/output streams +- Lower latency (no network overhead) +- Better security (no network exposure) + +#### Remote (HTTP/SSE) Transport + +Used for servers accessed over HTTP/HTTPS: + +- Can be hosted on a different machine +- Supports multiple client connections +- Requires network access +- Supports OAuth 2.0 authentication + +Kilo Code tries `StreamableHTTP` first, then falls back to `SSE` transport automatically for remote servers. + +For more details, see [STDIO & SSE Transports](server-transports). + +{% /tab %} +{% tab label="VSCode (Legacy)" %} MCP supports three transport types for server communication: @@ -143,6 +240,9 @@ SSE configuration example: } ``` +{% /tab %} +{% /tabs %} + ### Deleting a Server 1. Press the {% codicon name="trash" /%} next to the MCP server you would like to delete @@ -160,14 +260,43 @@ SSE configuration example: ### Network Timeout +{% tabs %} +{% tab label="VSCode" %} + +Set the `timeout` field (in milliseconds) in the server's config entry. The default is 10 seconds for local servers and 15 seconds for remote servers. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + To set the maximum time to wait for a response after a tool call to the MCP server: 1. Click the `Network Timeout` pulldown at the bottom of the individual MCP server's config box and change the time. Default is 1 minute but it can be set between 30 seconds and 5 minutes. {% image src="/docs/img/using-mcp-in-kilo-code/using-mcp-in-kilo-code-6.png" alt="Network Timeout pulldown" width="400" caption="Network Timeout pulldown" /%} +{% /tab %} +{% /tabs %} + ### Auto Approve Tools +{% tabs %} +{% tab label="VSCode" %} + +Tool permissions in the new extension are managed through the permission system. In your config file, set a tool's permission to `"allow"` to auto-approve it: + +```json +{ + "permission": { + "bash": "allow" + } +} +``` + +You can also approve individual MCP tool calls as "always allow" directly from the Permission Dock in the chat UI. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + MCP tool auto-approval works on a per-tool basis and is disabled by default. To configure auto-approval: 1. First enable the global "Use MCP servers" auto-approval option in [auto-approving-actions](/docs/getting-started/settings/auto-approving-actions) @@ -178,10 +307,14 @@ MCP tool auto-approval works on a per-tool basis and is disabled by default. To When enabled, Kilo Code will automatically approve this specific tool without prompting. Note that the global "Use MCP servers" setting takes precedence - if it's disabled, no MCP tools will be auto-approved. +{% /tab %} +{% /tabs %} + ## Finding and Installing MCP Servers Kilo Code does not come with any pre-installed MCP servers. You'll need to find and install them separately. +- **Kilo Marketplace:** Browse and install MCP servers directly from the Marketplace tab in the extension sidebar - **Community Repositories:** Check for community-maintained lists of MCP servers on GitHub - **Ask Kilo Code:** You can ask Kilo Code to help you find or even create MCP servers - **Build Your Own:** Create custom MCP servers using the SDK to extend Kilo Code with your own tools @@ -202,11 +335,25 @@ Example: "Analyze the performance of my API" might use an MCP tool that tests AP Common issues and solutions: +{% tabs %} +{% tab label="VSCode" %} + +- **Server Not Responding:** Check if the server process is running and verify network connectivity. Review server status in Settings > Agent Behaviour > MCP Servers. +- **`needs_auth` status:** For remote servers with OAuth, the extension will show a notification to start the auth flow. Click it to authenticate. +- **`failed` status:** Check the CLI output for error details. Ensure commands and paths are correct. +- **Tool Not Available:** Confirm the server is properly implementing the tool and it's not disabled in settings. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + - **Server Not Responding:** Check if the server process is running and verify network connectivity - **Permission Errors:** Ensure proper API keys and credentials are configured in your `mcp_settings.json` (for global settings) or `.kilocode/mcp.json` (for project settings). - **Tool Not Available:** Confirm the server is properly implementing the tool and it's not disabled in settings - **Slow Performance:** Try adjusting the network timeout value for the specific MCP server +{% /tab %} +{% /tabs %} + {% callout type="tip" %} **Reduce system prompt size:** If you're not using MCP, turn it off in Settings > Agent Behaviour > MCP Servers to significantly cut down the size of the system prompt and improve performance. {% /callout %} @@ -215,6 +362,26 @@ Common issues and solutions: ### Windows Configuration Example +{% tabs %} +{% tab label="VSCode" %} + +When setting up local MCP servers on Windows, use the full `cmd` invocation in the `command` array: + +```json +{ + "mcp": { + "puppeteer": { + "type": "local", + "command": ["cmd", "/c", "npx", "-y", "@modelcontextprotocol/server-puppeteer"], + "enabled": true + } + } +} +``` + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + When setting up MCP servers on Windows, you'll need to use the Windows Command Prompt (`cmd`) to execute commands. Here's an example of configuring a Puppeteer MCP server on Windows: ```json @@ -252,4 +419,7 @@ For macOS or Linux, you would use a different configuration: {% /callout %} +{% /tab %} +{% /tabs %} + The same approach can be used for other MCP servers on Windows, adjusting the package name as needed for different server types. diff --git a/packages/kilo-docs/pages/automate/tools/index.md b/packages/kilo-docs/pages/automate/tools/index.md index ac473fefdc0..4a441515cc9 100644 --- a/packages/kilo-docs/pages/automate/tools/index.md +++ b/packages/kilo-docs/pages/automate/tools/index.md @@ -11,6 +11,79 @@ Kilo Code implements a sophisticated tool system that allows AI models to intera ### Tool Groups +{% tabs %} +{% tab label="VSCode" %} + +Tools are organized into logical groups based on their functionality: + +| Category | Purpose | Tools | Common Use | +| ------------------ | --------------------------------- | ------------------------------------------------------------ | --------------------------------------- | +| **Read Group** | File system reading and searching | `read`, `glob`, `grep` | Code exploration and analysis | +| **Edit Group** | File system modifications | `edit`, `multiedit`, `write`, `apply_patch` | Code changes and file manipulation | +| **Execute Group** | Shell command execution | `bash` | Running scripts, building projects | +| **Web Group** | Fetch and search web content | `webfetch`, `websearch`, `codesearch` | Research, documentation lookup | +| **MCP Group** | External tool integration | MCP server tools (namespaced as `{server}_{tool}`) | Specialized functionality via MCP | +| **Workflow Group** | Sub-agents and task management | `question`, `task`, `todowrite`, `todoread`, `plan`, `skill` | Context switching and task organization | + +### Always Available Tools + +Certain tools are accessible regardless of the current agent: + +- `question`: Ask the user a clarifying question with selectable options +- `task`: Spawn a sub-agent session +- `todowrite` / `todoread`: Manage session task lists + +## Available Tools + +### Read Tools + +These tools help Kilo Code understand your code and project: + +- `read` - Reads file contents with line numbers +- `glob` - Finds files matching a glob pattern +- `grep` - Searches file contents with regex + +### Edit Tools + +These tools help Kilo Code make changes to your code: + +- `edit` - Makes precise text replacements in a file +- `multiedit` - Multiple edits in a single call +- `write` - Creates new files or fully overwrites existing ones +- `apply_patch` - Applies unified diffs (used with certain models) + +### Execute Tools + +These tools help Kilo Code run commands: + +- `bash` - Runs shell commands with configurable timeout and working directory + +### Web Tools + +These tools help Kilo Code access web content: + +- `webfetch` - Fetches a URL and returns the content +- `websearch` - Searches the web (available to Kilo/OpenRouter users) +- `codesearch` - Semantic code search (available to Kilo/OpenRouter users) + +### MCP Tools + +MCP server tools are automatically available when an MCP server is connected. Tool names are namespaced as `{server}_{tool}`. See [MCP Overview](/docs/automate/mcp/overview) for details. + +### Workflow Tools + +These tools help manage the conversation and task flow: + +- `question` - Asks you a clarifying question with selectable options +- `task` - Spawns a sub-agent (child session) +- `todowrite` - Creates and updates a session TODO list +- `todoread` - Reads the current session TODO list +- `plan` - Enters structured planning mode +- `skill` - Invokes a reusable skill (Markdown instruction module) + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + Tools are organized into logical groups based on their functionality: | Category | Purpose | Tools | Common Use | @@ -80,6 +153,9 @@ These tools help manage the conversation and task flow: - [new_task](/docs/automate/tools/new-task) - Creates a new subtask - [update_todo_list](/docs/automate/tools/update-todo-list) - Tracks task progress with step-by-step checklists +{% /tab %} +{% /tabs %} + ## Tool Calling Mechanism ### When Tools Are Called diff --git a/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md b/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md index 377f9dc108e..ed6747482a7 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md +++ b/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md @@ -14,6 +14,52 @@ Checkpoints let you: - Compare different implementation approaches - Revert to previous project states without losing work +## Configuration Options + +{% tabs %} +{% tab label="VSCode" %} + +Checkpoints (called **snapshots** in the new extension) are configured via the `snapshot` key in your config file (`kilo.json` or `~/.config/kilo/opencode.json`): + +```json +{ + "snapshot": true +} +``` + +You can also toggle this in Settings: + +1. Open Settings by clicking the gear icon {% codicon name="gear" /%} +2. Go to the `Checkpoints` tab +3. Toggle the snapshot setting + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + +Access checkpoint settings in Kilo Code settings under the "Checkpoints" section: + +1. Open Settings by clicking the gear icon {% codicon name="gear" /%} → Checkpoints +2. Check or uncheck the "Enable automatic checkpoints" checkbox + + {% image src="/docs/img/checkpoints/checkpoints.png" alt="Checkpoint settings in Kilo Code configuration" width="500" /%} + +{% /tab %} +{% /tabs %} + +## How Checkpoints Work + +{% tabs %} +{% tab label="VSCode" %} + +The new extension uses **git-based snapshots** of your working directory. Snapshots are taken before and after agent edits. They integrate with your existing Git repository — no separate shadow repository is created. + +**Reverting changes:** + +You can revert any message's changes from the chat. A **Revert Banner** appears at the top of the chat when the session is in a reverted state, making it clear that you are viewing an earlier state. Use the banner to unrevert and return to the latest state. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + {% callout type="info" title="Important Notes" %} - **Checkpoints are enabled by default.** @@ -25,17 +71,6 @@ Checkpoints let you: {% /callout %} -## Configuration Options - -Access checkpoint settings in Kilo Code settings under the "Checkpoints" section: - -1. Open Settings by clicking the gear icon {% codicon name="gear" /%} → Checkpoints -2. Check or uncheck the "Enable automatic checkpoints" checkbox - - {% image src="/docs/img/checkpoints/checkpoints.png" alt="Checkpoint settings in Kilo Code configuration" width="500" /%} - -## How Checkpoints Work - Kilo Code captures snapshots of your project's state using a shadow Git repository, separate from your main version control system. These snapshots, called checkpoints, automatically record changes throughout your AI-assisted workflow—whenever tasks begin, files change, or commands run. Checkpoints are stored as Git commits in the shadow repository, capturing: @@ -46,8 +81,24 @@ Checkpoints are stored as Git commits in the shadow repository, capturing: - Renamed files - Binary file changes +{% /tab %} +{% /tabs %} + ## Working with Checkpoints +{% tabs %} +{% tab label="VSCode" %} + +Checkpoints are integrated directly into your workflow through the chat interface. Each message that caused file changes shows a diff summary. You can: + +- Click the diff badge on a message to open the **Diff Viewer** and review what changed +- Click **Revert** on any message to restore the workspace to its state before that message + +A **Revert Banner** is shown at the top of the chat whenever you are in a reverted state, with an option to return to the current state. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + Checkpoints are integrated directly into your workflow through the chat interface. Checkpoints appear directly in your chat history in two forms: @@ -93,6 +144,9 @@ To restore a project to a previous checkpoint state: {% image src="/docs/img/checkpoints/checkpoints-9.png" alt="Confirmation dialog for restoring checkpoint with files & task" width="300" /%} +{% /tab %} +{% /tabs %} + ### Limitations and Considerations - **Scope**: Checkpoints only capture changes made during active Kilo Code tasks @@ -102,6 +156,14 @@ To restore a project to a previous checkpoint state: ## Technical Implementation +{% tabs %} +{% tab label="VSCode" %} + +The new extension uses the underlying Git repository in your workspace to create snapshot commits. No shadow repository is used. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + ### Checkpoint Architecture The checkpoint system consists of: @@ -183,9 +245,12 @@ Checkpoints do not support nested Git repositories. The working directory must b Operations are queued to prevent concurrent Git operations that might corrupt repository state. This ensures that rapid checkpoint operations complete safely even when requested in quick succession. +{% /tab %} +{% /tabs %} + ## Git Installation -Checkpoints require Git to be installed on your system. The implementation uses the `simple-git` library, which relies on Git command-line tools to create and manage shadow repositories. +Checkpoints require Git to be installed on your system. ### macOS diff --git a/packages/kilo-docs/pages/customize/custom-instructions.md b/packages/kilo-docs/pages/customize/custom-instructions.md index b7ea7b7d8fb..a0b80d5b312 100644 --- a/packages/kilo-docs/pages/customize/custom-instructions.md +++ b/packages/kilo-docs/pages/customize/custom-instructions.md @@ -17,6 +17,40 @@ Custom Instructions are IDE-wide and are applied across all workspaces and maint ## Setting Custom Instructions +{% tabs %} +{% tab label="VSCode" %} + +In the new extension, global and agent-specific instructions are managed through config files and agent Markdown files rather than a UI text area. + +**Global instructions** (applied to all agents) — add an `instructions` array to your global config (`~/.config/kilo/opencode.json`): + +```json +{ + "instructions": ["~/.config/kilo/global-rules.md"] +} +``` + +**Agent-specific instructions** — include them directly in the agent's Markdown file body (`.kilo/agents/my-agent.md`): + +```markdown +--- +model: anthropic/claude-3-5-sonnet-20241022 +--- + +You are a test engineer focused on code quality. +Always write tests in the describe/it style. +Include meaningful test descriptions. +``` + +You can also manage instruction file references from: + +1. Click the {% codicon name="gear" /%} icon in the sidebar toolbar to open Settings. +2. Click `Agent Behaviour` → `Rules` sub-tab. +3. Add or remove instruction file paths. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + **How to set them:** {% image src="/docs/img/custom-instructions/custom-instructions.png" alt="Kilo Code Modes tab showing global custom instructions interface" width="600" caption="Kilo Code Modes tab showing global custom instructions interface" /%} @@ -40,8 +74,21 @@ Mode-specific instructions can be set using the Modes Tab If the mode itself is global (not workspace-specific), any custom instructions you set for it will also apply globally for that mode across all workspaces. {% /callout %} +{% /tab %} +{% /tabs %} + ## Mode-Specific Instructions from Files +{% tabs %} +{% tab label="VSCode" %} + +Agent-specific instructions are written directly in the agent Markdown file body (`.kilo/agents/{agent-name}.md`). The file content after the YAML frontmatter is used as the agent's system prompt. + +For version-controlled per-agent instructions, simply commit the `.kilo/agents/` directory. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + For version-controlled mode instructions, use the mode rules file paths documented in [Custom Modes](/docs/customize/custom-modes#mode-specific-instructions-via-filesdirectories): - Preferred: `.kilo/rules-{mode-slug}/` (directory) @@ -51,6 +98,9 @@ For version-controlled mode instructions, use the mode rules file paths document Older naming like `.clinerules-{mode-slug}` is not the recommended path for current Kilo mode-specific instructions. {% /callout %} +{% /tab %} +{% /tabs %} + ## Related Features - [Custom Modes](/docs/customize/custom-modes) diff --git a/packages/kilo-docs/pages/customize/custom-modes.md b/packages/kilo-docs/pages/customize/custom-modes.md index 86bcc17a2c4..0b15fc87b12 100644 --- a/packages/kilo-docs/pages/customize/custom-modes.md +++ b/packages/kilo-docs/pages/customize/custom-modes.md @@ -5,7 +5,11 @@ description: "Create and configure custom modes in Kilo Code" # Custom Modes -Kilo Code allows you to create **custom modes** to tailor Kilo's behavior to specific tasks or workflows. Custom modes can be either **global** (available across all projects) or **project-specific** (defined within a single project). +Kilo Code allows you to create **custom modes** (also called **agents**) to tailor Kilo's behavior to specific tasks or workflows. Custom modes can be either **global** (available across all projects) or **project-specific** (defined within a single project). + +{% callout type="info" %} +The current VS Code extension (built on the Kilo CLI) uses **agent Markdown files** to define custom modes. The legacy extension used `custom_modes.yaml` / `.kilocodemodes`. See the tabs below for the relevant approach. +{% /callout %} ## Sticky Models for Efficient Workflow @@ -89,10 +93,56 @@ When importing modes, you can change the slug in the exported YAML file before i ## Methods for Creating and Configuring Custom Modes +{% tabs %} +{% tab label="VSCode" %} + +Custom agents are defined as Markdown files with optional YAML frontmatter. You can place them in: + +- **Project agents:** `.kilo/agents/*.md` (or `.opencode/agents/*.md`) +- **Global agents:** `~/.config/kilo/agents/*.md` + +### Agent File Format + +```markdown +--- +model: anthropic/claude-3-5-sonnet-20241022 +description: A specialized agent for writing documentation +mode: primary +--- + +You are a technical writer specializing in clear, concise documentation. +Focus on clarity, completeness, and consistent formatting. +``` + +**YAML frontmatter fields:** + +| Field | Description | +| ------------- | ----------------------------------------------------------------------------- | +| `model` | Override the default model for this agent | +| `description` | Short description shown in the agent selector | +| `mode` | `"primary"` (user-selectable), `"subagent"` (invoked by AI only), or `"all"` | +| `permission` | Tool permission overrides (same format as the global `permission` config key) | +| `temperature` | Model temperature override | +| `top_p` | Model top_p override | + +The filename (without `.md`) becomes the agent's slug and display name. + +### Installing via Marketplace + +You can also install community-contributed agents from the **Marketplace** tab in the extension sidebar. + +### Ask Kilo! (Recommended) + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + You can create and configure custom modes in several ways: ### 1. Ask Kilo! (Recommended) +{% /tab %} +{% /tabs %} + You can quickly create a basic custom mode by asking Kilo Code to do it for you. For example: ``` @@ -117,7 +167,15 @@ _The custom mode creation interface showing fields for name, slug, description, The interface provides fields for Name, Slug, Description, Save Location, Role Definition, When to Use (optional), Available Tools, and Custom Instructions. After filling these, click the "Create Mode" button. Kilo Code will save the new mode in YAML format. -### 3. Manual Configuration (YAML & JSON) +### 3. Manual Configuration + +{% tabs %} +{% tab label="VSCode" %} + +Create or edit agent Markdown files directly in `.kilo/agents/` (project) or `~/.config/kilo/agents/` (global). See the file format above. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} You can directly edit the configuration files to create or modify custom modes. This method offers the most control over all properties. Kilo Code now supports both YAML (preferred) and JSON formats. @@ -125,6 +183,9 @@ You can directly edit the configuration files to create or modify custom modes. - **Project Modes:** Edit `.kilocodemodes` in your project root (YAML preferred; JSON still supported for compatibility). - **Open from UI:** Open the Modes area, click next to Global or Project Modes, then choose **Edit Global Modes** or **Edit Project Modes**. +{% /tab %} +{% /tabs %} + These files define an array/list of custom modes. {% callout type="info" title="Why JSON Files May Still Exist" %} diff --git a/packages/kilo-docs/pages/customize/custom-rules.md b/packages/kilo-docs/pages/customize/custom-rules.md index ccecb0528ec..f4d74f96a78 100644 --- a/packages/kilo-docs/pages/customize/custom-rules.md +++ b/packages/kilo-docs/pages/customize/custom-rules.md @@ -9,7 +9,7 @@ Custom rules provide a powerful way to define project-specific and global behavi ## Overview -Custom rules allow you to create text-based instructions that all AI models will follow when interacting with your project. These rules act as guardrails and conventions that are consistently respected across all interactions with your codebase. Rules can be managed through both the file system and the built-in UI interface. +Custom rules allow you to create text-based instructions that all AI models will follow when interacting with your project. These rules act as guardrails and conventions that are consistently respected across all interactions with your codebase. ## Rule Format @@ -19,20 +19,59 @@ Custom rules can be written in plain text, but Markdown format is recommended fo - Use lists (`-`, `*`) to enumerate specific items or constraints - Use code blocks (` `) to include code examples when needed -## Rule Types +## Rule Location and Setup -Kilo Code supports two types of custom rules: +{% tabs %} +{% tab label="VSCode" %} -- **Project Rules**: Apply only to the current project workspace -- **Global Rules**: Apply across all projects and workspaces +Rules (called "instructions" in the new extension) are Markdown files referenced in your config. You can point to any Markdown file — `AGENTS.md`, `CLAUDE.md`, `.kilo/rules.md`, or any path you choose. -{% callout type="note" title="UI Support" %} -The built-in rules management UI is available for general rules only. Mode-specific rules must be managed through the file system. +### Project Instructions + +Add an `instructions` array to your project config (`kilo.json` or `.kilo/kilo.jsonc`): + +```json +{ + "instructions": ["./AGENTS.md", "./.kilo/rules.md"] +} +``` + +### Global Instructions + +Add the same `instructions` key to your global config (`~/.config/kilo/opencode.json`): + +```json +{ + "instructions": ["~/.config/kilo/rules.md"] +} +``` + +### Managing Instructions through the UI + +You can also manage instructions from the Settings UI: + +1. Click the {% codicon name="gear" /%} icon in the sidebar toolbar to open Settings. +2. Click the `Agent Behaviour` tab. +3. Select the `Rules` sub-tab. +4. Add, edit, or remove instruction file paths from here. + +### File Structure Example + +``` +project/ +├── AGENTS.md # auto-detected by the agent +├── kilo.json # references rules files +├── .kilo/ +│ └── rules.md # project-specific rules +└── src/ +``` + +{% callout type="tip" title="Pro Tip: File-Based Team Standards" %} +Committing your rules Markdown files (e.g. `AGENTS.md` or `.kilo/rules.md`) to version control ensures consistent agent behavior across your entire development team. {% /callout %} -## Rule Location - -### Project Rules +{% /tab %} +{% tab label="VSCode (Legacy)" %} Custom rules are primarily loaded from the **`.kilocode/rules/` directory**. This is the recommended approach for organizing your project-specific rules. Each rule is typically placed in its own Markdown file with a descriptive name: @@ -59,7 +98,7 @@ Global rules are stored in your home directory and apply to all projects: │ └── documentation_style.md ``` -## Managing Rules Through the UI +### Managing Rules Through the UI Kilo Code provides a built-in interface for managing your custom rules without manually editing files in the `.kilocode/rules/` directories. To access the UI, click on the icon in the **bottom right corner** of the Kilo Code window. @@ -70,9 +109,27 @@ You can access the rules management UI to: - Create and edit rules directly in the interface - Organize rules by category and priority +{% /tab %} +{% /tabs %} + +## Rule Types + +Kilo Code supports two types of custom rules: + +- **Project Rules**: Apply only to the current project workspace +- **Global Rules**: Apply across all projects and workspaces + ## Rule Loading Order -### General Rules (Any Mode) +{% tabs %} +{% tab label="VSCode" %} + +Instructions are loaded in the order specified in the `instructions` array in the config. The config precedence system applies (project config overrides global config). + +Files listed in `AGENTS.md`, `.kilo/AGENTS.md`, or `.opencode/AGENTS.md` at the project root are automatically detected without needing to list them explicitly. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} Rules are loaded in the following priority order: @@ -99,8 +156,23 @@ Additionally, the system supports mode-specific rules, which are loaded separate Currently, mode-specific rules are only supported at the project level. When both generic rules and mode-specific rules exist, the mode-specific rules are given priority in the final output. +{% /tab %} +{% /tabs %} + ## Creating Custom Rules +{% tabs %} +{% tab label="VSCode" %} + +1. Create a Markdown file (e.g. `.kilo/rules.md`) in your project +2. Add it to your `instructions` array in `kilo.json` or `.kilo/kilo.jsonc` +3. Write your rules using Markdown formatting + +Rules are applied automatically on the next session start. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + ### Using the UI Interface {% image src="/docs/img/custom-rules/rules-ui.png" alt="Rules tab in Kilo Code" width="400" /%} @@ -132,6 +204,9 @@ To create rules manually: Rules will be automatically applied to all future Kilo Code interactions. Any new changes will be applied immediately. +{% /tab %} +{% /tabs %} + ## Example Rules ### Example 1: Table Formatting @@ -192,10 +267,6 @@ Custom rules can be applied to a wide variety of scenarios: - **Keep It Simple**: Rules should be concise and easy to understand - **Update Regularly**: Review and update rules as project requirements change -{% callout type="tip" title="Pro Tip: File-Based Team Standards" %} -When working in team environments, placing `.kilocode/rules/codestyle.md` files under version control allows you to standardize Kilo's behavior across your entire development team. This ensures consistent code style, documentation practices, and development workflows for everyone on the project. -{% /callout %} - ## Limitations - Rules are applied on a best-effort basis by the AI models @@ -205,6 +276,18 @@ When working in team environments, placing `.kilocode/rules/codestyle.md` files ## Troubleshooting +{% tabs %} +{% tab label="VSCode" %} + +If your rules aren't being followed: + +1. **Check the `instructions` array** in your config to ensure the file path is correct. +2. **Verify Markdown formatting**: Ensure the file is valid Markdown. +3. **Restart the session**: Start a new chat session to pick up config changes. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + If your custom rules aren't being properly followed: 1. **Check rule status in the UI**: Use the rules management interface to verify that your rules are active and properly loaded @@ -216,6 +299,9 @@ If your custom rules aren't being properly followed: 1. **Rule specificity**: Verify that the rules are specific and unambiguous 1. **Restart VS Code**: Restart VS Code to ensure the rules are properly loaded +{% /tab %} +{% /tabs %} + ## Related Features - [Custom Modes](/docs/customize/custom-modes) diff --git a/packages/kilo-docs/pages/customize/workflows.md b/packages/kilo-docs/pages/customize/workflows.md index 302891b32a4..c5a64f2bf0d 100644 --- a/packages/kilo-docs/pages/customize/workflows.md +++ b/packages/kilo-docs/pages/customize/workflows.md @@ -5,12 +5,59 @@ description: "Create automated workflows with Kilo Code" # Workflows -Workflows automate repetitive tasks by defining step-by-step instructions for Kilo Code to execute. Invoke any workflow by typing `/[workflow-name.md]` in the chat. +Workflows (also called **slash commands** in the new extension) automate repetitive tasks by defining step-by-step instructions for Kilo Code to execute. {% image src="/docs/img/slash-commands/workflows.png" alt="Workflows tab in Kilo Code" width="600" caption="Workflows tab in Kilo Code" /%} ## Creating Workflows +{% tabs %} +{% tab label="VSCode" %} + +Workflows are Markdown files stored as **slash commands** in `.kilo/commands/`: + +- **Global commands**: `~/.config/kilo/commands/` (available in all projects) +- **Project commands**: `[project]/.kilo/commands/` (project-specific) + +### Basic Setup + +1. Create a `.md` file with step-by-step instructions +2. Save it in your commands directory +3. Type `/command-name` in the chat (just the filename without `.md` extension) to execute + +For example, a file at `.kilo/commands/submit-pr.md` is invoked with `/submit-pr`. + +### Optional Frontmatter + +Command files can include YAML frontmatter: + +```markdown +--- +description: Submit a pull request with checks +agent: code +--- + +You are helping submit a pull request... +``` + +| Field | Description | +| ------------- | --------------------------------------------- | +| `description` | Shown in the command picker | +| `agent` | Which agent to use when invoking this command | +| `model` | Model override for this command | +| `subtask` | When `true`, runs as a sub-agent session | + +### Workflow Capabilities + +Workflows can leverage all built-in tools: `read`, `glob`, `grep`, `edit`, `write`, `bash`, `webfetch`, and MCP server tools. + +### Migration from Legacy Workflows + +The new extension automatically migrates legacy workflows from `.kilocode/workflows/` to the new command format on startup. You can also manually move files and remove the `.md` extension from invocations. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + Workflows are markdown files stored in `.kilocode/workflows/`: - **Global workflows**: `~/.kilocode/workflows/` (available in all projects) @@ -31,6 +78,9 @@ Workflows can leverage: - [MCP integrations](/docs/automate/mcp/overview): Slack, databases, APIs - [Agent switching](/docs/code-with-ai/agents/using-agents): [`new_task()`](/docs/automate/tools/new-task) for specialized contexts +{% /tab %} +{% /tabs %} + ## Common Workflow Patterns **Release Management** @@ -64,7 +114,38 @@ Workflows can leverage: ## Example: PR Submission Workflow -Let's walk through creating a workflow for submitting a pull request. This workflow handles the entire process from code review to deployment notification. +Let's walk through creating a workflow for submitting a pull request. + +{% tabs %} +{% tab label="VSCode" %} + +Create a file called `submit-pr.md` in your `.kilo/commands` directory: + +```markdown +--- +description: Submit a pull request with full checks +--- + +# Submit PR Workflow + +You are helping submit a pull request. Follow these steps: + +1. First, use `grep` to check for any TODO comments or console.log statements that shouldn't be committed +2. Run tests using `bash` with `npm test` or the appropriate test command +3. If tests pass, stage and commit changes with a descriptive commit message +4. Push the branch and create a pull request using `bash` with `gh pr create` +5. Use `question` to get the PR title and description from the user + +Parameters needed (ask if not provided): + +- Branch name +- Reviewers to assign +``` + +Trigger this workflow by typing `/submit-pr` in the chat. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} Create a file called `submit-pr.md` in your `.kilocode/workflows` directory: @@ -85,12 +166,16 @@ Parameters needed (ask if not provided): - Reviewers to assign ``` -Now you can trigger this workflow by typing `/submit-pr.md` in the chat. Kilo Code will: +Trigger this workflow by typing `/submit-pr.md` in the chat. + +{% /tab %} +{% /tabs %} + +Kilo Code will: - Scan your code for common issues before committing - Run your test suite to catch problems early - Handle the Git operations and PR creation -- Notify your team automatically - Set up follow-up tasks for deployment -This saves you from manually running the same 7-step process every time you want to submit code for review. +This saves you from manually running the same steps every time you want to submit code for review. diff --git a/packages/kilo-docs/pages/getting-started/settings/index.md b/packages/kilo-docs/pages/getting-started/settings/index.md index 00e1cc30a2a..97e7045ee29 100644 --- a/packages/kilo-docs/pages/getting-started/settings/index.md +++ b/packages/kilo-docs/pages/getting-started/settings/index.md @@ -140,7 +140,30 @@ Use this option only if you are certain you want to remove all Kilo Code data or {% tabs %} {% tab label="VSCode" %} -The extension does not currently expose the same experimental feature toggles as the **VSCode (Legacy)** version. Advanced options are configured via the JSONC config files that the Settings webview reads and writes. Refer to the auto-generated `$schema` in your `kilo.jsonc` for the full list of available options. +The new extension exposes experimental features via the **Experimental** tab in Settings (click the gear icon {% codicon name="gear" /%} → Experimental). + +Available experimental toggles include: + +- **Share mode** — `manual`, `auto`, or `disabled` session sharing +- **LSP integration** — expose language server diagnostics to the agent +- **Paste summary** — summarize large clipboard pastes before including them +- **Batch tool** — allow the agent to batch multiple tool calls in one step +- **Codebase search** — semantic search across your codebase + +Advanced options not exposed in the UI can be configured via the `experimental` key in `kilo.jsonc`: + +```json +{ + "experimental": { + "codebase_search": true, + "batch_tool": false, + "disable_paste_summary": false, + "mcp_timeout": 30000 + } +} +``` + +Refer to the auto-generated `$schema` in your `kilo.jsonc` for the full list of available options. {% /tab %} {% tab label="CLI" %} From df4a0bd9cfb0654e249b9f504a96e2115a113118 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:24:26 +0000 Subject: [PATCH 156/261] docs: document default tool permissions and remove Cmd+Alt+A shortcut mention --- .../pages/automate/how-tools-work.md | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/packages/kilo-docs/pages/automate/how-tools-work.md b/packages/kilo-docs/pages/automate/how-tools-work.md index 6cc0d01be56..5086fdb075d 100644 --- a/packages/kilo-docs/pages/automate/how-tools-work.md +++ b/packages/kilo-docs/pages/automate/how-tools-work.md @@ -97,13 +97,41 @@ greet('World'); {% tabs %} {% tab label="VSCode" %} -Every tool use requires your explicit approval via the **Permission Dock** floating UI in the chat panel. For each tool call you can: +Every tool use is subject to a permission check. The default action for any tool with no matching rule in your config is **`ask`** — meaning Kilo will pause and prompt you before executing it. -- **Approve** — execute the tool once -- **Approve Always** — add this tool/pattern to your config so future calls are auto-approved -- **Deny** — decline the proposed tool call +**Default permissions by tool:** -You can also toggle **Auto-approve** for all tools for the current session using `Ctrl+Alt+A` / `Cmd+Alt+A`. +| Tool(s) | Default | +| :------------------------------------------- | :----------------------------------------------- | +| `read`, `glob`, `grep`, `list` | `ask` | +| `edit`, `write`, `multiedit`, `apply_patch` | `ask` | +| `bash` | `ask` (per-command) | +| `external_directory` | `ask` (when accessing paths outside the project) | +| `task` | `ask` | +| `webfetch`, `websearch`, `codesearch` | `ask` | +| `todowrite`, `todoread`, `question`, `skill` | `ask` | + +No tools are auto-approved out of the box. You must explicitly grant `allow` in your config, or approve them at runtime. + +**At runtime**, the **Permission Dock** floating UI in the chat panel shows each pending approval. For each tool call you can: + +- **Approve once** — execute this call only +- **Approve always** — save an `allow` rule to your config so future matching calls are auto-approved +- **Deny** — cancel the tool call + +To pre-configure permissions in your config file: + +```json +{ + "permission": { + "read": "allow", + "glob": "allow", + "grep": "allow", + "edit": "ask", + "bash": "ask" + } +} +``` This safety mechanism ensures you maintain control over which files are modified, what commands are executed, and how your codebase is changed. From 01b04a3d965d364f2c5debc5f2f7a7559a905e36 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:30:48 +0000 Subject: [PATCH 157/261] docs: fix tools overview and MCP page for new extension - tools/index: add browser group with kilo-playwright_* tool names - tools/index: add Browser Tools section documenting Playwright MCP tools - mcp/using-in-kilo-code: reference kilo.jsonc only, not opencode.json - mcp/using-in-kilo-code: fix auto-approve section to use correct MCP permission keys ({server}_{tool} pattern), not bash permissions --- .../pages/automate/mcp/using-in-kilo-code.md | 17 ++++++++++------- .../kilo-docs/pages/automate/tools/index.md | 13 +++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md b/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md index 219fc8cc364..bd216a894e1 100644 --- a/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md +++ b/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md @@ -16,8 +16,8 @@ Model Context Protocol (MCP) extends Kilo Code's capabilities by connecting to e MCP server configurations are stored inside the main Kilo config file. There are two levels: -1. **Global Configuration**: `~/.config/kilo/opencode.json` — applies to all projects. -2. **Project-level Configuration**: `kilo.json` or `.kilo/kilo.jsonc` in your project root. +1. **Global Configuration**: `~/.config/kilo/kilo.jsonc` — applies to all projects. +2. **Project-level Configuration**: `kilo.jsonc` in your project root, or `.kilo/kilo.jsonc` for a cleaner setup. **Precedence**: Project-level configuration takes precedence over global configuration. @@ -33,7 +33,7 @@ From here you can add, edit, enable/disable, and delete MCP servers. Changes are ### Config Format -MCP servers are configured under the `mcp` key in `opencode.json` / `kilo.jsonc`: +MCP servers are configured under the `mcp` key in `kilo.jsonc`: **Local (STDIO) server:** @@ -282,18 +282,21 @@ To set the maximum time to wait for a response after a tool call to the MCP serv {% tabs %} {% tab label="VSCode" %} -Tool permissions in the new extension are managed through the permission system. In your config file, set a tool's permission to `"allow"` to auto-approve it: +MCP tool calls use the same permission system as built-in tools. Each MCP tool's permission key is its namespaced name: `{server}_{tool}` (e.g. `my_server_do_something`). + +**At runtime:** When an MCP tool is called, the Permission Dock shows an approval prompt. Click **Approve Always** to save an allow rule to your config so future calls to that tool are auto-approved. + +**In your config file:** Add the tool name (or a wildcard pattern) to the `permission` key in `kilo.jsonc`: ```json { "permission": { - "bash": "allow" + "my_server_do_something": "allow", + "my_server_*": "allow" } } ``` -You can also approve individual MCP tool calls as "always allow" directly from the Permission Dock in the chat UI. - {% /tab %} {% tab label="VSCode (Legacy)" %} diff --git a/packages/kilo-docs/pages/automate/tools/index.md b/packages/kilo-docs/pages/automate/tools/index.md index 4a441515cc9..9949a96321d 100644 --- a/packages/kilo-docs/pages/automate/tools/index.md +++ b/packages/kilo-docs/pages/automate/tools/index.md @@ -22,6 +22,7 @@ Tools are organized into logical groups based on their functionality: | **Edit Group** | File system modifications | `edit`, `multiedit`, `write`, `apply_patch` | Code changes and file manipulation | | **Execute Group** | Shell command execution | `bash` | Running scripts, building projects | | **Web Group** | Fetch and search web content | `webfetch`, `websearch`, `codesearch` | Research, documentation lookup | +| **Browser Group** | Web browser automation | `kilo-playwright_*` (via built-in Playwright MCP) | Browser testing and interaction | | **MCP Group** | External tool integration | MCP server tools (namespaced as `{server}_{tool}`) | Specialized functionality via MCP | | **Workflow Group** | Sub-agents and task management | `question`, `task`, `todowrite`, `todoread`, `plan`, `skill` | Context switching and task organization | @@ -66,6 +67,18 @@ These tools help Kilo Code access web content: - `websearch` - Searches the web (available to Kilo/OpenRouter users) - `codesearch` - Semantic code search (available to Kilo/OpenRouter users) +### Browser Tools + +The VS Code extension has a built-in browser automation tool powered by [Playwright MCP](https://www.npmjs.com/package/@playwright/mcp). Enable it in Settings → Browser Automation. When enabled, it registers an MCP server named `kilo-playwright` and exposes tools such as: + +- `kilo-playwright_browser_navigate` - Navigate to a URL +- `kilo-playwright_browser_click` - Click an element +- `kilo-playwright_browser_type` - Type text into an element +- `kilo-playwright_browser_screenshot` - Capture a screenshot +- `kilo-playwright_browser_snapshot` - Capture an accessibility snapshot + +These follow the same permission model as all MCP tools (see below). + ### MCP Tools MCP server tools are automatically available when an MCP server is connected. Tool names are namespaced as `{server}_{tool}`. See [MCP Overview](/docs/automate/mcp/overview) for details. From f0a9742c8b22432ff24f16c91db34f27a7275ddc Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:34:11 +0000 Subject: [PATCH 158/261] docs: fix custom-modes tab structure - move all legacy YAML content into Legacy tab --- .../kilo-docs/pages/customize/custom-modes.md | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/kilo-docs/pages/customize/custom-modes.md b/packages/kilo-docs/pages/customize/custom-modes.md index 0b15fc87b12..871917b9ec9 100644 --- a/packages/kilo-docs/pages/customize/custom-modes.md +++ b/packages/kilo-docs/pages/customize/custom-modes.md @@ -133,6 +133,14 @@ You can also install community-contributed agents from the **Marketplace** tab i ### Ask Kilo! (Recommended) +You can also have Kilo create an agent file for you. For example: + +``` +Create a new agent called "Documentation Writer". It should only be able to read files and write Markdown files. +``` + +Kilo will create the appropriate `.kilo/agents/docs-writer.md` file with the right frontmatter. + {% /tab %} {% tab label="VSCode (Legacy)" %} @@ -140,9 +148,6 @@ You can create and configure custom modes in several ways: ### 1. Ask Kilo! (Recommended) -{% /tab %} -{% /tabs %} - You can quickly create a basic custom mode by asking Kilo Code to do it for you. For example: ``` @@ -167,15 +172,7 @@ _The custom mode creation interface showing fields for name, slug, description, The interface provides fields for Name, Slug, Description, Save Location, Role Definition, When to Use (optional), Available Tools, and Custom Instructions. After filling these, click the "Create Mode" button. Kilo Code will save the new mode in YAML format. -### 3. Manual Configuration - -{% tabs %} -{% tab label="VSCode" %} - -Create or edit agent Markdown files directly in `.kilo/agents/` (project) or `~/.config/kilo/agents/` (global). See the file format above. - -{% /tab %} -{% tab label="VSCode (Legacy)" %} +### 3. Manual Configuration (YAML & JSON) You can directly edit the configuration files to create or modify custom modes. This method offers the most control over all properties. Kilo Code now supports both YAML (preferred) and JSON formats. @@ -183,9 +180,6 @@ You can directly edit the configuration files to create or modify custom modes. - **Project Modes:** Edit `.kilocodemodes` in your project root (YAML preferred; JSON still supported for compatibility). - **Open from UI:** Open the Modes area, click next to Global or Project Modes, then choose **Edit Global Modes** or **Edit Project Modes**. -{% /tab %} -{% /tabs %} - These files define an array/list of custom modes. {% callout type="info" title="Why JSON Files May Still Exist" %} @@ -575,6 +569,9 @@ customModes: - **Hyphens for List Items:** List items start with a hyphen and a space (e.g., `- read`) - **Validate Your YAML:** Use online YAML validators or your editor's built-in validation +{% /tab %} +{% /tabs %} + ## Community Gallery Ready to explore more? Check out the [Show and Tell](https://github.com/Kilo-Org/kilocode/discussions/categories/show-and-tell) to discover and share custom modes created by the community! From 23c7d053f289cbe7f5f27af3b497f382e02e83ca Mon Sep 17 00:00:00 2001 From: Evgeny Shurakov Date: Mon, 30 Mar 2026 16:39:33 +0200 Subject: [PATCH 159/261] feat(cli): add WebSocket activity watchdog with heartbeat_ack support Add an inactivity watchdog to RemoteWS that force-closes and reconnects the WebSocket when no inbound messages arrive within a configurable timeout window (default 30s). Introduce a heartbeat_ack inbound message type so the server can respond to heartbeat pings, resetting the activity timer. --- .../src/kilo-sessions/remote-protocol.ts | 7 +- .../opencode/src/kilo-sessions/remote-ws.ts | 30 +++++++ .../kilo-sessions/remote-protocol.test.ts | 18 +++++ .../test/kilo-sessions/remote-ws.test.ts | 80 +++++++++++++++++++ 4 files changed, 134 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/kilo-sessions/remote-protocol.ts b/packages/opencode/src/kilo-sessions/remote-protocol.ts index ed8e19348e5..6500319fa81 100644 --- a/packages/opencode/src/kilo-sessions/remote-protocol.ts +++ b/packages/opencode/src/kilo-sessions/remote-protocol.ts @@ -71,7 +71,12 @@ export namespace RemoteProtocol { }) export type System = z.infer - export const Inbound = z.discriminatedUnion("type", [Subscribe, Unsubscribe, Command, System]) + export const HeartbeatAck = z.object({ + type: z.literal("heartbeat_ack"), + }) + export type HeartbeatAck = z.infer + + export const Inbound = z.discriminatedUnion("type", [Subscribe, Unsubscribe, Command, System, HeartbeatAck]) export type Inbound = z.infer /** Lightweight schema for diagnostic logging before full parse. */ diff --git a/packages/opencode/src/kilo-sessions/remote-ws.ts b/packages/opencode/src/kilo-sessions/remote-ws.ts index 88a1f2f36db..0232ec27785 100644 --- a/packages/opencode/src/kilo-sessions/remote-ws.ts +++ b/packages/opencode/src/kilo-sessions/remote-ws.ts @@ -18,6 +18,8 @@ export namespace RemoteWS { withContext?: (fn: () => R) => Promise | R /** Called when the server permanently closes the connection (e.g. auth failure, conflict) */ onClose?: (code: number, reason: string) => void + /** Inactivity timeout in ms — force-close if no inbound message within this window */ + timeout?: number } export type Connection = { @@ -56,6 +58,29 @@ export namespace RemoteWS { beat = undefined } + let activity = Date.now() + let watchdog: Timer | undefined + const timeout = options.timeout ?? 30_000 + + function startWatchdog() { + stopWatchdog() + watchdog = setInterval( + () => { + if (Date.now() - activity > timeout) { + options.log.warn("remote-ws activity timeout, forcing reconnect") + stopWatchdog() + ws?.close(4000, "activity timeout") + } + }, + Math.min(interval, timeout), + ) + } + + function stopWatchdog() { + if (watchdog) clearInterval(watchdog) + watchdog = undefined + } + async function open() { if (closed) return const token = await options.getToken() @@ -73,10 +98,13 @@ export namespace RemoteWS { backoff = 1000 for (const msg of buffer) ws!.send(msg) buffer.length = 0 + activity = Date.now() startHeartbeat() + startWatchdog() } ws.onmessage = (event) => { + activity = Date.now() const raw = String(event.data) let json: unknown try { @@ -99,6 +127,7 @@ export namespace RemoteWS { options.log.info("remote-ws closed", { code: event.code, reason: event.reason }) ws = undefined stopHeartbeat() + stopWatchdog() if (event.code === 4401 || event.code === 4403 || event.code === 4409) { options.log.warn("remote-ws closed permanently", { code: event.code, @@ -134,6 +163,7 @@ export namespace RemoteWS { function close() { closed = true stopHeartbeat() + stopWatchdog() if (timer) clearTimeout(timer) if (ws) ws.close() } diff --git a/packages/opencode/test/kilo-sessions/remote-protocol.test.ts b/packages/opencode/test/kilo-sessions/remote-protocol.test.ts index f61f3f40886..354662dae5e 100644 --- a/packages/opencode/test/kilo-sessions/remote-protocol.test.ts +++ b/packages/opencode/test/kilo-sessions/remote-protocol.test.ts @@ -237,4 +237,22 @@ describe("RemoteProtocol", () => { const result = RemoteProtocol.SessionInfo.safeParse({ id: "x" }) expect(result.success).toBe(false) }) + + test("valid heartbeat_ack parses", () => { + const msg = { type: "heartbeat_ack" } + const result = RemoteProtocol.HeartbeatAck.safeParse(msg) + expect(result.success).toBe(true) + if (result.success) { + expect(result.data.type).toBe("heartbeat_ack") + } + }) + + test("inbound union picks heartbeat_ack", () => { + const msg = { type: "heartbeat_ack" } + const result = RemoteProtocol.Inbound.safeParse(msg) + expect(result.success).toBe(true) + if (result.success) { + expect(result.data.type).toBe("heartbeat_ack") + } + }) }) diff --git a/packages/opencode/test/kilo-sessions/remote-ws.test.ts b/packages/opencode/test/kilo-sessions/remote-ws.test.ts index f6c1a83cdf1..7fe6152b23a 100644 --- a/packages/opencode/test/kilo-sessions/remote-ws.test.ts +++ b/packages/opencode/test/kilo-sessions/remote-ws.test.ts @@ -284,4 +284,84 @@ describe("RemoteWS", () => { expect(server.clients.length).toBe(0) expect(server.messages.length).toBe(0) }) + + test("force-reconnects on activity timeout", async () => { + server = createServer() + const ws1 = server.waitForConnect() + + conn = RemoteWS.connect({ + url: server.url, + getToken: async () => "tok", + getSessions: () => [], + log: nolog(), + heartbeat: 60_000, + timeout: 200, + }) + + await ws1 + await settled() + expect(conn.connected).toBe(true) + + // Don't send any server messages — timeout should fire + const ws2 = server.waitForConnect() + await Bun.sleep(450) + + // Should have reconnected + await ws2 + await settled() + expect(conn.connected).toBe(true) + }) + + test("resets activity timer on incoming messages", async () => { + server = createServer() + const ws1p = server.waitForConnect() + + conn = RemoteWS.connect({ + url: server.url, + getToken: async () => "tok", + getSessions: () => [], + log: nolog(), + heartbeat: 60_000, + timeout: 300, + }) + + const ws1 = await ws1p + await settled() + + // Send server messages at 100ms intervals — each resets the timer + for (let i = 0; i < 4; i++) { + await Bun.sleep(100) + ws1.send(JSON.stringify({ type: "subscribe", sessionId: `s${i}` })) + } + + await settled() + // Connection should still be alive — activity kept resetting the timer + expect(conn.connected).toBe(true) + expect(server.clients.length).toBe(1) + }) + + test("activity timeout uses custom timeout option", async () => { + server = createServer() + const ws1 = server.waitForConnect() + + conn = RemoteWS.connect({ + url: server.url, + getToken: async () => "tok", + getSessions: () => [], + log: nolog(), + heartbeat: 60_000, + timeout: 100, + }) + + await ws1 + await settled() + + // With 100ms timeout, should reconnect faster than default 30s + const ws2 = server.waitForConnect() + await Bun.sleep(250) + + await ws2 + await settled() + expect(conn.connected).toBe(true) + }) }) From afcf766c9efce47ddc18fd80bc78bfc27877c05e Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:41:36 +0000 Subject: [PATCH 160/261] docs: replace opencode.json with kilo.jsonc in VS Code pages; fix custom-instructions nested tabs; remove codebase search from experimental --- .../code-with-ai/features/checkpoints.md | 2 +- .../pages/customize/custom-instructions.md | 23 +++++++------------ .../kilo-docs/pages/customize/custom-rules.md | 2 +- .../pages/getting-started/settings/index.md | 1 - 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md b/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md index ed6747482a7..67da805952d 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md +++ b/packages/kilo-docs/pages/code-with-ai/features/checkpoints.md @@ -19,7 +19,7 @@ Checkpoints let you: {% tabs %} {% tab label="VSCode" %} -Checkpoints (called **snapshots** in the new extension) are configured via the `snapshot` key in your config file (`kilo.json` or `~/.config/kilo/opencode.json`): +Checkpoints (called **snapshots** in the new extension) are configured via the `snapshot` key in your config file (`kilo.jsonc` or `~/.config/kilo/kilo.jsonc`): ```json { diff --git a/packages/kilo-docs/pages/customize/custom-instructions.md b/packages/kilo-docs/pages/customize/custom-instructions.md index a0b80d5b312..d5fcad5d9ae 100644 --- a/packages/kilo-docs/pages/customize/custom-instructions.md +++ b/packages/kilo-docs/pages/customize/custom-instructions.md @@ -22,7 +22,7 @@ Custom Instructions are IDE-wide and are applied across all workspaces and maint In the new extension, global and agent-specific instructions are managed through config files and agent Markdown files rather than a UI text area. -**Global instructions** (applied to all agents) — add an `instructions` array to your global config (`~/.config/kilo/opencode.json`): +**Global instructions** (applied to all agents) — add an `instructions` array to your global config (`~/.config/kilo/kilo.jsonc`): ```json { @@ -48,6 +48,12 @@ You can also manage instruction file references from: 2. Click `Agent Behaviour` → `Rules` sub-tab. 3. Add or remove instruction file paths. +### Agent-Specific Instructions + +Agent-specific instructions are written directly in the agent Markdown file body (`.kilo/agents/{agent-name}.md`). The file content after the YAML frontmatter is used as the agent's system prompt. + +For version-controlled per-agent instructions, simply commit the `.kilo/agents/` directory. + {% /tab %} {% tab label="VSCode (Legacy)" %} @@ -74,20 +80,7 @@ Mode-specific instructions can be set using the Modes Tab If the mode itself is global (not workspace-specific), any custom instructions you set for it will also apply globally for that mode across all workspaces. {% /callout %} -{% /tab %} -{% /tabs %} - -## Mode-Specific Instructions from Files - -{% tabs %} -{% tab label="VSCode" %} - -Agent-specific instructions are written directly in the agent Markdown file body (`.kilo/agents/{agent-name}.md`). The file content after the YAML frontmatter is used as the agent's system prompt. - -For version-controlled per-agent instructions, simply commit the `.kilo/agents/` directory. - -{% /tab %} -{% tab label="VSCode (Legacy)" %} +#### Mode-Specific Instructions from Files For version-controlled mode instructions, use the mode rules file paths documented in [Custom Modes](/docs/customize/custom-modes#mode-specific-instructions-via-filesdirectories): diff --git a/packages/kilo-docs/pages/customize/custom-rules.md b/packages/kilo-docs/pages/customize/custom-rules.md index f4d74f96a78..04c8da1841f 100644 --- a/packages/kilo-docs/pages/customize/custom-rules.md +++ b/packages/kilo-docs/pages/customize/custom-rules.md @@ -38,7 +38,7 @@ Add an `instructions` array to your project config (`kilo.json` or `.kilo/kilo.j ### Global Instructions -Add the same `instructions` key to your global config (`~/.config/kilo/opencode.json`): +Add the same `instructions` key to your global config (`~/.config/kilo/kilo.jsonc`): ```json { diff --git a/packages/kilo-docs/pages/getting-started/settings/index.md b/packages/kilo-docs/pages/getting-started/settings/index.md index 97e7045ee29..acd1bd43ff6 100644 --- a/packages/kilo-docs/pages/getting-started/settings/index.md +++ b/packages/kilo-docs/pages/getting-started/settings/index.md @@ -148,7 +148,6 @@ Available experimental toggles include: - **LSP integration** — expose language server diagnostics to the agent - **Paste summary** — summarize large clipboard pastes before including them - **Batch tool** — allow the agent to batch multiple tool calls in one step -- **Codebase search** — semantic search across your codebase Advanced options not exposed in the UI can be configured via the `experimental` key in `kilo.jsonc`: From 14438b993665bebaf7770591c423c72b908aa9e7 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Mon, 30 Mar 2026 18:01:12 +0300 Subject: [PATCH 161/261] fix(cli): use git branch --list instead of -l --- packages/opencode/src/agent/agent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 833aea650c5..7e33ab303d7 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -165,7 +165,7 @@ export namespace Agent { "git name-rev *": "allow", "git stash list *": "allow", "git tag -l *": "allow", - "git branch -l *": "allow", + "git branch --list *": "allow", "git branch -a *": "allow", "git branch -r *": "allow", "git remote -v *": "allow", From 455f4c23b45fb8872f03dbbf6e5772b9d5545305 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Mon, 30 Mar 2026 17:31:21 +0200 Subject: [PATCH 162/261] =?UTF-8?q?fix(vscode):=20address=20review=20comme?= =?UTF-8?q?nts=20=E2=80=94=20assign=20promise=20directly,=20remove=20stale?= =?UTF-8?q?=20pending=20requests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Assign promise directly in leading-edge PendingRequest instead of null! (addresses chrarnoldus's review comment) - Remove stale pending requests when clearTimeout cancels a debounce timer, preventing never-resolving promises from lingering in the list (addresses kilo-code-bot's WARNING about stale pending requests) - Clear pending state in dispose() for completeness --- .../AutocompleteInlineCompletionProvider.ts | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider.ts b/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider.ts index 3783decc361..93ef16b749e 100644 --- a/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider.ts +++ b/packages/kilo-vscode/src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider.ts @@ -126,6 +126,8 @@ export class AutocompleteInlineCompletionProvider implements vscode.InlineComple private recentlyVisitedRangesService: RecentlyVisitedRangesService private recentlyEditedTracker: RecentlyEditedTracker private debounceTimer: NodeJS.Timeout | null = null + /** The pending request associated with the current debounce timer (if any) */ + private debouncedPendingRequest: PendingRequest | null = null private isFirstCall: boolean = true private ignoreController: Promise /** Abort controller for the current in-flight FIM request */ @@ -297,6 +299,8 @@ export class AutocompleteInlineCompletionProvider implements vscode.InlineComple clearTimeout(this.debounceTimer) this.debounceTimer = null } + this.debouncedPendingRequest = null + this.pendingRequests.length = 0 this.fimAbortController?.abort() this.fimAbortController = null this.telemetry?.dispose() @@ -503,21 +507,22 @@ export class AutocompleteInlineCompletionProvider implements vscode.InlineComple // but still track it as a pending request so subsequent calls can reuse it if (this.isFirstCall && this.debounceTimer === null) { this.isFirstCall = false - const leading: PendingRequest = { - prefix, - suffix, - promise: null!, - } - leading.promise = this.fetchAndCacheSuggestion(prompt, prefix, suffix, languageId).finally(() => { - this.removePendingRequest(leading) - }) + const promise = this.fetchAndCacheSuggestion(prompt, prefix, suffix, languageId) + const leading: PendingRequest = { prefix, suffix, promise } + promise.finally(() => this.removePendingRequest(leading)) this.pendingRequests.push(leading) - return leading.promise + return promise } - // Clear any existing timer (reset the debounce) + // Clear any existing timer and remove the stale pending request it belongs to. + // The cancelled timer's callback will never fire, so the pending entry would + // otherwise linger with a never-resolving promise. if (this.debounceTimer !== null) { clearTimeout(this.debounceTimer) + if (this.debouncedPendingRequest) { + this.removePendingRequest(this.debouncedPendingRequest) + this.debouncedPendingRequest = null + } } // Create the pending request object first so we can reference it in the cleanup @@ -530,6 +535,7 @@ export class AutocompleteInlineCompletionProvider implements vscode.InlineComple const requestPromise = new Promise((resolve) => { this.debounceTimer = setTimeout(async () => { this.debounceTimer = null + this.debouncedPendingRequest = null this.isFirstCall = true // Reset for next sequence await this.fetchAndCacheSuggestion(prompt, prefix, suffix, languageId) // Remove this request from pending when done @@ -541,6 +547,9 @@ export class AutocompleteInlineCompletionProvider implements vscode.InlineComple // Complete the pending request object pendingRequest.promise = requestPromise + // Track so we can remove it if the timer is cleared by a subsequent call + this.debouncedPendingRequest = pendingRequest + // Add to the list of pending requests this.pendingRequests.push(pendingRequest) From 614d830e6f8db1ca0a9d4a8680c4ca33b0e5a250 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 15:35:01 +0000 Subject: [PATCH 163/261] docs: fix provider IDs and env vars in ai-provider pages --- packages/kilo-docs/pages/ai-providers/bedrock.md | 2 +- packages/kilo-docs/pages/ai-providers/chutes-ai.md | 2 +- packages/kilo-docs/pages/ai-providers/claude-code.md | 6 +++--- packages/kilo-docs/pages/ai-providers/fireworks.md | 6 +++--- packages/kilo-docs/pages/ai-providers/moonshot.md | 2 +- packages/kilo-docs/pages/ai-providers/vercel-ai-gateway.md | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/kilo-docs/pages/ai-providers/bedrock.md b/packages/kilo-docs/pages/ai-providers/bedrock.md index 457955576e5..64f4bb7aea2 100644 --- a/packages/kilo-docs/pages/ai-providers/bedrock.md +++ b/packages/kilo-docs/pages/ai-providers/bedrock.md @@ -91,7 +91,7 @@ Then set your default model: ```jsonc { - "model": "bedrock/anthropic.claude-sonnet-4-20250514-v1:0", + "model": "amazon-bedrock/anthropic.claude-sonnet-4-20250514-v1:0", } ``` diff --git a/packages/kilo-docs/pages/ai-providers/chutes-ai.md b/packages/kilo-docs/pages/ai-providers/chutes-ai.md index b72af388f2a..348b3b84feb 100644 --- a/packages/kilo-docs/pages/ai-providers/chutes-ai.md +++ b/packages/kilo-docs/pages/ai-providers/chutes-ai.md @@ -62,7 +62,7 @@ Then set your default model: ```jsonc { - "model": "chutes-ai/model-name", + "model": "chutes/model-name", } ``` diff --git a/packages/kilo-docs/pages/ai-providers/claude-code.md b/packages/kilo-docs/pages/ai-providers/claude-code.md index 699a4af7f95..239e3d779ca 100644 --- a/packages/kilo-docs/pages/ai-providers/claude-code.md +++ b/packages/kilo-docs/pages/ai-providers/claude-code.md @@ -45,9 +45,9 @@ The specific models available depend on your Claude subscription and plan. See [ {% /tab %} {% tab label="VSCode" %} -Open **Settings** (gear icon) and go to the **Providers** tab. Claude Code uses your existing Anthropic credentials from the `claude` CLI — make sure it is installed and authenticated before adding the provider. - -The extension stores this in your `kilo.json` config file. You can also edit the config file directly — see the **CLI** tab for the file format. +{% callout type="warning" %} +Claude Code credentials no longer work in Kilo Code. Please use the [Anthropic provider](/docs/ai-providers/anthropic) with an API key instead. +{% /callout %} {% /tab %} {% tab label="CLI" %} diff --git a/packages/kilo-docs/pages/ai-providers/fireworks.md b/packages/kilo-docs/pages/ai-providers/fireworks.md index 18f08ad7911..f354b533760 100644 --- a/packages/kilo-docs/pages/ai-providers/fireworks.md +++ b/packages/kilo-docs/pages/ai-providers/fireworks.md @@ -40,7 +40,7 @@ Set the API key as an environment variable or configure it in your `kilo.json` c **Environment variable:** ```bash -export FIREWORKS_AI_API_KEY="your-api-key" +export FIREWORKS_API_KEY="your-api-key" ``` **Config file** (`~/.config/kilo/kilo.json` or `./kilo.json`): @@ -49,7 +49,7 @@ export FIREWORKS_AI_API_KEY="your-api-key" { "provider": { "fireworks-ai": { - "env": ["FIREWORKS_AI_API_KEY"], + "env": ["FIREWORKS_API_KEY"], }, }, } @@ -59,7 +59,7 @@ Then set your default model: ```jsonc { - "model": "fireworks/accounts/fireworks/models/llama4-scout-instruct-basic", + "model": "fireworks-ai/accounts/fireworks/models/llama4-scout-instruct-basic", } ``` diff --git a/packages/kilo-docs/pages/ai-providers/moonshot.md b/packages/kilo-docs/pages/ai-providers/moonshot.md index c1b97cfe8d6..7b92cf10287 100644 --- a/packages/kilo-docs/pages/ai-providers/moonshot.md +++ b/packages/kilo-docs/pages/ai-providers/moonshot.md @@ -59,7 +59,7 @@ Then set your default model: ```jsonc { - "model": "moonshot/moonshot-v1-auto", + "model": "moonshotai/moonshot-v1-auto", } ``` diff --git a/packages/kilo-docs/pages/ai-providers/vercel-ai-gateway.md b/packages/kilo-docs/pages/ai-providers/vercel-ai-gateway.md index aba308e59e3..bbfd9ccf991 100644 --- a/packages/kilo-docs/pages/ai-providers/vercel-ai-gateway.md +++ b/packages/kilo-docs/pages/ai-providers/vercel-ai-gateway.md @@ -96,7 +96,7 @@ Then set your default model: ```jsonc { - "model": "vercel-ai-gateway/anthropic/claude-sonnet-4", + "model": "vercel/anthropic/claude-sonnet-4", } ``` From 0ac666b17415ea4b54ee581f7d3a0fc231946eb6 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:00:30 +0000 Subject: [PATCH 164/261] docs(code-with-ai): move autocomplete note from VSCode tab to CLI tab adjusts the extension-only autocomplete note for CLI/TUI availability moves the info from the VSCode tab to the CLI tab for consistency --- .../pages/code-with-ai/features/autocomplete/index.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md b/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md index be5a983a472..6fecef62164 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md +++ b/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md @@ -10,10 +10,6 @@ Kilo Code's autocomplete feature provides intelligent code suggestions and compl {% tabs %} {% tab label="VSCode" %} -{% callout type="info" %} -Autocomplete is an **extension-only** feature. It is not available in the CLI/TUI. -{% /callout %} - ## How Autocomplete Works The extension uses **Fill-in-the-Middle (FIM)** completion powered by Codestral (`mistralai/codestral-2508`). It analyzes the code before and after your cursor to generate contextually accurate inline suggestions. @@ -47,6 +43,13 @@ You can temporarily disable autocomplete by clicking the status bar item to **sn The extension automatically detects if **GitHub Copilot** inline suggestions are enabled and warns you about potential conflicts. Disable Copilot's inline completions for the best experience with Kilo Code autocomplete. +{% /tab %} +{% tab label="CLI" %} + +{% callout type="info" %} +Autocomplete is an **extension-only** feature. It is not available in the CLI/TUI. +{% /callout %} + {% /tab %} {% tab label="VSCode (Legacy)" %} From 3d0f851809f270fa1be204526a8e6b7e0753ac6b Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:03:39 +0000 Subject: [PATCH 165/261] wip --- .../code-with-ai/features/browser-use.md | 32 +++---------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/features/browser-use.md b/packages/kilo-docs/pages/code-with-ai/features/browser-use.md index a8c2a979a8a..b5889112898 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/browser-use.md +++ b/packages/kilo-docs/pages/code-with-ai/features/browser-use.md @@ -27,20 +27,7 @@ Browser automation is auto-configured in the extension: {% /tab %} {% tab label="CLI" %} -Kilo Code uses [Playwright](https://playwright.dev/) via MCP (`@playwright/mcp@latest`) for browser automation. Add the MCP server to your `kilo.jsonc` configuration: - -```json -{ - "mcp": { - "playwright": { - "type": "local", - "command": ["npx", "-y", "@playwright/mcp@latest"] - } - } -} -``` - -Playwright downloads Chromium automatically on first use. +Browser automation is built into Kilo and requires no manual setup. Enable it from **Settings → Browser** and Kilo handles the rest automatically. {% /tab %} {% tab label="VSCode (Legacy)" %} @@ -162,20 +149,11 @@ Browser automation settings are available under **Settings → Browser**: {% /tab %} {% tab label="CLI" %} -Browser automation requires manual MCP configuration in your `kilo.jsonc` file: +Browser automation settings are available under **Settings → Browser**: -```json -{ - "mcp": { - "playwright": { - "type": "local", - "command": ["npx", "-y", "@playwright/mcp@latest"] - } - } -} -``` - -No additional settings are needed — the Playwright MCP server manages the browser lifecycle automatically. Chromium is downloaded on first use. +- **Enable browser automation**: Toggle to enable or disable browser automation +- **Headless mode**: Run the browser without a visible window (default: disabled) +- **Use system Chrome**: Use your installed Chrome instead of the bundled browser {% /tab %} {% tab label="VSCode (Legacy)" %} From 36a6b3f309fcb9a91c9c0e63c4bb19911f9ddf9b Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:05:43 +0000 Subject: [PATCH 166/261] docs(code-with-ai): update browser-use docs to describe built-in browser automation rewrite VSCode tab to describe built-in browser automation remove Playwright MCP references and auto-download details update CLI tab to describe natural-language driven browser actions adjust key characteristics to generic terms: enable, headless, system Chrome --- .../code-with-ai/features/browser-use.md | 35 +++---------------- 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/features/browser-use.md b/packages/kilo-docs/pages/code-with-ai/features/browser-use.md index b5889112898..077278a66bb 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/browser-use.md +++ b/packages/kilo-docs/pages/code-with-ai/features/browser-use.md @@ -16,13 +16,7 @@ Browser Use requires an advanced agentic model. It is typically most reliable wi {% tabs %} {% tab label="VSCode" %} -Kilo Code uses [Playwright](https://playwright.dev/) via MCP (`@playwright/mcp@latest`) for browser automation. The Playwright MCP server is registered dynamically as `kilo-playwright`. - -Browser automation is auto-configured in the extension: - -- Toggle it on from **Settings → Browser** tab -- Configure `browserAutomation.headless` and `browserAutomation.useSystemChrome` settings -- Playwright auto-downloads Chromium on first use +Browser automation is built into the extension and requires no manual setup. Enable it from **Settings → Browser** and Kilo handles the rest automatically. {% /tab %} {% tab label="CLI" %} @@ -64,26 +58,7 @@ For example: {% tabs %} {% tab label="VSCode" %} -The Playwright MCP server provides a set of browser tools for interacting with web pages. These tools return screenshots and accessibility snapshots after each action. - -Key characteristics: - -- The browser launches automatically when a browser tool is invoked -- Multiple browser tools can be used in sequence -- Screenshots are captured after each action for visual feedback - -### Available Browser Tools - -| Tool | Description | When to Use | -| -------------------- | ----------------------------------- | ------------------------------------- | -| `browser_navigate` | Navigates to a URL | Opening a web page | -| `browser_click` | Clicks an element on the page | Interacting with buttons, links, etc. | -| `browser_type` | Types text into an input element | Filling forms, search boxes | -| `browser_screenshot` | Captures a screenshot of the page | Inspecting visual state | -| `browser_scroll` | Scrolls the page or a specific area | Viewing content above or below | -| `browser_hover` | Hovers over an element | Revealing tooltips or menus | -| `browser_select` | Selects an option from a dropdown | Choosing from select elements | -| `browser_drag` | Drags an element to a target | Drag-and-drop interactions | +Kilo launches a browser automatically when asked and returns screenshots after each action so you can see what's happening. It can navigate to URLs, click elements, fill in forms, scroll, hover, select from dropdowns, and drag and drop — all driven by natural language instructions in chat. {% /tab %} {% tab label="CLI" %} @@ -142,9 +117,9 @@ Key characteristics: Browser automation settings are available under **Settings → Browser**: -- **Enable browser automation**: Toggle to enable or disable Playwright browser automation -- **Headless mode** (`browserAutomation.headless`): Run the browser without a visible window (default: disabled) -- **Use system Chrome** (`browserAutomation.useSystemChrome`): Use your installed Chrome instead of the bundled Chromium +- **Enable browser automation**: Toggle to enable or disable browser automation +- **Headless mode**: Run the browser without a visible window (default: disabled) +- **Use system Chrome**: Use your installed Chrome instead of the bundled browser {% /tab %} {% tab label="CLI" %} From 87e2a583ed40630e11107cd3cefd965693cdddb8 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:07:08 +0000 Subject: [PATCH 167/261] docs(kilo-docs): fix inaccuracies flagged in PR review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix instruction load order: project instructions load before global - Fix setting key: 'config.instructions' → top-level 'instructions' in kilo.jsonc - Fix legacy mode-specific rule filename: .kilorules-{mode} → .kilocoderules-{mode}, clarify .clinerules-{mode} is not supported - Fix agent config precedence: project config (step 3) loads before global agent markdown files (step 4) - Fix watcher setting key: config.watcher.ignore → watcher.ignore (4 occurrences) --- .../pages/customize/context/kilocodeignore.md | 8 ++++---- .../kilo-docs/pages/customize/custom-instructions.md | 12 ++++++------ .../kilo-docs/pages/customize/custom-subagents.md | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/kilo-docs/pages/customize/context/kilocodeignore.md b/packages/kilo-docs/pages/customize/context/kilocodeignore.md index b956db3bfb2..25e979374c2 100644 --- a/packages/kilo-docs/pages/customize/context/kilocodeignore.md +++ b/packages/kilo-docs/pages/customize/context/kilocodeignore.md @@ -29,7 +29,7 @@ The primary mechanism for controlling file access is the **permission system** i If you have an existing `.kilocodeignore` file, it is still supported. The **IgnoreMigrator** automatically converts `.kilocodeignore` patterns into permission `deny` rules on `read` and `edit` tools, so your existing rules continue to work without manual changes. -You can also exclude paths from the file watcher separately using `config.watcher.ignore`: +You can also exclude paths from the file watcher separately using `watcher.ignore`: ```json { @@ -55,7 +55,7 @@ The primary mechanism for controlling file access is the **permission system** i If you have an existing `.kilocodeignore` file, it is still supported. The **IgnoreMigrator** automatically converts `.kilocodeignore` patterns into permission `deny` rules on `read` and `edit` tools, so your existing rules continue to work without manual changes. -You can also exclude paths from the file watcher separately using `config.watcher.ignore`: +You can also exclude paths from the file watcher separately using `watcher.ignore`: ```json { @@ -180,7 +180,7 @@ If you already have a `.kilocodeignore` file, you don't need to do anything — ### File Watcher Exclusions -The `config.watcher.ignore` setting controls which paths the file watcher skips. This is separate from tool permissions and only affects change detection: +The `watcher.ignore` setting controls which paths the file watcher skips. This is separate from tool permissions and only affects change detection: ```json { @@ -220,7 +220,7 @@ If you already have a `.kilocodeignore` file, you don't need to do anything — ### File Watcher Exclusions -The `config.watcher.ignore` setting controls which paths the file watcher skips. This is separate from tool permissions and only affects change detection: +The `watcher.ignore` setting controls which paths the file watcher skips. This is separate from tool permissions and only affects change detection: ```json { diff --git a/packages/kilo-docs/pages/customize/custom-instructions.md b/packages/kilo-docs/pages/customize/custom-instructions.md index 24c4e744326..c46dda3120e 100644 --- a/packages/kilo-docs/pages/customize/custom-instructions.md +++ b/packages/kilo-docs/pages/customize/custom-instructions.md @@ -44,7 +44,7 @@ For instructions that apply across all your projects, place an `AGENTS.md` file - **Kilo:** `~/.config/kilo/AGENTS.md` - **Claude-compatible:** `~/.claude/CLAUDE.md` -Global instructions are loaded before project-level instructions and apply to every session. +Project-level instructions are loaded before global instructions and apply to every session. ### Per-Directory Instructions @@ -54,7 +54,7 @@ This is useful for providing context-specific guidance for different parts of a ## Additional Instruction Sources -The `config.instructions` setting accepts an array of paths, globs, or URLs pointing to additional instruction files. You can manage these in **Settings → Agent Behaviour → Rules** subtab. +The `instructions` key in `kilo.jsonc` accepts an array of paths, globs, or URLs pointing to additional instruction files. You can manage these in **Settings → Agent Behaviour → Rules** subtab. ```yaml # Examples of instruction sources @@ -121,7 +121,7 @@ For instructions that apply across all your projects, place an `AGENTS.md` file - **Kilo:** `~/.config/kilo/AGENTS.md` - **Claude-compatible:** `~/.claude/CLAUDE.md` -Global instructions are loaded before project-level instructions and apply to every session. +Project-level instructions are loaded before global instructions and apply to every session. ### Per-Directory Instructions @@ -131,7 +131,7 @@ This is useful for providing context-specific guidance for different parts of a ## Additional Instruction Sources -The `config.instructions` setting accepts an array of paths, globs, or URLs pointing to additional instruction files. Configure these in your `kilo.jsonc`: +The `instructions` key in `kilo.jsonc` accepts an array of paths, globs, or URLs pointing to additional instruction files. Configure these in your `kilo.jsonc`: ```jsonc // kilo.jsonc @@ -190,10 +190,10 @@ If the mode itself is global (not workspace-specific), any custom instructions y For version-controlled mode instructions, use the mode rules file paths documented in [Custom Modes](/docs/customize/custom-modes#mode-specific-instructions-via-filesdirectories): - Preferred: `.kilo/rules-{mode-slug}/` (directory) -- Fallback: `.kilorules-{mode-slug}` (single file) +- Fallback: `.kilocoderules-{mode-slug}` (single file) {% callout type="info" title="Legacy Naming Note" %} -Older naming like `.clinerules-{mode-slug}` is not the recommended path for current Kilo mode-specific instructions. +Only `.kilocoderules-{mode-slug}` is recognized as the legacy fallback. Older naming like `.clinerules-{mode-slug}` is not supported. {% /callout %} {% /tab %} diff --git a/packages/kilo-docs/pages/customize/custom-subagents.md b/packages/kilo-docs/pages/customize/custom-subagents.md index b6d7051994e..ed4b3340a40 100644 --- a/packages/kilo-docs/pages/customize/custom-subagents.md +++ b/packages/kilo-docs/pages/customize/custom-subagents.md @@ -246,8 +246,8 @@ Agent configurations are merged from multiple sources. Later sources override ea 1. **Built-in agent defaults** (native agents defined in the codebase) 2. **Global config** (`~/.config/kilo/config.json`) -3. **Global agent markdown files** (`~/.config/kilo/agents/*.md`) -4. **Project config** (`kilo.jsonc` in the project root) +3. **Project config** (`kilo.jsonc` in the project root) +4. **Global agent markdown files** (`~/.config/kilo/agents/*.md`) 5. **Project agent markdown files** (`.kilo/agents/*.md`) When overriding a built-in agent, properties are merged — only the fields you specify are overridden. When creating a new custom agent, unspecified fields use sensible defaults (`mode: "all"`, full permissions inherited from global config). From 8c646b6f236baa561bef0172faa841c52d13241e Mon Sep 17 00:00:00 2001 From: Josh Lambert Date: Mon, 30 Mar 2026 12:07:55 -0400 Subject: [PATCH 168/261] =?UTF-8?q?docs(kilo-docs):=20clarify=20migration?= =?UTF-8?q?=20skip=20list=20=E2=80=94=20these=20are=20legacy=20modes,=20no?= =?UTF-8?q?t=20CLI=20agents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build and architect are default legacy extension modes that map to the CLI's code and plan agents respectively. They aren't built-in CLI agents themselves. --- packages/kilo-docs/pages/customize/custom-modes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kilo-docs/pages/customize/custom-modes.md b/packages/kilo-docs/pages/customize/custom-modes.md index 73fcf24f8aa..f75a4a6b9c6 100644 --- a/packages/kilo-docs/pages/customize/custom-modes.md +++ b/packages/kilo-docs/pages/customize/custom-modes.md @@ -228,7 +228,7 @@ If you have existing `.kilocodemodes` or `custom_modes.yaml` files from the VSCo - `whenToUse` / `description` to `description` - Mode is set to `primary` -Built-in mode slugs (`code`, `build`, `architect`, `ask`, `debug`, `orchestrator`) are skipped since they have native agent equivalents. +Default legacy mode slugs (`code`, `build`, `architect`, `ask`, `debug`, `orchestrator`) are skipped during migration since they map to built-in agents (`build` → `code`, `architect` → `plan`). {% /tab %} {% tab label="CLI" %} @@ -446,7 +446,7 @@ If you have existing `.kilocodemodes` or `custom_modes.yaml` files from the VSCo - `whenToUse` / `description` to `description` - Mode is set to `primary` -Built-in mode slugs (`code`, `build`, `architect`, `ask`, `debug`, `orchestrator`) are skipped since they have native agent equivalents. +Default legacy mode slugs (`code`, `build`, `architect`, `ask`, `debug`, `orchestrator`) are skipped during migration since they map to built-in agents (`build` → `code`, `architect` → `plan`). {% /tab %} {% tab label="VSCode (Legacy)" %} From 9b3f50a8cbe7ff380dac5b4301e5374161f28255 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:42:47 +0000 Subject: [PATCH 169/261] docs(code-with-ai): remove CLI tab and its info callout in autocomplete docs --- .../pages/code-with-ai/features/autocomplete/index.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md b/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md index 6fecef62164..d26c1d6f086 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md +++ b/packages/kilo-docs/pages/code-with-ai/features/autocomplete/index.md @@ -43,13 +43,6 @@ You can temporarily disable autocomplete by clicking the status bar item to **sn The extension automatically detects if **GitHub Copilot** inline suggestions are enabled and warns you about potential conflicts. Disable Copilot's inline completions for the best experience with Kilo Code autocomplete. -{% /tab %} -{% tab label="CLI" %} - -{% callout type="info" %} -Autocomplete is an **extension-only** feature. It is not available in the CLI/TUI. -{% /callout %} - {% /tab %} {% tab label="VSCode (Legacy)" %} From d9c7abd31f3f17081e86f6abfbff32e6a45cc9a9 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:45:52 +0000 Subject: [PATCH 170/261] docs(code-with-ai): add Playwright config snippet and CLI browser notes - add Playwright config snippet to the CLI tab in browser-use.md - update CLI notes to reflect Playwright manages the browser lifecycle - update Use system Chrome text to clarify default and disable behavior --- .../code-with-ai/features/browser-use.md | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/kilo-docs/pages/code-with-ai/features/browser-use.md b/packages/kilo-docs/pages/code-with-ai/features/browser-use.md index 077278a66bb..40d29c18728 100644 --- a/packages/kilo-docs/pages/code-with-ai/features/browser-use.md +++ b/packages/kilo-docs/pages/code-with-ai/features/browser-use.md @@ -21,7 +21,20 @@ Browser automation is built into the extension and requires no manual setup. Ena {% /tab %} {% tab label="CLI" %} -Browser automation is built into Kilo and requires no manual setup. Enable it from **Settings → Browser** and Kilo handles the rest automatically. +Kilo Code uses [Playwright](https://playwright.dev/) for browser automation. Add it to your `kilo.jsonc` configuration: + +```json +{ + "mcp": { + "playwright": { + "type": "local", + "command": ["npx", "-y", "@playwright/mcp@latest"] + } + } +} +``` + +Playwright downloads Chromium automatically on first use. {% /tab %} {% tab label="VSCode (Legacy)" %} @@ -119,16 +132,12 @@ Browser automation settings are available under **Settings → Browser**: - **Enable browser automation**: Toggle to enable or disable browser automation - **Headless mode**: Run the browser without a visible window (default: disabled) -- **Use system Chrome**: Use your installed Chrome instead of the bundled browser +- **Use system Chrome**: Enabled by default — uses your installed Chrome. Disable to have Playwright download and use Chromium instead. {% /tab %} {% tab label="CLI" %} -Browser automation settings are available under **Settings → Browser**: - -- **Enable browser automation**: Toggle to enable or disable browser automation -- **Headless mode**: Run the browser without a visible window (default: disabled) -- **Use system Chrome**: Use your installed Chrome instead of the bundled browser +Browser automation is configured in your `kilo.jsonc` file. No additional settings are required — Playwright manages the browser lifecycle automatically. {% /tab %} {% tab label="VSCode (Legacy)" %} From 03691ebe4e4c736d3472b44b9c4ad74cae780fb6 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:50:24 +0000 Subject: [PATCH 171/261] fix(cli): restore directory tree in system prompt Remove accidental `&& false` that was introduced in upstream commit 351ddeed91 ("Permission rework #6319") which disabled the filetree from being included in the system prompt for git projects. Upstream issue: https://github.com/anomalyco/opencode/issues/19263 --- packages/opencode/src/session/system.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/session/system.ts b/packages/opencode/src/session/system.ts index 1550d03398b..9fce29731c3 100644 --- a/packages/opencode/src/session/system.ts +++ b/packages/opencode/src/session/system.ts @@ -74,7 +74,7 @@ export namespace SystemPrompt { ``, ``, ` ${ - project.vcs === "git" && false + project.vcs === "git" ? await Ripgrep.tree({ cwd: Instance.directory, limit: 50, From 76d8415ff1669be2ece3e46cf5731f7930b82310 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:57:55 +0000 Subject: [PATCH 172/261] docs(kilo-docs): fix issues flagged by kilo-code-bot review --- .../pages/automate/extending/shell-integration.md | 8 ++++---- packages/kilo-docs/pages/automate/index.md | 1 - .../kilo-docs/pages/automate/mcp/using-in-kilo-code.md | 8 ++++++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/kilo-docs/pages/automate/extending/shell-integration.md b/packages/kilo-docs/pages/automate/extending/shell-integration.md index c88399a1f61..4f1e3312846 100644 --- a/packages/kilo-docs/pages/automate/extending/shell-integration.md +++ b/packages/kilo-docs/pages/automate/extending/shell-integration.md @@ -391,10 +391,10 @@ When using the Kilo Code VS Code extension with the Agent Manager, each agent se ### Keyboard Shortcuts -| Shortcut | Action | -| --------------------------- | --------------------------------------- | -| Cmd+/ | Focus the session's terminal | -| Cmd+. | Return focus to the Agent Manager panel | +| Shortcut | Action | +| --------------------------- | ---------------------------- | +| Cmd+/ | Focus the session's terminal | +| Cmd+. | Cycle agent mode | ### Terminal Context Menu Actions diff --git a/packages/kilo-docs/pages/automate/index.md b/packages/kilo-docs/pages/automate/index.md index 9616faf4a7e..d71a6dce541 100644 --- a/packages/kilo-docs/pages/automate/index.md +++ b/packages/kilo-docs/pages/automate/index.md @@ -36,7 +36,6 @@ Connect Kilo Code to external tools and services: - [**Using MCP in Kilo Code**](/docs/automate/mcp/using-in-kilo-code) — Configuration guide - [**STDIO & SSE Transports**](/docs/automate/mcp/server-transports) — Local and remote server options - [**MCP vs API**](/docs/automate/mcp/mcp-vs-api) — When to use MCP -- [**Using MCP in Kilo Code**](/docs/automate/mcp/using-in-kilo-code) — Configure MCP servers ## Integrations diff --git a/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md b/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md index b89df65d57a..72f9994d1db 100644 --- a/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md +++ b/packages/kilo-docs/pages/automate/mcp/using-in-kilo-code.md @@ -615,6 +615,14 @@ Example: "Analyze the performance of my API" might use an MCP tool that tests AP - **Tool Not Available:** Confirm the server is properly implementing the tool and it's not disabled in settings - **Slow Performance:** Try adjusting the network timeout value for the specific MCP server +{% /tab %} +{% tab label="CLI" %} + +- **Server Not Responding:** Check if the server process is running. Use `kilo mcp debug ` to inspect the connection. +- **Permission Errors:** Ensure API keys and credentials are set in your `kilo.jsonc` config or via `{env:VARIABLE_NAME}` references. +- **Tool Not Available:** Confirm the server is properly implementing the tool and it is not disabled (`"enabled": false`) in your config. +- **Slow Performance:** Increase the `timeout` value for the specific MCP server in your config. + {% /tab %} {% /tabs %} From 5d9ea38171d3a38fce7ca628589899e659f5d530 Mon Sep 17 00:00:00 2001 From: Evgeny Shurakov Date: Mon, 30 Mar 2026 21:30:40 +0200 Subject: [PATCH 173/261] feat(cli): add remote_control config to auto-enable remote session relay Add a `remote_control` boolean config field so users can enable remote session relay by default without the KILO_REMOTE env var or /remote command. --- packages/opencode/src/config/config.ts | 4 ++++ packages/opencode/src/kilo-sessions/kilo-sessions.ts | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index eff231452e0..5b3e3b28de4 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -1159,6 +1159,10 @@ export namespace Config { .boolean() .optional() .describe("@deprecated Use 'share' field instead. Share newly created sessions automatically"), + remote_control: z // kilocode_change + .boolean() + .optional() + .describe("Enable remote control of sessions via Kilo Cloud. Equivalent to running /remote on startup."), autoupdate: z .union([z.boolean(), z.literal("notify")]) .optional() diff --git a/packages/opencode/src/kilo-sessions/kilo-sessions.ts b/packages/opencode/src/kilo-sessions/kilo-sessions.ts index 28c1f4f94e7..2a586ad43f7 100644 --- a/packages/opencode/src/kilo-sessions/kilo-sessions.ts +++ b/packages/opencode/src/kilo-sessions/kilo-sessions.ts @@ -10,6 +10,7 @@ import { clearInFlightCache, withInFlightCache } from "@/kilo-sessions/inflight- import type * as SDK from "@kilocode/sdk/v2" import z from "zod" import { KILO_API_BASE } from "@kilocode/kilo-gateway" +import { Config } from "@/config/config" import { Instance } from "@/project/instance" import { Vcs } from "@/project/vcs" import simpleGit from "simple-git" @@ -205,7 +206,9 @@ export namespace KiloSessions { await ingest.sync(evt.properties.sessionID, [{ type: "session_close", data: { reason: evt.properties.reason } }]) }) - if (remoteEnabled) enableRemote().catch((err) => log.warn("remote not enabled", { error: String(err) })) + const cfg = await Config.get() + if (remoteEnabled || cfg.remote_control) + enableRemote().catch((err) => log.warn("remote not enabled", { error: String(err) })) Bus.subscribe(Bus.InstanceDisposed, () => disableRemote()) } From 8c6d4481171637ce639aff7cd0c8f1f34a7efa79 Mon Sep 17 00:00:00 2001 From: Evgeny Shurakov Date: Mon, 30 Mar 2026 22:11:35 +0200 Subject: [PATCH 174/261] fix(cli): read remote_control from global config only --- packages/opencode/src/kilo-sessions/kilo-sessions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/kilo-sessions/kilo-sessions.ts b/packages/opencode/src/kilo-sessions/kilo-sessions.ts index 2a586ad43f7..76249cf9d5f 100644 --- a/packages/opencode/src/kilo-sessions/kilo-sessions.ts +++ b/packages/opencode/src/kilo-sessions/kilo-sessions.ts @@ -206,7 +206,7 @@ export namespace KiloSessions { await ingest.sync(evt.properties.sessionID, [{ type: "session_close", data: { reason: evt.properties.reason } }]) }) - const cfg = await Config.get() + const cfg = await Config.getGlobal() if (remoteEnabled || cfg.remote_control) enableRemote().catch((err) => log.warn("remote not enabled", { error: String(err) })) Bus.subscribe(Bus.InstanceDisposed, () => disableRemote()) From 12d292ec08d8a1c412cb50f59882ab07cbf22b34 Mon Sep 17 00:00:00 2001 From: Aarav Sharma Date: Mon, 30 Mar 2026 16:50:38 -0600 Subject: [PATCH 175/261] fix: propagate deprecated field in agent merge and show description in dialog --- packages/opencode/src/agent/agent.ts | 1 + packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 7886a5ee534..3e790f5b31c 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -383,6 +383,7 @@ export namespace Agent { item.mode = value.mode ?? item.mode item.color = value.color ?? item.color item.hidden = value.hidden ?? item.hidden + item.deprecated = value.deprecated ?? item.deprecated item.name = value.name ?? item.name item.steps = value.steps ?? item.steps item.options = mergeDeep(item.options, value.options ?? {}) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx index 6a8aa1f3f62..68ea2f4c432 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx @@ -13,7 +13,8 @@ export function DialogAgent() { value: item.name, title: item.displayName ?? item.name, // kilocode_change description: - [item.deprecated && "deprecated", item.native && "native"].filter(Boolean).join(", ") || item.description, + [item.deprecated && "deprecated", item.native && "native", item.description].filter(Boolean).join(", ") || + undefined, } }), ) From af83b19bec5676e6500a1cdf4a22f26c7ea1696b Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Tue, 31 Mar 2026 08:50:43 +0300 Subject: [PATCH 176/261] fix(cli): simplify self-config tips --- .../opencode/src/kilocode/components/tips.tsx | 57 +++++-------------- 1 file changed, 15 insertions(+), 42 deletions(-) diff --git a/packages/opencode/src/kilocode/components/tips.tsx b/packages/opencode/src/kilocode/components/tips.tsx index 5dd5981eeb3..13a3da92f2b 100644 --- a/packages/opencode/src/kilocode/components/tips.tsx +++ b/packages/opencode/src/kilocode/components/tips.tsx @@ -80,31 +80,24 @@ const TIPS = [ "Switch to {highlight}Plan{/highlight} agent to get suggestions without making actual changes", "Use {highlight}@agent-name{/highlight} in prompts to invoke specialized subagents", "Press {highlight}Ctrl+X Right/Left{/highlight} to cycle through parent and child sessions", - "Create {highlight}kilo.json{/highlight} for server settings and {highlight}tui.json{/highlight} for TUI settings", - "Place TUI settings in {highlight}~/.config/kilo/tui.json{/highlight} for global config", - "Add {highlight}$schema{/highlight} to your config for autocomplete in your editor", - "Configure {highlight}model{/highlight} in config to set your default model", - "Override any keybind in {highlight}tui.json{/highlight} via the {highlight}keybinds{/highlight} section", - "Set any keybind to {highlight}none{/highlight} to disable it completely", - "Configure local or remote MCP servers in the {highlight}mcp{/highlight} config section", + "Kilo can {highlight}configure itself{/highlight} if you ask it", + "Ask Kilo to {highlight}add Supabase MCP globally{/highlight}", + "Ask Kilo to {highlight}create a review agent for this project{/highlight}", + "Ask Kilo to {highlight}add a plugin for desktop alerts{/highlight}", + "Ask Kilo to {highlight}set Claude Sonnet as my default model{/highlight}", + "Ask Kilo to {highlight}make my review agent read-only{/highlight}", + "Ask Kilo to {highlight}require approval before git push{/highlight}", + "Ask Kilo to {highlight}turn off auto-formatting{/highlight}", + "Ask Kilo to {highlight}block access to .env files{/highlight}", + "Ask Kilo to {highlight}turn off the F2 shortcut{/highlight}", + "Ask Kilo to {highlight}match my terminal theme{/highlight}", + "Ask Kilo to {highlight}disable sharing for all sessions{/highlight}", + "Ask Kilo to {highlight}add rules from docs/ai-rules.md{/highlight}", + "Ask Kilo to {highlight}enable tui.scroll_acceleration{/highlight} for smooth macOS-style scrolling", + "Ask Kilo to {highlight}save this workflow as a /command{/highlight}", "Kilo auto-handles OAuth for remote MCP servers requiring auth", - "Add {highlight}.md{/highlight} files to {highlight}.kilo/command/{/highlight} to define reusable custom prompts", - "Use {highlight}$ARGUMENTS{/highlight}, {highlight}$1{/highlight}, {highlight}$2{/highlight} in custom commands for dynamic input", - "Use backticks in commands to inject shell output (e.g., {highlight}`git status`{/highlight})", - "Add {highlight}.md{/highlight} files to {highlight}.kilo/agent/{/highlight} for specialized AI personas", - "Configure per-agent permissions for {highlight}edit{/highlight}, {highlight}bash{/highlight}, and {highlight}webfetch{/highlight} tools", - 'Use patterns like {highlight}"git *": "allow"{/highlight} for granular bash permissions', - 'Set {highlight}"rm -rf *": "deny"{/highlight} to block destructive commands', - 'Configure {highlight}"git push": "ask"{/highlight} to require approval before pushing', "Kilo auto-formats files using prettier, gofmt, ruff, and more", - 'Set {highlight}"formatter": false{/highlight} in config to disable all auto-formatting', - "Define custom formatter commands with file extensions in config", "Kilo uses LSP servers for intelligent code analysis", - "Create {highlight}.ts{/highlight} files in {highlight}.kilo/tools/{/highlight} to define new LLM tools", - "Tool definitions can invoke scripts written in Python, Go, etc", - "Add {highlight}.ts{/highlight} files to {highlight}.kilo/plugin/{/highlight} for event hooks", - "Use plugins to send OS notifications when sessions complete", - "Create a plugin to prevent Kilo from reading sensitive files", "Use {highlight}kilo run{/highlight} for non-interactive scripting", "Use {highlight}kilo --continue{/highlight} to resume the last session", "Use {highlight}kilo run -f file.ts{/highlight} to attach files via CLI", @@ -113,34 +106,14 @@ const TIPS = [ "Use {highlight}kilo run --attach{/highlight} to connect to a running server", "Run {highlight}kilo upgrade{/highlight} to update to the latest version", "Run {highlight}kilo auth list{/highlight} to see all configured providers", - "Run {highlight}kilo agent create{/highlight} for guided agent creation", - 'Use {highlight}"theme": "system"{/highlight} to match your terminal\'s colors', - "Create JSON theme files in {highlight}.kilo/themes/{/highlight} directory", - "Themes support dark/light variants for both modes", - "Reference ANSI colors 0-255 in custom themes", - "Use {highlight}{env:VAR_NAME}{/highlight} syntax to reference environment variables in config", - "Use {highlight}{file:path}{/highlight} to include file contents in config values", - "Use {highlight}instructions{/highlight} in config to load additional rules files", - "Set agent {highlight}temperature{/highlight} from 0.0 (focused) to 1.0 (creative)", - "Configure {highlight}steps{/highlight} to limit agentic iterations per request", - 'Set {highlight}"tools": {"bash": false}{/highlight} to disable specific tools', - 'Set {highlight}"mcp_*": false{/highlight} to disable all tools from an MCP server', - "Override global tool settings per agent configuration", - 'Set {highlight}"share": "auto"{/highlight} to automatically share all sessions', - 'Set {highlight}"share": "disabled"{/highlight} to prevent any session sharing', "Run {highlight}/unshare{/highlight} to remove a session from public access", - "Permission {highlight}doom_loop{/highlight} prevents infinite tool call loops", - "Permission {highlight}external_directory{/highlight} protects files outside project", - "Run {highlight}kilo debug config{/highlight} to troubleshoot configuration", "Use {highlight}--print-logs{/highlight} flag to see detailed logs in stderr", "Press {highlight}Ctrl+X G{/highlight} or {highlight}/timeline{/highlight} to jump to specific messages", "Press {highlight}Ctrl+X S{/highlight} or {highlight}/status{/highlight} to see config paths, MCP servers, and system info", - "Enable {highlight}tui.scroll_acceleration{/highlight} for smooth macOS-style scrolling", "Toggle username display in chat via command palette ({highlight}Ctrl+P{/highlight})", "Commit your project's {highlight}AGENTS.md{/highlight} file to Git for team sharing", "Use {highlight}/review{/highlight} to review uncommitted changes, branches, or PRs", "Run {highlight}/help{/highlight} to show the help dialog", "Use {highlight}/rename{/highlight} to rename the current session", "Press {highlight}Ctrl+Z{/highlight} to suspend the terminal and return to your shell", - "Doing something often? Ask Kilo to save it as a {highlight}/command{/highlight}", ] From c4732a6c8c850b5dc9a68c74887e0e53cee015ab Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Tue, 31 Mar 2026 09:02:11 +0300 Subject: [PATCH 177/261] fix(cli): restore agent picker labels --- packages/opencode/src/agent/agent.ts | 2 +- packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 5773244ba45..8bfbe786a21 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -265,7 +265,7 @@ export namespace Agent { }, orchestrator: { name: "orchestrator", - description: "Deprecated. Coordinate complex tasks by delegating to specialized agents in parallel.", + description: "Coordinate complex tasks by delegating to specialized agents in parallel.", prompt: PROMPT_ORCHESTRATOR, options: {}, permission: PermissionNext.merge( diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx index 68ea2f4c432..6a8aa1f3f62 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx @@ -13,8 +13,7 @@ export function DialogAgent() { value: item.name, title: item.displayName ?? item.name, // kilocode_change description: - [item.deprecated && "deprecated", item.native && "native", item.description].filter(Boolean).join(", ") || - undefined, + [item.deprecated && "deprecated", item.native && "native"].filter(Boolean).join(", ") || item.description, } }), ) From 3558f5e84b143343864b1b9c9955b947d8a7dc29 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 07:47:59 +0000 Subject: [PATCH 178/261] fix(vscode): show friendly model name in notification "Try model" button Replace static "Try model" text with "Try " using the model catalog display name. The i18n template now uses {{model}} interpolation across all 18 locales. --- .../src/components/chat/KiloNotifications.tsx | 11 ++++++++++- packages/kilo-vscode/webview-ui/src/i18n/ar.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/br.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/bs.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/da.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/de.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/en.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/es.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/fr.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/ja.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/ko.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/nl.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/no.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/pl.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/ru.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/th.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/tr.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/zh.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/zht.ts | 2 +- 19 files changed, 28 insertions(+), 19 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/KiloNotifications.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/KiloNotifications.tsx index 7beffc2fc00..db18bcce517 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/KiloNotifications.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/KiloNotifications.tsx @@ -6,6 +6,7 @@ import { useProvider } from "../../context/provider" import { useLanguage } from "../../context/language" import { KILO_PROVIDER_ID } from "../../../../src/shared/provider-model" import { TelemetryEventName } from "../../../../src/services/telemetry/types" +import { sanitizeName, stripSubProviderPrefix } from "../shared/model-selector-utils" export const KiloNotifications: Component = () => { const { filteredNotifications, dismiss } = useNotifications() @@ -61,6 +62,14 @@ export const KiloNotifications: Component = () => { return true }) + const suggestedName = createMemo(() => { + const suggestion = suggestedModel() + if (!suggestion) return undefined + const model = provider.findModel(suggestion) + if (!model?.name) return undefined + return stripSubProviderPrefix(sanitizeName(model.name)) + }) + const handleTryModel = () => { const suggestion = suggestedModel() if (!suggestion) return @@ -88,7 +97,7 @@ export const KiloNotifications: Component = () => { + +
+ }> + + +
+
Chat Sessions & History
+
{sessions().length} sessions detected
+
+
+
+ {/* Default Model */}
@@ -734,20 +767,6 @@ const MigrationWizard: Component = (props) => {
- {/* Divider + Cannot be migrated */} -
- -
- -
-
{language.t("migration.migrate.chatHistory")}
-
{language.t("migration.migrate.chatHistoryDesc")}
-
-
- {/* Cleanup option after done */}
diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index cd7e25b9656..bc35beb8cc5 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -1053,6 +1053,7 @@ export interface MigrationStateMessage { providers: MigrationProviderInfo[] mcpServers: MigrationMcpServerInfo[] customModes: MigrationCustomModeInfo[] + sessions?: string[] defaultModel?: { provider: string; model: string } settings?: LegacySettings } @@ -1064,6 +1065,7 @@ export interface LegacyMigrationDataMessage { providers: MigrationProviderInfo[] mcpServers: MigrationMcpServerInfo[] customModes: MigrationCustomModeInfo[] + sessions?: string[] defaultModel?: { provider: string; model: string } settings?: LegacySettings } @@ -1100,6 +1102,7 @@ export interface StartLegacyMigrationMessage { providers: string[] mcpServers: string[] customModes: string[] + sessions?: string[] defaultModel: boolean settings: { autoApproval: MigrationAutoApprovalSelections diff --git a/packages/opencode/src/kilocode/session-import/routes.ts b/packages/opencode/src/kilocode/session-import/routes.ts new file mode 100644 index 00000000000..755a725f240 --- /dev/null +++ b/packages/opencode/src/kilocode/session-import/routes.ts @@ -0,0 +1,94 @@ +import { Hono } from "hono" +import { describeRoute, resolver, validator } from "hono-openapi" +import { lazy } from "../../util/lazy" +import { errors } from "../../server/error" +import { SessionImportService } from "./service" +import { SessionImportType } from "./types" + +export const SessionImportRoutes = lazy(() => + new Hono() + .post( + "/project", + describeRoute({ + summary: "Insert project for session import", + description: "Insert or update a project row used by legacy session import.", + operationId: "kilocode.sessionImport.project", + responses: { + 200: { + description: "Project import result", + content: { + "application/json": { + schema: resolver(SessionImportType.Result), + }, + }, + }, + ...errors(400), + }, + }), + validator("json", SessionImportType.Project), + async (c) => c.json(await SessionImportService.project(c.req.valid("json"))), + ) + .post( + "/session", + describeRoute({ + summary: "Insert session for session import", + description: "Insert or update a session row used by legacy session import.", + operationId: "kilocode.sessionImport.session", + responses: { + 200: { + description: "Session import result", + content: { + "application/json": { + schema: resolver(SessionImportType.Result), + }, + }, + }, + ...errors(400), + }, + }), + validator("json", SessionImportType.Session), + async (c) => c.json(await SessionImportService.session(c.req.valid("json"))), + ) + .post( + "/message", + describeRoute({ + summary: "Insert message for session import", + description: "Insert or update a message row used by legacy session import.", + operationId: "kilocode.sessionImport.message", + responses: { + 200: { + description: "Message import result", + content: { + "application/json": { + schema: resolver(SessionImportType.Result), + }, + }, + }, + ...errors(400), + }, + }), + validator("json", SessionImportType.Message), + async (c) => c.json(await SessionImportService.message(c.req.valid("json"))), + ) + .post( + "/part", + describeRoute({ + summary: "Insert part for session import", + description: "Insert or update a part row used by legacy session import.", + operationId: "kilocode.sessionImport.part", + responses: { + 200: { + description: "Part import result", + content: { + "application/json": { + schema: resolver(SessionImportType.Result), + }, + }, + }, + ...errors(400), + }, + }), + validator("json", SessionImportType.Part), + async (c) => c.json(await SessionImportService.part(c.req.valid("json"))), + ), +) diff --git a/packages/opencode/src/kilocode/session-import/service.ts b/packages/opencode/src/kilocode/session-import/service.ts new file mode 100644 index 00000000000..9c61a257182 --- /dev/null +++ b/packages/opencode/src/kilocode/session-import/service.ts @@ -0,0 +1,97 @@ +import { Database } from "../../storage/db" +import { SessionTable, MessageTable, PartTable } from "../../session/session.sql" +import { SessionImportType } from "./types" +import { Project } from "../../project/project" +import { eq } from "drizzle-orm" + +const key = (input: unknown) => [input] as never +const target = (input: unknown) => input as never + +export namespace SessionImportService { + export async function project(input: SessionImportType.Project): Promise { + // Do not resolve an empty legacy worktree, because that would fall back to the current + // process directory and silently attach the migrated session to the wrong project. + if (!input.worktree.trim()) { + throw new Error("Legacy project import requires a non-empty worktree") + } + + const result = await Project.fromDirectory(input.worktree) + return { ok: true, id: result.project.id } + } + + export async function session(input: SessionImportType.Session): Promise { + const row = Database.use((db) => db.select().from(SessionTable).where(eq(target(SessionTable.id), input.id)).get()) + if (row) return { ok: true, id: input.id, skipped: true } + + Database.use((db) => { + db.insert(SessionTable) + .values({ + id: input.id, + project_id: input.projectID, + workspace_id: input.workspaceID, + parent_id: input.parentID, + slug: input.slug, + directory: input.directory, + title: input.title, + version: input.version, + share_url: input.shareURL, + summary_additions: input.summary?.additions, + summary_deletions: input.summary?.deletions, + summary_files: input.summary?.files, + summary_diffs: input.summary?.diffs as never, + revert: input.revert, + permission: input.permission as never, + time_created: input.timeCreated, + time_updated: input.timeUpdated, + time_compacting: input.timeCompacting, + time_archived: input.timeArchived, + }) + .onConflictDoNothing({ + target: key(SessionTable.id), + }) + .run() + }) + return { ok: true, id: input.id } + } + + export async function message(input: SessionImportType.Message): Promise { + Database.use((db) => { + db.insert(MessageTable) + .values({ + id: input.id, + session_id: input.sessionID, + time_created: input.timeCreated, + data: input.data as never, + }) + .onConflictDoUpdate({ + target: key(MessageTable.id), + set: { + data: input.data as never, + }, + }) + .run() + }) + return { ok: true, id: input.id } + } + + export async function part(input: SessionImportType.Part): Promise { + Database.use((db) => { + db.insert(PartTable) + .values({ + id: input.id, + message_id: input.messageID, + session_id: input.sessionID, + time_created: input.timeCreated, + data: input.data as never, + }) + .onConflictDoUpdate({ + target: key(PartTable.id), + set: { + data: input.data as never, + }, + }) + .run() + }) + return { ok: true, id: input.id } + } +} diff --git a/packages/opencode/src/kilocode/session-import/types.ts b/packages/opencode/src/kilocode/session-import/types.ts new file mode 100644 index 00000000000..7bd5d6b9f14 --- /dev/null +++ b/packages/opencode/src/kilocode/session-import/types.ts @@ -0,0 +1,216 @@ +import z from "zod" + +export namespace SessionImportType { + export const UserMessageData = z.object({ + role: z.literal("user"), + time: z.object({ + created: z.number(), + }), + agent: z.string(), + model: z.object({ + providerID: z.string(), + modelID: z.string(), + }), + tools: z.record(z.string(), z.boolean()).optional(), + }) + + export const AssistantMessageData = z.object({ + role: z.literal("assistant"), + time: z.object({ + created: z.number(), + completed: z.number().optional(), + }), + parentID: z.string(), + modelID: z.string(), + providerID: z.string(), + mode: z.string(), + agent: z.string(), + path: z.object({ + cwd: z.string(), + root: z.string(), + }), + summary: z.boolean().optional(), + cost: z.number(), + tokens: z.object({ + total: z.number().optional(), + input: z.number(), + output: z.number(), + reasoning: z.number(), + cache: z.object({ + read: z.number(), + write: z.number(), + }), + }), + structured: z.unknown().optional(), + variant: z.string().optional(), + finish: z.string().optional(), + }) + + export const MessageData = z.discriminatedUnion("role", [UserMessageData, AssistantMessageData]) + + export const TextPartData = z.object({ + type: z.literal("text"), + text: z.string(), + synthetic: z.boolean().optional(), + ignored: z.boolean().optional(), + time: z + .object({ + start: z.number(), + end: z.number().optional(), + }) + .optional(), + metadata: z.record(z.string(), z.unknown()).optional(), + }) + + export const ReasoningPartData = z.object({ + type: z.literal("reasoning"), + text: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + end: z.number().optional(), + }), + }) + + export const ToolStatePending = z.object({ + status: z.literal("pending"), + input: z.record(z.string(), z.unknown()), + raw: z.string(), + }) + + export const ToolStateRunning = z.object({ + status: z.literal("running"), + input: z.record(z.string(), z.unknown()), + title: z.string().optional(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + }), + }) + + export const ToolStateCompleted = z.object({ + status: z.literal("completed"), + input: z.record(z.string(), z.unknown()), + output: z.string(), + title: z.string(), + metadata: z.record(z.string(), z.unknown()), + time: z.object({ + start: z.number(), + end: z.number(), + compacted: z.number().optional(), + }), + }) + + export const ToolStateError = z.object({ + status: z.literal("error"), + input: z.record(z.string(), z.unknown()), + error: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + end: z.number(), + }), + }) + + export const ToolState = z.discriminatedUnion("status", [ToolStatePending, ToolStateRunning, ToolStateCompleted, ToolStateError]) + + export const ToolPartData = z.object({ + type: z.literal("tool"), + callID: z.string(), + tool: z.string(), + state: ToolState, + metadata: z.record(z.string(), z.unknown()).optional(), + }) + + export const PartData = z.discriminatedUnion("type", [TextPartData, ReasoningPartData, ToolPartData]) + + export const Result = z.object({ + ok: z.boolean(), + id: z.string(), + skipped: z.boolean().optional(), + }) + + export const Project = z.object({ + id: z.string(), + worktree: z.string(), + vcs: z.string().optional(), + name: z.string().optional(), + iconUrl: z.string().optional(), + iconColor: z.string().optional(), + timeCreated: z.number(), + timeUpdated: z.number(), + timeInitialized: z.number().optional(), + sandboxes: z.array(z.string()), + commands: z + .object({ + start: z.string().optional(), + }) + .optional(), + }) + + export const Session = z.object({ + id: z.string(), + projectID: z.string(), + workspaceID: z.string().optional(), + parentID: z.string().optional(), + slug: z.string(), + directory: z.string(), + title: z.string(), + version: z.string(), + shareURL: z.string().optional(), + summary: z + .object({ + additions: z.number(), + deletions: z.number(), + files: z.number(), + diffs: z.array(z.record(z.string(), z.unknown())).optional(), + }) + .optional(), + revert: z + .object({ + messageID: z.string(), + partID: z.string().optional(), + snapshot: z.string().optional(), + diff: z.string().optional(), + }) + .optional(), + permission: z.record(z.string(), z.unknown()).optional(), + timeCreated: z.number(), + timeUpdated: z.number(), + timeCompacting: z.number().optional(), + timeArchived: z.number().optional(), + }) + + export const Message = z.object({ + id: z.string(), + sessionID: z.string(), + timeCreated: z.number(), + data: MessageData, + }) + + export const Part = z.object({ + id: z.string(), + messageID: z.string(), + sessionID: z.string(), + timeCreated: z.number().optional(), + data: PartData, + }) + + export type Result = z.infer + export type UserMessageData = z.infer + export type AssistantMessageData = z.infer + export type MessageData = z.infer + export type TextPartData = z.infer + export type ReasoningPartData = z.infer + export type ToolStatePending = z.infer + export type ToolStateRunning = z.infer + export type ToolStateCompleted = z.infer + export type ToolStateError = z.infer + export type ToolState = z.infer + export type ToolPartData = z.infer + export type PartData = z.infer + export type Project = z.infer + export type Session = z.infer + export type Message = z.infer + export type Part = z.infer +} diff --git a/packages/opencode/src/server/routes/kilocode.ts b/packages/opencode/src/server/routes/kilocode.ts index aa7d0503994..75572a9ad84 100644 --- a/packages/opencode/src/server/routes/kilocode.ts +++ b/packages/opencode/src/server/routes/kilocode.ts @@ -8,9 +8,11 @@ import { Skill } from "../../skill/skill" import { Agent } from "../../agent/agent" import { lazy } from "../../util/lazy" import { errors } from "../error" +import { SessionImportRoutes } from "../../kilocode/session-import/routes" export const KilocodeRoutes = lazy(() => new Hono() + .route("/session-import", SessionImportRoutes()) .post( "/skill/remove", describeRoute({ diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index 640cc66fb0d..84355f79a57 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -61,6 +61,14 @@ import type { KilocodeRemoveAgentResponses, KilocodeRemoveSkillErrors, KilocodeRemoveSkillResponses, + KilocodeSessionImportMessageErrors, + KilocodeSessionImportMessageResponses, + KilocodeSessionImportPartErrors, + KilocodeSessionImportPartResponses, + KilocodeSessionImportProjectErrors, + KilocodeSessionImportProjectResponses, + KilocodeSessionImportSessionErrors, + KilocodeSessionImportSessionResponses, KiloFimErrors, KiloFimResponses, KiloModesResponses, @@ -3095,6 +3103,388 @@ export class EnhancePrompt extends HeyApiClient { } } +export class SessionImport extends HeyApiClient { + /** + * Insert project for session import + * + * Insert or update a project row used by legacy session import. + */ + public project( + parameters?: { + directory?: string + workspace?: string + id?: string + worktree?: string + vcs?: string + name?: string + iconUrl?: string + iconColor?: string + timeCreated?: number + timeUpdated?: number + timeInitialized?: number + sandboxes?: Array + commands?: { + start?: string + } + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "body", key: "id" }, + { in: "body", key: "worktree" }, + { in: "body", key: "vcs" }, + { in: "body", key: "name" }, + { in: "body", key: "iconUrl" }, + { in: "body", key: "iconColor" }, + { in: "body", key: "timeCreated" }, + { in: "body", key: "timeUpdated" }, + { in: "body", key: "timeInitialized" }, + { in: "body", key: "sandboxes" }, + { in: "body", key: "commands" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post< + KilocodeSessionImportProjectResponses, + KilocodeSessionImportProjectErrors, + ThrowOnError + >({ + url: "/kilocode/session-import/project", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Insert session for session import + * + * Insert or update a session row used by legacy session import. + */ + public session( + parameters?: { + query_directory?: string + workspace?: string + id?: string + projectID?: string + workspaceID?: string + parentID?: string + slug?: string + body_directory?: string + title?: string + version?: string + shareURL?: string + summary?: { + additions: number + deletions: number + files: number + diffs?: Array<{ + [key: string]: unknown + }> + } + revert?: { + messageID: string + partID?: string + snapshot?: string + diff?: string + } + permission?: { + [key: string]: unknown + } + timeCreated?: number + timeUpdated?: number + timeCompacting?: number + timeArchived?: number + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { + in: "query", + key: "query_directory", + map: "directory", + }, + { in: "query", key: "workspace" }, + { in: "body", key: "id" }, + { in: "body", key: "projectID" }, + { in: "body", key: "workspaceID" }, + { in: "body", key: "parentID" }, + { in: "body", key: "slug" }, + { + in: "body", + key: "body_directory", + map: "directory", + }, + { in: "body", key: "title" }, + { in: "body", key: "version" }, + { in: "body", key: "shareURL" }, + { in: "body", key: "summary" }, + { in: "body", key: "revert" }, + { in: "body", key: "permission" }, + { in: "body", key: "timeCreated" }, + { in: "body", key: "timeUpdated" }, + { in: "body", key: "timeCompacting" }, + { in: "body", key: "timeArchived" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post< + KilocodeSessionImportSessionResponses, + KilocodeSessionImportSessionErrors, + ThrowOnError + >({ + url: "/kilocode/session-import/session", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Insert message for session import + * + * Insert or update a message row used by legacy session import. + */ + public message( + parameters?: { + directory?: string + workspace?: string + id?: string + sessionID?: string + timeCreated?: number + data?: + | { + role: "user" + time: { + created: number + } + agent: string + model: { + providerID: string + modelID: string + } + tools?: { + [key: string]: boolean + } + } + | { + role: "assistant" + time: { + created: number + completed?: number + } + parentID: string + modelID: string + providerID: string + mode: string + agent: string + path: { + cwd: string + root: string + } + summary?: boolean + cost: number + tokens: { + total?: number + input: number + output: number + reasoning: number + cache: { + read: number + write: number + } + } + structured?: unknown + variant?: string + finish?: string + } + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "body", key: "id" }, + { in: "body", key: "sessionID" }, + { in: "body", key: "timeCreated" }, + { in: "body", key: "data" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post< + KilocodeSessionImportMessageResponses, + KilocodeSessionImportMessageErrors, + ThrowOnError + >({ + url: "/kilocode/session-import/message", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Insert part for session import + * + * Insert or update a part row used by legacy session import. + */ + public part( + parameters?: { + directory?: string + workspace?: string + id?: string + messageID?: string + sessionID?: string + timeCreated?: number + data?: + | { + type: "text" + text: string + synthetic?: boolean + ignored?: boolean + time?: { + start: number + end?: number + } + metadata?: { + [key: string]: unknown + } + } + | { + type: "reasoning" + text: string + metadata?: { + [key: string]: unknown + } + time: { + start: number + end?: number + } + } + | { + type: "tool" + callID: string + tool: string + state: + | { + status: "pending" + input: { + [key: string]: unknown + } + raw: string + } + | { + status: "running" + input: { + [key: string]: unknown + } + title?: string + metadata?: { + [key: string]: unknown + } + time: { + start: number + } + } + | { + status: "completed" + input: { + [key: string]: unknown + } + output: string + title: string + metadata: { + [key: string]: unknown + } + time: { + start: number + end: number + compacted?: number + } + } + | { + status: "error" + input: { + [key: string]: unknown + } + error: string + metadata?: { + [key: string]: unknown + } + time: { + start: number + end: number + } + } + metadata?: { + [key: string]: unknown + } + } + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "body", key: "id" }, + { in: "body", key: "messageID" }, + { in: "body", key: "sessionID" }, + { in: "body", key: "timeCreated" }, + { in: "body", key: "data" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post< + KilocodeSessionImportPartResponses, + KilocodeSessionImportPartErrors, + ThrowOnError + >({ + url: "/kilocode/session-import/part", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } +} + export class Kilocode extends HeyApiClient { /** * Remove a skill @@ -3173,6 +3563,11 @@ export class Kilocode extends HeyApiClient { }, ) } + + private _sessionImport?: SessionImport + get sessionImport(): SessionImport { + return (this._sessionImport ??= new SessionImport({ client: this.client })) + } } export class Organization extends HeyApiClient { diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index fa05a8e95f9..b22f7018043 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -4529,6 +4529,325 @@ export type EnhancePromptEnhanceResponses = { export type EnhancePromptEnhanceResponse = EnhancePromptEnhanceResponses[keyof EnhancePromptEnhanceResponses] +export type KilocodeSessionImportProjectData = { + body?: { + id: string + worktree: string + vcs?: string + name?: string + iconUrl?: string + iconColor?: string + timeCreated: number + timeUpdated: number + timeInitialized?: number + sandboxes: Array + commands?: { + start?: string + } + } + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/kilocode/session-import/project" +} + +export type KilocodeSessionImportProjectErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type KilocodeSessionImportProjectError = + KilocodeSessionImportProjectErrors[keyof KilocodeSessionImportProjectErrors] + +export type KilocodeSessionImportProjectResponses = { + /** + * Project import result + */ + 200: { + ok: boolean + id: string + skipped?: boolean + } +} + +export type KilocodeSessionImportProjectResponse = + KilocodeSessionImportProjectResponses[keyof KilocodeSessionImportProjectResponses] + +export type KilocodeSessionImportSessionData = { + body?: { + id: string + projectID: string + workspaceID?: string + parentID?: string + slug: string + directory: string + title: string + version: string + shareURL?: string + summary?: { + additions: number + deletions: number + files: number + diffs?: Array<{ + [key: string]: unknown + }> + } + revert?: { + messageID: string + partID?: string + snapshot?: string + diff?: string + } + permission?: { + [key: string]: unknown + } + timeCreated: number + timeUpdated: number + timeCompacting?: number + timeArchived?: number + } + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/kilocode/session-import/session" +} + +export type KilocodeSessionImportSessionErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type KilocodeSessionImportSessionError = + KilocodeSessionImportSessionErrors[keyof KilocodeSessionImportSessionErrors] + +export type KilocodeSessionImportSessionResponses = { + /** + * Session import result + */ + 200: { + ok: boolean + id: string + skipped?: boolean + } +} + +export type KilocodeSessionImportSessionResponse = + KilocodeSessionImportSessionResponses[keyof KilocodeSessionImportSessionResponses] + +export type KilocodeSessionImportMessageData = { + body?: { + id: string + sessionID: string + timeCreated: number + data: + | { + role: "user" + time: { + created: number + } + agent: string + model: { + providerID: string + modelID: string + } + tools?: { + [key: string]: boolean + } + } + | { + role: "assistant" + time: { + created: number + completed?: number + } + parentID: string + modelID: string + providerID: string + mode: string + agent: string + path: { + cwd: string + root: string + } + summary?: boolean + cost: number + tokens: { + total?: number + input: number + output: number + reasoning: number + cache: { + read: number + write: number + } + } + structured?: unknown + variant?: string + finish?: string + } + } + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/kilocode/session-import/message" +} + +export type KilocodeSessionImportMessageErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type KilocodeSessionImportMessageError = + KilocodeSessionImportMessageErrors[keyof KilocodeSessionImportMessageErrors] + +export type KilocodeSessionImportMessageResponses = { + /** + * Message import result + */ + 200: { + ok: boolean + id: string + skipped?: boolean + } +} + +export type KilocodeSessionImportMessageResponse = + KilocodeSessionImportMessageResponses[keyof KilocodeSessionImportMessageResponses] + +export type KilocodeSessionImportPartData = { + body?: { + id: string + messageID: string + sessionID: string + timeCreated?: number + data: + | { + type: "text" + text: string + synthetic?: boolean + ignored?: boolean + time?: { + start: number + end?: number + } + metadata?: { + [key: string]: unknown + } + } + | { + type: "reasoning" + text: string + metadata?: { + [key: string]: unknown + } + time: { + start: number + end?: number + } + } + | { + type: "tool" + callID: string + tool: string + state: + | { + status: "pending" + input: { + [key: string]: unknown + } + raw: string + } + | { + status: "running" + input: { + [key: string]: unknown + } + title?: string + metadata?: { + [key: string]: unknown + } + time: { + start: number + } + } + | { + status: "completed" + input: { + [key: string]: unknown + } + output: string + title: string + metadata: { + [key: string]: unknown + } + time: { + start: number + end: number + compacted?: number + } + } + | { + status: "error" + input: { + [key: string]: unknown + } + error: string + metadata?: { + [key: string]: unknown + } + time: { + start: number + end: number + } + } + metadata?: { + [key: string]: unknown + } + } + } + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/kilocode/session-import/part" +} + +export type KilocodeSessionImportPartErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type KilocodeSessionImportPartError = KilocodeSessionImportPartErrors[keyof KilocodeSessionImportPartErrors] + +export type KilocodeSessionImportPartResponses = { + /** + * Part import result + */ + 200: { + ok: boolean + id: string + skipped?: boolean + } +} + +export type KilocodeSessionImportPartResponse = + KilocodeSessionImportPartResponses[keyof KilocodeSessionImportPartResponses] + export type KilocodeRemoveSkillData = { body?: { location: string diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 3f4f142364e..7211c8fd359 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -5042,6 +5042,15 @@ "isFree": { "type": "boolean" }, + "ai_sdk_provider": { + "type": "string", + "enum": [ + "anthropic", + "openai", + "openai-compatible", + "openrouter" + ] + }, "experimental": { "type": "boolean" }, @@ -5473,7 +5482,10 @@ "type": "boolean" } }, - "required": ["enabled", "connected"] + "required": [ + "enabled", + "connected" + ] } } } @@ -5523,7 +5535,10 @@ "type": "boolean" } }, - "required": ["enabled", "connected"] + "required": [ + "enabled", + "connected" + ] } } } @@ -5573,7 +5588,10 @@ "type": "boolean" } }, - "required": ["enabled", "connected"] + "required": [ + "enabled", + "connected" + ] } } } @@ -5753,6 +5771,946 @@ ] } }, + "/kilocode/session-import/project": { + "post": { + "operationId": "kilocode.sessionImport.project", + "parameters": [ + { + "in": "query", + "name": "directory", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "workspace", + "schema": { + "type": "string" + } + } + ], + "summary": "Insert project for session import", + "description": "Insert or update a project row used by legacy session import.", + "responses": { + "200": { + "description": "Project import result", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ok": { + "type": "boolean" + }, + "id": { + "type": "string" + } + }, + "required": [ + "ok", + "id" + ] + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "worktree": { + "type": "string" + }, + "vcs": { + "type": "string" + }, + "name": { + "type": "string" + }, + "iconUrl": { + "type": "string" + }, + "iconColor": { + "type": "string" + }, + "timeCreated": { + "type": "number" + }, + "timeUpdated": { + "type": "number" + }, + "timeInitialized": { + "type": "number" + }, + "sandboxes": { + "type": "array", + "items": { + "type": "string" + } + }, + "commands": { + "type": "object", + "properties": { + "start": { + "type": "string" + } + } + } + }, + "required": [ + "id", + "worktree", + "timeCreated", + "timeUpdated", + "sandboxes" + ] + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.kilocode.sessionImport.project({\n ...\n})" + } + ] + } + }, + "/kilocode/session-import/session": { + "post": { + "operationId": "kilocode.sessionImport.session", + "parameters": [ + { + "in": "query", + "name": "directory", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "workspace", + "schema": { + "type": "string" + } + } + ], + "summary": "Insert session for session import", + "description": "Insert or update a session row used by legacy session import.", + "responses": { + "200": { + "description": "Session import result", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ok": { + "type": "boolean" + }, + "id": { + "type": "string" + } + }, + "required": [ + "ok", + "id" + ] + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "projectID": { + "type": "string" + }, + "workspaceID": { + "type": "string" + }, + "parentID": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "directory": { + "type": "string" + }, + "title": { + "type": "string" + }, + "version": { + "type": "string" + }, + "shareURL": { + "type": "string" + }, + "summary": { + "type": "object", + "properties": { + "additions": { + "type": "number" + }, + "deletions": { + "type": "number" + }, + "files": { + "type": "number" + }, + "diffs": { + "type": "array", + "items": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + } + }, + "required": [ + "additions", + "deletions", + "files" + ] + }, + "revert": { + "type": "object", + "properties": { + "messageID": { + "type": "string" + }, + "partID": { + "type": "string" + }, + "snapshot": { + "type": "string" + }, + "diff": { + "type": "string" + } + }, + "required": [ + "messageID" + ] + }, + "permission": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "timeCreated": { + "type": "number" + }, + "timeUpdated": { + "type": "number" + }, + "timeCompacting": { + "type": "number" + }, + "timeArchived": { + "type": "number" + } + }, + "required": [ + "id", + "projectID", + "slug", + "directory", + "title", + "version", + "timeCreated", + "timeUpdated" + ] + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.kilocode.sessionImport.session({\n ...\n})" + } + ] + } + }, + "/kilocode/session-import/message": { + "post": { + "operationId": "kilocode.sessionImport.message", + "parameters": [ + { + "in": "query", + "name": "directory", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "workspace", + "schema": { + "type": "string" + } + } + ], + "summary": "Insert message for session import", + "description": "Insert or update a message row used by legacy session import.", + "responses": { + "200": { + "description": "Message import result", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ok": { + "type": "boolean" + }, + "id": { + "type": "string" + } + }, + "required": [ + "ok", + "id" + ] + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "sessionID": { + "type": "string" + }, + "timeCreated": { + "type": "number" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "role": { + "type": "string", + "const": "user" + }, + "time": { + "type": "object", + "properties": { + "created": { + "type": "number" + } + }, + "required": [ + "created" + ] + }, + "agent": { + "type": "string" + }, + "model": { + "type": "object", + "properties": { + "providerID": { + "type": "string" + }, + "modelID": { + "type": "string" + } + }, + "required": [ + "providerID", + "modelID" + ] + }, + "tools": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "type": "boolean" + } + } + }, + "required": [ + "role", + "time", + "agent", + "model" + ] + }, + { + "type": "object", + "properties": { + "role": { + "type": "string", + "const": "assistant" + }, + "time": { + "type": "object", + "properties": { + "created": { + "type": "number" + }, + "completed": { + "type": "number" + } + }, + "required": [ + "created" + ] + }, + "parentID": { + "type": "string" + }, + "modelID": { + "type": "string" + }, + "providerID": { + "type": "string" + }, + "mode": { + "type": "string" + }, + "agent": { + "type": "string" + }, + "path": { + "type": "object", + "properties": { + "cwd": { + "type": "string" + }, + "root": { + "type": "string" + } + }, + "required": [ + "cwd", + "root" + ] + }, + "summary": { + "type": "boolean" + }, + "cost": { + "type": "number" + }, + "tokens": { + "type": "object", + "properties": { + "total": { + "type": "number" + }, + "input": { + "type": "number" + }, + "output": { + "type": "number" + }, + "reasoning": { + "type": "number" + }, + "cache": { + "type": "object", + "properties": { + "read": { + "type": "number" + }, + "write": { + "type": "number" + } + }, + "required": [ + "read", + "write" + ] + } + }, + "required": [ + "input", + "output", + "reasoning", + "cache" + ] + }, + "structured": {}, + "variant": { + "type": "string" + }, + "finish": { + "type": "string" + } + }, + "required": [ + "role", + "time", + "parentID", + "modelID", + "providerID", + "mode", + "agent", + "path", + "cost", + "tokens" + ] + } + ] + } + }, + "required": [ + "id", + "sessionID", + "timeCreated", + "data" + ] + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.kilocode.sessionImport.message({\n ...\n})" + } + ] + } + }, + "/kilocode/session-import/part": { + "post": { + "operationId": "kilocode.sessionImport.part", + "parameters": [ + { + "in": "query", + "name": "directory", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "workspace", + "schema": { + "type": "string" + } + } + ], + "summary": "Insert part for session import", + "description": "Insert or update a part row used by legacy session import.", + "responses": { + "200": { + "description": "Part import result", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ok": { + "type": "boolean" + }, + "id": { + "type": "string" + } + }, + "required": [ + "ok", + "id" + ] + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "messageID": { + "type": "string" + }, + "sessionID": { + "type": "string" + }, + "timeCreated": { + "type": "number" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "text": { + "type": "string" + }, + "synthetic": { + "type": "boolean" + }, + "ignored": { + "type": "boolean" + }, + "time": { + "type": "object", + "properties": { + "start": { + "type": "number" + }, + "end": { + "type": "number" + } + }, + "required": [ + "start" + ] + }, + "metadata": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": [ + "type", + "text" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "reasoning" + }, + "text": { + "type": "string" + }, + "metadata": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "time": { + "type": "object", + "properties": { + "start": { + "type": "number" + }, + "end": { + "type": "number" + } + }, + "required": [ + "start" + ] + } + }, + "required": [ + "type", + "text", + "time" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "tool" + }, + "callID": { + "type": "string" + }, + "tool": { + "type": "string" + }, + "state": { + "anyOf": [ + { + "type": "object", + "properties": { + "status": { + "type": "string", + "const": "pending" + }, + "input": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "raw": { + "type": "string" + } + }, + "required": [ + "status", + "input", + "raw" + ] + }, + { + "type": "object", + "properties": { + "status": { + "type": "string", + "const": "running" + }, + "input": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "title": { + "type": "string" + }, + "metadata": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "time": { + "type": "object", + "properties": { + "start": { + "type": "number" + } + }, + "required": [ + "start" + ] + } + }, + "required": [ + "status", + "input", + "time" + ] + }, + { + "type": "object", + "properties": { + "status": { + "type": "string", + "const": "completed" + }, + "input": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "output": { + "type": "string" + }, + "title": { + "type": "string" + }, + "metadata": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "time": { + "type": "object", + "properties": { + "start": { + "type": "number" + }, + "end": { + "type": "number" + }, + "compacted": { + "type": "number" + } + }, + "required": [ + "start", + "end" + ] + } + }, + "required": [ + "status", + "input", + "output", + "title", + "metadata", + "time" + ] + }, + { + "type": "object", + "properties": { + "status": { + "type": "string", + "const": "error" + }, + "input": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "error": { + "type": "string" + }, + "metadata": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "time": { + "type": "object", + "properties": { + "start": { + "type": "number" + }, + "end": { + "type": "number" + } + }, + "required": [ + "start", + "end" + ] + } + }, + "required": [ + "status", + "input", + "error", + "time" + ] + } + ] + }, + "metadata": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": [ + "type", + "callID", + "tool", + "state" + ] + } + ] + } + }, + "required": [ + "id", + "messageID", + "sessionID", + "data" + ] + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.kilocode.sessionImport.part({\n ...\n})" + } + ] + } + }, "/kilocode/skill/remove": { "post": { "operationId": "kilocode.removeSkill", @@ -6158,7 +7116,32 @@ }, "groups": { "type": "array", - "items": {} + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "prefixItems": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "fileRegex": { + "type": "string" + }, + "description": { + "type": "string" + } + } + } + ] + } + ] + } } } } @@ -12659,6 +13642,15 @@ "isFree": { "type": "boolean" }, + "ai_sdk_provider": { + "type": "string", + "enum": [ + "anthropic", + "openai", + "openai-compatible", + "openrouter" + ] + }, "experimental": { "type": "boolean" }, @@ -13740,6 +14732,15 @@ }, "isFree": { "type": "boolean" + }, + "ai_sdk_provider": { + "type": "string", + "enum": [ + "anthropic", + "openai", + "openai-compatible", + "openrouter" + ] } }, "required": [ From 46daecebb1287c1aa1621fbb199d92dfcae162d8 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Tue, 31 Mar 2026 17:25:48 +0200 Subject: [PATCH 194/261] refactor: restrict PR to vscode changes only, revert cli/app/acp changes --- .../src/components/session-context-usage.tsx | 15 +----------- .../session/session-context-metrics.ts | 12 ++++------ .../session/session-context-tab.tsx | 15 +----------- packages/opencode/src/acp/agent.ts | 20 +--------------- .../src/cli/cmd/tui/routes/session/header.tsx | 23 ++++--------------- .../cli/cmd/tui/routes/session/sidebar.tsx | 13 +---------- 6 files changed, 12 insertions(+), 86 deletions(-) diff --git a/packages/app/src/components/session-context-usage.tsx b/packages/app/src/components/session-context-usage.tsx index 8a1a9ff5b12..08ae4d3194e 100644 --- a/packages/app/src/components/session-context-usage.tsx +++ b/packages/app/src/components/session-context-usage.tsx @@ -45,20 +45,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) { }), ) - // kilocode_change start - include subagent session costs in total - const childCost = createMemo(() => { - const id = params.id - if (!id) return 0 - return sync.data.session - .filter((s) => s.parentID === id) - .reduce( - (acc, child) => - acc + (sync.data.message[child.id] ?? []).reduce((sum, m) => sum + (m.role === "assistant" ? m.cost : 0), 0), - 0, - ) - }) - // kilocode_change end - const metrics = createMemo(() => getSessionContextMetrics(messages(), sync.data.provider.all, childCost())) + const metrics = createMemo(() => getSessionContextMetrics(messages(), sync.data.provider.all)) const context = createMemo(() => metrics().context) const cost = createMemo(() => { return usd().format(metrics().totalCost) diff --git a/packages/app/src/components/session/session-context-metrics.ts b/packages/app/src/components/session/session-context-metrics.ts index 78e09425f91..4bdcff52ebb 100644 --- a/packages/app/src/components/session/session-context-metrics.ts +++ b/packages/app/src/components/session/session-context-metrics.ts @@ -47,10 +47,8 @@ const lastAssistantWithTokens = (messages: Message[]) => { } } -// kilocode_change start - accept optional child cost to include subagent costs -const build = (messages: Message[] = [], providers: Provider[] = [], childCost = 0): Metrics => { - const totalCost = messages.reduce((sum, msg) => sum + (msg.role === "assistant" ? msg.cost : 0), 0) + childCost - // kilocode_change end +const build = (messages: Message[] = [], providers: Provider[] = []): Metrics => { + const totalCost = messages.reduce((sum, msg) => sum + (msg.role === "assistant" ? msg.cost : 0), 0) const message = lastAssistantWithTokens(messages) if (!message) return { totalCost, context: undefined } @@ -79,8 +77,6 @@ const build = (messages: Message[] = [], providers: Provider[] = [], childCost = } } -// kilocode_change start - accept optional child cost to include subagent costs -export function getSessionContextMetrics(messages: Message[] = [], providers: Provider[] = [], childCost = 0) { - return build(messages, providers, childCost) +export function getSessionContextMetrics(messages: Message[] = [], providers: Provider[] = []) { + return build(messages, providers) } -// kilocode_change end diff --git a/packages/app/src/components/session/session-context-tab.tsx b/packages/app/src/components/session/session-context-tab.tsx index 15c5b08e474..be5118c2eaf 100644 --- a/packages/app/src/components/session/session-context-tab.tsx +++ b/packages/app/src/components/session/session-context-tab.tsx @@ -134,20 +134,7 @@ export function SessionContextTab() { }), ) - // kilocode_change start - include subagent session costs in total - const childCost = createMemo(() => { - const id = params.id - if (!id) return 0 - return sync.data.session - .filter((s) => s.parentID === id) - .reduce( - (acc, child) => - acc + (sync.data.message[child.id] ?? []).reduce((sum, m) => sum + (m.role === "assistant" ? m.cost : 0), 0), - 0, - ) - }) - // kilocode_change end - const metrics = createMemo(() => getSessionContextMetrics(messages(), sync.data.provider.all, childCost())) + const metrics = createMemo(() => getSessionContextMetrics(messages(), sync.data.provider.all)) const ctx = createMemo(() => metrics().context) const formatter = createMemo(() => createSessionContextFormatter(language.intl())) diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index 3ad7446e18a..ac103a7ecfb 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -106,25 +106,7 @@ export namespace ACP { } const used = msg.tokens.input + (msg.tokens.cache?.read ?? 0) - // kilocode_change start - include subagent session costs in total - const children = await sdk.session - .children({ sessionID, directory }, { throwOnError: true }) - .then((x) => x.data ?? []) - .catch(() => [] as { id: string }[]) - const childCost = await Promise.all( - children.map((child) => - sdk.session - .messages({ sessionID: child.id, directory }, { throwOnError: true }) - .then((x) => - (x.data ?? []) - .filter((m): m is (typeof assistantMessages)[number] => m.info.role === "assistant") - .reduce((sum, m) => sum + m.info.cost, 0), - ) - .catch(() => 0), - ), - ).then((costs) => costs.reduce((a, b) => a + b, 0)) - const totalCost = assistantMessages.reduce((sum, m) => sum + m.info.cost, 0) + childCost - // kilocode_change end + const totalCost = assistantMessages.reduce((sum, m) => sum + m.info.cost, 0) await connection .sessionUpdate({ diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx index b1e9a9fb081..7999e392288 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx @@ -48,25 +48,10 @@ export function Header() { const messages = createMemo(() => sync.data.message[route.sessionID] ?? []) const cost = createMemo(() => { - // kilocode_change start - include subagent session costs in total - const sid = route.sessionID - const total = - pipe( - messages(), - sumBy((x) => (x.role === "assistant" ? x.cost : 0)), - ) + - sync.data.session - .filter((s) => s.parentID === sid) - .reduce( - (acc, child) => - acc + - pipe( - sync.data.message[child.id] ?? [], - sumBy((x) => (x.role === "assistant" ? x.cost : 0)), - ), - 0, - ) - // kilocode_change end + const total = pipe( + messages(), + sumBy((x) => (x.role === "assistant" ? x.cost : 0)), + ) return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx index 5c71bd8af06..45824208bfe 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx @@ -41,18 +41,7 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { ) const cost = createMemo(() => { - // kilocode_change start - include subagent session costs in total - const total = - messages().reduce((sum, x) => sum + (x.role === "assistant" ? x.cost : 0), 0) + - sync.data.session - .filter((s) => s.parentID === props.sessionID) - .reduce( - (acc, child) => - acc + - (sync.data.message[child.id] ?? []).reduce((sum, x) => sum + (x.role === "assistant" ? x.cost : 0), 0), - 0, - ) - // kilocode_change end + const total = messages().reduce((sum, x) => sum + (x.role === "assistant" ? x.cost : 0), 0) return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", From a59c59e66ce8bfbf2555ff49adf2c1b5933b1f3d Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Tue, 31 Mar 2026 17:32:33 +0200 Subject: [PATCH 195/261] fix(vscode): use sessionFamily BFS to sum subagent costs correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous approach searched store.sessions by parentID, but child sessions are not reliably present in store.sessions (they arrive via SSE and syncSession, not the initial sessions list). This caused the totalCost to miss subagent costs entirely—or even show a lower total than a single subagent's cost. Switch to sessionFamily() which does a BFS walk through tool parts to discover all descendant session IDs, then sum costs from their messages in the store. This is the same proven mechanism used for scoped permissions, questions, and familyData. --- .../kilo-vscode/webview-ui/src/context/session.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index c7c6356ecf0..65a47afcec7 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -1622,10 +1622,13 @@ export const SessionProvider: ParentComponent = (props) => { const totalCost = createMemo(() => { const id = currentSessionID() - const cost = calcTotalCost(messages()) - if (!id) return cost - const children = Object.values(store.sessions).filter((s) => s.parentID === id) - return children.reduce((acc, child) => acc + calcTotalCost(store.messages[child.id] ?? []), cost) + if (!id) return calcTotalCost(messages()) + const family = sessionFamily(id) + let total = 0 + for (const sid of family) { + total += calcTotalCost(store.messages[sid] ?? []) + } + return total }) // Status text derived from last assistant message parts From 0628696c18bb6d11128f220cd999debe291aad7c Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Tue, 31 Mar 2026 17:46:06 +0200 Subject: [PATCH 196/261] feat(vscode): show per-subagent cost breakdown in tooltip When a session has subagent costs, the cost tooltip in the task header now shows a line-by-line breakdown (e.g. 'Parent session: $0.12', 'Code review: $0.08'). Labels come from the task tool's input description or subagent_type. When there's only one session (no subagents), falls back to the simple 'Session cost' tooltip. --- .../src/components/chat/TaskHeader.tsx | 15 ++++--- .../webview-ui/src/context/session.tsx | 45 +++++++++++++++++++ .../kilo-vscode/webview-ui/src/i18n/en.ts | 1 + .../webview-ui/src/stories/StoryProviders.tsx | 1 + .../src/stories/history.stories.tsx | 1 + 5 files changed, 58 insertions(+), 5 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx index b79c775a03a..7a84feec650 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx @@ -27,13 +27,18 @@ export const TaskHeader: Component = (props) => { const busy = createMemo(() => session.status() === "busy") const canCompact = createMemo(() => !busy() && hasMessages() && !!session.selected()) + const fmt = (n: number) => new Intl.NumberFormat(language.locale(), { style: "currency", currency: "USD" }).format(n) + const cost = createMemo(() => { const total = session.totalCost() if (total === 0) return undefined - return new Intl.NumberFormat(language.locale(), { - style: "currency", - currency: "USD", - }).format(total) + return fmt(total) + }) + + const costTooltip = createMemo(() => { + const breakdown = session.costBreakdown() + if (breakdown.length <= 1) return language.t("context.usage.sessionCost") + return breakdown.map((e) => `${e.label}: ${fmt(e.cost)}`).join("\n") }) const context = createMemo(() => { @@ -69,7 +74,7 @@ export const TaskHeader: Component = (props) => {
{(c) => ( - + {c()} )} diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index 65a47afcec7..3354ef72c2e 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -127,6 +127,7 @@ interface SessionContextValue { // Cost and context usage for the current session totalCost: Accessor + costBreakdown: Accessor> contextUsage: Accessor // Skills loaded from the CLI backend @@ -1631,6 +1632,49 @@ export const SessionProvider: ParentComponent = (props) => { return total }) + /** + * Per-session cost breakdown for the current session family. + * Returns entries only for sessions with non-zero cost. + * Child session labels come from the task tool part that spawned them. + */ + const costBreakdown = createMemo>(() => { + const id = currentSessionID() + if (!id) return [] + const family = sessionFamily(id) + if (family.size <= 1) return [] + + // Build label map: child sessionID → label from the parent's task tool input + const labels = new Map() + for (const sid of family) { + const msgs = store.messages[sid] + if (!msgs) continue + for (const msg of msgs) { + const parts = store.parts[msg.id] + if (!parts) continue + for (const p of parts) { + if (p.type !== "tool") continue + const tp = p as { + tool: string + state?: { input?: { description?: string; subagent_type?: string }; metadata?: { sessionId?: string } } + } + const child = tp.state?.metadata?.sessionId + if (!child || !family.has(child)) continue + const desc = tp.state?.input?.description || tp.state?.input?.subagent_type || tp.tool + if (!labels.has(child)) labels.set(child, desc) + } + } + } + + const items: Array<{ label: string; cost: number }> = [] + for (const sid of family) { + const cost = calcTotalCost(store.messages[sid] ?? []) + if (cost === 0) continue + const label = sid === id ? language.t("context.stats.parentSession") : (labels.get(sid) ?? sid.slice(0, 8)) + items.push({ label, cost }) + } + return items + }) + // Status text derived from last assistant message parts const statusText = createMemo(() => { if (status() === "idle") return undefined @@ -1685,6 +1729,7 @@ export const SessionProvider: ParentComponent = (props) => { hasModelOverride, clearModelOverride, totalCost, + costBreakdown, contextUsage, agents, skills, diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 7e5d1c0f01e..9c3e83f943b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -945,6 +945,7 @@ export const dict = { "prompt.placeholder.error": "Connection failed. Check the output panel or restart the extension.", "context.usage.sessionCost": "Session cost", + "context.stats.parentSession": "Parent session", "time.justNow": "just now", "time.minutesAgo": "{{count}} min ago", diff --git a/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx b/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx index 4c0f733837c..b43be721d62 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx @@ -161,6 +161,7 @@ export function mockSessionValue(overrides?: { hasModelOverride: () => false, clearModelOverride: noop, totalCost: () => 0, + costBreakdown: () => [], contextUsage: () => undefined, agents: () => [{ name: "code", description: "Code mode", mode: "primary" as const }], skills: () => [], diff --git a/packages/kilo-vscode/webview-ui/src/stories/history.stories.tsx b/packages/kilo-vscode/webview-ui/src/stories/history.stories.tsx index c0cffaea1cf..8f746766bae 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/history.stories.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/history.stories.tsx @@ -74,6 +74,7 @@ const WithSessions: ParentComponent<{ sessions?: typeof mockSessions }> = (props hasModelOverride: () => false, clearModelOverride: noop, totalCost: () => 0, + costBreakdown: () => [], contextUsage: () => undefined, agents: () => [{ name: "code", description: "Code mode", mode: "primary" as const }], selectedAgent: () => "code", From bcbd2b423b977f6fcc7d78126088ba957de124ee Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:48:20 +0000 Subject: [PATCH 197/261] docs(vscode): prune completed items from migration plan - Remove Settings Migration, Upgrade Onboarding, and MemoryBank Migration docs (all covered by the migration wizard shipped in #7823) - Remove custom-openai-provider-ui.md (feature shipped) - Update MCP docs: remove connection status and enable/disable toggle (shipped in #7810) - Update settings-ui.md: remove import/export (shipped in #7794) - Update opencode-migration-plan.md accordingly --- .../agent-behaviour/mcp-server-creation.md | 8 +-- .../features/custom-openai-provider-ui.md | 15 ----- .../docs/migration/memorybank-migration.md | 12 ---- .../docs/migration/settings-migration.md | 30 --------- .../docs/migration/upgrade-onboarding.md | 15 ----- .../non-agent-features/mcp-and-mcp-hub.md | 6 +- .../docs/non-agent-features/settings-ui.md | 3 +- .../docs/opencode-migration-plan.md | 61 ++++++++----------- 8 files changed, 32 insertions(+), 118 deletions(-) delete mode 100644 packages/kilo-vscode/docs/features/custom-openai-provider-ui.md delete mode 100644 packages/kilo-vscode/docs/migration/memorybank-migration.md delete mode 100644 packages/kilo-vscode/docs/migration/settings-migration.md delete mode 100644 packages/kilo-vscode/docs/migration/upgrade-onboarding.md diff --git a/packages/kilo-vscode/docs/agent-behaviour/mcp-server-creation.md b/packages/kilo-vscode/docs/agent-behaviour/mcp-server-creation.md index 7656a450dcb..2b2096bb9c1 100644 --- a/packages/kilo-vscode/docs/agent-behaviour/mcp-server-creation.md +++ b/packages/kilo-vscode/docs/agent-behaviour/mcp-server-creation.md @@ -2,7 +2,7 @@ **Priority:** P2 -The legacy MCP Servers sub-tab (842 lines) had full server lifecycle management. The new sub-tab can only view and remove servers. +The legacy MCP Servers sub-tab (842 lines) had full server lifecycle management. The new sub-tab supports viewing, removing, and toggling servers with live connection status. ## Side-by-Side Comparison @@ -12,8 +12,8 @@ The legacy MCP Servers sub-tab (842 lines) had full server lifecycle management. | Add server | Via edit config file buttons | Not available | | Remove server | Delete button + confirmation | Remove button + confirmation | | Edit server config | Via edit config file buttons | Not available | -| Connection status | Colored dot (green/yellow/red) | Not displayed | -| Enable/disable toggle | `ToggleSwitch` per server | Not available | +| Connection status | Colored dot (green/yellow/red) | Live status display | +| Enable/disable toggle | `ToggleSwitch` per server | Connect/disconnect toggle | | Restart/refresh | Per-server refresh button | Not available | | Refresh all | "Refresh All MCP Servers" button | Not available | | Edit Global MCP config | Button to open file | Not available | @@ -42,8 +42,6 @@ The new extension has none of this expandable detail. - **Add MCP Server dialog**: Form to define a new server with name, transport type (stdio/SSE), command+args or URL, environment variables. Write to CLI config via `updateConfig()` - **Edit MCP Server**: Allow modifying existing server configurations -- **Connection status indicators**: Display per-server connection state. Requires CLI to expose MCP connection status via API or SSE events -- **Enable/disable toggle**: Per-server toggle that writes to CLI config without removing the server - **Restart/refresh button**: Per-server and "refresh all" buttons. Requires CLI endpoint to restart MCP servers - **Edit config file buttons**: Quick links to open global/project MCP config in the editor diff --git a/packages/kilo-vscode/docs/features/custom-openai-provider-ui.md b/packages/kilo-vscode/docs/features/custom-openai-provider-ui.md deleted file mode 100644 index b23f58af664..00000000000 --- a/packages/kilo-vscode/docs/features/custom-openai-provider-ui.md +++ /dev/null @@ -1,15 +0,0 @@ -# Custom OpenAI-Compatible Provider UI - -**Priority:** P1 -**Issue:** [#6163](https://github.com/Kilo-Org/kilocode/issues/6163) - -No UI for adding custom OpenAI-compatible providers. Users must manually edit `opencode.json`. The web/TUI app has a full `DialogCustomProvider`. - -## Remaining Work - -- Port `DialogCustomProvider` from `packages/app/src/components/dialog-custom-provider.tsx` to extension webview -- Add "Add custom provider" button to the Providers tab -- Dialog should collect: Provider ID, display name, base URL, API key, model entries, optional custom HTTP headers -- On save, write to CLI config via `handleUpdateConfig()` endpoint -- Validate inputs; show inline errors -- After adding, provider should appear in list and models in model selector diff --git a/packages/kilo-vscode/docs/migration/memorybank-migration.md b/packages/kilo-vscode/docs/migration/memorybank-migration.md deleted file mode 100644 index 6956da0d1cc..00000000000 --- a/packages/kilo-vscode/docs/migration/memorybank-migration.md +++ /dev/null @@ -1,12 +0,0 @@ -# MemoryBank Migration - -**Priority:** P1 -**Issue:** [#6091](https://github.com/Kilo-Org/kilocode/issues/6091) - -## Remaining Work - -- Detect whether user has MemoryBank content in old extension's `workspaceState` -- Offer to migrate MemoryBank content to `AGENTS.md` in workspace root (or `~/.kilocode/rules/` for global rules) -- Show content for review before writing — do not silently overwrite existing `AGENTS.md` -- If `AGENTS.md` already exists, offer to append with a clear delimiter -- Show documentation explaining that `AGENTS.md` / rules files are the equivalent of MemoryBank diff --git a/packages/kilo-vscode/docs/migration/settings-migration.md b/packages/kilo-vscode/docs/migration/settings-migration.md deleted file mode 100644 index 140a592f500..00000000000 --- a/packages/kilo-vscode/docs/migration/settings-migration.md +++ /dev/null @@ -1,30 +0,0 @@ -# Settings Migration from Old Extension - -**Priority:** P1 -**Issue:** [#6089](https://github.com/Kilo-Org/kilocode/issues/6089) - -## Remaining Work - -- On first activation, detect whether old extension settings exist in `vscode.ExtensionContext.globalState` or `vscode.workspace.getConfiguration('kilo-code')` -- Read relevant settings: API keys, provider configuration, model preferences, auto-approve rules, custom instructions -- Map old settings keys to CLI config equivalents in `opencode.json` -- If CLI config already has settings, show a diff and ask user to confirm before overwriting -- Write approved settings to CLI config via `/global/config` endpoint or directly to `opencode.json` -- Show what was migrated and what was not -- Mark migration as complete in `globalState` so it doesn't run again - -## Agent Behaviour Tab Settings to Migrate - -Settings from the legacy "Agent Behaviour" tab (Modes, MCP Servers, Rules, Workflows, Skills sub-tabs): - -| Legacy Setting | CLI Equivalent | Notes | -| ----------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------- | -| `customModes` (custom mode definitions) | CLI agent config in `opencode.json` | Map `roleDefinition` → `prompt`, `groups` → CLI tool permissions | -| `customModePrompts` (per-mode overrides) | Per-agent `prompt`, `temperature`, etc. | Map each mode slug to CLI agent name | -| `customInstructions` (global, shown in Modes sub-tab) | Rule files in `.kilocode/rules/` or `config.instructions` | May need a global instructions config key in CLI | -| `modeApiConfigs` (per-mode model) | Per-agent `model` | Map mode slug → agent name → model ID | -| MCP server configs | `config.mcp` | CLI owns MCP config | -| `localRulesToggles` / `globalRulesToggles` | `config.instructions` | Toggle state doesn't map directly — CLI has path list | -| `localWorkflowToggles` / `globalWorkflowToggles` | CLI custom commands (TBD) | Workflow concept mapping needs clarification | - -See [Agent Behaviour Tab Parity](../agent-behaviour/) docs for detailed sub-tab comparisons. diff --git a/packages/kilo-vscode/docs/migration/upgrade-onboarding.md b/packages/kilo-vscode/docs/migration/upgrade-onboarding.md deleted file mode 100644 index 4f409abd2ee..00000000000 --- a/packages/kilo-vscode/docs/migration/upgrade-onboarding.md +++ /dev/null @@ -1,15 +0,0 @@ -# Upgrade Onboarding Experience - -**Priority:** P1 -**Issue:** [#6188](https://github.com/Kilo-Org/kilocode/issues/6188) - -## Remaining Work - -- Detect upgraders by checking for old `globalState` keys (e.g., `kilo-code.taskHistory`) -- Show distinct onboarding screen that: - - Acknowledges they are an existing user - - Explains the new CLI backend architecture - - Shows what settings have been migrated and what hasn't - - Links to documentation on what changed -- Do not show generic "new user" welcome screen to upgraders -- Store `kilo-code.new.upgradeOnboardingShown` flag in `globalState` diff --git a/packages/kilo-vscode/docs/non-agent-features/mcp-and-mcp-hub.md b/packages/kilo-vscode/docs/non-agent-features/mcp-and-mcp-hub.md index 0d2e3eb1742..abfd67524fa 100644 --- a/packages/kilo-vscode/docs/non-agent-features/mcp-and-mcp-hub.md +++ b/packages/kilo-vscode/docs/non-agent-features/mcp-and-mcp-hub.md @@ -2,13 +2,11 @@ **Priority:** P1 -Settings UI shows a read-only list of configured MCP servers. HTTP client methods exist for add/connect/disconnect. +Settings UI supports viewing, removing, and toggling MCP servers with live connection status. Add/edit is not yet available. ## Remaining Work -- Add/edit/delete MCP server controls in the settings UI -- Connect/disconnect controls per server +- Add/edit MCP server controls in the settings UI - Tool allowlisting/disablement per server -- Connection status display per server (connected/disconnected/error) - Auto-reconnect and error history display - MCP Hub for discovering available MCP servers diff --git a/packages/kilo-vscode/docs/non-agent-features/settings-ui.md b/packages/kilo-vscode/docs/non-agent-features/settings-ui.md index 47dc84ffd58..0bd936280a0 100644 --- a/packages/kilo-vscode/docs/non-agent-features/settings-ui.md +++ b/packages/kilo-vscode/docs/non-agent-features/settings-ui.md @@ -2,14 +2,13 @@ **Priority:** P1 -12 of 14 tabs are functional. +12 of 14 tabs are functional. Import/export settings is available in the About tab. ## Remaining Work - **Terminal tab**: Shows "Not implemented" message - **Prompts tab**: Shows "Not implemented" message - **Workflows subtab** (inside AgentBehaviour): Renders a `` with no functionality -- Import/export settings functionality ## Related Docs diff --git a/packages/kilo-vscode/docs/opencode-migration-plan.md b/packages/kilo-vscode/docs/opencode-migration-plan.md index e16202e4dfd..bf244c5a446 100644 --- a/packages/kilo-vscode/docs/opencode-migration-plan.md +++ b/packages/kilo-vscode/docs/opencode-migration-plan.md @@ -22,23 +22,23 @@ This document tracks remaining work needed for feature parity with the old exten ## Non-Agent Feature Parity -| Feature | Remaining Work | Backend | Priority | -| ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -------- | -| [Authentication & Enterprise](non-agent-features/authentication-organization-enterprise-enforcement.md) | Org feature flags, MDM policy enforcement | CLI handles its auth; extension handles org/MDM | P1 | -| [Auto-Purge](non-agent-features/auto-purge.md) | Scheduled cleanup of old session/task storage | Extension-side (storage ownership TBD) | P3 | -| [Cloud Task Support](non-agent-features/cloud-task-support.md) | Upload local sessions to cloud, real-time sync, conflict resolution | Kilo cloud API + CLI; extension provides UI | P2 | -| [Code Reviews](non-agent-features/code-reviews.md) | Local review mode, automated AI review of uncommitted/branch changes | CLI (partial); extension for VS Code review UX | P2 | -| [Codebase Indexing & Semantic Search](non-agent-features/codebase-indexing-semantic-search.md) | Vector indexing, semantic search, embeddings infrastructure | CLI has grep/glob endpoints; semantic indexing is extension or cloud | P2 | -| [Contribution Tracking](non-agent-features/contribution-tracking.md) | AI attribution tracking, line fingerprinting, reporting | Extension-side | P3 | -| [Custom Commands](non-agent-features/custom-command-system.md) | Slash command system, project-level command discovery, YAML frontmatter support | CLI has custom commands; extension provides UI entry points | P2 | -| [Marketplace](non-agent-features/marketplace.md) | Catalog, install, update capabilities (toolbar button exists but renders a stub) | Extension-side | P2 | -| [MCP & MCP Hub](non-agent-features/mcp-and-mcp-hub.md) | MCP configuration UI (add/edit/delete servers), tool allowlisting, connection status display | CLI owns MCP lifecycle; extension provides config UI | P1 | -| [Repository Initialization](non-agent-features/repository-initialization.md) | /init command support for setting up agentic engineering | CLI /init endpoint; extension provides UI trigger | P3 | -| [Rules & Workflows](non-agent-features/rules-and-workflows.md) | Workflow management UI (rules subtab exists, workflows subtab is a stub) | CLI owns rules runtime; extension provides management UI | P3 | -| [Settings Sync](non-agent-features/settings-sync-integration.md) | VS Code Settings Sync allowlist registration | Extension-side (VS Code API) | P3 | -| [Settings UI](non-agent-features/settings-ui.md) | Terminal and Prompts tabs (show "Not implemented"), Workflows subtab stub, import/export settings | CLI exposes config; extension provides settings forms | P1 | -| [Skills System](non-agent-features/skills-system.md) | Skill execution, discovery, hot-reload (config UI for paths/URLs exists) | CLI has skills runtime; extension provides packaging/UI | P2 | -| [Speech-to-Text](non-agent-features/speech-to-text.md) | Voice input, streaming STT | Webview (mic capture); CLI-compatible STT optional | P3 | +| Feature | Remaining Work | Backend | Priority | +| ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -------- | +| [Authentication & Enterprise](non-agent-features/authentication-organization-enterprise-enforcement.md) | Org feature flags, MDM policy enforcement | CLI handles its auth; extension handles org/MDM | P1 | +| [Auto-Purge](non-agent-features/auto-purge.md) | Scheduled cleanup of old session/task storage | Extension-side (storage ownership TBD) | P3 | +| [Cloud Task Support](non-agent-features/cloud-task-support.md) | Upload local sessions to cloud, real-time sync, conflict resolution | Kilo cloud API + CLI; extension provides UI | P2 | +| [Code Reviews](non-agent-features/code-reviews.md) | Local review mode, automated AI review of uncommitted/branch changes | CLI (partial); extension for VS Code review UX | P2 | +| [Codebase Indexing & Semantic Search](non-agent-features/codebase-indexing-semantic-search.md) | Vector indexing, semantic search, embeddings infrastructure | CLI has grep/glob endpoints; semantic indexing is extension or cloud | P2 | +| [Contribution Tracking](non-agent-features/contribution-tracking.md) | AI attribution tracking, line fingerprinting, reporting | Extension-side | P3 | +| [Custom Commands](non-agent-features/custom-command-system.md) | Slash command system, project-level command discovery, YAML frontmatter support | CLI has custom commands; extension provides UI entry points | P2 | +| [Marketplace](non-agent-features/marketplace.md) | Catalog, install, update capabilities (toolbar button exists but renders a stub) | Extension-side | P2 | +| [MCP & MCP Hub](non-agent-features/mcp-and-mcp-hub.md) | MCP configuration UI (add/edit/delete servers), tool allowlisting | CLI owns MCP lifecycle; extension provides config UI | P1 | +| [Repository Initialization](non-agent-features/repository-initialization.md) | /init command support for setting up agentic engineering | CLI /init endpoint; extension provides UI trigger | P3 | +| [Rules & Workflows](non-agent-features/rules-and-workflows.md) | Workflow management UI (rules subtab exists, workflows subtab is a stub) | CLI owns rules runtime; extension provides management UI | P3 | +| [Settings Sync](non-agent-features/settings-sync-integration.md) | VS Code Settings Sync allowlist registration | Extension-side (VS Code API) | P3 | +| [Settings UI](non-agent-features/settings-ui.md) | Terminal and Prompts tabs (show "Not implemented"), Workflows subtab stub | CLI exposes config; extension provides settings forms | P1 | +| [Skills System](non-agent-features/skills-system.md) | Skill execution, discovery, hot-reload (config UI for paths/URLs exists) | CLI has skills runtime; extension provides packaging/UI | P2 | +| [Speech-to-Text](non-agent-features/speech-to-text.md) | Voice input, streaming STT | Webview (mic capture); CLI-compatible STT optional | P3 | --- @@ -49,7 +49,7 @@ The "Agent Behaviour" settings tab contains 5 sub-tabs in both the legacy and ne | Sub-Tab | Remaining Work | Priority | | --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------- | | [Modes / Agents](agent-behaviour/modes-subtab-parity.md) | Core CRUD done (PR #7225). Remaining: when-to-use, system prompt preview, import/export, default variant, hidden/disable, org features | P2 | -| [MCP Servers](agent-behaviour/mcp-server-creation.md) | Add/edit servers, connection status, enable/disable toggle, restart, per-server timeout, expandable detail (tools/resources/logs/auth) | P2 | +| [MCP Servers](agent-behaviour/mcp-server-creation.md) | Add/edit servers, restart, per-server timeout, expandable detail (tools/resources/logs/auth) | P2 | | [Rules & Workflows](agent-behaviour/rules-workflows-subtab-parity.md) | Rules: description text, global/workspace separation, per-rule toggles, new file creation, auto-discovery. Workflows: entire sub-tab is a stub | P2/P3 | | Skills | Minor gaps: project/global separation, mode badge per skill. Covered by [Skills System](non-agent-features/skills-system.md) | P2 | @@ -70,28 +70,19 @@ Open issues from the [GitHub project board](https://github.com/orgs/Kilo-Org/pro ### Features -| Feature | Remaining Work | Priority | -| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------- | -------- | -| [File Attachments](features/file-attachments.md) | Add non-image file attachment via button, drag-and-drop, or file picker | P2 | -| [Task Completion Notification](features/task-completion-notification.md) | VS Code toast when task completes or awaits input while panel is hidden | P2 | -| [Custom OpenAI-Compatible Provider UI](features/custom-openai-provider-ui.md) | Port `DialogCustomProvider` from `packages/app` to extension webview | P1 | -| [Remember Last Model Choice](features/remember-last-model.md) | Persist last-used model and pre-select it for new sessions | P2 | -| [Expandable MCP Tools](features/expandable-mcp-tools.md) | Make MCP tool rows expandable to show inputs/outputs like regular tools | P2 | -| [Session Preview Improvements](features/session-preview-improvements.md) | Evaluate showing first message snippet or improving title generation | P2 | - -### Migration (old extension → new) - -| Feature | Remaining Work | Priority | -| --------------------------------------------------------- | ---------------------------------------------------------------------------- | -------- | -| [Settings Migration](migration/settings-migration.md) | Read old extension settings and offer to import into CLI config on first run | P1 | -| [MemoryBank Migration](migration/memorybank-migration.md) | Detect MemoryBank content and offer to migrate it to AGENTS.md | P1 | -| [Upgrade Onboarding](migration/upgrade-onboarding.md) | Show distinct onboarding for upgraders explaining what changed | P1 | +| Feature | Remaining Work | Priority | +| ------------------------------------------------------------------------ | ----------------------------------------------------------------------- | -------- | +| [File Attachments](features/file-attachments.md) | Add non-image file attachment via button, drag-and-drop, or file picker | P2 | +| [Task Completion Notification](features/task-completion-notification.md) | VS Code toast when task completes or awaits input while panel is hidden | P2 | +| [Remember Last Model Choice](features/remember-last-model.md) | Persist last-used model and pre-select it for new sessions | P2 | +| [Expandable MCP Tools](features/expandable-mcp-tools.md) | Make MCP tool rows expandable to show inputs/outputs like regular tools | P2 | +| [Session Preview Improvements](features/session-preview-improvements.md) | Evaluate showing first message snippet or improving title generation | P2 | ### Error Handling & Reliability | Feature | Remaining Work | Priority | | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -------- | -| [Pre-Release Switch CPU Spike](error-handling/pre-release-switch-crash.md) | Fix race condition / process conflict when switching release ↔ pre-release | P0 | +| [Pre-Release Switch CPU Spike](error-handling/pre-release-switch-crash.md) | Fix race condition / process conflict when switching release ↔ pre-release | P0 | | [Extension View Doesn't Refresh on Update](error-handling/extension-refresh-on-update.md) | Force webview reload when extension version changes | P1 | | [Propagate CLI Errors to UI](error-handling/propagate-cli-errors-to-ui.md) | Surface CLI stderr errors in chat or as VS Code notifications | P1 | | [CLI Startup Errors](error-handling/cli-startup-errors.md) | Detect CLI process exit before connection; show error with details and retry | P1 | From c0cf8dface90f146aa6a3da0d1c744abce0fea35 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Tue, 31 Mar 2026 17:50:13 +0200 Subject: [PATCH 198/261] fix(vscode): render cost breakdown tooltip as JSX with proper line breaks - Use
per entry instead of newline-joined string (Tooltip value prop accepts JSX, not plain text with newlines) - Prefer subagent_type over description for shorter labels - Truncate labels longer than 24 chars - Add white-space: nowrap to prevent wrapping within entries --- .../webview-ui/src/components/chat/TaskHeader.tsx | 8 ++++++-- packages/kilo-vscode/webview-ui/src/context/session.tsx | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx index 7a84feec650..6e317da3261 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx @@ -37,8 +37,12 @@ export const TaskHeader: Component = (props) => { const costTooltip = createMemo(() => { const breakdown = session.costBreakdown() - if (breakdown.length <= 1) return language.t("context.usage.sessionCost") - return breakdown.map((e) => `${e.label}: ${fmt(e.cost)}`).join("\n") + if (breakdown.length <= 1) return {language.t("context.usage.sessionCost")} + return ( +
+ {(e) =>
{`${e.label}: ${fmt(e.cost)}`}
}
+
+ ) }) const context = createMemo(() => { diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index 3354ef72c2e..54e2935ca22 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -1659,7 +1659,8 @@ export const SessionProvider: ParentComponent = (props) => { } const child = tp.state?.metadata?.sessionId if (!child || !family.has(child)) continue - const desc = tp.state?.input?.description || tp.state?.input?.subagent_type || tp.tool + const raw = tp.state?.input?.subagent_type || tp.state?.input?.description || tp.tool + const desc = raw.length > 24 ? raw.slice(0, 22) + "…" : raw if (!labels.has(child)) labels.set(child, desc) } } From 6778099552cb72166a2e9d62266bc0135707e9ad Mon Sep 17 00:00:00 2001 From: Marius Date: Tue, 31 Mar 2026 18:16:59 +0200 Subject: [PATCH 199/261] fix(vscode): wire continueInWorktreeHandler for tab panels (#8013) Tab KiloProvider instances (Open in Tab and TabPanel deserializer) were missing setContinueInWorktreeHandler, causing "Continue in Worktree" to silently no-op and leave the spinner stuck on "Capturing changes..." forever. Wire the handler for both openKiloInNewTab and the tab deserializer, and add a defensive error fallback in KiloProvider when the handler is null. --- packages/kilo-vscode/src/KiloProvider.ts | 7 ++ packages/kilo-vscode/src/extension.ts | 14 ++- .../tests/unit/extension-arch.test.ts | 99 +++++++++++++++++++ 3 files changed, 118 insertions(+), 2 deletions(-) diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index f380ea6c01f..c6e1a046da1 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -598,6 +598,13 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper error: err instanceof Error ? err.message : String(err), }) }) + } else if (message.sessionId) { + console.error("[Kilo New] continueInWorktree: no handler registered") + this.postMessage({ + type: "continueInWorktreeProgress", + status: "error", + error: "Continue in Worktree is not available", + }) } break case "retryConnection": diff --git a/packages/kilo-vscode/src/extension.ts b/packages/kilo-vscode/src/extension.ts index 56d8124d8f6..bf6d27da0f2 100644 --- a/packages/kilo-vscode/src/extension.ts +++ b/packages/kilo-vscode/src/extension.ts @@ -90,6 +90,9 @@ export function activate(context: vscode.ExtensionContext) { vscode.window.registerWebviewPanelSerializer("kilo-code.new.TabPanel", { deserializeWebviewPanel(panel: vscode.WebviewPanel) { const tabProvider = new KiloProvider(context.extensionUri, connectionService, context) + tabProvider.setContinueInWorktreeHandler((sessionId, progress) => + agentManagerProvider.continueFromSidebar(sessionId, progress), + ) tabProvider.resolveWebviewPanel(panel) panel.onDidDispose( () => { @@ -196,7 +199,7 @@ export function activate(context: vscode.ExtensionContext) { provider.postMessage({ type: "triggerTask", text: `Generate a terminal command: ${input}` }) }), vscode.commands.registerCommand("kilo-code.new.openInTab", () => { - return openKiloInNewTab(context, connectionService) + return openKiloInNewTab(context, connectionService, agentManagerProvider) }), vscode.commands.registerCommand("kilo-code.new.showChanges", () => { diffViewerProvider.openPanel() @@ -323,7 +326,11 @@ export function deactivate() { TelemetryProxy.getInstance().shutdown() } -async function openKiloInNewTab(context: vscode.ExtensionContext, connectionService: KiloConnectionService) { +async function openKiloInNewTab( + context: vscode.ExtensionContext, + connectionService: KiloConnectionService, + agentManagerProvider: AgentManagerProvider, +) { const lastCol = Math.max(...vscode.window.visibleTextEditors.map((e) => e.viewColumn || 0), 0) const hasVisibleEditors = vscode.window.visibleTextEditors.length > 0 @@ -345,6 +352,9 @@ async function openKiloInNewTab(context: vscode.ExtensionContext, connectionServ } const tabProvider = new KiloProvider(context.extensionUri, connectionService, context) + tabProvider.setContinueInWorktreeHandler((sessionId, progress) => + agentManagerProvider.continueFromSidebar(sessionId, progress), + ) tabProvider.resolveWebviewPanel(panel) // Wait for the new panel to become active before locking the editor group. diff --git a/packages/kilo-vscode/tests/unit/extension-arch.test.ts b/packages/kilo-vscode/tests/unit/extension-arch.test.ts index 8a935d450d2..233f844bdb3 100644 --- a/packages/kilo-vscode/tests/unit/extension-arch.test.ts +++ b/packages/kilo-vscode/tests/unit/extension-arch.test.ts @@ -14,6 +14,8 @@ import path from "node:path" const ROOT = path.resolve(import.meta.dir, "../..") const PKG_JSON_FILE = path.join(ROOT, "package.json") const SRC_DIR = path.join(ROOT, "src") +const EXTENSION_FILE = path.join(ROOT, "src/extension.ts") +const KILO_PROVIDER_FILE = path.join(ROOT, "src/KiloProvider.ts") function readSrcFiles(dir: string): string { const parts: string[] = [] @@ -84,3 +86,100 @@ describe("Extension — package.json command sync", () => { ).toEqual([]) }) }) + +// --------------------------------------------------------------------------- +// KiloProvider handler wiring — every new KiloProvider() must get +// setContinueInWorktreeHandler() called before resolving its webview. +// +// Regression: tab panels created via openKiloInNewTab() and the TabPanel +// deserializer were missing the handler, causing "Capturing changes..." to +// spin forever because the webview message was silently dropped. +// --------------------------------------------------------------------------- + +describe("Extension — KiloProvider handler wiring", () => { + const ext = fs.readFileSync(EXTENSION_FILE, "utf-8") + + /** + * Every `new KiloProvider(` in extension.ts must be followed (before the + * next `new KiloProvider(`) by a `setContinueInWorktreeHandler` call. + * This prevents future tab/panel additions from silently missing the handler. + */ + it("every KiloProvider instance gets setContinueInWorktreeHandler wired", () => { + const pattern = /new KiloProvider\(/g + const instances: number[] = [] + let match + while ((match = pattern.exec(ext)) !== null) { + instances.push(match.index) + } + + expect( + instances.length, + "expected at least 3 KiloProvider instances (sidebar, tab, deserializer)", + ).toBeGreaterThanOrEqual(3) + + const missing: string[] = [] + for (let i = 0; i < instances.length; i++) { + const start = instances[i] + const end = instances[i + 1] ?? ext.length + const region = ext.slice(start, end) + + if (!region.includes("setContinueInWorktreeHandler")) { + const line = ext.slice(0, start).split("\n").length + missing.push(`KiloProvider at line ${line}`) + } + } + + expect( + missing, + `These KiloProvider instances are missing setContinueInWorktreeHandler.\n` + + `Without it, "Continue in Worktree" silently no-ops and the spinner\n` + + `stays stuck on "Capturing changes..." forever.\n\n` + + missing.map((m) => ` - ${m}`).join("\n"), + ).toEqual([]) + }) + + it("openKiloInNewTab wires setContinueInWorktreeHandler before resolveWebviewPanel", () => { + const fn = ext.indexOf("function openKiloInNewTab") + expect(fn, "openKiloInNewTab must exist").toBeGreaterThan(-1) + const body = ext.slice(fn, fn + 1500) + const handler = body.indexOf("setContinueInWorktreeHandler") + const resolve = body.indexOf("resolveWebviewPanel") + expect(handler, "setContinueInWorktreeHandler must be called").toBeGreaterThan(-1) + expect(resolve, "resolveWebviewPanel must be called").toBeGreaterThan(-1) + expect(handler, "handler must be wired before resolving the panel").toBeLessThan(resolve) + }) + + it("TabPanel deserializer wires setContinueInWorktreeHandler before resolveWebviewPanel", () => { + const serializer = ext.indexOf('"kilo-code.new.TabPanel"') + expect(serializer, "TabPanel serializer must exist").toBeGreaterThan(-1) + const body = ext.slice(serializer, serializer + 800) + const handler = body.indexOf("setContinueInWorktreeHandler") + const resolve = body.indexOf("resolveWebviewPanel") + expect(handler, "setContinueInWorktreeHandler must be called in deserializer").toBeGreaterThan(-1) + expect(resolve, "resolveWebviewPanel must be called in deserializer").toBeGreaterThan(-1) + expect(handler, "handler must be wired before resolving the panel").toBeLessThan(resolve) + }) +}) + +// --------------------------------------------------------------------------- +// KiloProvider — continueInWorktree error fallback +// +// Regression: when continueInWorktreeHandler is null, the message handler +// must send an error back to the webview so the spinner resets. Previously +// it silently no-op'd, leaving the UI stuck. +// --------------------------------------------------------------------------- + +describe("KiloProvider — continueInWorktree error fallback", () => { + const provider = fs.readFileSync(KILO_PROVIDER_FILE, "utf-8") + + it("sends error progress when handler is missing", () => { + const caseStart = provider.indexOf('case "continueInWorktree"') + expect(caseStart, "continueInWorktree case must exist").toBeGreaterThan(-1) + const caseEnd = provider.indexOf("break", caseStart) + const block = provider.slice(caseStart, caseEnd) + + expect(block, "must have else branch for missing handler").toContain("else if") + expect(block, "must send error status back to webview").toContain('"error"') + expect(block, "must use continueInWorktreeProgress message type").toContain("continueInWorktreeProgress") + }) +}) From ce2c4ecf8c7556354f7d24515be233c96eca286a Mon Sep 17 00:00:00 2001 From: Marius Date: Tue, 31 Mar 2026 18:17:50 +0200 Subject: [PATCH 200/261] fix(agent-manager): prevent model comparison popover from dismissing on interaction (#8014) * fix(agent-manager): prevent model comparison popover from dismissing on interaction Harden Popover dismiss logic against SolidJS DOM detachment during reactive updates that caused the multi-model selector to close on every click (Windows). Disable Kobalte built-in interact/focus-outside dismissal in favor of custom window-level handlers with isConnected and relatedTarget guards. Change compare popover placement to top-start with flip disabled. Closes #7990 * fix(ui): drop relatedTarget guard that blocked keyboard focus-outside dismiss The isConnected check already handles SolidJS DOM detachment. The relatedTarget guard prevented closing when tabbing out because the element losing focus was still inside the popover. --- .../webview-ui/agent-manager/NewWorktreeDialog.tsx | 3 ++- packages/ui/src/components/popover.tsx | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx index eef2a0a4031..18a62cdeb4e 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx @@ -515,7 +515,8 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran (props: PopoverProps const target = event.target if (!(target instanceof Node)) return if (inside(target)) return + // Node was detached by a reactive update — treat as inside + if (!target.isConnected) return close("outside") } @@ -102,6 +104,8 @@ export function Popover(props: PopoverProps const target = event.target if (!(target instanceof Node)) return if (inside(target)) return + // Node was detached by a reactive update — treat as inside + if (!target.isConnected) return close("outside") } @@ -140,8 +144,14 @@ export function Popover(props: PopoverProps [local.class ?? ""]: !!local.class, }} style={local.style} + onInteractOutside={(event: Event) => { + // Custom window-level handlers manage outside dismissal; + // always prevent Kobalte's built-in interact-outside close + // to avoid double-firing and stale-node false positives. + event.preventDefault() + }} onFocusOutside={(event: Event) => { - if (!ready()) event.preventDefault() + event.preventDefault() }} onCloseAutoFocus={(event: Event) => { if (dismiss() === "outside") event.preventDefault() From 7b738b8c671b085c1e54c034f42dca1aac96db6f Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Tue, 31 Mar 2026 18:38:27 +0200 Subject: [PATCH 201/261] refactor(vscode): remove totalCost, derive from costBreakdown at callsite totalCost was a redundant memo that duplicated the same sessionFamily walk already done by costBreakdown. TaskHeader now sums the breakdown entries directly, eliminating the extra accessor from the context. --- .../webview-ui/src/components/chat/TaskHeader.tsx | 10 ++++++---- .../kilo-vscode/webview-ui/src/context/session.tsx | 13 ------------- .../webview-ui/src/stories/StoryProviders.tsx | 1 - .../webview-ui/src/stories/chat.stories.tsx | 2 +- .../webview-ui/src/stories/history.stories.tsx | 1 - 5 files changed, 7 insertions(+), 20 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx index 6e317da3261..685d80faca1 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx @@ -29,18 +29,20 @@ export const TaskHeader: Component = (props) => { const fmt = (n: number) => new Intl.NumberFormat(language.locale(), { style: "currency", currency: "USD" }).format(n) + const breakdown = () => session.costBreakdown() + const cost = createMemo(() => { - const total = session.totalCost() + const total = breakdown().reduce((sum, e) => sum + e.cost, 0) if (total === 0) return undefined return fmt(total) }) const costTooltip = createMemo(() => { - const breakdown = session.costBreakdown() - if (breakdown.length <= 1) return {language.t("context.usage.sessionCost")} + const items = breakdown() + if (items.length <= 1) return {language.t("context.usage.sessionCost")} return (
- {(e) =>
{`${e.label}: ${fmt(e.cost)}`}
}
+ {(e) =>
{`${e.label}: ${fmt(e.cost)}`}
}
) }) diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index 54e2935ca22..a289bbd9c56 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -126,7 +126,6 @@ interface SessionContextValue { clearModelOverride: () => void // Cost and context usage for the current session - totalCost: Accessor costBreakdown: Accessor> contextUsage: Accessor @@ -1621,17 +1620,6 @@ export const SessionProvider: ParentComponent = (props) => { .sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()), ) - const totalCost = createMemo(() => { - const id = currentSessionID() - if (!id) return calcTotalCost(messages()) - const family = sessionFamily(id) - let total = 0 - for (const sid of family) { - total += calcTotalCost(store.messages[sid] ?? []) - } - return total - }) - /** * Per-session cost breakdown for the current session family. * Returns entries only for sessions with non-zero cost. @@ -1729,7 +1717,6 @@ export const SessionProvider: ParentComponent = (props) => { selectModel, hasModelOverride, clearModelOverride, - totalCost, costBreakdown, contextUsage, agents, diff --git a/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx b/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx index b43be721d62..c803943eb1f 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx @@ -160,7 +160,6 @@ export function mockSessionValue(overrides?: { selectModel: noop, hasModelOverride: () => false, clearModelOverride: noop, - totalCost: () => 0, costBreakdown: () => [], contextUsage: () => undefined, agents: () => [{ name: "code", description: "Code mode", mode: "primary" as const }], diff --git a/packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx b/packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx index 2372b719e4a..93c64ab4ade 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx @@ -99,7 +99,7 @@ export const ChatViewWithMessages: Story = { const session = { ...mockSessionValue({ id: SESSION_ID, status: "idle" }), messages: () => [{ id: "msg-001" }] as any[], - totalCost: () => 0.0012, + costBreakdown: () => [{ label: "Parent session", cost: 0.0012 }], contextUsage: () => ({ tokens: 512, percentage: 6 }), } return ( diff --git a/packages/kilo-vscode/webview-ui/src/stories/history.stories.tsx b/packages/kilo-vscode/webview-ui/src/stories/history.stories.tsx index 8f746766bae..0c0ebab98b3 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/history.stories.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/history.stories.tsx @@ -73,7 +73,6 @@ const WithSessions: ParentComponent<{ sessions?: typeof mockSessions }> = (props selectModel: noop, hasModelOverride: () => false, clearModelOverride: noop, - totalCost: () => 0, costBreakdown: () => [], contextUsage: () => undefined, agents: () => [{ name: "code", description: "Code mode", mode: "primary" as const }], From 368aef12b54aff88761ec5e96a180efded600b37 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 16:37:07 +0000 Subject: [PATCH 202/261] feat(i18n): add context.stats.parentSession translations across locales add new i18n key context.stats.parentSession across locales to display the parent session in the UI across languages --- packages/kilo-vscode/webview-ui/src/i18n/ar.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/br.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/bs.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/da.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/de.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/es.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/fr.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/ja.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/ko.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/nl.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/no.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/pl.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/ru.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/th.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/tr.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/zh.ts | 1 + packages/kilo-vscode/webview-ui/src/i18n/zht.ts | 1 + 17 files changed, 17 insertions(+) diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index d915e5ff3f0..3020f7c2327 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -939,6 +939,7 @@ export const dict = { "prompt.placeholder.default": "اكتب رسالة... (Enter للإرسال، Shift+Enter لسطر جديد)", "context.usage.sessionCost": "تكلفة الجلسة", + "context.stats.parentSession": "الجلسة الرئيسية", "time.justNow": "الآن", "time.minutesAgo": "قبل {{count}} دقيقة", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 646ace5e035..d482a623797 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -947,6 +947,7 @@ export const dict = { "prompt.placeholder.default": "Digite uma mensagem... (Enter para enviar, Shift+Enter para nova linha)", "context.usage.sessionCost": "Custo da sessão", + "context.stats.parentSession": "Sessão pai", "time.justNow": "agora mesmo", "time.minutesAgo": "{{count}} min atrás", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 5dfa0817e15..5c5a11e0866 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -952,6 +952,7 @@ export const dict = { "prompt.placeholder.default": "Unesite poruku... (Enter za slanje, Shift+Enter za novi red)", "context.usage.sessionCost": "Cijena sesije", + "context.stats.parentSession": "Roditeljska sesija", "time.justNow": "upravo sada", "time.minutesAgo": "prije {{count}} min", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 161c3a283ca..3109a0fa295 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -945,6 +945,7 @@ export const dict = { "prompt.placeholder.default": "Skriv en besked... (Enter for at sende, Shift+Enter for ny linje)", "context.usage.sessionCost": "Sessionsomkostning", + "context.stats.parentSession": "Overordnet session", "time.justNow": "lige nu", "time.minutesAgo": "{{count}} min. siden", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index efe7ecdf898..77a55bb58bc 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -958,6 +958,7 @@ export const dict = { "prompt.placeholder.default": "Nachricht eingeben... (Enter zum Senden, Shift+Enter für neue Zeile)", "context.usage.sessionCost": "Sitzungskosten", + "context.stats.parentSession": "Übergeordnete Sitzung", "time.justNow": "gerade eben", "time.minutesAgo": "vor {{count}} Min.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 1b0a8b80b3a..578a57d3f68 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -953,6 +953,7 @@ export const dict = { "prompt.placeholder.default": "Escribe un mensaje... (Enter para enviar, Shift+Enter para nueva línea)", "context.usage.sessionCost": "Coste de la sesión", + "context.stats.parentSession": "Sesión principal", "time.justNow": "justo ahora", "time.minutesAgo": "hace {{count}} min", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index e1865dbfbae..c7057f268eb 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -959,6 +959,7 @@ export const dict = { "prompt.placeholder.default": "Tapez un message... (Entrée pour envoyer, Maj+Entrée pour un saut de ligne)", "context.usage.sessionCost": "Coût de la session", + "context.stats.parentSession": "Session parente", "time.justNow": "à l'instant", "time.minutesAgo": "il y a {{count}} min", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 038f2a7f4b6..5b14ca16855 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -944,6 +944,7 @@ export const dict = { "prompt.placeholder.default": "メッセージを入力... (Enterで送信、Shift+Enterで改行)", "context.usage.sessionCost": "セッションコスト", + "context.stats.parentSession": "親セッション", "time.justNow": "たった今", "time.minutesAgo": "{{count}}分前", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index fd28bd4da0c..c12a7ab1e3b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -944,6 +944,7 @@ export const dict = { "prompt.placeholder.default": "메시지를 입력하세요... (Enter로 전송, Shift+Enter로 줄 바꿈)", "context.usage.sessionCost": "세션 비용", + "context.stats.parentSession": "상위 세션", "time.justNow": "방금", "time.minutesAgo": "{{count}}분 전", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 14dd51e58ef..f170166a866 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -945,6 +945,7 @@ export const dict = { "prompt.placeholder.error": "Verbinding mislukt. Controleer het uitvoerpaneel of herstart de extensie.", "context.usage.sessionCost": "Sessiekosten", + "context.stats.parentSession": "Bovenliggende sessie", "time.justNow": "zojuist", "time.minutesAgo": "{{count}} min geleden", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 306fd74428a..21cd193cd4e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -949,6 +949,7 @@ export const dict = { "prompt.placeholder.default": "Skriv en melding... (Enter for å sende, Shift+Enter for ny linje)", "context.usage.sessionCost": "Sesjonskostnad", + "context.stats.parentSession": "Overordnet sesjon", "time.justNow": "akkurat nå", "time.minutesAgo": "{{count}} min siden", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 3518ab6cd44..d4b384cd6ba 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -949,6 +949,7 @@ export const dict = { "prompt.placeholder.default": "Wpisz wiadomość... (Enter, aby wysłać, Shift+Enter dla nowej linii)", "context.usage.sessionCost": "Koszt sesji", + "context.stats.parentSession": "Sesja nadrzędna", "time.justNow": "przed chwilą", "time.minutesAgo": "{{count}} min temu", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 7f5866475dc..7ff7a77aa84 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -952,6 +952,7 @@ export const dict = { "prompt.placeholder.default": "Введите сообщение... (Enter для отправки, Shift+Enter для новой строки)", "context.usage.sessionCost": "Стоимость сессии", + "context.stats.parentSession": "Родительская сессия", "time.justNow": "только что", "time.minutesAgo": "{{count}} мин. назад", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index f19a93d25aa..91105e4b810 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -940,6 +940,7 @@ export const dict = { "prompt.placeholder.default": "พิมพ์ข้อความ... (Enter เพื่อส่ง, Shift+Enter เพื่อขึ้นบรรทัดใหม่)", "context.usage.sessionCost": "ค่าใช้จ่ายเซสชัน", + "context.stats.parentSession": "เซสชันหลัก", "time.justNow": "เมื่อสักครู่", "time.minutesAgo": "{{count}} นาทีที่แล้ว", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index ff0dc211a26..ee05514a8b2 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -948,6 +948,7 @@ export const dict = { "prompt.placeholder.error": "Bağlantı başarısız. Çıktı panelini kontrol edin veya uzantıyı yeniden başlatın.", "context.usage.sessionCost": "Oturum maliyeti", + "context.stats.parentSession": "Üst oturum", "time.justNow": "az önce", "time.minutesAgo": "{{count}} dk önce", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index f7eb55f25c5..1b186b4ce01 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -932,6 +932,7 @@ export const dict = { "prompt.placeholder.default": "输入消息... (Enter 发送,Shift+Enter 换行)", "context.usage.sessionCost": "会话费用", + "context.stats.parentSession": "父会话", "time.justNow": "刚刚", "time.minutesAgo": "{{count}} 分钟前", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 677e7ed3478..3ab32aa139d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -934,6 +934,7 @@ export const dict = { "prompt.placeholder.default": "輸入訊息... (Enter 送出,Shift+Enter 換行)", "context.usage.sessionCost": "工作階段費用", + "context.stats.parentSession": "父工作階段", "time.justNow": "剛剛", "time.minutesAgo": "{{count}} 分鐘前", From 24709aa7ff7b7585728f0c27e4e8234243613c33 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Tue, 31 Mar 2026 18:53:20 +0200 Subject: [PATCH 203/261] fix(vscode): return cost breakdown for standalone sessions too The family.size <= 1 early-return caused costBreakdown to return [] for sessions without subagents, making TaskHeader sum to 0 and hide the cost badge entirely. Remove the guard so single-session cost is still reported. --- packages/kilo-vscode/webview-ui/src/context/session.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index a289bbd9c56..2a764126cfd 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -1629,7 +1629,6 @@ export const SessionProvider: ParentComponent = (props) => { const id = currentSessionID() if (!id) return [] const family = sessionFamily(id) - if (family.size <= 1) return [] // Build label map: child sessionID → label from the parent's task tool input const labels = new Map() From d6eeb00b7b51be4692154efa72ea2766536a095a Mon Sep 17 00:00:00 2001 From: Imanol Maiztegui Date: Tue, 31 Mar 2026 19:06:51 +0200 Subject: [PATCH 204/261] Migration error handling (#8010) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(vscode): detect sessions in old extension * feat(vscode): added session types * feat(cli): add endpoints for inserting a session * feat(vscode): use session types from sdk for parsing * feat(kilo-vscode): parsing session project * feat(vscode): parse legacy session details * feat(kilo-vscode): refactoring * feat(vscode): parse legacy session messages * feat(vscode): parse legacy session parts * feat(vscode): added testing files and id creation * feat(vscode): merge tool parts on imported session * feat(vscode): session message part refactoring * feat(vscode): cover provider-specific reasoning parts on session migration * feat(kilo-vscode): handle completion result parts * feat: type hardening on session migration * feat(kilo-vscode): create tool part correctly * feat(kilo-vscode): adjust session part processing * feat(vscode): persist migrated session in kilo.db * feat(vscode): add error handling to session migration * feat(vscode): add directory field to session migration * feat(kilo-vscode): display completion check on session migration * feat(vscode): prevent migrating sessions twice * feat(cli): use correct project id when inserting migrated session * feat(kilo-vscode): Use correct project id for session migration * feat(kilo-vscode): load sessions on migration complete * feat(kilo-vscode): ignore environment details user part when migrating sessions * feat(cli): create project details following current backend logic * feat(kilo-vscode): cleaner messages without environment_details parts * feat(kilo-vscode): refactoring * feat(kilo-vscode): refactoring and organization * feat(kilo-vscode): method renaming to improve clarity * feat(kilo-vscode): added session migration test strategy * test(kilo-vscode): implement legacy migration unit tests for all migration modules Replace todo stubs with full test implementations across messages, parts, tools, reasoning, parser, migrate, project, and session test files. Add new project.test.ts and session.test.ts covering project construction, session metadata, and deterministic ID generation. * style(kilo-vscode): apply prettier formatting across legacy migration source and test files * fix(legacy-migration): filter out non-user/assistant entries before parsing messages Exclude system and other non-conversational roles from the conversation array prior to mapping, ensuring parentID references remain consistent across imported messages when skipped entries exist. * refactor(parts): skip part generation for non-conversational message roles Entries with roles other than user or assistant should not produce parts, keeping part output consistent with the messages that are actually imported during legacy migration. * fix(ids): use semantic kind strings to prevent part ID collisions for reasoning entries Replace numeric indices with descriptive kind strings ("reasoning", "provider-reasoning") in extra part ID generation to avoid collisions between reasoning parts and regular content parts within the same message. Introduce `createExtraPartID` to distinguish reasoning-specific IDs from standard sequential part IDs produced by `createPartID`. * refactor(session-import): guard against empty worktree in legacy project import Prevent silent misattribution of migrated sessions by rejecting empty worktree paths before resolving the project directory. Without this check, an empty string would fall back to the current process directory, causing the imported session to be attached to the wrong project. * perf(cli): cache MCP listTools results to avoid redundant RPCs per loop step (#7922) MCP.tools() called client.listTools() for every connected server on every agent loop iteration. With multiple servers this added hundreds of milliseconds of overhead per step (measured ~300-750ms for remote servers like Vercel). Cache listTools results in a module-level Map and return them on subsequent calls. The cache is invalidated on: - ToolListChangedNotification from the MCP server - Server add/connect/disconnect - Instance dispose (config change, project switch, shutdown) * fix(agent-manager): add retries to worktree cleanup for macOS .app bundles (#7921) * chore: hide non-English localization files in GitHub PR diffs Mark all non-English i18n locale files as linguist-generated=true so they are collapsed by default in GitHub PR diffs, reducing noise when reviewing changes that touch translation files. * feat(vscode): add Browse Marketplace button to MCP settings Add a "Browse Marketplace" button to the MCP Servers subtab in Agent Behaviour settings, guiding users to discover and install MCPs from the marketplace rather than only configuring them manually. - Add button above the MCP server list that opens the Marketplace panel - Add openMarketplacePanel webview message type and handler - Add translations for all 18 supported languages * fix(vscode): preserve project directory when opening marketplace from settings Pass the current panel's project directory through to the marketplace panel so project-scoped MCP installs work correctly in multi-root workspaces. Without this, the marketplace panel would fall back to null project directory since there is no active text editor when clicking from a webview. * feat(vscode): add Browse Marketplace button to agents and skills tabs Add the Browse Marketplace button to the Agents and Skills subtabs in Agent Behaviour settings, matching the existing button in the MCP Servers subtab. This lets users discover marketplace items from any of the three configuration tabs. - Agents tab: added as a ghost button in the header row alongside Import and Create Mode buttons - Skills tab: added as a secondary button at the top-right, matching the MCP tab layout - Extracted the browse handler to the component scope for reuse * chore: update kilo-vscode visual regression baselines * perf(agent-manager): extend slimPart to strip heavy tool metadata for faster session switching (#7927) Extend slim-metadata.ts to handle apply_patch, multiedit, write, and bash tools in addition to edit. Previously only edit tool parts had their heavy metadata stripped before IPC serialization. apply_patch parts carried full file before/after contents per file, write parts carried the entire written file, and bash parts carried up to 30KB of output — all serialized on every session switch. This reduces session-switch time by ~2x for sessions with many tool calls. * style(legacy-migration): reformat long reasoning push call for readability * refactor(legacy-migration): filter non-user/assistant entries before indexing Move the role filter from inside `parseParts` to `parsePartsFromConversation` so that message indices are derived only from the filtered list. This ensures part message IDs stay aligned with the imported messages and skipped entries (e.g. system role) do not cause index gaps in the generated IDs. * fix(legacy-migration): add `_migrated_` infix to generated IDs Prefix all migrated entity IDs (sessions, messages, parts) with a `_migrated_` segment so they are clearly distinguishable from IDs produced by the regular runtime. Updates tests to assert the new prefix format. * refactor(legacy-migration): consolidate conversation parsing into `parseSession` Remove the intermediate `createMessages` and `createParts` async wrappers that each independently read and parsed the conversation file. The file is now fetched and parsed once in `parseSession`, with the resulting conversation passed directly to `parseMessagesFromConversation` and `parsePartsFromConversation`, eliminating redundant I/O. * fix(parts-builder): remove `toTextWithinMessage` and use `toText` directly `toTextWithinMessage` was a duplicate of `toText` with identical behavior. Replace all call sites with `toText` and delete the redundant function. * fix(parts-builder): skip provider-specific reasoning when explicit reasoning entry exists Guard `isProviderSpecificReasoning` with `!isReasoning` to prevent duplicate reasoning parts when an entry carries both a `type: "reasoning"` field and a provider-specific reasoning field (e.g. `reasoning_content`). The explicit reasoning entry takes precedence. * test(legacy-migration): add coverage for edge cases in parts and tools parsing Add unit tests for two previously uncovered scenarios: - Task block extraction: verify only the content inside `` tags is kept when text exists outside the legacy task wrapper - Empty tool result: verify the tool name is used as fallback output when `tool_result` carries no readable text content Also replace the dynamic `FileType.Directory` workaround with the direct `vscode.FileType.Directory` enum reference, and harden `parseFile` to throw on non-array JSON instead of silently returning an empty array. * fix(migration): require all items to succeed before marking migration complete Tighten the completion condition so migration is only marked "completed" when every item succeeds, not just when at least one does. Introduce a dedicated "error" phase in the wizard UI so partial failures are surfaced clearly rather than silently collapsed into the "done" state. - `handleStartLegacyMigration`: gate `setMigrationStatus("completed")` on `!failed && success` instead of `success` alone - `migrate`: propagate the actual `Error.message` from a failed session migration instead of a generic fallback string - `MigrationWizard`: add `"error"` phase, show per-group error messages inline, add a "Continue" button to proceed past the error screen, and trigger `loadSessions` on completion - `migration.css`: add `.migration-wizard__error-text` style using `--vscode-errorForeground` * fix(migration): defer disposeGlobal and loadSessions until after error check Move `disposeGlobal` call inside the success-only branch so the extension is not torn down when migration partially fails. Similarly, defer the `loadSessions` webview message to the "Continue" button on the error screen so sessions are only reloaded after the user acknowledges the failure. - `handleStartLegacyMigration`: move `disposeGlobal` inside the `!failed && success` guard to avoid disposing on partial failure - `MigrationWizard`: skip `loadSessions` post-message when errors are present; send it from the "Continue" button instead * refactor(migration): extract MigrationError component and error selector utilities Replace inline error text rendering in MigrationWizard with a dedicated MigrationError component that displays a structured error box with a copy-to-clipboard action. Extract error parsing logic into reusable selector functions in a separate module. - Add `MigrationError` component with header, detail text, and preformatted error code block; copy button writes error to clipboard and shows a success toast - Add `error-selectors.ts` with `getMigrationError` (strips error type prefix), `getSessionMigrationError`, and `getSessionMigrationErrorDetail` - Replace `` + raw `error-text` div in MigrationWizard sessions row with `` using the new selector-derived signals * feat(migration): introduce view-model module for migration state derivations Extract `ProgressEntry` type and inline derived-state functions from `MigrationWizard` into a dedicated `migration-view-model.ts` module, and update call sites to use the new public API. - Add `migration-view-model.ts` exporting `ProgressEntry`, `getGroupStatus`, `getGroupMessage`, `getSuccessCount`, `getTotalCount`, `getCurrentSessionError`, and `getCurrentSessionErrorDetail` - Remove duplicated logic from `MigrationWizard` and delegate to the new module, keeping the component focused on rendering concerns - Consolidate the `getGroupMessage` resolver used by error selectors so it is derived from a single source of truth * refactor(legacy-migration): split shared types into dedicated modules Move `MigrationResultItem` out of `legacy-types.ts` into a new `migration-types.ts` module, and introduce a `MigrationFailure` typed error structure in `errors/migration-failure.ts`. - Add `migration-types.ts` exporting `MigrationResultItem` to separate runtime migration result types from legacy configuration types - Add `errors/migration-failure.ts` defining `MigrationFailure` and `MigrationFailureKind` for structured error classification - Remove `MigrationResultItem` from `legacy-types.ts` to eliminate the coupling between legacy config shapes and migration output types - Update `migration-service.ts` import to reference the new module * feat(errors): add migration error normalization utilities Introduce `migration-error.ts` with `normalizeMigrationError` and `getMigrationErrorMessage` to convert arbitrary thrown values into typed `MigrationFailure` objects. - Classify errors by kind (`http`, `sdk`, `generic`, `unknown`) based on the presence of `status`, `data`, `body`, or `Error` instance - Extract human-readable message from `message`, `body`, `data`, or raw string fallback, defaulting to "Unknown migration error" - Compose a `detail` string from status code, body, and data fields when they differ from the primary message - Propagate nested `cause` text for additional diagnostic context * refactor(migrate): wrap migrate return in typed Result and normalize errors * chore(migration): inline view-model helpers and remove extracted modules Remove the separately extracted `migration-view-model.ts`, `error-selectors.ts`, `MigrationError.tsx`, and `MigrationFailure` type in favour of inlined logic directly in `MigrationWizard` and a simplified `getMigrationErrorMessage` utility. - Delete `MigrationFailure` type and `normalizeMigrationError`; replace with a flat `getMigrationErrorMessage` function - Inline `ProgressEntry` interface, group-status logic, and count helpers into `MigrationWizard` - Replace `MigrationError` component with inline clipboard copy handler using `showToast` - Simplify session migrate result shape: drop structured `error` field, surface plain `message` string instead * feat(i18n): add migration error copy-to-clipboard translations across all locales * style(migration): add error box and copy button styles for migration wizard Add CSS for the error display box and copy-to-clipboard button in the migration wizard, including layout, typography, theming via VSCode CSS variables, hover/active/focus-visible states, and high-contrast border overrides. Also align wizard items to flex-start for multi-line content. * fix: merge conflict issues resolved * fix: formatting * i18n(migration): add localized strings for session migration progress and errors * fix:formatting * feat(session-import): remove temporary test error from project import * fix(vscode): remove unused migration progress translations * fix: formatting * fix(migration): track individual session progress instead of grouping all sessions Replace the single "Chat sessions" progress item with per-session tracking, passing the session ID directly to onProgress calls and mapping each session to its own pending item in the wizard's progress list. * fix: formatting --------- Co-authored-by: Marius Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> Co-authored-by: Mark IJbema Co-authored-by: github-actions[bot] --- .../src/kilo-provider/handlers/migration.ts | 12 ++- .../errors/migration-error.ts | 83 ++++++++++++++++++ .../src/legacy-migration/legacy-types.ts | 7 -- .../src/legacy-migration/migration-service.ts | 19 ++--- .../src/legacy-migration/migration-types.ts | 6 ++ .../src/legacy-migration/sessions/migrate.ts | 17 +++- .../components/migration/MigrationWizard.tsx | 75 ++++++++++++++--- .../src/components/migration/migration.css | 84 ++++++++++++++++++- .../kilo-vscode/webview-ui/src/i18n/ar.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/br.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/bs.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/da.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/de.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/en.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/es.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/fr.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/ja.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/ko.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/nl.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/no.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/pl.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/ru.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/th.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/tr.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/zh.ts | 5 ++ .../kilo-vscode/webview-ui/src/i18n/zht.ts | 5 ++ .../src/kilocode/session-import/service.ts | 1 + 27 files changed, 355 insertions(+), 39 deletions(-) create mode 100644 packages/kilo-vscode/src/legacy-migration/errors/migration-error.ts create mode 100644 packages/kilo-vscode/src/legacy-migration/migration-types.ts diff --git a/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts b/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts index ee8a32f28a2..b95d630610f 100644 --- a/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts +++ b/packages/kilo-vscode/src/kilo-provider/handlers/migration.ts @@ -114,15 +114,13 @@ export async function handleStartLegacyMigration( ctx.cachedLegacyData?.settings, ) - // Dispose all instances after migration - // Reloading the data will be handled once the server replies with a global.disposed event - await ctx.disposeGlobal() - - // Only mark as completed if at least one item succeeded — if everything failed - // the user can still re-run migration via Settings → About. + const failed = results.some((r) => r.status === "error") const success = results.some((r) => r.status === "success") - if (success) { + if (!failed && success) { + // Dispose all instances after a fully successful migration. + // Reloading the data will be handled once the server replies with a global.disposed event. + await ctx.disposeGlobal() await MigrationService.setMigrationStatus( ctx.extensionContext as Parameters[0], "completed", diff --git a/packages/kilo-vscode/src/legacy-migration/errors/migration-error.ts b/packages/kilo-vscode/src/legacy-migration/errors/migration-error.ts new file mode 100644 index 00000000000..a54892df80e --- /dev/null +++ b/packages/kilo-vscode/src/legacy-migration/errors/migration-error.ts @@ -0,0 +1,83 @@ +interface ErrorLike { + message?: unknown + status?: unknown + data?: unknown + body?: unknown +} + +function isObject(value: unknown): value is Record { + return typeof value === "object" && value !== null +} + +function getText(value: unknown): string | undefined { + if (typeof value === "string") { + const text = value.trim() + return text || undefined + } + + if (typeof value === "number" || typeof value === "boolean") { + return String(value) + } + + return undefined +} + +function getMessage(value: unknown) { + if (!isObject(value)) return undefined + return getText((value as ErrorLike).message) +} + +function getStatus(value: unknown) { + if (!isObject(value)) return undefined + const status = (value as ErrorLike).status + return typeof status === "number" ? String(status) : getText(status) +} + +function getBody(value: unknown) { + if (!isObject(value)) return undefined + + const body = (value as ErrorLike).body + const text = getText(body) + if (text) return text + + if (isObject(body)) { + const msg = getMessage(body) + if (msg) return msg + } + + return undefined +} + +function getData(value: unknown) { + if (!isObject(value)) return undefined + + const data = (value as ErrorLike).data + const text = getText(data) + if (text) return text + + if (isObject(data)) { + const msg = getMessage(data) + if (msg) return msg + } + + return undefined +} + +export function getMigrationErrorMessage(err: unknown) { + const message = getMessage(err) + if (message) return message + + const body = getBody(err) + if (body) return body + + const data = getData(err) + if (data) return data + + const status = getStatus(err) + if (status) return `Request failed (${status})` + + const text = getText(err) + if (text) return text + + return "Unknown migration error" +} diff --git a/packages/kilo-vscode/src/legacy-migration/legacy-types.ts b/packages/kilo-vscode/src/legacy-migration/legacy-types.ts index c5a9231d5ed..854a7655bfb 100644 --- a/packages/kilo-vscode/src/legacy-migration/legacy-types.ts +++ b/packages/kilo-vscode/src/legacy-migration/legacy-types.ts @@ -323,10 +323,3 @@ export interface MigrationSelections { defaultModel: boolean settings: MigrationSettingsSelections } - -export interface MigrationResultItem { - item: string - category: "provider" | "mcpServer" | "customMode" | "defaultModel" | "settings" | "session" - status: "success" | "warning" | "error" - message?: string -} diff --git a/packages/kilo-vscode/src/legacy-migration/migration-service.ts b/packages/kilo-vscode/src/legacy-migration/migration-service.ts index b3e4986aac8..1f4d4117204 100644 --- a/packages/kilo-vscode/src/legacy-migration/migration-service.ts +++ b/packages/kilo-vscode/src/legacy-migration/migration-service.ts @@ -16,6 +16,7 @@ import type { } from "@kilocode/sdk/v2/client" import { PROVIDER_MAP, UNSUPPORTED_PROVIDERS, DEFAULT_MODE_SLUGS } from "./provider-mapping" import type { ProviderMapping } from "./provider-mapping" +import { getMigrationErrorMessage } from "./errors/migration-error" import type { LegacyProviderProfiles, LegacyProviderSettings, @@ -30,8 +31,9 @@ import type { MigrationProviderInfo, MigrationMcpServerInfo, MigrationCustomModeInfo, - MigrationResultItem, } from "./legacy-types" +import type { MigrationResultItem } from "./migration-types" +import { createSessionID } from "./sessions/lib/ids" import { migrate as migrateSession } from "./sessions/migrate" // --------------------------------------------------------------------------- @@ -212,19 +214,16 @@ export async function migrate( if (selections.sessions?.length) { for (const id of selections.sessions) { - onProgress("Chat sessions", "migrating") + onProgress(id, "migrating") const result = await migrateSession(id, context, client) + const reason = result.ok ? "Session migrated" : result.message results.push({ item: id, category: "session", status: result.ok ? "success" : "error", - message: result.ok ? "Session migrated" : "Session migration failed", + message: reason, }) - onProgress( - "Chat sessions", - result.ok ? "success" : "error", - result.ok ? "Session migrated" : "Session migration failed", - ) + onProgress(id, result.ok ? "success" : "error", reason) } } @@ -666,7 +665,7 @@ async function migrateAutocomplete(settings: LegacyAutocompleteSettings): Promis item: "Autocomplete settings", category: "settings", status: "error", - message: err instanceof Error ? err.message : String(err), + message: getMigrationErrorMessage(err), } } } @@ -714,7 +713,7 @@ async function migrateLanguage(language: string): Promise { item: "Language preference", category: "settings", status: "error", - message: err instanceof Error ? err.message : String(err), + message: getMigrationErrorMessage(err), } } } diff --git a/packages/kilo-vscode/src/legacy-migration/migration-types.ts b/packages/kilo-vscode/src/legacy-migration/migration-types.ts new file mode 100644 index 00000000000..bd32d39ffd5 --- /dev/null +++ b/packages/kilo-vscode/src/legacy-migration/migration-types.ts @@ -0,0 +1,6 @@ +export interface MigrationResultItem { + item: string + category: "provider" | "mcpServer" | "customMode" | "defaultModel" | "settings" | "session" + status: "success" | "warning" | "error" + message?: string +} diff --git a/packages/kilo-vscode/src/legacy-migration/sessions/migrate.ts b/packages/kilo-vscode/src/legacy-migration/sessions/migrate.ts index 8ca481e3178..0fa38fdaf0d 100644 --- a/packages/kilo-vscode/src/legacy-migration/sessions/migrate.ts +++ b/packages/kilo-vscode/src/legacy-migration/sessions/migrate.ts @@ -1,9 +1,22 @@ import * as vscode from "vscode" import type { KiloClient } from "@kilocode/sdk/v2/client" +import { getMigrationErrorMessage } from "../errors/migration-error" import type { LegacyHistoryItem } from "./lib/legacy-types" import { parseSession } from "./parser" -export async function migrate(id: string, context: vscode.ExtensionContext, client: KiloClient) { +type Result = + | { + ok: true + skipped?: boolean + payload: Awaited> + } + | { + ok: false + payload: Awaited> + message: string + } + +export async function migrate(id: string, context: vscode.ExtensionContext, client: KiloClient): Promise { const dir = vscode.Uri.joinPath(context.globalStorageUri, "tasks").fsPath const items = context.globalState.get("taskHistory", []) const item = items.find((item) => item.id === id) @@ -46,7 +59,7 @@ export async function migrate(id: string, context: vscode.ExtensionContext, clie return { ok: false, payload, - error, + message: getMigrationErrorMessage(error), } } } 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 3cfda340070..deca1fdb570 100644 --- a/packages/kilo-vscode/webview-ui/src/components/migration/MigrationWizard.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/migration/MigrationWizard.tsx @@ -8,6 +8,7 @@ import { Show, createSignal, onMount, onCleanup } from "solid-js" import type { Component, JSX } from "solid-js" +import { showToast } from "@kilocode/kilo-ui/toast" import { useVSCode } from "../../context/vscode" import { useLanguage } from "../../context/language" import type { @@ -154,7 +155,7 @@ const WarningSvg = (): JSX.Element => ( // --------------------------------------------------------------------------- type Screen = "whats-new" | "migrate" -type MigratePhase = "selecting" | "migrating" | "done" +type MigratePhase = "selecting" | "migrating" | "error" | "done" interface ProgressEntry { item: string @@ -263,7 +264,11 @@ const MigrationWizard: Component = (props) => { if (msg?.type === "legacyMigrationComplete") { const complete = msg as LegacyMigrationCompleteMessage setResults(complete.results) - setPhase("done") + const hasErrors = complete.results.some((r) => r.status === "error") + setPhase(hasErrors ? "error" : "done") + if (!hasErrors) { + vscode.postMessage({ type: "loadSessions" }) + } } } @@ -323,8 +328,8 @@ const MigrationWizard: Component = (props) => { const mode = customModes().find((m) => m.slug === slug) return { item: mode?.name ?? slug, group: "customModes", status: "pending" as const } }), - ...(migrateSessions() && sessions().length > 0 - ? [{ item: "Chat sessions", group: "sessions", status: "pending" as const }] + ...(migrateSessions() + ? sessions().map((id) => ({ item: id, group: "sessions", status: "pending" as const })) : []), ...(migrateDefaultModel() && defaultModel() ? [{ item: "Default model", group: "defaultModel", status: "pending" as const }] @@ -382,6 +387,11 @@ const MigrationWizard: Component = (props) => { props.onComplete() } + const copySessionError = async (text: string) => { + await navigator.clipboard.writeText(text) + showToast({ variant: "success", title: language.t("migration.error.toast.copied") }) + } + // --------------------------------------------------------------------------- // Data helpers // --------------------------------------------------------------------------- @@ -431,17 +441,19 @@ const MigrationWizard: Component = (props) => { // Group-level status for progress display const groupStatus = (group: string): ProgressEntry["status"] => { - const entries = progressEntries().filter((e) => e.group === group) + const entries = progressEntries().filter((entry) => entry.group === group) if (entries.length === 0) return "pending" - if (entries.some((e) => e.status === "error")) return "error" - if (entries.some((e) => e.status === "warning")) return "warning" - if (entries.every((e) => e.status === "success")) return "success" - if (entries.some((e) => e.status === "migrating")) 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" return "pending" } - const successCount = () => results().filter((r) => r.status === "success").length + 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 // --------------------------------------------------------------------------- // Status icon renderer @@ -677,8 +689,33 @@ const MigrationWizard: Component = (props) => {
-
Chat Sessions & History
-
{sessions().length} sessions detected
+
{language.t("migration.migrate.chatHistory")}
+
+ {language.t("migration.migrate.sessionsDetected", { count: String(sessions().length) })} +
+ +
+
+
+ {language.t("migration.error.sessionFailed")} +
+ +
+
{groupMessage("sessions")}
+
+
@@ -768,6 +805,7 @@ const MigrationWizard: Component = (props) => { {/* Cleanup option after done */} + {/*
@@ -787,6 +825,7 @@ const MigrationWizard: Component = (props) => {
+ */}
@@ -818,6 +857,18 @@ const MigrationWizard: Component = (props) => { {language.t("migration.migrate.button")} + + +

{current()?.message}

0}> )} - - {(action) => ( - - )} -
0}> diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index fcc2e70cbc3..037b8d2ead4 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -253,7 +253,6 @@ export interface KilocodeNotification { title: string message: string action?: KilocodeNotificationAction - actions?: KilocodeNotificationAction[] showIn?: string[] suggestModelId?: string } From b02abce97ef4d3e9c3c244cd68d26670f5519200 Mon Sep 17 00:00:00 2001 From: Imanol Maiztegui Date: Wed, 1 Apr 2026 00:33:49 +0200 Subject: [PATCH 220/261] Migration fix (#8032) * fix(vscode): read session IDs from globalState instead of filesystem in migration Replace filesystem directory scanning with globalState lookup when reading sessions during legacy migration detection. The previous approach read from the `tasks` directory in globalStorageUri, which was fragile and error-prone; the task history is already tracked in `context.globalState` under `taskHistory`. * refactor(migration): filter session IDs by verifying conversation history file existence Only include sessions in the legacy migration detection result when their `api_conversation_history.json` file is present on disk. This prevents phantom session IDs stored in `taskHistory` (e.g. from incomplete or interrupted tasks) from being treated as valid legacy data. --- .../src/legacy-migration/migration-service.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/kilo-vscode/src/legacy-migration/migration-service.ts b/packages/kilo-vscode/src/legacy-migration/migration-service.ts index edc520c0a3f..a3ea98ca44e 100644 --- a/packages/kilo-vscode/src/legacy-migration/migration-service.ts +++ b/packages/kilo-vscode/src/legacy-migration/migration-service.ts @@ -114,12 +114,18 @@ export async function detectLegacyData(context: vscode.ExtensionContext): Promis } async function readSessionsInGlobalStorage(context: vscode.ExtensionContext) { - const dir = vscode.Uri.joinPath(context.globalStorageUri, "tasks") - const items = await vscode.workspace.fs.readDirectory(dir).then( - (items) => items, - () => [] as [string, vscode.FileType][], - ) - return items.filter(([, type]) => type === vscode.FileType.Directory).map(([name]) => name) + const items = context.globalState.get<{ id: string }[]>("taskHistory", []) + const base = vscode.Uri.joinPath(context.globalStorageUri, "tasks") + const ids: string[] = [] + for (const item of items) { + const file = vscode.Uri.joinPath(base, item.id, "api_conversation_history.json") + const exists = await vscode.workspace.fs.stat(file).then( + () => true, + () => false, + ) + if (exists) ids.push(item.id) + } + return ids } // --------------------------------------------------------------------------- From 1e8e07f9dc9119b66cf61d9c13891970361896c1 Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Tue, 31 Mar 2026 22:51:56 +0000 Subject: [PATCH 221/261] release: v7.1.12 --- bun.lock | 32 +++++++++++++------------- package.json | 2 +- packages/app/package.json | 2 +- packages/desktop-electron/package.json | 2 +- packages/desktop/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++----- packages/kilo-docs/package.json | 2 +- packages/kilo-gateway/package.json | 2 +- packages/kilo-i18n/package.json | 2 +- packages/kilo-telemetry/package.json | 2 +- packages/kilo-ui/package.json | 2 +- packages/kilo-vscode/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/script/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/storybook/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- script/upstream/package.json | 2 +- sdks/vscode/package.json | 2 +- 21 files changed, 41 insertions(+), 41 deletions(-) diff --git a/bun.lock b/bun.lock index 533df254384..c7c85cebbe6 100644 --- a/bun.lock +++ b/bun.lock @@ -27,7 +27,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "@kilocode/kilo-i18n": "workspace:*", "@kilocode/kilo-ui": "workspace:*", @@ -79,7 +79,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -112,7 +112,7 @@ }, "packages/desktop-electron": { "name": "@opencode-ai/desktop-electron", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -142,7 +142,7 @@ }, "packages/kilo-docs": { "name": "@kilocode/kilo-docs", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "@docsearch/css": "^4", "@docsearch/js": "^4", @@ -171,7 +171,7 @@ }, "packages/kilo-gateway": { "name": "@kilocode/kilo-gateway", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "@ai-sdk/anthropic": "2.0.65", "@ai-sdk/openai": "2.0.101", @@ -206,7 +206,7 @@ }, "packages/kilo-i18n": { "name": "@kilocode/kilo-i18n", - "version": "7.1.11", + "version": "7.1.12", "devDependencies": { "@tsconfig/node22": "catalog:", "@types/bun": "catalog:", @@ -216,7 +216,7 @@ }, "packages/kilo-telemetry": { "name": "@kilocode/kilo-telemetry", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "@kilocode/kilo-gateway": "workspace:*", "@opentelemetry/api": "1.9.0", @@ -236,7 +236,7 @@ }, "packages/kilo-ui": { "name": "@kilocode/kilo-ui", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "@kobalte/core": "0.13.11", "@opencode-ai/util": "workspace:*", @@ -271,7 +271,7 @@ }, "packages/kilo-vscode": { "name": "kilo-code", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "@anthropic-ai/sdk": "^0.39.0", "@kilocode/kilo-i18n": "workspace:*", @@ -324,7 +324,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "7.1.11", + "version": "7.1.12", "bin": { "kilo": "./bin/kilo", "kilocode": "./bin/kilo", @@ -446,7 +446,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "@kilocode/sdk": "workspace:*", "zod": "catalog:", @@ -460,14 +460,14 @@ }, "packages/script": { "name": "@opencode-ai/script", - "version": "7.1.11", + "version": "7.1.12", "devDependencies": { "@types/bun": "catalog:", }, }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "7.1.11", + "version": "7.1.12", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -478,7 +478,7 @@ }, "packages/storybook": { "name": "@opencode-ai/storybook", - "version": "7.1.11", + "version": "7.1.12", "devDependencies": { "@opencode-ai/ui": "workspace:*", "@solidjs/meta": "catalog:", @@ -501,7 +501,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -548,7 +548,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "7.1.11", + "version": "7.1.12", "dependencies": { "zod": "catalog:", }, diff --git a/package.json b/package.json index c2ac3d84d61..832994311a2 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,6 @@ "@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch", "ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch" }, - "version": "7.1.11", + "version": "7.1.12", "peerDependencies": {} } diff --git a/packages/app/package.json b/packages/app/package.json index 44dc2a05125..79e2d4a7f5f 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "7.1.11", + "version": "7.1.12", "description": "", "type": "module", "exports": { diff --git a/packages/desktop-electron/package.json b/packages/desktop-electron/package.json index 445b83336a3..aed0249011e 100644 --- a/packages/desktop-electron/package.json +++ b/packages/desktop-electron/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop-electron", "private": true, - "version": "7.1.11", + "version": "7.1.12", "type": "module", "license": "MIT", "homepage": "https://opencode.ai", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 75eec5cdc73..b9b67e28063 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "7.1.11", + "version": "7.1.12", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 12b55abae7e..f9f644386dd 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "kilo" name = "Kilo" description = "The open source coding agent." -version = "7.1.11" +version = "7.1.12" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/Kilo-Org/kilocode" @@ -11,26 +11,26 @@ name = "Kilo" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.11/opencode-darwin-arm64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.12/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.11/opencode-darwin-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.12/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.11/opencode-linux-arm64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.12/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.11/opencode-linux-x64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.12/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.11/opencode-windows-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.12/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/kilo-docs/package.json b/packages/kilo-docs/package.json index 32f86b32191..33f8ab6751a 100644 --- a/packages/kilo-docs/package.json +++ b/packages/kilo-docs/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-docs", - "version": "7.1.11", + "version": "7.1.12", "private": true, "scripts": { "dev": "next dev --webpack --port 3002", diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index cc0c2cc9aef..953ba40dfb5 100644 --- a/packages/kilo-gateway/package.json +++ b/packages/kilo-gateway/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-gateway", - "version": "7.1.11", + "version": "7.1.12", "type": "module", "license": "MIT", "description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration", diff --git a/packages/kilo-i18n/package.json b/packages/kilo-i18n/package.json index b709bbcea07..43d34af4943 100644 --- a/packages/kilo-i18n/package.json +++ b/packages/kilo-i18n/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-i18n", - "version": "7.1.11", + "version": "7.1.12", "type": "module", "license": "MIT", "description": "Kilo-specific i18n translations and overrides", diff --git a/packages/kilo-telemetry/package.json b/packages/kilo-telemetry/package.json index c4c56bb6060..673aa62f638 100644 --- a/packages/kilo-telemetry/package.json +++ b/packages/kilo-telemetry/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-telemetry", - "version": "7.1.11", + "version": "7.1.12", "type": "module", "license": "MIT", "description": "Telemetry for Kilo CLI - PostHog analytics integration", diff --git a/packages/kilo-ui/package.json b/packages/kilo-ui/package.json index 1e9a2132eac..9a144014897 100644 --- a/packages/kilo-ui/package.json +++ b/packages/kilo-ui/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-ui", - "version": "7.1.11", + "version": "7.1.12", "type": "module", "license": "MIT", "exports": { diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 233cd852845..69ef88cbe9c 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -2,7 +2,7 @@ "name": "kilo-code", "displayName": "Kilo Code: AI Coding Agent, Copilot, and Autocomplete", "description": "Open Source AI coding agent that generates code from natural language, automates tasks, and runs terminal commands. Features inline autocomplete, browser automation, automated refactoring, and custom modes for planning, coding, and debugging. Supports 500+ AI models including Claude (Anthropic), Gemini, Grok, GPT, Codex and GLM.", - "version": "7.1.11", + "version": "7.1.12", "icon": "assets/icons/logo-outline-black.png", "galleryBanner": { "color": "#FFFFFF", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 3a0c5bc7f5c..a27a05a8086 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.1.11", + "version": "7.1.12", "name": "@kilocode/cli", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index b95a1cdd854..5e9bbbb3955 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/plugin", - "version": "7.1.11", + "version": "7.1.12", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/script/package.json b/packages/script/package.json index f781c6a94f3..af7b94ef478 100644 --- a/packages/script/package.json +++ b/packages/script/package.json @@ -8,7 +8,7 @@ "exports": { ".": "./src/index.ts" }, - "version": "7.1.11", + "version": "7.1.12", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 7a29e2e3a1a..488ae3e44c5 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/sdk", - "version": "7.1.11", + "version": "7.1.12", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/storybook/package.json b/packages/storybook/package.json index 1f2134e219d..f7c1c7534a4 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -26,7 +26,7 @@ "typescript": "catalog:", "vite": "catalog:" }, - "version": "7.1.11", + "version": "7.1.12", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/ui/package.json b/packages/ui/package.json index e8e085b071c..97741a93cbe 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "7.1.11", + "version": "7.1.12", "type": "module", "license": "MIT", "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index d7d0f372f25..3e74068f88a 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "7.1.11", + "version": "7.1.12", "private": true, "type": "module", "license": "MIT", diff --git a/script/upstream/package.json b/script/upstream/package.json index 056f044d700..14bc0b4e13b 100644 --- a/script/upstream/package.json +++ b/script/upstream/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/upstream-merge", - "version": "7.1.11", + "version": "7.1.12", "private": true, "type": "module", "description": "Scripts for automating upstream opencode merges into Kilo", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index fdf47120b4a..57615b29ee1 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "7.1.11", + "version": "7.1.12", "publisher": "sst-dev", "repository": { "type": "git", From 75a111e8f3e21de775d83087cf3b9e289f7c8276 Mon Sep 17 00:00:00 2001 From: Joshua Lambert <25085430+lambertjosh@users.noreply.github.com> Date: Wed, 1 Apr 2026 02:35:58 -0400 Subject: [PATCH 222/261] fix(kilo-docs): correct Agent Manager keyboard shortcuts and claims (#7958) * fix(kilo-docs): correct Agent Manager keyboard shortcuts and claims - Fix 8 of 12 keyboard shortcuts in the table: Cmd+N = new worktree (not Cmd+Shift+W) Cmd+Shift+W = close worktree (not new) Cmd+T = new tab (not Cmd+N) Cmd+Alt+Up/Down = prev/next worktree (not bracket keys) Cmd+Alt+Left/Right = prev/next tab (not comma/period) Cmd+/ = show terminal (not Cmd+Alt+T) Cmd+D = toggle diff (not Cmd+Alt+D) Cmd+Shift+/ = show shortcuts (not Cmd+Alt+?) - Add missing shortcuts: Cmd+Shift+N (advanced worktree), Cmd+T (new tab) - Fix body text referencing wrong shortcuts (lines 36, 66, 74) - Remove false .env auto-copy claim (it's a commented-out example in the setup script template, not automatic) - Remove non-existent error message from troubleshooting Validated against package.json keybinding definitions. * Update packages/kilo-docs/pages/automate/agent-manager.md Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com> * fix(kilo-docs): add Windows/Linux keybindings to Agent Manager docs --------- Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com> --- .../kilo-docs/pages/automate/agent-manager.md | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/kilo-docs/pages/automate/agent-manager.md b/packages/kilo-docs/pages/automate/agent-manager.md index 17162a67172..36f4d816539 100644 --- a/packages/kilo-docs/pages/automate/agent-manager.md +++ b/packages/kilo-docs/pages/automate/agent-manager.md @@ -33,7 +33,7 @@ Each Agent Manager session runs in an isolated git worktree on a separate branch ### Creating a New Worktree Session -1. Click **New Worktree** or press `Cmd+Shift+W` to create a new worktree +1. Click **New Worktree** or press `Cmd+N` (macOS) / `Ctrl+N` (Windows/Linux) to create a new worktree 2. Enter a branch name (or let Kilo generate one) 3. Type your first message to start the agent @@ -63,7 +63,7 @@ You can run up to 4 parallel implementations of the same prompt across separate ## Diff / Review Panel -Press `Cmd+Alt+D` to toggle the diff panel. It shows a live-updating diff between the worktree and its parent branch. +Press `Cmd+D` (macOS) / `Ctrl+D` (Windows/Linux) to toggle the diff panel. It shows a live-updating diff between the worktree and its parent branch. - Select files and click **Apply to Main Branch** to merge changes - Conflicts are surfaced with a resolution dialog @@ -71,11 +71,11 @@ Press `Cmd+Alt+D` to toggle the diff panel. It shows a live-updating diff betwee ## Terminals -Each session has a dedicated integrated terminal. Press `Cmd+Alt+T` to focus the terminal for the active session. +Each session has a dedicated integrated terminal. Press `Cmd+/` (macOS) / `Ctrl+/` (Windows/Linux) to focus the terminal for the active session. ## Setup Scripts -Place an executable script at `.kilo/setup-script` in your project root. It runs automatically whenever a new worktree is created (useful for `npm install`, env setup, etc.). `.env` files are also auto-copied from the main repo. +Place an executable script at `.kilo/setup-script` in your project root. It runs automatically whenever a new worktree is created (useful for `npm install`, env setup, etc.). Root-level `.env` and `.env.*` files are also auto-copied from the main repo before the setup script runs. ## Session State and Persistence @@ -83,26 +83,26 @@ Agent Manager state is persisted in `.kilo/agent-manager.json`. Sessions, worktr ## Keyboard Shortcuts (Agent Manager Panel) -| Shortcut | Action | -| ----------------- | --------------------------------- | -| `Cmd+Shift+M` | Open Agent Manager | -| `Cmd+Shift+W` | New worktree | -| `Cmd+Shift+O` | Import/open worktree | -| `Cmd+Shift+X` | Close current worktree | -| `Cmd+N` | New tab (session) in worktree | -| `Cmd+W` | Close current tab | -| `Cmd+Alt+[` / `]` | Previous / next worktree | -| `Cmd+Alt+,` / `.` | Previous / next tab in worktree | -| `Cmd+Alt+T` | Show terminal for current session | -| `Cmd+Alt+D` | Toggle diff panel | -| `Cmd+Alt+?` | Show keyboard shortcuts | -| `Cmd+1` … `Cmd+9` | Jump to worktree/session by index | +| Shortcut (macOS) | Shortcut (Windows/Linux) | Action | +| ------------------------ | ------------------------- | --------------------------------- | +| `Cmd+Shift+M` | `Ctrl+Shift+M` | Open Agent Manager | +| `Cmd+N` | `Ctrl+N` | New worktree | +| `Cmd+Shift+N` | `Ctrl+Shift+N` | New worktree (advanced options) | +| `Cmd+Shift+O` | `Ctrl+Shift+O` | Import/open worktree | +| `Cmd+Shift+W` | `Ctrl+Shift+W` | Close current worktree | +| `Cmd+T` | `Ctrl+T` | New tab (session) in worktree | +| `Cmd+W` | `Ctrl+W` | Close current tab | +| `Cmd+Alt+Up` / `Down` | `Ctrl+Alt+Up` / `Down` | Previous / next worktree | +| `Cmd+Alt+Left` / `Right` | `Ctrl+Alt+Left` / `Right` | Previous / next tab in worktree | +| `Cmd+/` | `Ctrl+/` | Show terminal for current session | +| `Cmd+D` | `Ctrl+D` | Toggle diff panel | +| `Cmd+Shift+/` | `Ctrl+Shift+/` | Show keyboard shortcuts | +| `Cmd+1` … `Cmd+9` | `Ctrl+1` … `Ctrl+9` | Jump to worktree/session by index | ## Troubleshooting - **"Please open a folder…" error** — the Agent Manager requires a VS Code workspace folder -- **"Cannot use parallel mode from within a git worktree"** — open the main repository (where `.git` is a directory), not a worktree checkout -- **Worktree creation fails** — ensure Git is installed and the workspace is a valid git repository +- **Worktree creation fails** — ensure Git is installed and the workspace is a valid git repository. Open the main repository (where `.git` is a directory), not an existing worktree checkout. {% /tab %} {% tab label="VSCode (Legacy)" %} From 664bccc9aa7508c214f7ff7cf9db0c411ae759a0 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 1 Apr 2026 08:50:46 +0200 Subject: [PATCH 223/261] Revert "fix(cli): restore directory tree in system prompt" --- packages/opencode/src/session/system.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/session/system.ts b/packages/opencode/src/session/system.ts index 9fce29731c3..1550d03398b 100644 --- a/packages/opencode/src/session/system.ts +++ b/packages/opencode/src/session/system.ts @@ -74,7 +74,7 @@ export namespace SystemPrompt { ``, ``, ` ${ - project.vcs === "git" + project.vcs === "git" && false ? await Ripgrep.tree({ cwd: Instance.directory, limit: 50, From b7fc4201cbb6f7a588e1733f93fbc3960879328c Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 07:27:18 +0000 Subject: [PATCH 224/261] feat(vscode): add toolbar buttons to editor tab panel Show the same navigation buttons (new task, history, agent manager, marketplace, profile, settings) in the editor/title area when Kilo is open as a tab panel, matching the sidebar experience. --- packages/kilo-vscode/package.json | 30 +++++++++++++++++++++++++++ packages/kilo-vscode/src/extension.ts | 24 ++++++++++++++++++--- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 69ef88cbe9c..2e401e489aa 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -373,6 +373,36 @@ "command": "kilo-code.new.openInTab", "group": "navigation", "when": "true" + }, + { + "command": "kilo-code.new.plusButtonClicked", + "group": "navigation@0", + "when": "activeWebviewPanelId == kilo-code.new.TabPanel" + }, + { + "command": "kilo-code.new.historyButtonClicked", + "group": "navigation@1", + "when": "activeWebviewPanelId == kilo-code.new.TabPanel" + }, + { + "command": "kilo-code.new.agentManagerOpen", + "group": "navigation@2", + "when": "activeWebviewPanelId == kilo-code.new.TabPanel" + }, + { + "command": "kilo-code.new.marketplaceButtonClicked", + "group": "navigation@3", + "when": "activeWebviewPanelId == kilo-code.new.TabPanel" + }, + { + "command": "kilo-code.new.profileButtonClicked", + "group": "navigation@4", + "when": "activeWebviewPanelId == kilo-code.new.TabPanel" + }, + { + "command": "kilo-code.new.settingsButtonClicked", + "group": "navigation@5", + "when": "activeWebviewPanelId == kilo-code.new.TabPanel" } ], "editor/context": [ diff --git a/packages/kilo-vscode/src/extension.ts b/packages/kilo-vscode/src/extension.ts index bf6d27da0f2..7b7c48bed87 100644 --- a/packages/kilo-vscode/src/extension.ts +++ b/packages/kilo-vscode/src/extension.ts @@ -45,6 +45,15 @@ export function activate(context: vscode.ExtensionContext) { } }) + // Track all open tab panel providers so toolbar button commands can target them + const tabPanels = new Map() + const activeTabProvider = () => { + for (const [panel, p] of tabPanels) { + if (panel.active) return p + } + return undefined + } + // Create the provider with shared service const provider = new KiloProvider(context.extensionUri, connectionService, context) @@ -94,9 +103,11 @@ export function activate(context: vscode.ExtensionContext) { agentManagerProvider.continueFromSidebar(sessionId, progress), ) tabProvider.resolveWebviewPanel(panel) + tabPanels.set(panel, tabProvider) panel.onDidDispose( () => { console.log("[Kilo New] Tab panel restored from restart disposed") + tabPanels.delete(panel) tabProvider.dispose() }, null, @@ -158,7 +169,9 @@ export function activate(context: vscode.ExtensionContext) { // Register toolbar button command handlers context.subscriptions.push( vscode.commands.registerCommand("kilo-code.new.plusButtonClicked", () => { - provider.postMessage({ type: "action", action: "plusButtonClicked" }) + const tab = activeTabProvider() + if (tab) tab.postMessage({ type: "action", action: "plusButtonClicked" }) + else provider.postMessage({ type: "action", action: "plusButtonClicked" }) }), vscode.commands.registerCommand("kilo-code.new.agentManagerOpen", () => { agentManagerProvider.openPanel() @@ -167,7 +180,9 @@ export function activate(context: vscode.ExtensionContext) { settingsEditorProvider.openPanel("marketplace", undefined, directory) }), vscode.commands.registerCommand("kilo-code.new.historyButtonClicked", () => { - provider.postMessage({ type: "action", action: "historyButtonClicked" }) + const tab = activeTabProvider() + if (tab) tab.postMessage({ type: "action", action: "historyButtonClicked" }) + else provider.postMessage({ type: "action", action: "historyButtonClicked" }) }), vscode.commands.registerCommand("kilo-code.new.cycleAgentMode", () => { provider.postMessage({ type: "action", action: "cycleAgentMode" }) @@ -199,7 +214,7 @@ export function activate(context: vscode.ExtensionContext) { provider.postMessage({ type: "triggerTask", text: `Generate a terminal command: ${input}` }) }), vscode.commands.registerCommand("kilo-code.new.openInTab", () => { - return openKiloInNewTab(context, connectionService, agentManagerProvider) + return openKiloInNewTab(context, connectionService, agentManagerProvider, tabPanels) }), vscode.commands.registerCommand("kilo-code.new.showChanges", () => { diffViewerProvider.openPanel() @@ -330,6 +345,7 @@ async function openKiloInNewTab( context: vscode.ExtensionContext, connectionService: KiloConnectionService, agentManagerProvider: AgentManagerProvider, + tabPanels: Map, ) { const lastCol = Math.max(...vscode.window.visibleTextEditors.map((e) => e.viewColumn || 0), 0) const hasVisibleEditors = vscode.window.visibleTextEditors.length > 0 @@ -356,6 +372,7 @@ async function openKiloInNewTab( agentManagerProvider.continueFromSidebar(sessionId, progress), ) tabProvider.resolveWebviewPanel(panel) + tabPanels.set(panel, tabProvider) // Wait for the new panel to become active before locking the editor group. // This avoids the race where VS Code hasn't switched focus yet. @@ -365,6 +382,7 @@ async function openKiloInNewTab( panel.onDidDispose( () => { console.log("[Kilo New] Tab panel disposed") + tabPanels.delete(panel) tabProvider.dispose() }, null, From 3cc4d38f12b8905d659a50242bf45e6b8b31f5f6 Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Wed, 1 Apr 2026 07:35:46 +0000 Subject: [PATCH 225/261] release: v7.1.13 --- bun.lock | 32 +++++++++++++------------- package.json | 2 +- packages/app/package.json | 2 +- packages/desktop-electron/package.json | 2 +- packages/desktop/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++----- packages/kilo-docs/package.json | 2 +- packages/kilo-gateway/package.json | 2 +- packages/kilo-i18n/package.json | 2 +- packages/kilo-telemetry/package.json | 2 +- packages/kilo-ui/package.json | 2 +- packages/kilo-vscode/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/script/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/storybook/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- script/upstream/package.json | 2 +- sdks/vscode/package.json | 2 +- 21 files changed, 41 insertions(+), 41 deletions(-) diff --git a/bun.lock b/bun.lock index c7c85cebbe6..0dae651f9e8 100644 --- a/bun.lock +++ b/bun.lock @@ -27,7 +27,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "@kilocode/kilo-i18n": "workspace:*", "@kilocode/kilo-ui": "workspace:*", @@ -79,7 +79,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -112,7 +112,7 @@ }, "packages/desktop-electron": { "name": "@opencode-ai/desktop-electron", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -142,7 +142,7 @@ }, "packages/kilo-docs": { "name": "@kilocode/kilo-docs", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "@docsearch/css": "^4", "@docsearch/js": "^4", @@ -171,7 +171,7 @@ }, "packages/kilo-gateway": { "name": "@kilocode/kilo-gateway", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "@ai-sdk/anthropic": "2.0.65", "@ai-sdk/openai": "2.0.101", @@ -206,7 +206,7 @@ }, "packages/kilo-i18n": { "name": "@kilocode/kilo-i18n", - "version": "7.1.12", + "version": "7.1.13", "devDependencies": { "@tsconfig/node22": "catalog:", "@types/bun": "catalog:", @@ -216,7 +216,7 @@ }, "packages/kilo-telemetry": { "name": "@kilocode/kilo-telemetry", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "@kilocode/kilo-gateway": "workspace:*", "@opentelemetry/api": "1.9.0", @@ -236,7 +236,7 @@ }, "packages/kilo-ui": { "name": "@kilocode/kilo-ui", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "@kobalte/core": "0.13.11", "@opencode-ai/util": "workspace:*", @@ -271,7 +271,7 @@ }, "packages/kilo-vscode": { "name": "kilo-code", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "@anthropic-ai/sdk": "^0.39.0", "@kilocode/kilo-i18n": "workspace:*", @@ -324,7 +324,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "7.1.12", + "version": "7.1.13", "bin": { "kilo": "./bin/kilo", "kilocode": "./bin/kilo", @@ -446,7 +446,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "@kilocode/sdk": "workspace:*", "zod": "catalog:", @@ -460,14 +460,14 @@ }, "packages/script": { "name": "@opencode-ai/script", - "version": "7.1.12", + "version": "7.1.13", "devDependencies": { "@types/bun": "catalog:", }, }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "7.1.12", + "version": "7.1.13", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -478,7 +478,7 @@ }, "packages/storybook": { "name": "@opencode-ai/storybook", - "version": "7.1.12", + "version": "7.1.13", "devDependencies": { "@opencode-ai/ui": "workspace:*", "@solidjs/meta": "catalog:", @@ -501,7 +501,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -548,7 +548,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "7.1.12", + "version": "7.1.13", "dependencies": { "zod": "catalog:", }, diff --git a/package.json b/package.json index 832994311a2..c501942aa0f 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,6 @@ "@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch", "ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch" }, - "version": "7.1.12", + "version": "7.1.13", "peerDependencies": {} } diff --git a/packages/app/package.json b/packages/app/package.json index 79e2d4a7f5f..a70f1d47fa6 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "7.1.12", + "version": "7.1.13", "description": "", "type": "module", "exports": { diff --git a/packages/desktop-electron/package.json b/packages/desktop-electron/package.json index aed0249011e..5cbdfb439f1 100644 --- a/packages/desktop-electron/package.json +++ b/packages/desktop-electron/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop-electron", "private": true, - "version": "7.1.12", + "version": "7.1.13", "type": "module", "license": "MIT", "homepage": "https://opencode.ai", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index b9b67e28063..8e9efcbf626 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "7.1.12", + "version": "7.1.13", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index f9f644386dd..a5b7fe328d0 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "kilo" name = "Kilo" description = "The open source coding agent." -version = "7.1.12" +version = "7.1.13" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/Kilo-Org/kilocode" @@ -11,26 +11,26 @@ name = "Kilo" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.12/opencode-darwin-arm64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.13/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.12/opencode-darwin-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.13/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.12/opencode-linux-arm64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.13/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.12/opencode-linux-x64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.13/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.12/opencode-windows-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.13/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/kilo-docs/package.json b/packages/kilo-docs/package.json index 33f8ab6751a..8101d074b57 100644 --- a/packages/kilo-docs/package.json +++ b/packages/kilo-docs/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-docs", - "version": "7.1.12", + "version": "7.1.13", "private": true, "scripts": { "dev": "next dev --webpack --port 3002", diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index 953ba40dfb5..1d21915242a 100644 --- a/packages/kilo-gateway/package.json +++ b/packages/kilo-gateway/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-gateway", - "version": "7.1.12", + "version": "7.1.13", "type": "module", "license": "MIT", "description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration", diff --git a/packages/kilo-i18n/package.json b/packages/kilo-i18n/package.json index 43d34af4943..9f8c37ec7e9 100644 --- a/packages/kilo-i18n/package.json +++ b/packages/kilo-i18n/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-i18n", - "version": "7.1.12", + "version": "7.1.13", "type": "module", "license": "MIT", "description": "Kilo-specific i18n translations and overrides", diff --git a/packages/kilo-telemetry/package.json b/packages/kilo-telemetry/package.json index 673aa62f638..b6814c97573 100644 --- a/packages/kilo-telemetry/package.json +++ b/packages/kilo-telemetry/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-telemetry", - "version": "7.1.12", + "version": "7.1.13", "type": "module", "license": "MIT", "description": "Telemetry for Kilo CLI - PostHog analytics integration", diff --git a/packages/kilo-ui/package.json b/packages/kilo-ui/package.json index 9a144014897..3ed656d5c14 100644 --- a/packages/kilo-ui/package.json +++ b/packages/kilo-ui/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-ui", - "version": "7.1.12", + "version": "7.1.13", "type": "module", "license": "MIT", "exports": { diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 69ef88cbe9c..d4bd4dd56bd 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -2,7 +2,7 @@ "name": "kilo-code", "displayName": "Kilo Code: AI Coding Agent, Copilot, and Autocomplete", "description": "Open Source AI coding agent that generates code from natural language, automates tasks, and runs terminal commands. Features inline autocomplete, browser automation, automated refactoring, and custom modes for planning, coding, and debugging. Supports 500+ AI models including Claude (Anthropic), Gemini, Grok, GPT, Codex and GLM.", - "version": "7.1.12", + "version": "7.1.13", "icon": "assets/icons/logo-outline-black.png", "galleryBanner": { "color": "#FFFFFF", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index a27a05a8086..0628c068c6a 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.1.12", + "version": "7.1.13", "name": "@kilocode/cli", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 5e9bbbb3955..40896bd3421 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/plugin", - "version": "7.1.12", + "version": "7.1.13", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/script/package.json b/packages/script/package.json index af7b94ef478..d6a3b986d13 100644 --- a/packages/script/package.json +++ b/packages/script/package.json @@ -8,7 +8,7 @@ "exports": { ".": "./src/index.ts" }, - "version": "7.1.12", + "version": "7.1.13", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 488ae3e44c5..ff81ac84c3c 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/sdk", - "version": "7.1.12", + "version": "7.1.13", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/storybook/package.json b/packages/storybook/package.json index f7c1c7534a4..ada3ffb8c60 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -26,7 +26,7 @@ "typescript": "catalog:", "vite": "catalog:" }, - "version": "7.1.12", + "version": "7.1.13", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/ui/package.json b/packages/ui/package.json index 97741a93cbe..0ae1a67d433 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "7.1.12", + "version": "7.1.13", "type": "module", "license": "MIT", "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index 3e74068f88a..374a644b191 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "7.1.12", + "version": "7.1.13", "private": true, "type": "module", "license": "MIT", diff --git a/script/upstream/package.json b/script/upstream/package.json index 14bc0b4e13b..f5e543fd49e 100644 --- a/script/upstream/package.json +++ b/script/upstream/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/upstream-merge", - "version": "7.1.12", + "version": "7.1.13", "private": true, "type": "module", "description": "Scripts for automating upstream opencode merges into Kilo", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 57615b29ee1..88f7571c831 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "7.1.12", + "version": "7.1.13", "publisher": "sst-dev", "repository": { "type": "git", From 649ca688c13b9bff6ba8d91770c57e6df40f2972 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 1 Apr 2026 09:52:14 +0200 Subject: [PATCH 226/261] fix(vscode): remove agent manager and marketplace buttons from tab toolbar --- packages/kilo-vscode/package.json | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 2e401e489aa..882c27b1ad3 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -385,23 +385,13 @@ "when": "activeWebviewPanelId == kilo-code.new.TabPanel" }, { - "command": "kilo-code.new.agentManagerOpen", + "command": "kilo-code.new.profileButtonClicked", "group": "navigation@2", "when": "activeWebviewPanelId == kilo-code.new.TabPanel" }, - { - "command": "kilo-code.new.marketplaceButtonClicked", - "group": "navigation@3", - "when": "activeWebviewPanelId == kilo-code.new.TabPanel" - }, - { - "command": "kilo-code.new.profileButtonClicked", - "group": "navigation@4", - "when": "activeWebviewPanelId == kilo-code.new.TabPanel" - }, { "command": "kilo-code.new.settingsButtonClicked", - "group": "navigation@5", + "group": "navigation@3", "when": "activeWebviewPanelId == kilo-code.new.TabPanel" } ], From 79f1bf4bfcb8e7135b7c42d391041d4b7afef991 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 1 Apr 2026 09:57:43 +0200 Subject: [PATCH 227/261] docs(vscode): explain why tab toolbar omits agent manager and marketplace --- packages/kilo-vscode/src/extension.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/src/extension.ts b/packages/kilo-vscode/src/extension.ts index 7b7c48bed87..6679ac84453 100644 --- a/packages/kilo-vscode/src/extension.ts +++ b/packages/kilo-vscode/src/extension.ts @@ -45,7 +45,10 @@ export function activate(context: vscode.ExtensionContext) { } }) - // Track all open tab panel providers so toolbar button commands can target them + // Track all open tab panel providers so toolbar button commands can target them. + // NOTE: The editor/title toolbar for tab panels intentionally omits Agent Manager + // and Marketplace buttons (unlike the sidebar). Too many icons causes VS Code to + // collapse them into a "..." overflow menu, hiding important buttons like Settings. const tabPanels = new Map() const activeTabProvider = () => { for (const [panel, p] of tabPanels) { From 7faec3ee95ee74cca5a4034f50a08fb9be47af18 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 08:28:04 +0000 Subject: [PATCH 228/261] feat(i18n): add uk translations across packages introduce ukrainian locale files (uk.ts) across i18n, UI, and VSCode UI to enable Ukrainian language support - packages/kilo-i18n/src/uk.ts - packages/kilo-ui/src/i18n/uk.ts - packages/kilo-vscode/src/services/cli-backend/i18n/uk.ts - packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts - packages/kilo-vscode/webview-ui/src/i18n/uk.ts - packages/ui/src/i18n/uk.ts --- packages/kilo-i18n/src/uk.ts | 72 + packages/kilo-ui/src/i18n/uk.ts | 1 + .../src/services/cli-backend/i18n/uk.ts | 4 + .../webview-ui/agent-manager/i18n/uk.ts | 173 +++ .../kilo-vscode/webview-ui/src/i18n/uk.ts | 1304 +++++++++++++++++ packages/ui/src/i18n/uk.ts | 153 ++ 6 files changed, 1707 insertions(+) create mode 100644 packages/kilo-i18n/src/uk.ts create mode 100644 packages/kilo-ui/src/i18n/uk.ts create mode 100644 packages/kilo-vscode/src/services/cli-backend/i18n/uk.ts create mode 100644 packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts create mode 100644 packages/kilo-vscode/webview-ui/src/i18n/uk.ts create mode 100644 packages/ui/src/i18n/uk.ts diff --git a/packages/kilo-i18n/src/uk.ts b/packages/kilo-i18n/src/uk.ts new file mode 100644 index 00000000000..fe56df66a46 --- /dev/null +++ b/packages/kilo-i18n/src/uk.ts @@ -0,0 +1,72 @@ +export const dict = { + // Kilo Gateway provider translations + "provider.connect.kiloGateway.line1": + "Kilo Gateway надає доступ до добірки надійних оптимізованих моделей для агентів кодування.", + "provider.connect.kiloGateway.line2": + "За допомогою одного API-ключа ви отримаєте доступ до таких моделей, як Claude, GPT, Gemini, GLM та інших.", + "provider.connect.kiloGateway.visit.prefix": "Відвідайте ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " щоб отримати свій API-ключ.", + + // Provider dialog translations + "dialog.provider.group.recommended": "Рекомендовані", + "dialog.provider.kilo.note": "Доступ до 500+ моделей ШІ", + + // Reasoning block label + "ui.permission.run": "Виконати", + "ui.reasoning.label": "Міркування", + + // Marketplace + "marketplace.tab.skills": "Навички", + "marketplace.tab.mcpServers": "MCP-сервери", + "marketplace.tab.modes": "Режими", + "marketplace.category.all": "Усі", + "marketplace.placeholder": "Буде реалізовано", + "marketplace.card.installed": "Встановлено", + "marketplace.card.install": "Встановити", + "marketplace.card.remove": "Видалити", + "marketplace.card.removeScope": "Видалити ({{scope}})", + "marketplace.card.showMore": "Показати більше", + "marketplace.card.showLess": "Показати менше", + "marketplace.install.title": "Встановити {{name}}", + "marketplace.install.scope": "Область", + "marketplace.install.scope.project": "Проєкт", + "marketplace.install.scope.global": "Глобально", + "marketplace.install.prerequisites": "Передумови", + "marketplace.install.installing": "Встановлення...", + "marketplace.install.cancel": "Скасувати", + "marketplace.install.success": "Успішно встановлено!", + "marketplace.install.failed": "Встановлення не вдалося", + "marketplace.install.done": "Готово", + "marketplace.install.close": "Закрити", + "marketplace.remove.title": "Видалити {{name}}?", + "marketplace.remove.confirm": + "Ви впевнені, що хочете видалити цей {{type}}? Це видалить його з вашої конфігурації {{scope}}.", + "marketplace.remove.cancel": "Скасувати", + "marketplace.remove.confirm.button": "Видалити", + "marketplace.tab.mcp": "MCP", + "marketplace.search": "Пошук...", + "marketplace.filter.all": "Усі елементи", + "marketplace.filter.notInstalled": "Не встановлено", + "marketplace.empty": "Елементів не знайдено", + "marketplace.badge.mcpServer": "MCP-сервер", + "marketplace.badge.mode": "Режим", + "marketplace.card.by": "від {{author}}", + "marketplace.install.method": "Метод встановлення", + "marketplace.install.parameters": "Параметри", + "marketplace.install.optional": "(необов'язково)", + "marketplace.install.required": "{{name}} є обов'язковим", + "marketplace.scope.project": "проєкт", + "marketplace.scope.global": "глобально", + "marketplace.remove.type.mcp": "MCP-сервер", + "marketplace.remove.type.skill": "навичка", + "marketplace.remove.type.mode": "режим", + "marketplace.remove.failed": "Не вдалося видалити {{name}}", + "marketplace.install": "Встановити", + "marketplace.filter.installed": "Встановлено", + "marketplace.error.dismiss": "Закрити", + "marketplace.warning.busyOne": "Одна сесія виконується і буде перервана", + "marketplace.warning.busyMany": "Кілька сесій виконуються і будуть перервані", + "marketplace.warning.installAnyway": "Встановити все одно", + "marketplace.warning.cancel": "Скасувати", +} diff --git a/packages/kilo-ui/src/i18n/uk.ts b/packages/kilo-ui/src/i18n/uk.ts new file mode 100644 index 00000000000..197e28172a4 --- /dev/null +++ b/packages/kilo-ui/src/i18n/uk.ts @@ -0,0 +1 @@ +export * from "@opencode-ai/ui/i18n/uk" diff --git a/packages/kilo-vscode/src/services/cli-backend/i18n/uk.ts b/packages/kilo-vscode/src/services/cli-backend/i18n/uk.ts new file mode 100644 index 00000000000..fe0c703d0e7 --- /dev/null +++ b/packages/kilo-vscode/src/services/cli-backend/i18n/uk.ts @@ -0,0 +1,4 @@ +export const dict = { + "server.processExited": "Процес CLI завершився з кодом {{code}} до запуску сервера", + "server.startupTimeout": "Час очікування запуску сервера вичерпано після {{seconds}} секунд", +} as const diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts new file mode 100644 index 00000000000..1077cd54384 --- /dev/null +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts @@ -0,0 +1,173 @@ +export const dict = { + "agentManager.local": "локальний", + "agentManager.section.worktrees": "РОБОЧІ ДЕРЕВА", + "agentManager.section.sessions": "СЕСІЇ", + "agentManager.notGitRepo": "Не є git-репозиторієм", + + "agentManager.worktree.settings": "Налаштування робочого дерева", + "agentManager.worktree.new": "Нове робоче дерево", + "agentManager.worktree.setupScript": "Скрипт налаштування робочого дерева", + "agentManager.worktree.delete": "Видалити робоче дерево", + "agentManager.worktree.confirmDelete": "Видалити?", + "agentManager.worktree.stale": "Застаріле", + "agentManager.worktree.staleTooltip": "Відсутнє на диску або більше не відстежується git worktree", + "agentManager.worktree.removeStale": "Видалити застаріле робоче дерево", + "agentManager.worktree.doubleClickRename": "Двічі клацніть для перейменування", + "agentManager.worktree.versions": "{{count}} версій", + "agentManager.worktree.advancedOptions": "Розширені параметри робочого дерева", + "agentManager.worktree.defaultBaseBranch": "Гілка за замовчуванням", + "agentManager.worktree.defaultBaseBranchAuto": "Автоматичне визначення", + "agentManager.worktree.copyPath": "Копіювати шлях", + "agentManager.worktree.openInVscode": "Відкрити у VS Code", + "agentManager.worktree.rename": "Перейменувати", + + "agentManager.hoverCard.branch": "ГІЛКА", + "agentManager.hoverCard.base": "База", + "agentManager.hoverCard.sessions": "Сесії", + "agentManager.hoverCard.files": "Файли", + "agentManager.hoverCard.changes": "Зміни", + "agentManager.hoverCard.commits": "Коміти", + + "agentManager.session.new": "Нова сесія", + "agentManager.session.untitled": "Без назви", + "agentManager.session.newSession": "Нова сесія", + "agentManager.session.openInWorktree": "Відкрити у робочому дереві", + "agentManager.session.openLocally": "Відкрити локально", + "agentManager.session.readonly": "Сесія лише для читання", + "agentManager.session.noSessions": "Немає відкритих сесій", + + "agentManager.tab.close": "Закрити", + "agentManager.tab.closeTab": "Закрити вкладку", + "agentManager.tab.forkSession": "Розгалужити сесію", + "agentManager.tab.terminal": "Термінал", + "agentManager.tab.openTerminal": "Відкрити термінал", + + "agentManager.setup.failed": "Налаштування робочого дерева не вдалося", + "agentManager.setup.settingUp": "Налаштування робочого дерева", + "agentManager.setup.error.git_not_found": + "Git не встановлено або не знайдено в PATH. Будь ласка, встановіть Git і перезапустіть VS Code.", + "agentManager.setup.error.not_git_repo": + "Відкрийте папку, що містить git-репозиторій, щоб використовувати робочі дерева.", + "agentManager.setup.error.lfs_missing": + "Цей репозиторій використовує Git LFS, але git-lfs не знайдено. Будь ласка, встановіть Git LFS.", + "agentManager.shortcuts.title": "Клавіатурні скорочення", + "agentManager.shortcuts.category.sidebar": "Бічна панель", + "agentManager.shortcuts.category.tabs": "Вкладки", + "agentManager.shortcuts.category.terminal": "Термінал", + "agentManager.shortcuts.category.global": "Глобальні", + "agentManager.shortcuts.previousItem": "Попередній елемент", + "agentManager.shortcuts.nextItem": "Наступний елемент", + "agentManager.shortcuts.newWorktree": "Нове робоче дерево", + "agentManager.shortcuts.openWorktree": "Відкрити робоче дерево", + "agentManager.shortcuts.advancedWorktree": "Розширене робоче дерево", + "agentManager.shortcuts.deleteWorktree": "Видалити робоче дерево", + "agentManager.shortcuts.previousTab": "Попередня вкладка", + "agentManager.shortcuts.nextTab": "Наступна вкладка", + "agentManager.shortcuts.newTab": "Нова вкладка", + "agentManager.shortcuts.closeTab": "Закрити вкладку", + "agentManager.shortcuts.toggleTerminal": "Перемкнути термінал", + "agentManager.shortcuts.openAgentManager": "Відкрити Agent Manager", + "agentManager.shortcuts.cycleAgentMode": "Наступний режим агента", + "agentManager.shortcuts.cyclePreviousAgentMode": "Попередній режим агента", + "agentManager.shortcuts.showShortcuts": "Показати клавіатурні скорочення", + + "agentManager.dialog.removeStaleWorktree.title": "Видалити застаріле робоче дерево", + "agentManager.dialog.removeStaleWorktree.messagePre": "Видалити застаріле робоче дерево ", + "agentManager.dialog.removeStaleWorktree.messagePost": + "? Це лише видалить відображення в Agent Manager і не торкнеться файлів на диску.", + "agentManager.dialog.removeStaleWorktree.cancel": "Скасувати", + "agentManager.dialog.removeStaleWorktree.confirm": "Видалити застаріле робоче дерево", + + "agentManager.dialog.openWorktree": "Нове робоче дерево", + "agentManager.dialog.tab.new": "Нове", + "agentManager.dialog.tab.import": "Імпортувати", + "agentManager.dialog.namePlaceholder": "Назва робочого дерева (необов'язково)", + "agentManager.dialog.promptPlaceholder.mac": "Введіть повідомлення (\u2318Enter для надсилання)", + "agentManager.dialog.promptPlaceholder.other": "Введіть повідомлення (Ctrl+Enter для надсилання)", + "agentManager.dialog.advancedOptions": "Розширені параметри", + "agentManager.dialog.branchName": "Назва гілки", + "agentManager.dialog.branchNamePlaceholder": "автоматично згенерована", + "agentManager.dialog.baseBranch": "Базова гілка", + "agentManager.dialog.searchBranches": "Пошук гілок...", + "agentManager.dialog.branchBadge.default": "за замовчуванням", + "agentManager.dialog.branchBadge.remote": "віддалена", + "agentManager.dialog.versions": "Версії", + "agentManager.dialog.versionHint": "{{count}} робочих дерев виконуватимуться паралельно", + "agentManager.dialog.compareModels": "Порівняти моделі", + "agentManager.dialog.compareModels.tooltip": + "Запустіть агентів на різних моделях паралельно для порівняння результатів", + "agentManager.dialog.compareModels.searchModels": "Пошук моделей...", + "agentManager.dialog.compareModels.selectModels": "Оберіть моделі...", + "agentManager.dialog.creating": "Створення...", + "agentManager.dialog.createWorktree": "Створити робоче дерево", + "agentManager.dialog.removeImage": "Видалити зображення", + "agentManager.dialog.advanced": "Розширено...", + + "agentManager.diff.toggle": "Перемкнути diff", + "agentManager.diff.openFile": "Відкрити файл", + "agentManager.open.button": "Відкрити", + "agentManager.open.tooltip": "Відкрити це робоче дерево у VS Code", + "agentManager.apply.button": "Застосувати локально", + "agentManager.apply.globalButton": "Застосувати", + "agentManager.apply.tooltip": "Застосувати вибрані зміни робочого дерева до локальної гілки", + "agentManager.apply.dialogTitle": "Застосувати зміни до локальної гілки", + "agentManager.apply.confirm": "Застосувати зараз", + "agentManager.apply.retry": "Повторити застосування", + "agentManager.apply.previewTitle": "Застосувати ці зміни до локальної гілки?", + "agentManager.apply.previewSummary": "{{files}} файлів, +{{additions}} -{{deletions}}", + "agentManager.apply.selectionSummary": "{{selected}} з {{total}} файлів вибрано", + "agentManager.apply.selectAll": "Вибрати все", + "agentManager.apply.selectNone": "Зняти вибір", + "agentManager.apply.moreFiles": "+{{count}} ще", + "agentManager.apply.moreReasons": "{{reason}} (+{{count}} ще)", + "agentManager.apply.checking": "Перевірка...", + "agentManager.apply.applying": "Застосування...", + "agentManager.apply.success": "Зміни застосовано", + "agentManager.apply.conflict": "Застосування має конфлікти", + "agentManager.apply.conflictToast": + "{{count}} конфліктів у {{files}} файлах. Перегляньте деталі в розділі Застосувати.", + "agentManager.apply.error": "Застосування не вдалося", + "agentManager.apply.conflictsTitle": "Конфлікти", + "agentManager.apply.unknownFile": "Нерозв'язаний файл", + "agentManager.apply.reason.index": "Локальний файл відрізняється від очікуваної версії", + "agentManager.apply.reason.patch": "Патч неможливо застосувати без конфліктів", + "agentManager.apply.reason.contents": "Неможливо прочитати вміст поточного локального файлу", + "agentManager.apply.reason.unknown": "Виявлено конфлікт", + "agentManager.apply.inline.success": "Застосовано", + "agentManager.apply.inline.conflict": "Конфлікти", + "agentManager.apply.inline.error": "Не вдалося", + "agentManager.shortcuts.toggleDiff": "Перемкнути панель diff", + "agentManager.shortcuts.category.quickSwitch": "Швидке перемикання", + "agentManager.shortcuts.jumpToItem": "Перейти до елемента 1\u20139", + "agentManager.review.sendAllToChat": "Надіслати все до чату", + "agentManager.review.sendAllToChatWithCount": "Надіслати все до чату ({{count}})", + "agentManager.review.sendAllShortcut.mac": "⌘Enter", + "agentManager.review.sendAllShortcut.other": "Ctrl+Enter", + "agentManager.review.modalTitle": "Переглянути коментар", + "agentManager.review.inlineCount": "Переглянути коментарі ({{count}})", + "agentManager.review.clearAll": "Очистити все", + "agentManager.review.commentOnLine": "Коментар до рядка {{line}}", + "agentManager.review.editCommentOnLine": "Редагувати коментар до рядка {{line}}", + "agentManager.review.commentPlaceholder": "Залишити коментар...", + "agentManager.review.commentAction": "Коментувати", + "agentManager.review.sendToChat": "Надіслати до чату", + "agentManager.review.metaFile": "Файл", + "agentManager.review.metaLine": "Рядок", + "agentManager.review.metaComment": "Коментар користувача", + "agentManager.review.collapsedOnly": "{{count}} згорнуто", + "agentManager.review.collapsedWithLarge": "{{collapsed}} згорнуто, {{large}} великих", + "agentManager.review.largeFileCollapsed": "Великий файл (згорнуто)", + "agentManager.review.endOfLongDiff": "Ви дійшли до кінця!", + + "agentManager.import.pullRequest": "Pull Request", + "agentManager.import.pastePrUrl": "Вставте URL PR...", + "agentManager.import.open": "Відкрити", + "agentManager.import.branches": "Гілки", + "agentManager.import.selectBranch": "Оберіть гілку...", + "agentManager.import.loading": "Завантаження...", + "agentManager.import.loadingBranches": "Завантаження гілок...", + "agentManager.import.noMatchingBranches": "Відповідних гілок не знайдено", + "agentManager.import.noBranchesFound": "Гілок не знайдено.", + "agentManager.import.noBranchesHint": "Вставте URL PR вище або створіть нове робоче дерево.", + "agentManager.import.failed": "Імпортування не вдалося", +} diff --git a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts new file mode 100644 index 00000000000..f84fc439d32 --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts @@ -0,0 +1,1304 @@ +export const dict = { + "command.category.suggested": "Запропоновані", + "command.category.view": "Вигляд", + "command.category.project": "Проєкт", + "command.category.provider": "Провайдер", + "command.category.server": "Сервер", + "command.category.session": "Сесія", + "command.category.theme": "Тема", + "command.category.language": "Мова", + "command.category.file": "Файл", + "command.category.context": "Контекст", + "command.category.terminal": "Термінал", + "command.category.model": "Модель", + "command.category.mcp": "MCP", + "command.category.agent": "Агент", + "command.category.permissions": "Дозволи", + "command.category.workspace": "Робочий простір", + "command.category.settings": "Налаштування", + + "theme.scheme.system": "Системна", + "theme.scheme.light": "Світла", + "theme.scheme.dark": "Темна", + + "command.sidebar.toggle": "Перемкнути бічну панель", + "command.project.open": "Відкрити проєкт", + "command.provider.connect": "Підключити провайдера", + "command.server.switch": "Переключити сервер", + "command.settings.open": "Відкрити налаштування", + "command.session.previous": "Попередня сесія", + "command.session.next": "Наступна сесія", + "command.session.previous.unseen": "Попередня непрочитана сесія", + "command.session.next.unseen": "Наступна непрочитана сесія", + "command.session.archive": "Архівувати сесію", + + "command.palette": "Палітра команд", + + "command.theme.cycle": "Змінити тему", + "command.theme.set": "Використати тему: {{theme}}", + "command.theme.scheme.cycle": "Змінити кольорову схему", + "command.theme.scheme.set": "Використати кольорову схему: {{scheme}}", + + "command.language.cycle": "Змінити мову", + "command.language.set": "Використати мову: {{language}}", + + "command.session.new": "Нова сесія", + "command.session.new.task": "Нове завдання", + "command.session.show.changes": "Показати зміни", + "command.file.open": "Відкрити файл", + "command.tab.close": "Закрити вкладку", + "command.context.addSelection": "Додати виділення до контексту", + "command.context.addSelection.description": "Додати виділені рядки з поточного файлу", + "command.terminal.toggle": "Перемкнути термінал", + "command.fileTree.toggle": "Перемкнути дерево файлів", + "command.review.toggle": "Перемкнути огляд", + "command.terminal.new": "Новий термінал", + "command.terminal.new.description": "Створити нову вкладку терміналу", + "command.steps.toggle": "Перемкнути кроки", + "command.steps.toggle.description": "Показати або приховати кроки для поточного повідомлення", + "command.message.previous": "Попереднє повідомлення", + "command.message.previous.description": "Перейти до попереднього повідомлення користувача", + "command.message.next": "Наступне повідомлення", + "command.message.next.description": "Перейти до наступного повідомлення користувача", + "command.model.choose": "Вибрати модель", + "command.model.choose.description": "Вибрати іншу модель", + "command.mcp.toggle": "Перемкнути MCP", + "command.mcp.toggle.description": "Увімкнути або вимкнути MCP", + "command.agent.cycle": "Змінити агента", + "command.agent.cycle.description": "Перейти до наступного агента", + "command.agent.cycle.reverse": "Змінити агента назад", + "command.agent.cycle.reverse.description": "Перейти до попереднього агента", + "command.model.variant.cycle": "Змінити зусилля мислення", + "command.model.variant.cycle.description": "Перейти до наступного рівня зусиль", + "command.permissions.autoaccept.enable": "Автоматично приймати редагування", + "command.permissions.autoaccept.disable": "Зупинити автоматичне прийняття", + "command.workspace.toggle": "Перемкнути робочі простори", + "command.workspace.toggle.description": "Показати або приховати кілька робочих просторів на бічній панелі", + "command.session.undo": "Скасувати", + "command.session.undo.description": "Скасувати останнє повідомлення", + "command.session.redo": "Повторити", + "command.session.redo.description": "Повторити останнє скасоване повідомлення", + "revert.banner.count_one": "{{count}} повідомлення скасовано", + "revert.banner.count_other": "{{count}} повідомлень скасовано", + "revert.banner.redo": "Повторити", + "revert.banner.redo.all": "Повторити все", + "revert.banner.hint": "Надішліть нове повідомлення, щоб зробити це постійним", + "revert.disabled.agentBusy": "Зачекайте завершення агента", + "command.session.compact": "Стиснути сесію", + "command.session.compact.description": "Підсумувати сесію для зменшення розміру контексту", + "command.session.fork": "Розгалужити від повідомлення", + "command.session.fork.description": "Створити нову сесію від попереднього повідомлення", + "command.session.share": "Поділитися сесією", + "command.session.share.description": "Поділитися цією сесією та скопіювати URL до буфера обміну", + "command.session.unshare": "Скасувати публікацію", + "command.session.unshare.description": "Зупинити публікацію цієї сесії", + + "palette.search.placeholder": "Пошук файлів, команд і сесій", + "palette.empty": "Результатів не знайдено", + "palette.group.commands": "Команди", + "palette.group.files": "Файли", + + "dialog.provider.search.placeholder": "Пошук провайдера", + "dialog.provider.empty": "Провайдерів не знайдено", + "dialog.provider.group.popular": "Популярні", + "dialog.provider.group.other": "Інші", + "dialog.provider.tag.recommended": "Рекомендовано", + "dialog.provider.opencode.note": "Добірка моделей включаючи Claude, GPT, Gemini та інші", + "dialog.provider.anthropic.note": "Прямий доступ до моделей Claude включаючи Pro та Max", + "dialog.provider.copilot.note": "Моделі Claude для допомоги з кодуванням", + "dialog.provider.openai.note": "Моделі GPT для швидких і потужних загальних завдань ШІ", + "dialog.provider.google.note": "Моделі Gemini для швидких і структурованих відповідей", + "dialog.provider.openrouter.note": "Доступ до всіх підтримуваних моделей від одного провайдера", + "dialog.provider.vercel.note": "Уніфікований доступ до моделей ШІ з інтелектуальною маршрутизацією", + + "dialog.model.select.title": "Вибір моделі", + "dialog.model.search.placeholder": "Пошук моделі", + "dialog.model.empty": "Моделей не знайдено", + "dialog.model.manage": "Керувати моделями", + "dialog.model.manage.description": "Налаштуйте, які моделі відображаються у виборі моделей.", + "dialog.model.select": "Вибрати", + "dialog.model.expand": "Розгорнути", + "dialog.model.collapse": "Згорнути", + + "dialog.model.unpaid.freeModels.title": "Безкоштовні моделі від Kilo", + "dialog.model.unpaid.addMore.title": "Додайте більше моделей від популярних провайдерів", + + "dialog.provider.viewAll": "Показати більше провайдерів", + + "provider.connect.title": "Підключити {{provider}}", + "provider.connect.title.anthropicProMax": "Увійти через Claude Pro/Max", + "provider.connect.selectMethod": "Оберіть метод входу для {{provider}}.", + "provider.connect.method.apiKey": "API-ключ", + "provider.connect.status.inProgress": "Авторизація виконується...", + "provider.connect.status.waiting": "Очікування авторизації...", + "provider.connect.status.failed": "Авторизація не вдалася: {{error}}", + "provider.connect.apiKey.description": + "Введіть свій API-ключ {{provider}}, щоб підключити акаунт {{provider}} і використовувати моделі {{provider}} в Kilo.", + "provider.connect.apiKey.label": "API-ключ {{provider}}", + "provider.connect.apiKey.placeholder": "API-ключ", + "provider.connect.apiKey.required": "API-ключ обов'язковий", + "provider.connect.opencodeZen.line1": + "OpenCode Zen надає доступ до добірки надійних оптимізованих моделей для агентів кодування.", + "provider.connect.opencodeZen.line2": + "За допомогою одного API-ключа ви отримаєте доступ до таких моделей, як Claude, GPT, Gemini, GLM та інших.", + "provider.connect.opencodeZen.visit.prefix": "", + "provider.connect.opencodeZen.visit.link": "https://opencode.ai/zen", + "provider.connect.opencodeZen.visit.suffix": " відвідайте, щоб отримати свій API-ключ.", + "provider.connect.oauth.code.visit.prefix": "Щоб підключити акаунт і використовувати моделі {{provider}} в Kilo, ", + "provider.connect.oauth.code.visit.link": "перейдіть за цим посиланням", + "provider.connect.oauth.code.visit.suffix": " щоб отримати код авторизації.", + "provider.connect.oauth.code.label": "Код авторизації {{method}}", + "provider.connect.oauth.code.placeholder": "Код авторизації", + "provider.connect.oauth.code.required": "Код авторизації обов'язковий", + "provider.connect.oauth.code.invalid": "Недійсний код авторизації", + "provider.connect.oauth.auto.visit.prefix": "", + "provider.connect.oauth.auto.visit.link": "Перейдіть за цим посиланням", + "provider.connect.oauth.auto.visit.suffix": + " і введіть код нижче, щоб підключити акаунт та використовувати моделі {{provider}} в Kilo.", + "provider.connect.oauth.auto.confirmationCode": "Код підтвердження", + "provider.connect.toast.connected.title": "{{provider}} підключено", + "provider.connect.toast.connected.description": "Моделі {{provider}} тепер доступні.", + + "provider.disconnect.toast.disconnected.title": "{{provider}} відключено", + "provider.disconnect.toast.disconnected.description": "Моделі {{provider}} більше недоступні.", + + "model.tag.free": "Безкоштовно", + "model.tag.latest": "Остання", + "model.group.recommended": "Рекомендовані", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "текст", + "model.input.image": "зображення", + "model.input.audio": "аудіо", + "model.input.video": "відео", + "model.input.pdf": "pdf", + "model.tooltip.allows": "Підтримує: {{inputs}}", + "model.tooltip.reasoning.allowed": "Підтримує міркування", + "model.tooltip.reasoning.none": "Без міркування", + "model.tooltip.context": "Ліміт контексту {{limit}}", + + "common.search.placeholder": "Пошук", + "common.goBack": "Назад", + "common.goForward": "Вперед", + "common.loading": "Завантаження", + "common.loading.ellipsis": "...", + "common.cancel": "Скасувати", + "common.connect": "Підключити", + "common.disconnect": "Відключити", + "common.submit": "Надіслати", + "common.save": "Зберегти", + "common.saving": "Збереження...", + "common.default": "За замовчуванням", + "common.attachment": "вкладення", + + "prompt.placeholder.shell": "Введіть команду оболонки...", + "prompt.placeholder.normal": 'Запитайте щось... "{{example}}"', + "prompt.placeholder.summarizeComments": "Підсумувати коментарі…", + "prompt.placeholder.summarizeComment": "Підсумувати коментар…", + "prompt.mode.shell": "Оболонка", + "prompt.mode.shell.exit": "esc для виходу", + + "prompt.example.1": "Виправити TODO у кодовій базі", + "prompt.example.2": "Який технологічний стек у цьому проєкті?", + "prompt.example.3": "Виправити зламані тести", + "prompt.example.4": "Пояснити, як працює автентифікація", + "prompt.example.5": "Знайти і виправити вразливості безпеки", + "prompt.example.6": "Додати модульні тести для сервісу користувача", + "prompt.example.7": "Зробити цю функцію більш читабельною", + "prompt.example.8": "Що означає ця помилка?", + "prompt.example.9": "Допоможи мені налагодити цю проблему", + "prompt.example.10": "Згенерувати документацію API", + "prompt.example.11": "Оптимізувати запити до бази даних", + "prompt.example.12": "Додати валідацію введення", + "prompt.example.13": "Створити новий компонент для...", + "prompt.example.14": "Як розгорнути цей проєкт?", + "prompt.example.15": "Переглянути мій код на відповідність найкращим практикам", + "prompt.example.16": "Додати обробку помилок до цієї функції", + "prompt.example.17": "Пояснити цей шаблон регулярного виразу", + "prompt.example.18": "Конвертувати це у TypeScript", + "prompt.example.19": "Додати логування в кодову базу", + "prompt.example.20": "Які залежності застаріли?", + "prompt.example.21": "Допоможи написати скрипт міграції", + "prompt.example.22": "Реалізувати кешування для цього ендпоінту", + "prompt.example.23": "Додати пагінацію до цього списку", + "prompt.example.24": "Створити CLI-команду для...", + "prompt.example.25": "Як тут працюють змінні середовища?", + + "prompt.popover.emptyResults": "Збігів не знайдено", + "prompt.popover.emptyCommands": "Команд не знайдено", + "prompt.dropzone.label": "Скиньте сюди зображення або PDF", + "prompt.slash.badge.custom": "власна", + "prompt.slash.badge.skill": "навичка", + "prompt.slash.badge.mcp": "mcp", + "prompt.context.active": "активний", + "prompt.context.includeActiveFile": "Включити активний файл", + "prompt.context.removeActiveFile": "Видалити активний файл з контексту", + "prompt.context.removeFile": "Видалити файл з контексту", + "prompt.action.attachFile": "Прикріпити файл", + "prompt.attachment.remove": "Видалити вкладення", + "prompt.action.send": "Надіслати", + "prompt.action.send.blocked": "Спочатку дайте відповідь або закрийте очікуюче питання", + "prompt.action.stop": "Зупинити", + "prompt.action.enhance": "Покращити запит", + "prompt.action.resetModel": "Скинути модель до стандартної", + "prompt.action.enhanceDescription": + "Кнопка 'Покращити запит' допомагає вдосконалити ваш запит, надаючи додатковий контекст, уточнення або перефразування. Введіть запит тут і натисніть кнопку ще раз, щоб побачити, як це працює.", + + "prompt.toast.pasteUnsupported.title": "Вставка не підтримується", + "prompt.toast.pasteUnsupported.description": "Сюди можна вставляти лише зображення або PDF.", + "prompt.toast.modelAgentRequired.title": "Виберіть агента і модель", + "prompt.toast.modelAgentRequired.description": "Перед надсиланням запиту виберіть агента і модель.", + "prompt.toast.worktreeCreateFailed.title": "Не вдалося створити робоче дерево", + "prompt.toast.sessionCreateFailed.title": "Не вдалося створити сесію", + "prompt.toast.shellSendFailed.title": "Не вдалося надіслати команду оболонки", + "prompt.toast.commandSendFailed.title": "Не вдалося надіслати команду", + "prompt.toast.promptSendFailed.title": "Не вдалося надіслати запит", + + "dialog.mcp.title": "MCP", + "dialog.mcp.description": "{{enabled}} з {{total}} увімкнено", + "dialog.mcp.empty": "MCP не налаштовано", + + "dialog.lsp.empty": "LSP автоматично визначаються за типами файлів", + "dialog.plugins.empty": "Плагіни налаштовуються в opencode.json", + + "mcp.status.connected": "підключено", + "mcp.status.failed": "помилка", + "mcp.status.needs_auth": "потрібна автентифікація", + "mcp.status.needs_registration": "потрібна реєстрація клієнта", + "mcp.status.disabled": "вимкнено", + + "dialog.fork.empty": "Немає повідомлень для розгалуження", + + "dialog.directory.search.placeholder": "Пошук папки", + "dialog.directory.empty": "Папок не знайдено", + + "dialog.server.title": "Сервери", + "dialog.server.description": "Змінити, до якого сервера Kilo підключається цей додаток.", + "dialog.server.search.placeholder": "Пошук сервера", + "dialog.server.empty": "Поки що немає серверів", + "dialog.server.add.title": "Додати сервер", + "dialog.server.add.url": "URL сервера", + "dialog.server.add.placeholder": "http://localhost:4096", + "dialog.server.add.error": "Не вдалося підключитися до сервера", + "dialog.server.add.checking": "Перевірка...", + "dialog.server.add.button": "Додати сервер", + "dialog.server.default.title": "Сервер за замовчуванням", + "dialog.server.default.description": + "Підключатися до цього сервера замість запуску локального під час запуску програми. Потрібен перезапуск.", + "dialog.server.default.none": "Сервер не вибрано", + "dialog.server.default.set": "Встановити поточний сервер як стандартний", + "dialog.server.default.clear": "Очистити", + "dialog.server.action.remove": "Видалити сервер", + + "dialog.server.menu.edit": "Редагувати", + "dialog.server.menu.default": "Встановити як стандартний", + "dialog.server.menu.defaultRemove": "Видалити стандартний", + "dialog.server.menu.delete": "Видалити", + "dialog.server.current": "Поточний сервер", + "dialog.server.status.default": "Стандартний", + + "dialog.project.edit.title": "Редагувати проєкт", + "dialog.project.edit.name": "Назва", + "dialog.project.edit.icon": "Іконка", + "dialog.project.edit.icon.alt": "Іконка проєкту", + "dialog.project.edit.icon.hint": "Клацніть або перетягніть зображення", + "dialog.project.edit.icon.recommended": "Рекомендовано: 128x128px", + "dialog.project.edit.color": "Колір", + "dialog.project.edit.color.select": "Вибрати колір {{color}}", + "dialog.project.edit.worktree.startup": "Скрипт запуску робочого простору", + "dialog.project.edit.worktree.startup.description": + "Виконується після створення нового робочого простору (worktree).", + "dialog.project.edit.worktree.startup.placeholder": "напр. bun install", + + "context.breakdown.title": "Розбивка контексту", + "context.breakdown.note": + 'Приблизна розбивка вхідних токенів. "Інше" включає визначення інструментів і накладні витрати.', + "context.breakdown.system": "Система", + "context.breakdown.user": "Користувач", + "context.breakdown.assistant": "Асистент", + "context.breakdown.tool": "Виклики інструментів", + "context.breakdown.other": "Інше", + + "context.systemPrompt.title": "Системний запит", + "context.rawMessages.title": "Необроблені повідомлення", + + "context.stats.session": "Сесія", + "context.stats.messages": "Повідомлення", + "context.stats.provider": "Провайдер", + "context.stats.model": "Модель", + "context.stats.limit": "Ліміт контексту", + "context.stats.totalTokens": "Всього токенів", + "context.stats.usage": "Використання", + "context.stats.inputTokens": "Вхідні токени", + "context.stats.outputTokens": "Вихідні токени", + "context.stats.reasoningTokens": "Токени міркування", + "context.stats.cacheTokens": "Токени кешу (читання/запис)", + "context.stats.userMessages": "Повідомлення користувача", + "context.stats.assistantMessages": "Повідомлення асистента", + "context.stats.totalCost": "Загальна вартість", + "context.stats.sessionCreated": "Сесію створено", + "context.stats.lastActivity": "Остання активність", + + "context.usage.tokens": "Токени", + "context.usage.usage": "Використання", + "context.usage.cost": "Вартість", + "context.usage.clickToView": "Переглянути контекст", + "context.usage.view": "Переглянути використання контексту", + + "language.en": "English", + "language.zh": "简体中文", + "language.zht": "繁體中文", + "language.ko": "한국어", + "language.de": "Deutsch", + "language.es": "Español", + "language.fr": "Français", + "language.da": "Dansk", + "language.ja": "日本語", + "language.pl": "Polski", + "language.ru": "Русский", + "language.ar": "العربية", + "language.no": "Norsk", + "language.br": "Português (Brasil)", + "language.bs": "Bosanski", + "language.th": "ไทย", + "language.tr": "Türkçe", + "language.uk": "Українська", + + "toast.language.title": "Мова", + "toast.language.description": "Перейшли на {{language}}", + + "toast.theme.title": "Тему змінено", + "toast.scheme.title": "Кольорова схема", + + "toast.workspace.enabled.title": "Робочі простори увімкнено", + "toast.workspace.enabled.description": "На бічній панелі відображатимуться кілька робочих просторів", + "toast.workspace.disabled.title": "Робочі простори вимкнено", + "toast.workspace.disabled.description": "На бічній панелі відображатиметься лише основний робочий простір", + + "toast.permissions.autoaccept.on.title": "Редагування приймаються автоматично", + "toast.permissions.autoaccept.on.description": "Дозволи на редагування і запис схвалюватимуться автоматично", + "toast.permissions.autoaccept.off.title": "Автоматичне прийняття зупинено", + "toast.permissions.autoaccept.off.description": "Дозволи на редагування і запис потребуватимуть підтвердження", + + "toast.model.none.title": "Модель не вибрано", + "toast.model.none.description": "Підключіть провайдера, щоб підсумувати цю сесію", + + "toast.file.loadFailed.title": "Не вдалося завантажити файл", + "toast.file.listFailed.title": "Не вдалося отримати список файлів", + + "toast.context.noLineSelection.title": "Немає виділення рядків", + "toast.context.noLineSelection.description": "Спочатку виділіть діапазон рядків у вкладці файлу.", + + "toast.session.share.copyFailed.title": "Не вдалося скопіювати URL до буфера обміну", + "toast.session.share.success.title": "Сесію опубліковано", + "toast.session.share.success.description": "URL публікації скопійовано до буфера обміну!", + "toast.session.share.failed.title": "Не вдалося опублікувати сесію", + "toast.session.share.failed.description": "Під час публікації сесії сталася помилка", + + "toast.session.unshare.success.title": "Публікацію сесії скасовано", + "toast.session.unshare.success.description": "Публікацію сесії успішно скасовано!", + "toast.session.unshare.failed.title": "Не вдалося скасувати публікацію сесії", + "toast.session.unshare.failed.description": "Під час скасування публікації сесії сталася помилка", + + "toast.session.listFailed.title": "Не вдалося завантажити сесії для {{project}}", + + "toast.update.title": "Доступне оновлення", + "toast.update.description": "Нова версія Kilo ({{version}}) готова до встановлення.", + "toast.update.action.installRestart": "Встановити і перезапустити", + "toast.update.action.notYet": "Не зараз", + + "error.page.title": "Щось пішло не так", + "error.page.description": "Під час завантаження програми сталася помилка.", + "error.page.details.label": "Деталі помилки", + "error.page.action.restart": "Перезапустити", + "error.page.action.checking": "Перевірка...", + "error.page.action.checkUpdates": "Перевірити оновлення", + "error.page.action.updateTo": "Оновити до {{version}}", + "error.page.report.prefix": "Будь ласка, повідомте про цю помилку команді Kilo", + "error.page.report.discord": "через Discord", + "error.page.version": "Версія: {{version}}", + + "error.dev.rootNotFound": + "Кореневий елемент не знайдено. Чи не забули ви додати його до index.html? Або можливо неправильно написано атрибут id?", + + "error.globalSync.connectFailed": "Не вдалося підключитися до сервера. Чи запущений сервер на `{{url}}`?", + + "error.startup.title": "Підключення до сервера не вдалося", + + "error.paidModel.title": "Для використання цієї моделі потрібно увійти", + "error.paidModel.description": + "Увійдіть або створіть акаунт для доступу до 500+ моделей, використання кредитів за вартістю або підключення власного ключа.", + "error.paidModel.action": "Увійти", + "error.promotionLimit.title": "Для продовження потрібна реєстрація", + "error.promotionLimit.description": + "Зареєструйтеся безкоштовно для продовження та доступу до 500+ моделей. Займе 2 хвилини, кредитна картка не потрібна. Або поверніться пізніше.", + "error.promotionLimit.action": "Зареєструватися", + + "error.chain.unknown": "Невідома помилка", + "error.chain.causedBy": "Спричинено:", + "error.chain.apiError": "Помилка API", + "error.chain.status": "Статус: {{status}}", + "error.chain.retryable": "Можна повторити: {{retryable}}", + "error.chain.responseBody": "Тіло відповіді:\n{{body}}", + "error.chain.didYouMean": "Можливо ви мали на увазі: {{suggestions}}", + "error.chain.modelNotFound": "Модель не знайдено: {{provider}}/{{model}}", + "error.chain.checkConfig": "Перевірте назви провайдера/моделі у файлі конфігурації (opencode.json)", + "error.chain.mcpFailed": 'MCP-сервер "{{name}}" зазнав помилки. Примітка: Kilo поки не підтримує автентифікацію MCP.', + "error.chain.providerAuthFailed": "Автентифікація провайдера не вдалася ({{provider}}): {{message}}", + "error.chain.providerInitFailed": + 'Не вдалося ініціалізувати провайдера "{{provider}}". Перевірте облікові дані та конфігурацію.', + "error.chain.configJsonInvalid": "Файл конфігурації за адресою {{path}} не є дійсним JSON(C)", + "error.chain.configJsonInvalidWithMessage": "Файл конфігурації за адресою {{path}} не є дійсним JSON(C): {{message}}", + "error.chain.configDirectoryTypo": + 'Директорія "{{dir}}" недійсна в {{path}}. Перейменуйте або видаліть директорію на "{{suggestion}}". Це поширена помилка написання.', + "error.chain.configFrontmatterError": "Не вдалося розібрати frontmatter у {{path}}:\n{{message}}", + "error.chain.configInvalid": "Файл конфігурації за адресою {{path}} недійсний", + "error.chain.configInvalidWithMessage": "Файл конфігурації за адресою {{path}} недійсний: {{message}}", + + "notification.permission.title": "Потрібен дозвіл", + "notification.permission.titleSubagent": "Потрібен дозвіл (підагент)", + "notification.permission.description": "{{sessionTitle}} у {{projectName}} потребує дозволу", + "ui.permission.manageAutoApprove": "Керувати правилами автоматичного схвалення", + "ui.permission.rule.addToAllowed": "Додати до дозволених", + "ui.permission.rule.removeFromAllowed": "Видалити з дозволених", + "ui.permission.rule.addToDenied": "Додати до заблокованих", + "ui.permission.rule.removeFromDenied": "Видалити із заблокованих", + "ui.permission.toolLabel.read": "Читати", + "ui.permission.toolLabel.edit": "Редагувати", + "ui.permission.toolLabel.write": "Записати", + "ui.permission.toolLabel.patch": "Патч", + "ui.permission.toolLabel.globSearch": "Пошук Glob", + "ui.permission.toolLabel.grepSearch": "Пошук Grep", + "ui.permission.toolLabel.webSearch": "Веб-пошук", + "ui.permission.toolLabel.list": "Список", + "ui.permission.toolLabel.externalDirectory": "Читати зовнішню директорію", + "ui.permission.toolLabel.webFetch": "Веб-запит", + "ui.permission.toolLabel.task": "Завдання", + "ui.permission.toolLabel.skill": "Навичка", + "ui.permission.toolLabel.lsp": "LSP", + "ui.permission.toolLabel.bash": "Bash", + "ui.permission.toolLabel.todoRead": "Читати завдання", + "ui.permission.toolLabel.todoWrite": "Записати завдання", + "ui.permission.toolLabel.codeSearch": "Пошук коду", + "ui.permission.toggleWrap": "Перемкнути перенос рядків", + "ui.permission.copyCommand": "Копіювати", + "notification.question.title": "Питання", + "notification.question.description": "{{sessionTitle}} у {{projectName}} задає питання", + "notification.action.goToSession": "Перейти до сесії", + + "notification.session.responseReady.title": "Відповідь готова", + "notification.session.error.title": "Помилка сесії", + "notification.session.error.fallbackDescription": "Сталася помилка", + + "home.recentProjects": "Останні проєкти", + "home.empty.title": "Немає останніх проєктів", + "home.empty.description": "Почніть з відкриття локального проєкту", + + "session.tab.session": "Сесія", + "session.tab.review": "Огляд", + "session.tab.context": "Контекст", + "session.panel.reviewAndFiles": "Огляд і файли", + "session.review.filesChanged": "{{count}} файлів змінено", + "session.review.change.one": "Зміна", + "session.review.change.other": "Змін", + "session.review.loadingChanges": "Завантаження змін...", + "session.review.empty": "У цій сесії ще немає змін", + "session.review.noChanges": "Змін немає", + + "session.files.selectToOpen": "Виберіть файл для відкриття", + "session.files.all": "Усі файли", + "session.files.binaryContent": "Бінарний файл (вміст не відображається)", + + "session.messages.renderEarlier": "Показати попередні повідомлення", + "session.messages.loadingEarlier": "Завантаження попередніх повідомлень...", + "session.messages.loadEarlier": "Завантажити попередні повідомлення", + "session.messages.loading": "Завантаження повідомлень...", + "session.messages.jumpToLatest": "Перейти до останнього", + + "session.context.addToContext": "Додати {{selection}} до контексту", + + "session.new.worktree.main": "Основна гілка", + "session.new.worktree.mainWithBranch": "Основна гілка ({{branch}})", + "session.new.worktree.create": "Створити нове робоче дерево", + "session.new.lastModified": "Останнє змінення", + + "session.header.search.placeholder": "Пошук {{project}}", + "session.header.searchFiles": "Пошук файлів", + "session.header.openIn": "Відкрити в", + "session.header.open.action": "Відкрити в {{app}}", + "session.header.open.ariaLabel": "Відкрити в {{app}}", + "session.header.open.menu": "Параметри відкриття", + "session.header.open.copyPath": "Копіювати шлях", + + "status.popover.trigger": "Статус", + "status.popover.ariaLabel": "Конфігурації сервера", + "status.popover.tab.servers": "Сервери", + "status.popover.tab.mcp": "MCP", + "status.popover.tab.lsp": "LSP", + "status.popover.tab.plugins": "Плагіни", + "status.popover.action.manageServers": "Керувати серверами", + + "session.share.popover.title": "Опублікувати в інтернеті", + "session.share.popover.description.shared": + "Ця сесія публічно доступна в інтернеті. Будь-хто з посиланням може отримати доступ.", + "session.share.popover.description.unshared": + "Опублікуйте сесію публічно в інтернеті. Будь-хто з посиланням зможе переглянути її.", + "session.share.action.share": "Поділитися", + "session.share.action.publish": "Опублікувати", + "session.share.action.publishing": "Публікація...", + "session.share.action.unpublish": "Зняти з публікації", + "session.share.action.unpublishing": "Зняття з публікації...", + "session.share.action.view": "Переглянути", + "session.share.copy.copied": "Скопійовано", + "session.share.copy.copyLink": "Копіювати посилання", + + "lsp.tooltip.none": "Немає LSP-серверів", + "lsp.label.connected": "{{count}} LSP", + + "prompt.loading": "Завантаження запиту...", + "terminal.loading": "Завантаження терміналу...", + "terminal.title": "Термінал", + "terminal.title.numbered": "Термінал {{number}}", + "terminal.close": "Закрити термінал", + "terminal.connectionLost.title": "З'єднання втрачено", + "terminal.connectionLost.description": "З'єднання з терміналом перервано. Це може статися після перезапуску сервера.", + + "common.closeTab": "Закрити вкладку", + "common.signIn": "Увійти", + "common.signOut": "Вийти", + "common.dismiss": "Закрити", + "common.requestFailed": "Запит не вдався", + "common.moreOptions": "Більше параметрів", + "common.learnMore": "Дізнатися більше", + "common.rename": "Перейменувати", + "common.reset": "Скинути", + "common.archive": "Архівувати", + "common.delete": "Видалити", + "common.close": "Закрити", + "common.edit": "Редагувати", + "common.loadMore": "Завантажити більше", + "common.key.esc": "ESC", + + "sidebar.menu.toggle": "Перемкнути меню", + "sidebar.nav.projectsAndSessions": "Проєкти і сесії", + "sidebar.settings": "Налаштування", + "sidebar.help": "Допомога", + "sidebar.workspaces.enable": "Увімкнути робочі простори", + "sidebar.workspaces.disable": "Вимкнути робочі простори", + "sidebar.gettingStarted.title": "Початок роботи", + "sidebar.gettingStarted.line1": "Kilo включає безкоштовні моделі, тому ви можете почати відразу.", + "sidebar.gettingStarted.line2": "Підключіть будь-якого провайдера для використання моделей Claude, GPT, Gemini тощо.", + "sidebar.project.recentSessions": "Останні сесії", + "sidebar.project.viewAllSessions": "Переглянути всі сесії", + + "app.name.desktop": "Kilo Desktop", + + "settings.section.desktop": "Робочий стіл", + "settings.section.server": "Сервер", + "settings.tab.general": "Загальні", + "settings.tab.shortcuts": "Скорочення", + + "settings.general.section.appearance": "Вигляд", + "settings.general.section.notifications": "Системні сповіщення", + "settings.general.section.updates": "Оновлення", + "settings.general.section.sounds": "Звукові ефекти", + + "settings.general.row.language.title": "Мова", + "settings.general.row.language.description": "Змінити мову відображення Kilo", + "settings.general.row.appearance.title": "Вигляд", + "settings.general.row.appearance.description": "Налаштувати вигляд Kilo на вашому пристрої", + "settings.general.row.theme.title": "Тема", + "settings.general.row.theme.description": "Налаштувати тему Kilo.", + "settings.general.row.font.title": "Шрифт", + "settings.general.row.font.description": "Налаштувати моноширинний шрифт, що використовується в блоках коду", + + "settings.general.row.releaseNotes.title": "Примітки до випуску", + "settings.general.row.releaseNotes.description": "Показувати сповіщення про новини після оновлень", + + "settings.updates.row.startup.title": "Перевіряти оновлення під час запуску", + "settings.updates.row.startup.description": "Автоматично перевіряти оновлення при запуску Kilo", + "settings.updates.row.check.title": "Перевірити оновлення", + "settings.updates.row.check.description": "Вручну перевірити та встановити оновлення", + "settings.updates.action.checkNow": "Перевірити зараз", + "settings.updates.action.checking": "Перевірка...", + "settings.updates.toast.latest.title": "Ви використовуєте актуальну версію", + "settings.updates.toast.latest.description": "У вас встановлена остання версія Kilo.", + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "Сигнал 01", + "sound.option.alert02": "Сигнал 02", + "sound.option.alert03": "Сигнал 03", + "sound.option.alert04": "Сигнал 04", + "sound.option.alert05": "Сигнал 05", + "sound.option.alert06": "Сигнал 06", + "sound.option.alert07": "Сигнал 07", + "sound.option.alert08": "Сигнал 08", + "sound.option.alert09": "Сигнал 09", + "sound.option.alert10": "Сигнал 10", + "sound.option.bipbop01": "Біп-боп 01", + "sound.option.bipbop02": "Біп-боп 02", + "sound.option.bipbop03": "Біп-боп 03", + "sound.option.bipbop04": "Біп-боп 04", + "sound.option.bipbop05": "Біп-боп 05", + "sound.option.bipbop06": "Біп-боп 06", + "sound.option.bipbop07": "Біп-боп 07", + "sound.option.bipbop08": "Біп-боп 08", + "sound.option.bipbop09": "Біп-боп 09", + "sound.option.bipbop10": "Біп-боп 10", + "sound.option.staplebops01": "Staplebops 01", + "sound.option.staplebops02": "Staplebops 02", + "sound.option.staplebops03": "Staplebops 03", + "sound.option.staplebops04": "Staplebops 04", + "sound.option.staplebops05": "Staplebops 05", + "sound.option.staplebops06": "Staplebops 06", + "sound.option.staplebops07": "Staplebops 07", + "sound.option.nope01": "Ні 01", + "sound.option.nope02": "Ні 02", + "sound.option.nope03": "Ні 03", + "sound.option.nope04": "Ні 04", + "sound.option.nope05": "Ні 05", + "sound.option.nope06": "Ні 06", + "sound.option.nope07": "Ні 07", + "sound.option.nope08": "Ні 08", + "sound.option.nope09": "Ні 09", + "sound.option.nope10": "Ні 10", + "sound.option.nope11": "Ні 11", + "sound.option.nope12": "Ні 12", + "sound.option.yup01": "Так 01", + "sound.option.yup02": "Так 02", + "sound.option.yup03": "Так 03", + "sound.option.yup04": "Так 04", + "sound.option.yup05": "Так 05", + "sound.option.yup06": "Так 06", + + "settings.general.notifications.agent.title": "Агент", + "settings.general.notifications.agent.description": + "Показувати системне сповіщення, коли агент завершив роботу або потребує уваги", + "settings.general.notifications.permissions.title": "Дозволи", + "settings.general.notifications.permissions.description": "Показувати системне сповіщення при запиті дозволу", + "settings.general.notifications.errors.title": "Помилки", + "settings.general.notifications.errors.description": "Показувати системне сповіщення при виникненні помилки", + + "settings.general.sounds.agent.title": "Агент", + "settings.general.sounds.agent.description": "Відтворювати звук, коли агент завершив роботу або потребує уваги", + "settings.general.sounds.permissions.title": "Дозволи", + "settings.general.sounds.permissions.description": "Відтворювати звук при запиті дозволу", + "settings.general.sounds.errors.title": "Помилки", + "settings.general.sounds.errors.description": "Відтворювати звук при виникненні помилки", + + "settings.shortcuts.title": "Клавіатурні скорочення", + "settings.shortcuts.reset.button": "Скинути до стандартних", + "settings.shortcuts.reset.toast.title": "Скорочення скинуто", + "settings.shortcuts.reset.toast.description": "Клавіатурні скорочення скинуто до стандартних.", + "settings.shortcuts.conflict.title": "Скорочення вже використовується", + "settings.shortcuts.conflict.description": "{{keybind}} вже призначено для {{titles}}.", + "settings.shortcuts.unassigned": "Не призначено", + "settings.shortcuts.pressKeys": "Натисніть клавіші", + "settings.shortcuts.search.placeholder": "Пошук скорочень", + "settings.shortcuts.search.empty": "Скорочень не знайдено", + + "settings.shortcuts.group.general": "Загальні", + "settings.shortcuts.group.session": "Сесія", + "settings.shortcuts.group.navigation": "Навігація", + "settings.shortcuts.group.modelAndAgent": "Модель і агент", + "settings.shortcuts.group.terminal": "Термінал", + "settings.shortcuts.group.prompt": "Запит", + + "settings.providers.title": "Провайдери", + "settings.providers.description": "Тут можна буде налаштовувати параметри провайдерів.", + "settings.providers.betaNotice": + "Наразі в інтерфейсі налаштувань можна налаштувати лише провайдера Kilo Gateway. Підтримка інших провайдерів з'явиться в бета-версії найближчим часом. Тим часом ви можете налаштовувати провайдерів через CLI або файл конфігурації. Kilo залишається відкритим — без прив'язки.", + "settings.providers.section.connected": "Підключені провайдери", + "settings.providers.connected.empty": "Підключених провайдерів немає", + "settings.providers.section.popular": "Популярні провайдери", + "settings.providers.tag.gateway": "Gateway", + "settings.providers.tag.environment": "Середовище", + "settings.providers.tag.config": "Конфігурація", + "settings.providers.tag.custom": "Власний", + "settings.providers.tag.customProvider": "Власний провайдер", + "settings.providers.tag.other": "Інші", + "settings.providers.connected.environmentDescription": "Підключено зі змінних середовища", + "settings.providers.custom.description": "Додати OpenAI-сумісного провайдера через базовий URL.", + + "provider.custom.title": "Власний провайдер", + "provider.custom.description.prefix": "Налаштувати OpenAI-сумісного провайдера. ", + "provider.custom.description.link": "Документація щодо налаштування провайдера", + "provider.custom.description.suffix": ".", + "provider.custom.field.providerID.label": "Ідентифікатор провайдера", + "provider.custom.field.providerID.placeholder": "miy-provyder", + "provider.custom.field.providerID.description": "Малі літери, цифри, дефіс або підкреслення", + "provider.custom.field.name.label": "Відображувана назва", + "provider.custom.field.name.placeholder": "Мій ШІ-провайдер", + "provider.custom.field.baseURL.label": "Базовий URL", + "provider.custom.field.baseURL.placeholder": "https://api.miy-provyder.com/v1", + "provider.custom.field.apiKey.label": "API-ключ", + "provider.custom.field.apiKey.placeholder": "API-ключ", + "provider.custom.field.apiKey.description": + "Необов'язково. Залиште порожнім, якщо автентифікація керується заголовками.", + "provider.custom.models.label": "Моделі", + "provider.custom.models.id.label": "Ідентифікатор", + "provider.custom.models.id.placeholder": "ідентифікатор-моделі", + "provider.custom.models.name.label": "Назва", + "provider.custom.models.name.placeholder": "Відображувана назва", + "provider.custom.models.remove": "Видалити модель", + "provider.custom.models.add": "Додати модель", + "provider.custom.models.fetch": "Отримати моделі", + "provider.custom.models.fetching": "Отримання\u2026", + "provider.custom.models.fetch.error": "Не вдалося отримати моделі: {{error}}", + "provider.custom.models.fetch.authError": "Автентифікація не вдалася. Перевірте API-ключ вище і спробуйте ще раз.", + "provider.custom.models.fetch.empty": "На цьому сервері моделей не знайдено.", + "provider.custom.models.fetch.added": "Додано {{count}} моделей.", + "provider.custom.models.fetch.allExist": "Усі отримані моделі вже додано.", + "provider.custom.models.fetch.selectAll": "Вибрати все", + "provider.custom.models.fetch.deselectAll": "Зняти весь вибір", + "provider.custom.models.fetch.found": "Знайдено {{count}} моделей", + "provider.custom.models.fetch.showing": "Показано {{shown}} з {{total}} моделей", + "provider.custom.models.fetch.search": "Пошук моделей\u2026", + "provider.custom.models.fetch.add": "Додати {{count}} моделей", + "provider.custom.edit.title": "Редагувати провайдера", + "provider.custom.headers.label": "Заголовки (необов'язково)", + "provider.custom.headers.key.label": "Заголовок", + "provider.custom.headers.key.placeholder": "Назва-заголовка", + "provider.custom.headers.value.label": "Значення", + "provider.custom.headers.value.placeholder": "значення", + "provider.custom.headers.remove": "Видалити заголовок", + "provider.custom.headers.add": "Додати заголовок", + "provider.custom.error.providerID.required": "Ідентифікатор провайдера обов'язковий", + "provider.custom.error.providerID.format": "Використовуйте малі літери, цифри, дефіс або підкреслення", + "provider.custom.error.providerID.exists": "Такий ідентифікатор провайдера вже існує", + "provider.custom.error.name.required": "Відображувана назва обов'язкова", + "provider.custom.error.baseURL.required": "Базовий URL обов'язковий", + "provider.custom.error.baseURL.format": "Має починатися з http:// або https://", + "provider.custom.error.required": "Обов'язкове поле", + "provider.custom.error.duplicate": "Дублікат", + "settings.models.title": "Моделі", + "settings.models.description": "Тут можна буде налаштовувати параметри моделей.", + "settings.agents.title": "Агенти", + "settings.agents.description": "Тут можна буде налаштовувати параметри агентів.", + "settings.commands.title": "Команди", + "settings.commands.description": "Тут можна буде налаштовувати параметри команд.", + "settings.mcp.title": "MCP", + "settings.mcp.description": "Тут можна буде налаштовувати параметри MCP.", + + "settings.permissions.title": "Дозволи", + "settings.permissions.description": "Контролюйте, які інструменти сервер може використовувати за замовчуванням.", + "settings.permissions.section.tools": "Інструменти", + "settings.permissions.toast.updateFailed.title": "Не вдалося оновити дозволи", + + "settings.permissions.action.allow": "Дозволити", + "settings.permissions.action.ask": "Запитувати", + "settings.permissions.action.deny": "Відхилити", + + "settings.permissions.tool.read.title": "Читати", + "settings.permissions.tool.read.description": "Читати файл (відповідає шляху файлу)", + "settings.permissions.tool.edit.title": "Редагувати", + "settings.permissions.tool.edit.description": + "Змінювати файли включаючи редагування, запис, патч і множинне редагування", + "settings.permissions.tool.glob.title": "Glob", + "settings.permissions.tool.glob.description": "Зіставляти файли за шаблонами glob", + "settings.permissions.tool.grep.title": "Grep", + "settings.permissions.tool.grep.description": "Шукати вміст файлів за регулярними виразами", + "settings.permissions.tool.list.title": "Список", + "settings.permissions.tool.list.description": "Перелічити файли в директорії", + "settings.permissions.tool.bash.title": "Bash", + "settings.permissions.tool.bash.description": "Виконувати команди оболонки", + "settings.permissions.tool.task.title": "Завдання", + "settings.permissions.tool.task.description": "Запускати підагентів", + "settings.permissions.tool.skill.title": "Навичка", + "settings.permissions.tool.skill.description": "Завантажувати навичку за назвою", + "settings.permissions.tool.lsp.title": "LSP", + "settings.permissions.tool.lsp.description": "Виконувати запити до мовного сервера", + "settings.permissions.tool.todoread.title": "Читати завдання", + "settings.permissions.tool.todoread.description": "Читати список завдань", + "settings.permissions.tool.todowrite.title": "Записати завдання", + "settings.permissions.tool.todowrite.description": "Оновлювати список завдань", + "settings.permissions.tool.webfetch.title": "Веб-запит", + "settings.permissions.tool.webfetch.description": "Отримати вміст з URL", + "settings.permissions.tool.websearch.title": "Веб-пошук", + "settings.permissions.tool.websearch.description": "Шукати в інтернеті", + "settings.permissions.tool.codesearch.title": "Пошук коду", + "settings.permissions.tool.codesearch.description": "Шукати код в інтернеті", + "settings.permissions.tool.external_directory.title": "Зовнішня директорія", + "settings.permissions.tool.external_directory.description": "Доступ до файлів поза директорією проєкту", + "settings.permissions.tool.doom_loop.title": "Нескінченний цикл", + "settings.permissions.tool.doom_loop.description": + "Виявляти повторювані виклики інструментів з однаковими вхідними даними", + + "session.delete.failed.title": "Не вдалося видалити сесію", + "session.delete.title": "Видалити сесію", + "session.delete.confirm": 'Видалити сесію "{{name}}"?', + "session.delete.button": "Видалити сесію", + "session.untitled": "Без назви", + "session.recent": "Останні", + "session.showHistory": "Показати історію", + "session.search.placeholder": "Пошук сесій...", + "session.empty": "Сесій поки немає. Натисніть +, щоб почати новий чат.", + "session.tab.local": "Локальний", + "session.tab.cloud": "Хмарний", + "session.cloud.repoOnly": "Лише цей репозиторій", + "session.cloud.import": "Імпортувати з хмари", + "feedback.button": "Зворотний зв'язок і підтримка", + "feedback.dialog.message": "Ми раді отримати ваш відгук або допомогти з будь-якими проблемами, які у вас виникли.", + "feedback.dialog.github": "Повідомити про проблему на GitHub", + "feedback.dialog.discord": "Приєднатися до нашої спільноти Discord", + "feedback.dialog.support": "Служба підтримки клієнтів", + "session.cloud.import.title": "Імпортувати з хмари", + "session.cloud.import.placeholder": "Ідентифікатор сесії, URL або команда kilo import", + "session.cloud.import.button": "Імпортувати", + "session.cloud.import.invalid": "Недійсний формат ідентифікатора сесії", + "session.cloud.import.legacy": "Схоже, це застаріла сесія, яка більше не підтримується.", + "session.cloud.import.failed": "Не вдалося імпортувати хмарну сесію", + + "workspace.new": "Новий робочий простір", + "workspace.type.local": "локальний", + "workspace.type.sandbox": "пісочниця", + "workspace.create.failed.title": "Не вдалося створити робочий простір", + "workspace.delete.failed.title": "Не вдалося видалити робочий простір", + "workspace.resetting.title": "Скидання робочого простору", + "workspace.resetting.description": "Це може зайняти хвилину.", + "workspace.reset.failed.title": "Не вдалося скинути робочий простір", + "workspace.reset.success.title": "Робочий простір скинуто", + "workspace.reset.success.description": "Робочий простір тепер відповідає основній гілці.", + "workspace.error.stillPreparing": "Робочий простір ще підготовлюється", + "workspace.status.checking": "Перевірка неприйнятих змін...", + "workspace.status.error": "Не вдалося перевірити статус git.", + "workspace.status.clean": "Неприйнятих змін не виявлено.", + "workspace.status.dirty": "У цьому робочому просторі виявлено неприйняті зміни.", + "workspace.delete.title": "Видалити робочий простір", + "workspace.delete.confirm": 'Видалити робочий простір "{{name}}"?', + "workspace.delete.button": "Видалити робочий простір", + "workspace.reset.title": "Скинути робочий простір", + "workspace.reset.confirm": 'Скинути робочий простір "{{name}}"?', + "workspace.reset.button": "Скинути робочий простір", + "workspace.reset.archived.none": "Немає активних сесій для архівування.", + "workspace.reset.archived.one": "1 сесію буде архівовано.", + "workspace.reset.archived.many": "{{count}} сесій буде архівовано.", + "workspace.reset.note": "Ця дія скине робочий простір відповідно до основної гілки.", + + "deviceAuth.toast.urlCopied": "URL скопійовано до буфера обміну", + "deviceAuth.toast.codeCopied": "Код скопійовано до буфера обміну", + "deviceAuth.toast.errorCopied": "Помилку скопійовано до буфера обміну", + "deviceAuth.status.initiating": "Ініціалізація входу...", + "deviceAuth.title": "Увійти до Kilo Code", + "deviceAuth.step1": "Крок 1: Відкрийте цей URL", + "deviceAuth.action.copyUrl": "Копіювати URL", + "deviceAuth.action.openBrowser": "Відкрити браузер", + "deviceAuth.qrCode.alt": "QR-код", + "deviceAuth.step2": "Крок 2: Введіть цей код", + "deviceAuth.action.clickToCopy": "Клацніть для копіювання", + "deviceAuth.status.waiting": "Очікування авторизації...", + "deviceAuth.status.success": "Вхід виконано успішно!", + "deviceAuth.status.failed": "Вхід не вдався", + "deviceAuth.status.cancelled": "Вхід скасовано", + "deviceAuth.action.copyError": "Копіювати помилку", + "deviceAuth.action.showDetails": "Показати деталі", + "deviceAuth.action.tryAgain": "Спробувати ще раз", + "deviceAuth.error.detailsTitle": "Деталі помилки входу", + + "common.retry": "Спробувати ще раз", + "common.refresh": "Оновити", + + "profile.title": "Профіль", + "profile.notLoggedIn": "Не увійшов", + "profile.action.login": "Увійти через Kilo Code", + "profile.balance.title": "Баланс", + "profile.balance.refresh": "Оновити баланс", + "profile.action.dashboard": "Панель керування", + "profile.action.logout": "Вийти", + + "settings.section.configuration": "Конфігурація", + "settings.agentBehaviour.title": "Поведінка агента", + "settings.autoApprove.title": "Автоматичне схвалення", + "settings.browser.title": "Браузер", + "settings.checkpoints.title": "Контрольні точки", + "settings.display.title": "Відображення", + "settings.autocomplete.title": "Автодоповнення", + "settings.notifications.title": "Сповіщення", + "settings.context.title": "Контекст", + + "settings.experimental.title": "Експериментальне", + "settings.language.title": "Мова", + "settings.aboutKiloCode.title": "Про Kilo Code", + + "session.messages.empty": "Напишіть повідомлення нижче, щоб розпочати чат.", + "session.messages.welcome": + "Kilo Code — це асистент з кодування на базі ШІ. Попросіть його розробити функцію, виправити помилку або пояснити вашу кодову базу.", + "session.messages.scrollToBottom": "Прокрутити до низу", + "session.status.writingResponse": "Пишу відповідь...", + "session.status.retry": "Повторна спроба…", + "session.status.retrying": "Повторна спроба (спроба {{ attempt }})… {{ message }}", + "session.status.working": "Працює...", + + "dialog.model.noProviders": "Немає провайдерів", + + "prompt.placeholder.connecting": "Підключення до сервера...", + "prompt.placeholder.default": "Напишіть повідомлення... (Enter для надсилання, Shift+Enter для нового рядка)", + "prompt.placeholder.error": "Підключення не вдалося. Перевірте панель виводу або перезапустіть розширення.", + + "context.usage.sessionCost": "Вартість сесії", + "context.stats.thisSession": "Ця сесія", + + "time.justNow": "щойно", + "time.minutesAgo": "{{count}} хв тому", + "time.hoursAgo": "{{count}} г тому", + "time.daysAgo": "{{count}} д тому", + "time.monthsAgo": "{{count}} міс тому", + "time.today": "Сьогодні", + "time.yesterday": "Вчора", + "time.thisWeek": "Цього тижня", + "time.thisMonth": "Цього місяця", + "time.older": "Раніше", + + "settings.aboutKiloCode.status.connected": "Підключено", + "settings.aboutKiloCode.status.connecting": "Підключення...", + "settings.aboutKiloCode.status.disconnected": "Відключено", + "settings.aboutKiloCode.status.error": "Помилка", + "settings.aboutKiloCode.cliServer": "CLI-сервер", + "settings.aboutKiloCode.status.label": "Статус:", + "settings.aboutKiloCode.port.label": "Порт:", + "settings.aboutKiloCode.versionInfo": "Інформація про версію", + "settings.aboutKiloCode.version.label": "Версія:", + "settings.aboutKiloCode.extensionName": "Розширення Kilo Code", + "settings.aboutKiloCode.community": "Спільнота і підтримка", + "settings.aboutKiloCode.feedback.prefix": "Якщо у вас є питання або відгуки, будь ласка, відкрийте тікет на:", + "settings.aboutKiloCode.feedback.or": "або", + "settings.aboutKiloCode.support.prefix": "З питань виставлення рахунків або акаунту зверніться до служби підтримки:", + "settings.aboutKiloCode.resetSettings.title": "Скидання налаштувань", + "settings.aboutKiloCode.resetSettings.description": + "Це скине лише налаштування, специфічні для розширення VS Code, до стандартних значень. Налаштування, що зберігаються в конфігурації CLI (такі як режими та правила автоматичного схвалення), не будуть скинуті.", + "settings.aboutKiloCode.resetSettings.button": "Скинути всі налаштування", + "settings.aboutKiloCode.settingsTransfer.title": "Перенесення налаштувань", + "settings.aboutKiloCode.settingsTransfer.description": + "Експортуйте або імпортуйте налаштування для перенесення між екземплярами VS Code.", + "settings.aboutKiloCode.exportSettings": "Експортувати", + "settings.aboutKiloCode.importSettings": "Імпортувати", + "settings.aboutKiloCode.importSettings.invalidJson": + "Недійсний файл JSON. Будь ласка, виберіть дійсний файл налаштувань.", + "settings.aboutKiloCode.importSettings.invalidConfig": "Файл не містить дійсних налаштувань Kilo.", + "settings.aboutKiloCode.importSettings.tooLarge": "Файл занадто великий. Файли налаштувань мають бути менше 1 МБ.", + "settings.aboutKiloCode.importSettings.newerVersion": + "Цей файл було експортовано з новішої версії Kilo. Деякі налаштування можуть бути проігноровані.", + "settings.aboutKiloCode.importSettings.success": + "Налаштування імпортовано. Перегляньте зміни вище, потім натисніть Зберегти.", + + "settings.agentBehaviour.subtab.modes": "Режими", + "settings.agentBehaviour.subtab.agents": "Агенти", + "settings.agentBehaviour.subtab.mcpServers": "MCP-сервери", + "settings.agentBehaviour.subtab.rules": "Правила", + "settings.agentBehaviour.subtab.workflows": "Робочі процеси", + "settings.agentBehaviour.subtab.skills": "Навички", + + "settings.browser.description": + "Після увімкнення агент ШІ може взаємодіяти з веб-сторінками — навігація, натискання, введення тексту та знімки екрана. Відкриється вікно Chrome, щоб ви могли стежити за роботою агента.", + "settings.browser.enable.title": "Увімкнути автоматизацію браузера", + "settings.browser.enable.description": "Зареєструвати MCP-сервер Playwright з CLI-бекендом.", + "settings.browser.systemChrome.title": "Використовувати системний Chrome", + "settings.browser.systemChrome.description": + "Використовувати встановлений браузер Chrome замість окремого екземпляра Chromium.", + "settings.browser.headless.title": "Безголовий режим", + "settings.browser.headless.description": "Запускати в безголовому режимі (без видимого вікна браузера).", + + "settings.language.description": + '"Автоматично" використовує мову відображення VS Code. Виберіть мову для інтерфейсу Kilo Code.', + "settings.language.auto": "Автоматично (мова VS Code)", + "settings.language.current": "Поточна:", + + "common.add": "Додати", + "common.choose": "Вибрати…", + + "settings.autocomplete.autoTrigger.title": "Увімкнути автоматичні підказки", + "settings.autocomplete.autoTrigger.description": "Автоматично показувати підказки під час введення", + "settings.autocomplete.smartKeybinding.title": "Увімкнути розумне прив'язування клавіш", + "settings.autocomplete.smartKeybinding.description": + "Використовувати розумне прив'язування клавіш для активації підказок", + "settings.autocomplete.chatAutocomplete.title": "Увімкнути автодоповнення в полі чату", + "settings.autocomplete.chatAutocomplete.description": "Показувати підказки автодоповнення в полі введення чату", + + "settings.notifications.agent.title": "Завершення агента", + "settings.notifications.agent.description": "Показувати сповіщення, коли агент завершить завдання", + "settings.notifications.permissions.title": "Запити дозволів", + "settings.notifications.permissions.description": "Показувати сповіщення при запитах дозволів", + "settings.notifications.errors.title": "Помилки", + "settings.notifications.errors.description": "Показувати сповіщення при виникненні помилок", + "settings.notifications.sounds": "Звуки", + "settings.notifications.agentSound.title": "Звук завершення агента", + "settings.notifications.agentSound.description": "Звук, що відтворюється після завершення агента", + "settings.notifications.permSound.title": "Звук запиту дозволу", + "settings.notifications.permSound.description": "Звук, що відтворюється при запитах дозволів", + "settings.notifications.errorSound.title": "Звук помилки", + "settings.notifications.errorSound.description": "Звук, що відтворюється при виникненні помилок", + "settings.notifications.sound.default": "За замовчуванням", + "settings.notifications.sound.none": "Немає", + + "settings.experimental.share.title": "Режим публікації", + "settings.experimental.share.description": "Як поводиться публікація сесій", + "settings.experimental.share.manual": "Вручну", + "settings.experimental.share.auto": "Автоматично", + "settings.experimental.share.disabled": "Вимкнено", + "settings.experimental.formatter.title": "Форматер", + "settings.experimental.formatter.description": "Увімкнути автоматичне форматування коду", + "settings.experimental.lsp.title": "LSP", + "settings.experimental.lsp.description": "Увімкнути інтеграцію з мовним сервером", + "settings.experimental.pasteSummary.title": "Вимкнути підсумовування вставки", + "settings.experimental.pasteSummary.description": "Підсумовувати великий вставлений вміст", + "settings.experimental.batch.title": "Пакетний інструмент", + "settings.experimental.batch.description": "Увімкнути пакетну обробку кількох викликів інструментів", + "settings.experimental.codebaseSearch.title": "Пошук по кодовій базі", + "settings.experimental.codebaseSearch.description": + "Увімкнути пошук природною мовою на основі ШІ по всій кодовій базі", + "settings.experimental.continueOnDeny.title": "Продовжувати при відхиленні", + "settings.experimental.continueOnDeny.description": "Продовжувати цикл агента, коли дозвіл відхилено", + "settings.experimental.mcpTimeout.title": "Тайм-аут MCP (мс)", + "settings.experimental.mcpTimeout.description": "Тайм-аут у мілісекундах для запитів до MCP-сервера", + "settings.experimental.toolToggles": "Перемикачі інструментів", + + "settings.agentBehaviour.defaultAgent.title": "Агент за замовчуванням", + "settings.agentBehaviour.defaultAgent.description": "Агент, що використовується, якщо не вказано інший", + "settings.agentBehaviour.availableAgents": "Доступні агенти", + "settings.agentBehaviour.selectAgent": "Виберіть агента для налаштування…", + "settings.agentBehaviour.selectAgent.title": "Агент", + "settings.agentBehaviour.selectAgent.description": "Виберіть агента для налаштування…", + "settings.agentBehaviour.modelOverride.title": "Перевизначення моделі", + "settings.agentBehaviour.modelOverride.description": "Перевизначити стандартну модель для цього агента", + "settings.agentBehaviour.prompt.title": "Власний запит", + "settings.agentBehaviour.prompt.description": "Додатковий системний запит для цього агента", + "settings.agentBehaviour.temperature.title": "Температура", + "settings.agentBehaviour.temperature.description": "Температура вибірки (0-2)", + "settings.agentBehaviour.topP.title": "Top P", + "settings.agentBehaviour.topP.description": "Параметр nucleus sampling (0-1)", + "settings.agentBehaviour.maxSteps.title": "Максимальна кількість кроків", + "settings.agentBehaviour.maxSteps.description": "Максимальна кількість ітерацій агента", + "settings.agentBehaviour.hidden.title": "Прихований", + "settings.agentBehaviour.hidden.description": "Приховати цього агента з перемикача режимів у полі введення чату", + "settings.agentBehaviour.disable.title": "Вимкнений", + "settings.agentBehaviour.disable.description": "Повністю вимкнути цього агента — він ніде не відображатиметься", + "settings.agentBehaviour.badge.hidden": "прихований", + "settings.agentBehaviour.badge.disabled": "вимкнений", + "settings.agentBehaviour.badge.deprecated": "Застарілий", + "settings.agentBehaviour.discoveredSkills": "Виявлені навички", + "settings.agentBehaviour.noSkillsFound": + "Навичок не виявлено. Додайте шляхи до папок навичок або URL нижче, щоб зробити їх доступними.", + "settings.agentBehaviour.availableModes": "Доступні власні режими", + "settings.agentBehaviour.noModesFound": "Режимів не знайдено.", + "settings.agentBehaviour.importMode": "Імпортувати", + "settings.agentBehaviour.importMode.invalidName": + "Назва режиму у файлі недійсна. Назва має починатися з малої літери і містити лише малі літери, цифри та дефіси.", + "settings.agentBehaviour.importMode.nameTaken": "Режим з такою назвою вже існує.", + "settings.agentBehaviour.importMode.invalidJson": + "Недійсний файл JSON. Будь ласка, виберіть дійсний файл визначення агента.", + "settings.agentBehaviour.importMode.tooLarge": "Файл занадто великий. Визначення агентів мають бути менше 1 МБ.", + "settings.agentBehaviour.exportMode": "Експортувати визначення агента", + "settings.agentBehaviour.removeMode.title": "Видалити режим", + "settings.agentBehaviour.removeMode.confirm": + 'Видалити режим "{{name}}"? Це оновить вашу конфігурацію, щоб вимкнути режим.', + "settings.agentBehaviour.removeMode.button": "Видалити", + "settings.agentBehaviour.skillPaths": "Шляхи до папок навичок", + "settings.agentBehaviour.skillUrls": "URL навичок", + "settings.agentBehaviour.removeSkill.title": "Видалити навичку", + "settings.agentBehaviour.removeSkill.confirm": 'Видалити навичку "{{name}}"? Це видалить файли навичок з диска.', + "settings.agentBehaviour.removeSkill.button": "Видалити", + "settings.agentBehaviour.rules.description": + "Правила — це файли інструкцій, що спрямовують поведінку агента. Вони включаються до системного запиту для кожної розмови. Додайте шляхи до файлів нижче для додаткових правил.", + "settings.agentBehaviour.instructionFiles": "Додаткові файли інструкцій", + "settings.agentBehaviour.instructionFiles.description": + "Шляхи до додаткових файлів інструкцій, що включаються до системного запиту", + "settings.agentBehaviour.removeMcp.title": "Видалити MCP-сервер", + "settings.agentBehaviour.removeMcp.confirm": 'Видалити MCP-сервер "{{name}}"? Це видалить його з вашої конфігурації.', + "settings.agentBehaviour.removeMcp.button": "Видалити", + "settings.agentBehaviour.mcpDetail.command": "Команда", + "settings.agentBehaviour.mcpDetail.args": "Аргументи", + "settings.agentBehaviour.mcpDetail.env": "Середовище", + "settings.agentBehaviour.mcpDetail.disabled": "Цей сервер вимкнено.", + "settings.agentBehaviour.editMcp": "Редагувати MCP-сервер", + "settings.agentBehaviour.editMcp.transportLocal": "Локальний сервер (stdio транспорт)", + "settings.agentBehaviour.editMcp.transportRemote": "Віддалений сервер (SSE/HTTP транспорт)", + "settings.agentBehaviour.editMcp.env": "Змінні середовища", + "settings.agentBehaviour.editMcp.env.help": "Змінні, що передаються процесу MCP-сервера.", + "settings.agentBehaviour.addMcp.command": "Команда", + "settings.agentBehaviour.addMcp.command.placeholder": "напр. npx", + "settings.agentBehaviour.addMcp.args": "Аргументи", + "settings.agentBehaviour.addMcp.args.help": "Один аргумент на рядок. Шляхи з пробілами зберігаються як є.", + "settings.agentBehaviour.addMcp.args.placeholder": "напр.\n-y\n@modelcontextprotocol/server-filesystem\n/tmp", + "settings.agentBehaviour.addMcp.url": "URL сервера", + "settings.agentBehaviour.addMcp.url.placeholder": "напр. http://localhost:3000/sse", + "settings.agentBehaviour.mcpBrowseMarketplace": "Переглянути Marketplace", + "settings.agentBehaviour.mcpEmpty": + "MCP-серверів не налаштовано. Додайте MCP-сервери до kilo.jsonc або попросіть агента додати їх.", + "settings.agentBehaviour.workflowsPlaceholder": + "Робочими процесами керують файли робочих процесів у вашому робочому просторі.", + "settings.agentBehaviour.workflows.description": + "Робочі процеси — це власні команди з косою рискою, визначені у вашій конфігурації. Введіть /назва-команди в чаті, щоб викликати їх. Команди налаштовуються в розділі 'command' файлу opencode.json.", + "settings.agentBehaviour.workflows.empty": + "Власних команд не налаштовано. Додайте команди до opencode.json, щоб вони з'явилися тут.", + "settings.agentBehaviour.workflows.detail.description": "Опис", + "settings.agentBehaviour.workflows.detail.template": "Шаблон", + + "settings.autoApprove.description": + "Визначте, як виконуються інструменти. Більшість інструментів за замовчуванням — Дозволити. doom_loop та external_directory за замовчуванням — Запитувати.", + "settings.autoApprove.level.allow": "Дозволити", + "settings.autoApprove.level.ask": "Запитувати", + "settings.autoApprove.level.deny": "Відхилити", + "settings.autoApprove.wildcardLabel.commands": "Усі команди (*)", + "settings.autoApprove.wildcardLabel.paths": "Усі шляхи (*)", + "settings.autoApprove.exceptions": "Винятки", + "settings.autoApprove.addCommand": "Додати команду", + "settings.autoApprove.addPath": "Додати шлях", + "settings.autoApprove.placeholder.command": "напр. git *", + "settings.autoApprove.placeholder.path": "напр. *.env", + "settings.autoApprove.tool.external_directory": + "Доступ до файлів поза робочим простором. Спрацьовує при зверненні до файлів поза поточною директорією проєкту.", + "settings.autoApprove.tool.bash": + "Виконувати команди терміналу. Дозволяє виконання команд оболонки (напр. git status).", + "settings.autoApprove.tool.read": "Читати файли. Дозволяє агенту читати файли, що відповідають вказаному шляху.", + "settings.autoApprove.tool.edit": + "Змінювати файли. Дозволяє агенту створювати або редагувати файли, включаючи патчі та оновлення кількох файлів.", + "settings.autoApprove.tool.glob": + "Зіставляти файли за шаблоном. Дозволяє зіставлення файлів за glob-шаблонами (напр. src/**/*.ts).", + "settings.autoApprove.tool.grep": "Шукати вміст файлів. Дозволяє пошук за регулярними виразами у файлах.", + "settings.autoApprove.tool.list": "Перелічити вміст директорії. Дозволяє переглядати файли і папки в директорії.", + "settings.autoApprove.tool.task": + "Запускати підагентів. Дозволяє запуск спеціалізованих підагентів для конкретних завдань.", + "settings.autoApprove.tool.skill": + "Завантажувати навички. Дозволяє завантаження попередньо визначених навичок за назвою.", + "settings.autoApprove.tool.lsp": "Запитувати мовний сервер. Дозволяє запити до мовного сервера для аналізу коду.", + "settings.autoApprove.tool.todoreadwrite": + "Керувати списком завдань. Дозволяє читання та оновлення внутрішнього списку завдань.", + "settings.autoApprove.tool.webfetch": "Отримати URL. Дозволяє отримання вмісту з вказаного URL.", + "settings.autoApprove.tool.websearchcodesearch": + "Шукати в мережі або коді. Дозволяє зовнішній веб-пошук або пошук коду.", + "settings.autoApprove.tool.doom_loop": + "Запобігати повторюваним діям. Спрацьовує, коли той самий виклик інструменту повторюється з однаковими вхідними даними.", + + "settings.checkpoints.enable.title": "Увімкнути знімки", + "settings.checkpoints.enable.description": + "Створювати контрольні точки перед редагуванням файлів, щоб мати можливість відновити попередні стани", + + "settings.context.autoCompaction.title": "Автоматичне стиснення", + "settings.context.autoCompaction.description": "Автоматично стискати при заповненні контексту", + "settings.context.prune.title": "Очищати старі виводи", + "settings.context.prune.description": "Видаляти старі виводи інструментів під час стиснення", + "settings.context.watcherPatterns": "Шаблони ігнорування спостерігача файлів", + "settings.context.watcherPatterns.description": "Glob-шаблони для файлів, які спостерігач має ігнорувати", + + "settings.display.username.title": "Ім'я користувача", + "settings.display.username.description": "Власне ім'я користувача, що відображається в чатах", + "settings.display.layout.title": "Макет", + "settings.display.layout.description": "Режим макету для інтерфейсу чату", + "settings.display.layout.auto": "Автоматично", + "settings.display.layout.stretch": "Розтягнути", + + "settings.providers.defaultModel.title": "Модель за замовчуванням", + "settings.providers.defaultModel.description": "Основна модель для чатів", + "settings.providers.smallModel.title": "Мала модель", + "settings.providers.smallModel.description": + "Легка модель для генерації заголовків, повідомлень комітів, покращення запитів та інших швидких завдань", + "settings.providers.modeModels": "Модель для кожного режиму", + "settings.providers.modeModels.description": + "Перевизначити стандартну модель для певних режимів. Якщо не встановлено, використовується загальна стандартна модель.", + "settings.providers.disabled": "Вимкнені провайдери", + "settings.providers.disabled.description": "Провайдери, що будуть приховані у списку провайдерів", + "settings.providers.enabled": "Увімкнені провайдери (список дозволених)", + "settings.providers.enabled.description": "Якщо встановлено, доступні лише ці провайдери (власний список дозволених)", + "settings.providers.notSet": "Не встановлено (використовувати стандартний сервера)", + "settings.providers.custom.note": "Додати OpenAI-сумісного провайдера через базовий URL.", + "settings.providers.search.placeholder": "Пошук провайдера", + "settings.providers.select.placeholder": "Вибрати провайдера...", + + "dialog.model.notSet": "Не встановлено", + + "profile.personalAccount": "Особистий акаунт", + + // Agent Manager strings live in webview-ui/agent-manager/i18n/uk.ts + + "question.summary": "{{n}} з {{total}} питань", + "common.review": "Переглянути", + + // legacy-migration start + "settings.legacyMigration.link": "Перенести зі старої версії", + "settings.aboutKiloCode.legacyMigration.title": "Перенесення зі старої версії", + "settings.aboutKiloCode.legacyMigration.description": + "Перенести налаштування з попередньої версії Kilo Code, включаючи API-ключі провайдерів та стандартну модель.", + + // 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": "Agent Manager", + "migration.whatsNew.features.agentManager.detail": + "Єдиний інтерфейс для запуску кількох агентів паралельно, кожен у власному worktree — стежте за прогресом, перемикайте контекст і переглядайте зміни з одного місця.", + "migration.whatsNew.features.foundation.title": "Спільна основа", + "migration.whatsNew.features.foundation.detail": + "Малий та ефективний ядерний модуль у кожному продукті Kilo. Знайомий досвід незалежно від того, як ви вважаєте за краще працювати.", + "migration.whatsNew.blogLink": "Читати повне оголошення", + "migration.whatsNew.continue": "Продовжити", + + // Screen 2 — Migrate Settings + "migration.migrate.title": "Перенесіть свої налаштування", + "migration.migrate.subtitle": "Ми знайшли налаштування з попередньої версії. Ось що можна перенести.", + "migration.migrate.selectLabel": "Вибрати для перенесення", + "migration.migrate.cannotMigrate": "Неможливо перенести", + "migration.migrate.chatHistory": "Сесії чату та історія", + "migration.migrate.chatHistoryDesc": "Несумісно з новою архітектурою", + "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.sessionFailed": "Перенесення сесії не вдалося", + "migration.error.continue": "Продовжити", + "migration.error.action.copy": "Копіювати", + "migration.error.toast.copied": "Помилку скопійовано до буфера обміну", + // legacy-migration end + + "error.details.show": "Деталі", + + "task.todos.progress": "{{done}} з {{total}} завдань виконано", + "task.todos.allDone": "{{count}} завдань виконано", + + "settings.saveBar.unsavedChanges": "Незбережені зміни", + "settings.saveBar.discard": "Скасувати", + "settings.saveBar.save": "Зберегти", + "settings.saveBar.warning.one": "Одна сесія виконується і буде перервана", + "settings.saveBar.warning.many": "Кілька сесій виконуються і будуть перервані", + "settings.saveBar.saveAnyway": "Зберегти все одно", + "settings.saveBar.cancel": "Скасувати", + "notifications.action.next": "Далі", + "notifications.action.close": "Закрити", + "notifications.action.tryModel": "Спробувати {{model}}", +} diff --git a/packages/ui/src/i18n/uk.ts b/packages/ui/src/i18n/uk.ts new file mode 100644 index 00000000000..a7fa1dae028 --- /dev/null +++ b/packages/ui/src/i18n/uk.ts @@ -0,0 +1,153 @@ +import { dict as en } from "./en" + +type Keys = keyof typeof en + +export const dict = { + "ui.sessionReview.title": "Зміни сесії", + "ui.sessionReview.title.lastTurn": "Зміни останнього кроку", + "ui.sessionReview.diffStyle.unified": "Об'єднаний", + "ui.sessionReview.diffStyle.split": "Розділений", + "ui.sessionReview.openFile": "Відкрити файл", + "ui.sessionReview.selection.line": "рядок {{line}}", + "ui.sessionReview.selection.lines": "рядки {{start}}-{{end}}", + "ui.sessionReview.expandAll": "Розгорнути все", + "ui.sessionReview.collapseAll": "Згорнути все", + + "ui.sessionReview.change.added": "Додано", + "ui.sessionReview.change.removed": "Видалено", + "ui.sessionReview.change.modified": "Змінено", + "ui.sessionReview.image.loading": "Завантаження...", + "ui.sessionReview.image.placeholder": "Зображення", + "ui.sessionReview.largeDiff.title": "Різниця занадто велика для відображення", + "ui.sessionReview.largeDiff.meta": "Ліміт: {{limit}} змінених рядків. Поточне: {{current}} змінених рядків.", + "ui.sessionReview.largeDiff.renderAnyway": "Відобразити все одно", + + "ui.fileMedia.kind.image": "зображення", + "ui.fileMedia.kind.audio": "аудіо", + "ui.fileMedia.state.removed": "{{kind}} видалено", + "ui.fileMedia.state.loading": "{{kind}} завантажується...", + "ui.fileMedia.state.error": "{{kind}} не вдалося завантажити", + "ui.fileMedia.state.unavailable": "попередній перегляд {{kind}} недоступний", + "ui.fileMedia.binary.title": "Бінарний файл", + "ui.fileMedia.binary.description.path": "{{path}} є бінарним файлом.", + "ui.fileMedia.binary.description.default": "Бінарний вміст", + + "ui.lineComment.label.prefix": "Коментар до ", + "ui.lineComment.label.suffix": "", + "ui.lineComment.editorLabel.prefix": "Коментування: ", + "ui.lineComment.editorLabel.suffix": "", + "ui.lineComment.placeholder": "Додати коментар", + "ui.lineComment.submit": "Коментувати", + + "ui.sessionTurn.steps.show": "Показати кроки", + "ui.sessionTurn.steps.hide": "Приховати кроки", + "ui.sessionTurn.summary.response": "Відповідь", + "ui.sessionTurn.diff.showMore": "Показати більше змін ({{count}})", + + "ui.sessionTurn.retry.retrying": "повтор спроби", + "ui.sessionTurn.retry.inSeconds": "через {{seconds}}с", + "ui.sessionTurn.retry.attempt": "спроба №{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - спроба №{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini зараз перевантажений", + "ui.sessionTurn.error.freeUsageExceeded": "Безкоштовний ліміт вичерпано", + "ui.sessionTurn.error.addCredits": "Поповнити кредити", + + "ui.sessionTurn.status.delegating": "Делегування роботи", + "ui.sessionTurn.status.planning": "Планування наступних кроків", + "ui.sessionTurn.status.gatheringContext": "Дослідження", + "ui.sessionTurn.status.gatheredContext": "Досліджено", + "ui.sessionTurn.status.searchingCodebase": "Пошук у кодовій базі", + "ui.sessionTurn.status.searchingWeb": "Пошук у мережі", + "ui.sessionTurn.status.makingEdits": "Внесення змін", + "ui.sessionTurn.status.runningCommands": "Виконання команд", + "ui.sessionTurn.status.thinking": "Думаю", + "ui.sessionTurn.status.thinkingWithTopic": "Думаю - {{topic}}", + "ui.sessionTurn.status.gatheringThoughts": "Збираю думки", + "ui.sessionTurn.status.consideringNextSteps": "Обмірковую наступні кроки", + + "ui.messagePart.questions.dismissed": "Питання відхилено", + "ui.messagePart.compaction": "Історію стиснуто", + "ui.messagePart.context.read.one": "{{count}} читання", + "ui.messagePart.context.read.other": "{{count}} читань", + "ui.messagePart.context.search.one": "{{count}} пошук", + "ui.messagePart.context.search.other": "{{count}} пошуків", + "ui.messagePart.context.list.one": "{{count}} список", + "ui.messagePart.context.list.other": "{{count}} списків", + "ui.messagePart.diagnostic.error": "Помилка", + "ui.messagePart.title.edit": "Редагувати", + "ui.messagePart.title.write": "Записати", + "ui.messagePart.option.typeOwnAnswer": "Введіть власну відповідь", + "ui.messagePart.review.title": "Перегляньте свої відповіді", + + "ui.list.loading": "Завантаження", + "ui.list.empty": "Результатів не знайдено", + "ui.list.clearFilter": "Очистити фільтр", + "ui.list.emptyWithFilter.prefix": "Результатів не знайдено:", + "ui.list.emptyWithFilter.suffix": "", + + "ui.messageNav.newMessage": "Нове повідомлення", + + "ui.textField.copyToClipboard": "Скопіювати в буфер обміну", + "ui.textField.copyLink": "Скопіювати посилання", + "ui.textField.copied": "Скопійовано", + + "ui.imagePreview.alt": "Попередній перегляд зображення", + "ui.scrollView.ariaLabel": "вміст з прокруткою", + + "ui.tool.read": "Читати", + "ui.tool.loaded": "Завантажено", + "ui.tool.list": "Список", + "ui.tool.glob": "Glob", + "ui.tool.grep": "Grep", + "ui.tool.webfetch": "Веб-запит", + "ui.tool.websearch": "Веб-пошук", + "ui.tool.codesearch": "Пошук коду", + "ui.tool.shell": "Оболонка", + "ui.tool.patch": "Патч", + "ui.tool.todos": "Завдання", + "ui.tool.todos.read": "Читати завдання", + "ui.tool.questions": "Питання", + "ui.tool.agent": "{{type}} Агент", + "ui.tool.agent.default": "Агент", + + "ui.common.file.one": "файл", + "ui.common.file.other": "файлів", + "ui.common.question.one": "питання", + "ui.common.question.other": "питань", + + "ui.common.add": "Додати", + "ui.common.back": "Назад", + "ui.common.cancel": "Скасувати", + "ui.common.confirm": "Підтвердити", + "ui.common.dismiss": "Закрити", + "ui.common.close": "Закрити", + "ui.common.next": "Далі", + "ui.common.submit": "Надіслати", + + "ui.permission.deny": "Відхилити", + "ui.permission.allowAlways": "Завжди дозволяти", + "ui.permission.allowOnce": "Дозволити один раз", + + "ui.message.expand": "Розгорнути повідомлення", + "ui.message.collapse": "Згорнути повідомлення", + "ui.message.copy": "Копіювати", + "ui.message.copyMessage": "Копіювати повідомлення", + "ui.message.copyResponse": "Копіювати відповідь", + "ui.message.copied": "Скопійовано", + "ui.message.revert": "Повернутися до цього місця", + "ui.message.interrupted": "Перервано", + "ui.message.queued": "В черзі", + "ui.message.attachment.alt": "вкладення", + + "ui.patch.action.deleted": "Видалено", + "ui.patch.action.created": "Створено", + "ui.patch.action.moved": "Переміщено", + "ui.patch.action.patched": "Застосовано патч", + + "ui.question.subtitle.answered": "{{count}} відповідей", + "ui.question.answer.none": "(без відповіді)", + "ui.question.review.notAnswered": "(не відповіли)", + "ui.question.multiHint": "Виберіть усі відповідні варіанти", + "ui.question.singleHint": "Виберіть одну відповідь", + "ui.question.custom.placeholder": "Введіть свою відповідь...", +} satisfies Partial> From a606f2eab5e6f68592b402924a0ddd4a0866adb1 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 08:36:47 +0000 Subject: [PATCH 229/261] feat(i18n): add complete Ukrainian (uk) translation --- packages/kilo-vscode/package.json | 6 ++++-- packages/kilo-vscode/src/services/cli-backend/i18n/index.ts | 2 ++ .../kilo-vscode/webview-ui/src/context/language-utils.ts | 2 ++ packages/kilo-vscode/webview-ui/src/context/language.tsx | 6 ++++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 9856944fd1f..cb602918acc 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -653,7 +653,8 @@ "th", "bs", "tr", - "nl" + "nl", + "uk" ], "enumDescriptions": [ "Auto (VS Code language)", @@ -674,7 +675,8 @@ "ภาษาไทย", "Bosanski", "Türkçe", - "Nederlands" + "Nederlands", + "Українська" ] }, "kilo-code.new.model.providerID": { diff --git a/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts b/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts index b758b4ba105..494688559ec 100644 --- a/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts +++ b/packages/kilo-vscode/src/services/cli-backend/i18n/index.ts @@ -15,6 +15,7 @@ import { dict as ru } from "./ru" import { dict as th } from "./th" import { dict as zh } from "./zh" import { dict as tr } from "./tr" +import { dict as uk } from "./uk" import { dict as zht } from "./zht" import { type dict as enDict } from "./en" @@ -35,6 +36,7 @@ const bundles: Record> = { ru, th, tr, + uk, zh, zht, } diff --git a/packages/kilo-vscode/webview-ui/src/context/language-utils.ts b/packages/kilo-vscode/webview-ui/src/context/language-utils.ts index 5ea74bca858..68cc50fe55d 100644 --- a/packages/kilo-vscode/webview-ui/src/context/language-utils.ts +++ b/packages/kilo-vscode/webview-ui/src/context/language-utils.ts @@ -17,6 +17,7 @@ export type Locale = | "bs" | "tr" | "nl" + | "uk" export const LOCALES: readonly Locale[] = [ "en", @@ -37,6 +38,7 @@ export const LOCALES: readonly Locale[] = [ "bs", "tr", "nl", + "uk", ] /** diff --git a/packages/kilo-vscode/webview-ui/src/context/language.tsx b/packages/kilo-vscode/webview-ui/src/context/language.tsx index 5d063e1cc7a..692e9836a5c 100644 --- a/packages/kilo-vscode/webview-ui/src/context/language.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/language.tsx @@ -27,6 +27,7 @@ import { dict as uiTh } from "@kilocode/kilo-ui/i18n/th" import { dict as uiBs } from "@kilocode/kilo-ui/i18n/bs" import { dict as uiTr } from "@kilocode/kilo-ui/i18n/tr" import { dict as uiNl } from "@kilocode/kilo-ui/i18n/nl" +import { dict as uiUk } from "@kilocode/kilo-ui/i18n/uk" import { dict as appEn } from "../i18n/en" import { dict as appZh } from "../i18n/zh" import { dict as appZht } from "../i18n/zht" @@ -45,6 +46,7 @@ import { dict as appTh } from "../i18n/th" import { dict as appBs } from "../i18n/bs" import { dict as appTr } from "../i18n/tr" import { dict as appNl } from "../i18n/nl" +import { dict as appUk } from "../i18n/uk" import { dict as amEn } from "../../agent-manager/i18n/en" import { dict as amZh } from "../../agent-manager/i18n/zh" import { dict as amZht } from "../../agent-manager/i18n/zht" @@ -63,6 +65,7 @@ import { dict as amTh } from "../../agent-manager/i18n/th" import { dict as amBs } from "../../agent-manager/i18n/bs" import { dict as amTr } from "../../agent-manager/i18n/tr" import { dict as amNl } from "../../agent-manager/i18n/nl" +import { dict as amUk } from "../../agent-manager/i18n/uk" import { dict as kiloEn } from "@kilocode/kilo-i18n/en" import { dict as kiloZh } from "@kilocode/kilo-i18n/zh" import { dict as kiloZht } from "@kilocode/kilo-i18n/zht" @@ -81,6 +84,7 @@ import { dict as kiloTh } from "@kilocode/kilo-i18n/th" import { dict as kiloBs } from "@kilocode/kilo-i18n/bs" import { dict as kiloTr } from "@kilocode/kilo-i18n/tr" import { dict as kiloNl } from "@kilocode/kilo-i18n/nl" +import { dict as kiloUk } from "@kilocode/kilo-i18n/uk" import { useVSCode } from "./vscode" import { normalizeLocale as _normalizeLocale, resolveTemplate as _resolveTemplate } from "./language-utils" @@ -108,6 +112,7 @@ export const LOCALE_LABELS: Record = { bs: "Bosanski", tr: "Türkçe", nl: "Nederlands", + uk: "Українська", } // Merge 4 dict layers: app + ui + kilo + agent manager (kilo and agent manager override last) @@ -131,6 +136,7 @@ const dicts: Record> = { bs: { ...base, ...appBs, ...uiBs, ...kiloBs, ...amEn, ...amBs }, tr: { ...base, ...appTr, ...uiTr, ...kiloTr, ...amEn, ...amTr }, nl: { ...base, ...appNl, ...uiNl, ...kiloNl, ...amEn, ...amNl }, + uk: { ...base, ...appUk, ...uiUk, ...kiloUk, ...amEn, ...amUk }, } function normalizeLocale(lang: string): Locale { From 2de6c363e3d822441ab8579b445b60851e440d92 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 09:04:30 +0000 Subject: [PATCH 230/261] fix(cli): prevent zombie kilo serve processes on extension host crash When the VS Code extension host is hard-killed (crash, OOM, kill -9), dispose() is never called and the kilo serve child process is orphaned. Fix by using a stdin keepalive pipe: the extension keeps stdin open after spawning the CLI. The CLI watches for EOF on stdin (only when KILO_CLIENT=vscode) and triggers a clean shutdown. The OS closes the write-end of the pipe on any parent death, so the CLI always exits regardless of how the extension host terminates. On clean dispose(), stdin is explicitly closed before sending SIGTERM, so the shutdown path is consistent in both the crash and clean cases. Closes #8050 --- .../src/services/cli-backend/server-manager.ts | 9 +++++++-- packages/opencode/src/cli/cmd/serve.ts | 12 ++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/kilo-vscode/src/services/cli-backend/server-manager.ts b/packages/kilo-vscode/src/services/cli-backend/server-manager.ts index 4b08a6284e7..2c5cce07d13 100644 --- a/packages/kilo-vscode/src/services/cli-backend/server-manager.ts +++ b/packages/kilo-vscode/src/services/cli-backend/server-manager.ts @@ -81,7 +81,10 @@ export class ServerManager { KILO_APP_VERSION: this.context.extension.packageJSON.version, KILO_VSCODE_VERSION: vscode.version, }, - stdio: ["ignore", "pipe", "pipe"], + // stdin is kept open as a keepalive pipe. The CLI watches for EOF on + // stdin and shuts itself down. This ensures the server exits even when + // the extension host is hard-killed and dispose() is never called. + stdio: ["pipe", "pipe", "pipe"], detached: true, }) console.log("[Kilo New] ServerManager: 📦 Process spawned with PID:", serverProcess.pid) @@ -181,7 +184,9 @@ export class ServerManager { const proc = this.instance.process this.instance = null - console.log("[Kilo New] ServerManager: 🔴 Disposing — sending SIGTERM to process group, PID:", proc.pid) + console.log("[Kilo New] ServerManager: 🔴 Disposing — closing stdin pipe, PID:", proc.pid) + // Closing stdin signals the CLI to shut down gracefully via its EOF watcher. + proc.stdin?.end() ServerManager.killProcess(proc, "SIGTERM") // SIGKILL fallback after 5s: mirrors the desktop app going straight to diff --git a/packages/opencode/src/cli/cmd/serve.ts b/packages/opencode/src/cli/cmd/serve.ts index 8ccde9b7ce1..fa58baccecc 100644 --- a/packages/opencode/src/cli/cmd/serve.ts +++ b/packages/opencode/src/cli/cmd/serve.ts @@ -39,6 +39,18 @@ export const ServeCommand = cmd({ process.on("SIGTERM", shutdown) process.on("SIGINT", shutdown) process.on("SIGHUP", shutdown) + + // When spawned by the VS Code extension, stdin is kept open as a keepalive + // pipe. If the extension host is hard-killed (crash, OOM) the write-end of + // the pipe is closed by the OS, causing an EOF here. We detect that and + // trigger a clean shutdown so no zombie process is left behind. + if (process.env["KILO_CLIENT"] === "vscode") { + process.stdin.resume() + process.stdin.on("end", () => { + shutdown().catch(() => {}) + }) + } + await new Promise((resolve) => abort.signal.addEventListener("abort", resolve)) // kilocode_change end }, From df568fc8cc9e8623d10655510be54293aeaaaf1a Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 09:07:26 +0000 Subject: [PATCH 231/261] fix(i18n): refine ukrainian translation wording --- packages/kilo-i18n/src/uk.ts | 4 +- .../webview-ui/agent-manager/i18n/uk.ts | 10 +-- .../kilo-vscode/webview-ui/src/i18n/uk.ts | 64 +++++++++---------- packages/ui/src/i18n/uk.ts | 12 ++-- 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/packages/kilo-i18n/src/uk.ts b/packages/kilo-i18n/src/uk.ts index fe56df66a46..458772d31b1 100644 --- a/packages/kilo-i18n/src/uk.ts +++ b/packages/kilo-i18n/src/uk.ts @@ -65,8 +65,8 @@ export const dict = { "marketplace.install": "Встановити", "marketplace.filter.installed": "Встановлено", "marketplace.error.dismiss": "Закрити", - "marketplace.warning.busyOne": "Одна сесія виконується і буде перервана", - "marketplace.warning.busyMany": "Кілька сесій виконуються і будуть перервані", + "marketplace.warning.busyOne": "Виконується одна сесія, її буде перервано", + "marketplace.warning.busyMany": "Виконується кілька сесій, їх буде перервано", "marketplace.warning.installAnyway": "Встановити все одно", "marketplace.warning.cancel": "Скасувати", } diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts index 1077cd54384..ae8f2cd143f 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts @@ -10,7 +10,7 @@ export const dict = { "agentManager.worktree.delete": "Видалити робоче дерево", "agentManager.worktree.confirmDelete": "Видалити?", "agentManager.worktree.stale": "Застаріле", - "agentManager.worktree.staleTooltip": "Відсутнє на диску або більше не відстежується git worktree", + "agentManager.worktree.staleTooltip": "Відсутнє на диску або більше не відстежується як робоче дерево Git", "agentManager.worktree.removeStale": "Видалити застаріле робоче дерево", "agentManager.worktree.doubleClickRename": "Двічі клацніть для перейменування", "agentManager.worktree.versions": "{{count}} версій", @@ -103,7 +103,7 @@ export const dict = { "agentManager.dialog.removeImage": "Видалити зображення", "agentManager.dialog.advanced": "Розширено...", - "agentManager.diff.toggle": "Перемкнути diff", + "agentManager.diff.toggle": "Показати або приховати diff", "agentManager.diff.openFile": "Відкрити файл", "agentManager.open.button": "Відкрити", "agentManager.open.tooltip": "Відкрити це робоче дерево у VS Code", @@ -123,7 +123,7 @@ export const dict = { "agentManager.apply.checking": "Перевірка...", "agentManager.apply.applying": "Застосування...", "agentManager.apply.success": "Зміни застосовано", - "agentManager.apply.conflict": "Застосування має конфлікти", + "agentManager.apply.conflict": "Під час застосування виникли конфлікти", "agentManager.apply.conflictToast": "{{count}} конфліктів у {{files}} файлах. Перегляньте деталі в розділі Застосувати.", "agentManager.apply.error": "Застосування не вдалося", @@ -136,14 +136,14 @@ export const dict = { "agentManager.apply.inline.success": "Застосовано", "agentManager.apply.inline.conflict": "Конфлікти", "agentManager.apply.inline.error": "Не вдалося", - "agentManager.shortcuts.toggleDiff": "Перемкнути панель diff", + "agentManager.shortcuts.toggleDiff": "Показати або приховати панель diff", "agentManager.shortcuts.category.quickSwitch": "Швидке перемикання", "agentManager.shortcuts.jumpToItem": "Перейти до елемента 1\u20139", "agentManager.review.sendAllToChat": "Надіслати все до чату", "agentManager.review.sendAllToChatWithCount": "Надіслати все до чату ({{count}})", "agentManager.review.sendAllShortcut.mac": "⌘Enter", "agentManager.review.sendAllShortcut.other": "Ctrl+Enter", - "agentManager.review.modalTitle": "Переглянути коментар", + "agentManager.review.modalTitle": "Перегляд коментаря", "agentManager.review.inlineCount": "Переглянути коментарі ({{count}})", "agentManager.review.clearAll": "Очистити все", "agentManager.review.commentOnLine": "Коментар до рядка {{line}}", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts index f84fc439d32..78627eb44b6 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts @@ -72,8 +72,8 @@ export const dict = { "command.model.variant.cycle.description": "Перейти до наступного рівня зусиль", "command.permissions.autoaccept.enable": "Автоматично приймати редагування", "command.permissions.autoaccept.disable": "Зупинити автоматичне прийняття", - "command.workspace.toggle": "Перемкнути робочі простори", - "command.workspace.toggle.description": "Показати або приховати кілька робочих просторів на бічній панелі", + "command.workspace.toggle": "Перемкнути робочі дерева", + "command.workspace.toggle.description": "Показати або приховати кілька робочих дерев на бічній панелі", "command.session.undo": "Скасувати", "command.session.undo.description": "Скасувати останнє повідомлення", "command.session.redo": "Повторити", @@ -88,10 +88,10 @@ export const dict = { "command.session.compact.description": "Підсумувати сесію для зменшення розміру контексту", "command.session.fork": "Розгалужити від повідомлення", "command.session.fork.description": "Створити нову сесію від попереднього повідомлення", - "command.session.share": "Поділитися сесією", - "command.session.share.description": "Поділитися цією сесією та скопіювати URL до буфера обміну", - "command.session.unshare": "Скасувати публікацію", - "command.session.unshare.description": "Зупинити публікацію цієї сесії", + "command.session.share": "Відкрити доступ до сесії", + "command.session.share.description": "Відкрити доступ до цієї сесії та скопіювати URL до буфера обміну", + "command.session.unshare": "Закрити доступ до сесії", + "command.session.unshare.description": "Закрити доступ до цієї сесії", "palette.search.placeholder": "Пошук файлів, команд і сесій", "palette.empty": "Результатів не знайдено", @@ -141,20 +141,21 @@ export const dict = { "OpenCode Zen надає доступ до добірки надійних оптимізованих моделей для агентів кодування.", "provider.connect.opencodeZen.line2": "За допомогою одного API-ключа ви отримаєте доступ до таких моделей, як Claude, GPT, Gemini, GLM та інших.", - "provider.connect.opencodeZen.visit.prefix": "", + "provider.connect.opencodeZen.visit.prefix": "Відвідайте ", "provider.connect.opencodeZen.visit.link": "https://opencode.ai/zen", - "provider.connect.opencodeZen.visit.suffix": " відвідайте, щоб отримати свій API-ключ.", - "provider.connect.oauth.code.visit.prefix": "Щоб підключити акаунт і використовувати моделі {{provider}} в Kilo, ", - "provider.connect.oauth.code.visit.link": "перейдіть за цим посиланням", - "provider.connect.oauth.code.visit.suffix": " щоб отримати код авторизації.", + "provider.connect.opencodeZen.visit.suffix": " щоб отримати свій API-ключ.", + "provider.connect.oauth.code.visit.prefix": "Перейдіть за ", + "provider.connect.oauth.code.visit.link": "цим посиланням", + "provider.connect.oauth.code.visit.suffix": + " щоб отримати код авторизації для підключення акаунта та використання моделей {{provider}} у Kilo.", "provider.connect.oauth.code.label": "Код авторизації {{method}}", "provider.connect.oauth.code.placeholder": "Код авторизації", "provider.connect.oauth.code.required": "Код авторизації обов'язковий", "provider.connect.oauth.code.invalid": "Недійсний код авторизації", - "provider.connect.oauth.auto.visit.prefix": "", - "provider.connect.oauth.auto.visit.link": "Перейдіть за цим посиланням", + "provider.connect.oauth.auto.visit.prefix": "Перейдіть за ", + "provider.connect.oauth.auto.visit.link": "цим посиланням", "provider.connect.oauth.auto.visit.suffix": - " і введіть код нижче, щоб підключити акаунт та використовувати моделі {{provider}} в Kilo.", + " та введіть код нижче, щоб підключити акаунт і використовувати моделі {{provider}} у Kilo.", "provider.connect.oauth.auto.confirmationCode": "Код підтвердження", "provider.connect.toast.connected.title": "{{provider}} підключено", "provider.connect.toast.connected.description": "Моделі {{provider}} тепер доступні.", @@ -308,9 +309,8 @@ export const dict = { "dialog.project.edit.icon.recommended": "Рекомендовано: 128x128px", "dialog.project.edit.color": "Колір", "dialog.project.edit.color.select": "Вибрати колір {{color}}", - "dialog.project.edit.worktree.startup": "Скрипт запуску робочого простору", - "dialog.project.edit.worktree.startup.description": - "Виконується після створення нового робочого простору (worktree).", + "dialog.project.edit.worktree.startup": "Скрипт запуску робочого дерева", + "dialog.project.edit.worktree.startup.description": "Виконується після створення нового робочого дерева.", "dialog.project.edit.worktree.startup.placeholder": "напр. bun install", "context.breakdown.title": "Розбивка контексту", @@ -373,10 +373,10 @@ export const dict = { "toast.theme.title": "Тему змінено", "toast.scheme.title": "Кольорова схема", - "toast.workspace.enabled.title": "Робочі простори увімкнено", - "toast.workspace.enabled.description": "На бічній панелі відображатимуться кілька робочих просторів", - "toast.workspace.disabled.title": "Робочі простори вимкнено", - "toast.workspace.disabled.description": "На бічній панелі відображатиметься лише основний робочий простір", + "toast.workspace.enabled.title": "Робочі дерева увімкнено", + "toast.workspace.enabled.description": "На бічній панелі тепер відображаються кілька робочих дерев", + "toast.workspace.disabled.title": "Робочі дерева вимкнено", + "toast.workspace.disabled.description": "На бічній панелі відображається лише основне робоче дерево", "toast.permissions.autoaccept.on.title": "Редагування приймаються автоматично", "toast.permissions.autoaccept.on.description": "Дозволи на редагування і запис схвалюватимуться автоматично", @@ -393,15 +393,15 @@ export const dict = { "toast.context.noLineSelection.description": "Спочатку виділіть діапазон рядків у вкладці файлу.", "toast.session.share.copyFailed.title": "Не вдалося скопіювати URL до буфера обміну", - "toast.session.share.success.title": "Сесію опубліковано", - "toast.session.share.success.description": "URL публікації скопійовано до буфера обміну!", - "toast.session.share.failed.title": "Не вдалося опублікувати сесію", - "toast.session.share.failed.description": "Під час публікації сесії сталася помилка", + "toast.session.share.success.title": "Доступ до сесії відкрито", + "toast.session.share.success.description": "Посилання на сесію скопійовано до буфера обміну!", + "toast.session.share.failed.title": "Не вдалося відкрити доступ до сесії", + "toast.session.share.failed.description": "Під час відкриття доступу до сесії сталася помилка", - "toast.session.unshare.success.title": "Публікацію сесії скасовано", - "toast.session.unshare.success.description": "Публікацію сесії успішно скасовано!", - "toast.session.unshare.failed.title": "Не вдалося скасувати публікацію сесії", - "toast.session.unshare.failed.description": "Під час скасування публікації сесії сталася помилка", + "toast.session.unshare.success.title": "Доступ до сесії закрито", + "toast.session.unshare.success.description": "Доступ до сесії успішно закрито!", + "toast.session.unshare.failed.title": "Не вдалося закрити доступ до сесії", + "toast.session.unshare.failed.description": "Під час закриття доступу до сесії сталася помилка", "toast.session.listFailed.title": "Не вдалося завантажити сесії для {{project}}", @@ -586,8 +586,8 @@ export const dict = { "sidebar.nav.projectsAndSessions": "Проєкти і сесії", "sidebar.settings": "Налаштування", "sidebar.help": "Допомога", - "sidebar.workspaces.enable": "Увімкнути робочі простори", - "sidebar.workspaces.disable": "Вимкнути робочі простори", + "sidebar.workspaces.enable": "Увімкнути робочі дерева", + "sidebar.workspaces.disable": "Вимкнути робочі дерева", "sidebar.gettingStarted.title": "Початок роботи", "sidebar.gettingStarted.line1": "Kilo включає безкоштовні моделі, тому ви можете почати відразу.", "sidebar.gettingStarted.line2": "Підключіть будь-якого провайдера для використання моделей Claude, GPT, Gemini тощо.", @@ -1243,7 +1243,7 @@ export const dict = { "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. Знайомий досвід незалежно від того, як ви вважаєте за краще працювати.", diff --git a/packages/ui/src/i18n/uk.ts b/packages/ui/src/i18n/uk.ts index a7fa1dae028..f14551d8e34 100644 --- a/packages/ui/src/i18n/uk.ts +++ b/packages/ui/src/i18n/uk.ts @@ -24,10 +24,10 @@ export const dict = { "ui.fileMedia.kind.image": "зображення", "ui.fileMedia.kind.audio": "аудіо", - "ui.fileMedia.state.removed": "{{kind}} видалено", + "ui.fileMedia.state.removed": "Файл {{kind}} видалено.", "ui.fileMedia.state.loading": "{{kind}} завантажується...", - "ui.fileMedia.state.error": "{{kind}} не вдалося завантажити", - "ui.fileMedia.state.unavailable": "попередній перегляд {{kind}} недоступний", + "ui.fileMedia.state.error": "Не вдалося завантажити {{kind}}.", + "ui.fileMedia.state.unavailable": "Попередній перегляд {{kind}} недоступний.", "ui.fileMedia.binary.title": "Бінарний файл", "ui.fileMedia.binary.description.path": "{{path}} є бінарним файлом.", "ui.fileMedia.binary.description.default": "Бінарний вміст", @@ -48,7 +48,7 @@ export const dict = { "ui.sessionTurn.retry.inSeconds": "через {{seconds}}с", "ui.sessionTurn.retry.attempt": "спроба №{{attempt}}", "ui.sessionTurn.retry.attemptLine": "{{line}} - спроба №{{attempt}}", - "ui.sessionTurn.retry.geminiHot": "gemini зараз перевантажений", + "ui.sessionTurn.retry.geminiHot": "Gemini зараз перевантажений", "ui.sessionTurn.error.freeUsageExceeded": "Безкоштовний ліміт вичерпано", "ui.sessionTurn.error.addCredits": "Поповнити кредити", @@ -67,8 +67,8 @@ export const dict = { "ui.messagePart.questions.dismissed": "Питання відхилено", "ui.messagePart.compaction": "Історію стиснуто", - "ui.messagePart.context.read.one": "{{count}} читання", - "ui.messagePart.context.read.other": "{{count}} читань", + "ui.messagePart.context.read.one": "{{count}} прочитання", + "ui.messagePart.context.read.other": "{{count}} прочитань", "ui.messagePart.context.search.one": "{{count}} пошук", "ui.messagePart.context.search.other": "{{count}} пошуків", "ui.messagePart.context.list.one": "{{count}} список", From 2196893b9dfced4ae61b495748eee8e80f319fdc Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 09:42:47 +0000 Subject: [PATCH 232/261] feat(vscode): set RTL direction on html element for Arabic locale When the user selects Arabic (or any future RTL locale), set document.documentElement.dir to 'rtl' and update the lang attribute to match the active locale. This fixes the layout direction so the VS Code webview UI renders correctly for RTL scripts. Closes #8056 --- .../kilo-vscode/webview-ui/src/context/language-utils.ts | 3 +++ packages/kilo-vscode/webview-ui/src/context/language.tsx | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/webview-ui/src/context/language-utils.ts b/packages/kilo-vscode/webview-ui/src/context/language-utils.ts index 5ea74bca858..c92e6539003 100644 --- a/packages/kilo-vscode/webview-ui/src/context/language-utils.ts +++ b/packages/kilo-vscode/webview-ui/src/context/language-utils.ts @@ -18,6 +18,9 @@ export type Locale = | "tr" | "nl" +/** Locales that use right-to-left script. */ +export const RTL_LOCALES = new Set(["ar"]) + export const LOCALES: readonly Locale[] = [ "en", "zh", diff --git a/packages/kilo-vscode/webview-ui/src/context/language.tsx b/packages/kilo-vscode/webview-ui/src/context/language.tsx index 5d063e1cc7a..f18d14bc0a9 100644 --- a/packages/kilo-vscode/webview-ui/src/context/language.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/language.tsx @@ -87,7 +87,7 @@ import { normalizeLocale as _normalizeLocale, resolveTemplate as _resolveTemplat export type { Locale } from "./language-utils" export { LOCALES } from "./language-utils" import type { Locale } from "./language-utils" -import { LOCALES } from "./language-utils" +import { LOCALES, RTL_LOCALES } from "./language-utils" export const LOCALE_LABELS: Record = { en: "English", @@ -176,6 +176,13 @@ export const LanguageProvider: ParentComponent = (props) const dict = createMemo(() => dicts[locale()] ?? dicts.en) + // Update and when locale changes + createEffect(() => { + const loc = locale() + document.documentElement.lang = loc + document.documentElement.dir = RTL_LOCALES.has(loc) ? "rtl" : "ltr" + }) + const t = (key: UiI18nKey, params?: UiI18nParams) => { const text = (dict() as Record)[key] ?? String(key) return resolveTemplate(text, params) From 64809791f958ce28dc18218e488f766545dace5b Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 09:49:26 +0000 Subject: [PATCH 233/261] fix(vscode): use valid BCP 47 lang tags for html lang attribute Map internal locale IDs (br, zht) to proper BCP 47 tags (pt-BR, zh-TW) when setting document.documentElement.lang, so screen readers and browser language detection work correctly. --- .../webview-ui/src/context/language-utils.ts | 11 +++++++++++ .../kilo-vscode/webview-ui/src/context/language.tsx | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/context/language-utils.ts b/packages/kilo-vscode/webview-ui/src/context/language-utils.ts index c92e6539003..b41c120aa3d 100644 --- a/packages/kilo-vscode/webview-ui/src/context/language-utils.ts +++ b/packages/kilo-vscode/webview-ui/src/context/language-utils.ts @@ -21,6 +21,17 @@ export type Locale = /** Locales that use right-to-left script. */ export const RTL_LOCALES = new Set(["ar"]) +/** Map internal locale IDs to valid BCP 47 language tags for the HTML lang attribute. */ +export const LOCALE_BCP47: Partial> = { + br: "pt-BR", + zht: "zh-TW", +} + +/** Return the BCP 47 language tag for a locale (falls back to the locale id itself). */ +export function localeToBcp47(locale: Locale): string { + return LOCALE_BCP47[locale] ?? locale +} + export const LOCALES: readonly Locale[] = [ "en", "zh", diff --git a/packages/kilo-vscode/webview-ui/src/context/language.tsx b/packages/kilo-vscode/webview-ui/src/context/language.tsx index f18d14bc0a9..72ef5f328f5 100644 --- a/packages/kilo-vscode/webview-ui/src/context/language.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/language.tsx @@ -87,7 +87,7 @@ import { normalizeLocale as _normalizeLocale, resolveTemplate as _resolveTemplat export type { Locale } from "./language-utils" export { LOCALES } from "./language-utils" import type { Locale } from "./language-utils" -import { LOCALES, RTL_LOCALES } from "./language-utils" +import { LOCALES, RTL_LOCALES, localeToBcp47 } from "./language-utils" export const LOCALE_LABELS: Record = { en: "English", @@ -179,7 +179,7 @@ export const LanguageProvider: ParentComponent = (props) // Update and when locale changes createEffect(() => { const loc = locale() - document.documentElement.lang = loc + document.documentElement.lang = localeToBcp47(loc) document.documentElement.dir = RTL_LOCALES.has(loc) ? "rtl" : "ltr" }) From 645ad36303e2b28a4efe9db18b9169bd5f061633 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 1 Apr 2026 12:06:26 +0200 Subject: [PATCH 234/261] fix: skip request logging for /telemetry/capture endpoint The server middleware logs 3 lines per HTTP request (request, started, completed). For /telemetry/capture this creates unnecessary log volume since autocomplete telemetry can fire multiple events per keystroke (Suggestion Requested, LLM Suggestion Returned, Unique Suggestion Shown). Add /telemetry/capture to the skipLogging check alongside /log to reduce noise in the kilo server log files at ~/.local/share/kilo/log/. --- packages/opencode/src/server/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index e883480e405..463c0d7cc95 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -90,7 +90,7 @@ export namespace Server { return basicAuth({ username, password })(c, next) }) .use(async (c, next) => { - const skipLogging = c.req.path === "/log" + const skipLogging = c.req.path === "/log" || c.req.path === "/telemetry/capture" // kilocode_change if (!skipLogging) { log.info("request", { method: c.req.method, From c9d4d1ac87c493623039a24ba630b0a700d5eff3 Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Wed, 1 Apr 2026 10:39:53 +0000 Subject: [PATCH 235/261] release: v7.1.14 --- bun.lock | 32 +++++++++++++------------- package.json | 2 +- packages/app/package.json | 2 +- packages/desktop-electron/package.json | 2 +- packages/desktop/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++----- packages/kilo-docs/package.json | 2 +- packages/kilo-gateway/package.json | 2 +- packages/kilo-i18n/package.json | 2 +- packages/kilo-telemetry/package.json | 2 +- packages/kilo-ui/package.json | 2 +- packages/kilo-vscode/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/script/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/storybook/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- script/upstream/package.json | 2 +- sdks/vscode/package.json | 2 +- 21 files changed, 41 insertions(+), 41 deletions(-) diff --git a/bun.lock b/bun.lock index 0dae651f9e8..f642ec44e16 100644 --- a/bun.lock +++ b/bun.lock @@ -27,7 +27,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "@kilocode/kilo-i18n": "workspace:*", "@kilocode/kilo-ui": "workspace:*", @@ -79,7 +79,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -112,7 +112,7 @@ }, "packages/desktop-electron": { "name": "@opencode-ai/desktop-electron", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -142,7 +142,7 @@ }, "packages/kilo-docs": { "name": "@kilocode/kilo-docs", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "@docsearch/css": "^4", "@docsearch/js": "^4", @@ -171,7 +171,7 @@ }, "packages/kilo-gateway": { "name": "@kilocode/kilo-gateway", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "@ai-sdk/anthropic": "2.0.65", "@ai-sdk/openai": "2.0.101", @@ -206,7 +206,7 @@ }, "packages/kilo-i18n": { "name": "@kilocode/kilo-i18n", - "version": "7.1.13", + "version": "7.1.14", "devDependencies": { "@tsconfig/node22": "catalog:", "@types/bun": "catalog:", @@ -216,7 +216,7 @@ }, "packages/kilo-telemetry": { "name": "@kilocode/kilo-telemetry", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "@kilocode/kilo-gateway": "workspace:*", "@opentelemetry/api": "1.9.0", @@ -236,7 +236,7 @@ }, "packages/kilo-ui": { "name": "@kilocode/kilo-ui", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "@kobalte/core": "0.13.11", "@opencode-ai/util": "workspace:*", @@ -271,7 +271,7 @@ }, "packages/kilo-vscode": { "name": "kilo-code", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "@anthropic-ai/sdk": "^0.39.0", "@kilocode/kilo-i18n": "workspace:*", @@ -324,7 +324,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "7.1.13", + "version": "7.1.14", "bin": { "kilo": "./bin/kilo", "kilocode": "./bin/kilo", @@ -446,7 +446,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "@kilocode/sdk": "workspace:*", "zod": "catalog:", @@ -460,14 +460,14 @@ }, "packages/script": { "name": "@opencode-ai/script", - "version": "7.1.13", + "version": "7.1.14", "devDependencies": { "@types/bun": "catalog:", }, }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "7.1.13", + "version": "7.1.14", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -478,7 +478,7 @@ }, "packages/storybook": { "name": "@opencode-ai/storybook", - "version": "7.1.13", + "version": "7.1.14", "devDependencies": { "@opencode-ai/ui": "workspace:*", "@solidjs/meta": "catalog:", @@ -501,7 +501,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -548,7 +548,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "7.1.13", + "version": "7.1.14", "dependencies": { "zod": "catalog:", }, diff --git a/package.json b/package.json index c501942aa0f..1f1d255436e 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,6 @@ "@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch", "ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch" }, - "version": "7.1.13", + "version": "7.1.14", "peerDependencies": {} } diff --git a/packages/app/package.json b/packages/app/package.json index a70f1d47fa6..b706664d2e2 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "7.1.13", + "version": "7.1.14", "description": "", "type": "module", "exports": { diff --git a/packages/desktop-electron/package.json b/packages/desktop-electron/package.json index 5cbdfb439f1..d476eed5774 100644 --- a/packages/desktop-electron/package.json +++ b/packages/desktop-electron/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop-electron", "private": true, - "version": "7.1.13", + "version": "7.1.14", "type": "module", "license": "MIT", "homepage": "https://opencode.ai", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 8e9efcbf626..fea11bbd376 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "7.1.13", + "version": "7.1.14", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index a5b7fe328d0..a2e26887e8f 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "kilo" name = "Kilo" description = "The open source coding agent." -version = "7.1.13" +version = "7.1.14" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/Kilo-Org/kilocode" @@ -11,26 +11,26 @@ name = "Kilo" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.13/opencode-darwin-arm64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.14/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.13/opencode-darwin-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.14/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.13/opencode-linux-arm64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.14/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.13/opencode-linux-x64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.14/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.13/opencode-windows-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.14/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/kilo-docs/package.json b/packages/kilo-docs/package.json index 8101d074b57..507632f9b21 100644 --- a/packages/kilo-docs/package.json +++ b/packages/kilo-docs/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-docs", - "version": "7.1.13", + "version": "7.1.14", "private": true, "scripts": { "dev": "next dev --webpack --port 3002", diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index 1d21915242a..b34e350a7e0 100644 --- a/packages/kilo-gateway/package.json +++ b/packages/kilo-gateway/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-gateway", - "version": "7.1.13", + "version": "7.1.14", "type": "module", "license": "MIT", "description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration", diff --git a/packages/kilo-i18n/package.json b/packages/kilo-i18n/package.json index 9f8c37ec7e9..cc1dacbca8f 100644 --- a/packages/kilo-i18n/package.json +++ b/packages/kilo-i18n/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-i18n", - "version": "7.1.13", + "version": "7.1.14", "type": "module", "license": "MIT", "description": "Kilo-specific i18n translations and overrides", diff --git a/packages/kilo-telemetry/package.json b/packages/kilo-telemetry/package.json index b6814c97573..60d157e58d5 100644 --- a/packages/kilo-telemetry/package.json +++ b/packages/kilo-telemetry/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-telemetry", - "version": "7.1.13", + "version": "7.1.14", "type": "module", "license": "MIT", "description": "Telemetry for Kilo CLI - PostHog analytics integration", diff --git a/packages/kilo-ui/package.json b/packages/kilo-ui/package.json index 3ed656d5c14..6e9a4bbd426 100644 --- a/packages/kilo-ui/package.json +++ b/packages/kilo-ui/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-ui", - "version": "7.1.13", + "version": "7.1.14", "type": "module", "license": "MIT", "exports": { diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index cb602918acc..bbb7e1c08ce 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -2,7 +2,7 @@ "name": "kilo-code", "displayName": "Kilo Code: AI Coding Agent, Copilot, and Autocomplete", "description": "Open Source AI coding agent that generates code from natural language, automates tasks, and runs terminal commands. Features inline autocomplete, browser automation, automated refactoring, and custom modes for planning, coding, and debugging. Supports 500+ AI models including Claude (Anthropic), Gemini, Grok, GPT, Codex and GLM.", - "version": "7.1.13", + "version": "7.1.14", "icon": "assets/icons/logo-outline-black.png", "galleryBanner": { "color": "#FFFFFF", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 0628c068c6a..44b1b555bab 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.1.13", + "version": "7.1.14", "name": "@kilocode/cli", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 40896bd3421..b7e748393d4 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/plugin", - "version": "7.1.13", + "version": "7.1.14", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/script/package.json b/packages/script/package.json index d6a3b986d13..ce8a5483a21 100644 --- a/packages/script/package.json +++ b/packages/script/package.json @@ -8,7 +8,7 @@ "exports": { ".": "./src/index.ts" }, - "version": "7.1.13", + "version": "7.1.14", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index ff81ac84c3c..eb207df942a 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/sdk", - "version": "7.1.13", + "version": "7.1.14", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/storybook/package.json b/packages/storybook/package.json index ada3ffb8c60..13eaaaaca89 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -26,7 +26,7 @@ "typescript": "catalog:", "vite": "catalog:" }, - "version": "7.1.13", + "version": "7.1.14", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/ui/package.json b/packages/ui/package.json index 0ae1a67d433..7fe097b179d 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "7.1.13", + "version": "7.1.14", "type": "module", "license": "MIT", "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index 374a644b191..daba9965d91 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "7.1.13", + "version": "7.1.14", "private": true, "type": "module", "license": "MIT", diff --git a/script/upstream/package.json b/script/upstream/package.json index f5e543fd49e..6ab5a1363ea 100644 --- a/script/upstream/package.json +++ b/script/upstream/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/upstream-merge", - "version": "7.1.13", + "version": "7.1.14", "private": true, "type": "module", "description": "Scripts for automating upstream opencode merges into Kilo", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 88f7571c831..d0ab327489c 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "7.1.13", + "version": "7.1.14", "publisher": "sst-dev", "repository": { "type": "git", From cbae0ece8f0226963c91dfd4793e8465a0bc5712 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 11:00:54 +0000 Subject: [PATCH 236/261] fix(vscode): publish extension as release instead of pre-release Remove --pre-release flag from vsce package and vsce publish commands. Previously the VS Code Marketplace received a pre-release VSIX while Open VSX received a production VSIX. Now both receive the same production VSIX built without --pre-release, eliminating the separate out/prod/ directory. --- packages/kilo-vscode/script/build.ts | 13 ++----------- packages/kilo-vscode/script/publish.ts | 8 +++----- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/packages/kilo-vscode/script/build.ts b/packages/kilo-vscode/script/build.ts index 86eb685dcbc..ee00dbb778e 100644 --- a/packages/kilo-vscode/script/build.ts +++ b/packages/kilo-vscode/script/build.ts @@ -36,10 +36,9 @@ const targets = [ const binDir = join(import.meta.dir, "..", "bin") const distDir = join(import.meta.dir, "..", "dist") const outDir = join(import.meta.dir, "..", "out") -const outDirProd = join(import.meta.dir, "..", "out", "prod") console.log("\n🧹 Cleaning up directories...") -for (const dir of [binDir, distDir, outDir, outDirProd]) { +for (const dir of [binDir, distDir, outDir]) { if (existsSync(dir)) { rmSync(dir, { recursive: true, force: true }) console.log(` ✓ Cleaned ${dir}`) @@ -48,7 +47,6 @@ for (const dir of [binDir, distDir, outDir, outDirProd]) { mkdirSync(outDir, { recursive: true }) mkdirSync(distDir, { recursive: true }) -mkdirSync(outDirProd, { recursive: true }) console.log("\n🔄 Rebuilding SDK types (ensures dist/ is in sync with server API)...") await $`bun run --cwd ${join(import.meta.dir, "..", "..", "sdk", "js")} build` @@ -84,18 +82,11 @@ for (const config of targets) { console.log(` 📦 Packaging .vsix for ${config.target}...`) const vsixPath = join(outDir, `kilo-vscode-${config.target}.vsix`) - await $`vsce package --pre-release --no-dependencies --skip-license --target ${config.target} -o ${vsixPath}`.env({ + await $`vsce package --no-dependencies --skip-license --target ${config.target} -o ${vsixPath}`.env({ ...process.env, npm_config_ignore_scripts: "true", }) console.log(` ✅ Created ${vsixPath}`) - - const prodVsixPath = join(outDirProd, `kilo-vscode-${config.target}.vsix`) - await $`vsce package --no-dependencies --skip-license --target ${config.target} -o ${prodVsixPath}`.env({ - ...process.env, - npm_config_ignore_scripts: "true", - }) - console.log(` ✅ Created ${prodVsixPath}`) } console.log("\n✨ All VSIX packages built successfully!") diff --git a/packages/kilo-vscode/script/publish.ts b/packages/kilo-vscode/script/publish.ts index 3a526e86d5a..ef891606266 100755 --- a/packages/kilo-vscode/script/publish.ts +++ b/packages/kilo-vscode/script/publish.ts @@ -7,7 +7,6 @@ import { Script } from "@opencode-ai/script" console.log(`Publishing VSCode extension for release: v${Script.version}`) const outDir = process.env.VSIX_DIR || join(import.meta.dir, "..", "out") -const outDirProd = join(outDir, "prod") console.log(`Using VSIX directory: ${outDir}`) @@ -40,13 +39,12 @@ console.log(`\nFound ${vsixFiles.length} VSIX files`) for (const target of targets) { const vsixPath = join(outDir, `kilo-vscode-${target}.vsix`) console.log(`\n🚀 Publishing ${target} to VS Code Marketplace...`) - await $`vsce publish --pre-release --packagePath ${vsixPath}` + await $`vsce publish --packagePath ${vsixPath}` console.log(` ✅ Published ${target} to VS Code Marketplace`) - const prodVsixPath = join(outDirProd, `kilo-vscode-${target}.vsix`) console.log(`\n📤 Publishing ${target} to Open VSX...`) - await $`npx ovsx publish --pat ${process.env.OPENVSX_TOKEN} --packagePath ${prodVsixPath}` - console.log(` ✅ Published Prod ${target} to Open VSX`) + await $`npx ovsx publish --pat ${process.env.OPENVSX_TOKEN} --packagePath ${vsixPath}` + console.log(` ✅ Published ${target} to Open VSX`) } if (Script.release) { From 098b8c3971d6a5ed9285d5f80fba65e2e20beddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Wed, 1 Apr 2026 08:06:02 -0300 Subject: [PATCH 237/261] fix(vscode): drain pending permissions and questions before config save MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When saving settings, the CLI backend's Config.updateGlobal() triggers Instance.disposeAll(), which silently orphans pending Permission and Question Promises — permanently freezing active sessions. Before calling config.update(), reject all pending permissions and questions via the SDK so the CLI-side Promises resolve cleanly. After the update, post a clearPendingPrompts message to the webview to clear any stale permission/question UI state. Closes #7673 --- packages/kilo-vscode/src/KiloProvider.ts | 35 +++++++++++++++++-- .../webview-ui/src/context/session.tsx | 6 ++++ .../webview-ui/src/types/messages.ts | 5 +++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index c6e1a046da1..aa68fd9448d 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -65,6 +65,7 @@ import { import { handlePermissionResponse, fetchAndSendPendingPermissions, + recoveryDirs, type PermissionContext, } from "./kilo-provider/handlers/permission-handler" import { handleQuestionReply, handleQuestionReject } from "./kilo-provider/handlers/question" @@ -1988,6 +1989,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper // races with the async config.update() write on the CLI backend). this.pending++ try { + // Reject all pending permissions and questions so their CLI-side + // Promises resolve before disposeAll() wipes Instance state. + await this.drainPendingPrompts() + await this.client.global.config.update({ config: partial }, { throwOnError: true }) // Re-fetch the full merged config (global + project + all layers) so the @@ -2000,6 +2005,11 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.cachedConfigMessage = { type: "configLoaded", config: merged } this.postMessage({ type: "configUpdated", config: merged }) + // Clear stale permission/question UI after the dispose cycle. + // The drain above resolved them on the CLI side, but SSE events + // may race with the dispose — this ensures the webview is clean. + this.postMessage({ type: "clearPendingPrompts" }) + if (refreshProviders) { await this.fetchAndSendProviders() } @@ -2020,10 +2030,29 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper } /** - * Handle sending a message from the webview. - * Uses promptAsync (fire-and-forget) — the server queues concurrent prompts - * internally, so the client doesn't need to block on busy sessions. + * Reject all pending permission requests and questions across all tracked + * directories. Called before config saves that trigger Instance.disposeAll() + * on the CLI backend, to prevent orphaned Promises from freezing sessions. */ + private async drainPendingPrompts(): Promise { + if (!this.client) return + const dirs = recoveryDirs(this.getWorkspaceDirectory(), this.sessionDirectories) + for (const dir of dirs) { + const { data: perms } = await this.client.permission.list({ directory: dir }) + if (perms) { + for (const perm of perms) { + await this.client.permission.reply({ requestID: perm.id, reply: "reject", directory: dir }) + } + } + const { data: qs } = await this.client.question.list({ directory: dir }) + if (qs) { + for (const q of qs) { + await this.client.question.reject({ requestID: q.id, directory: dir }) + } + } + } + } + /** * Ensure a session exists, creating one if needed. Returns the resolved * session ID and workspace directory, or undefined when the client is diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index e3ebadb7004..1c120b89c7e 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -638,6 +638,12 @@ export const SessionProvider: ParentComponent = (props) => { handleQuestionError(message.requestID) break + case "clearPendingPrompts": + setPermissions([]) + setQuestions([]) + setRespondingPermissions(new Set()) + break + case "sessionsLoaded": handleSessionsLoaded(message.sessions) break diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index 037b8d2ead4..29f5ff081dd 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -1152,6 +1152,10 @@ export interface DiffViewerLoadingMessage { loading: boolean } +export interface ClearPendingPromptsMessage { + type: "clearPendingPrompts" +} + // ============================================ // Marketplace Messages // ============================================ @@ -1338,6 +1342,7 @@ export type ExtensionMessage = | ContinueInWorktreeProgressMessage | WorktreeStatsLoadedMessage | McpStatusLoadedMessage + | ClearPendingPromptsMessage // ============================================ // Messages FROM webview TO extension From ba2ecf13f2b9d955ef5c81f395d8379aa7da7169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Wed, 1 Apr 2026 08:40:20 -0300 Subject: [PATCH 238/261] =?UTF-8?q?fix(vscode):=20address=20PR=20review=20?= =?UTF-8?q?=E2=80=94=20broadcast=20drain=20across=20all=20providers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move drainPendingPrompts() to KiloConnectionService so it covers all KiloProvider instances (sidebar, settings panel, Agent Manager). Each provider registers a directory callback so the drain covers worktree directories, not just the root workspace. Drain failures now throw to abort the config save. clearPendingPrompts is broadcast to all webviews via the shared listener pattern. --- packages/kilo-vscode/src/KiloProvider.ts | 53 ++++++-------- .../cli-backend/connection-service.ts | 70 +++++++++++++++++++ .../kilo-provider-session-refresh.test.ts | 2 + 3 files changed, 92 insertions(+), 33 deletions(-) diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index aa68fd9448d..80348a3c9a3 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -65,7 +65,6 @@ import { import { handlePermissionResponse, fetchAndSendPendingPermissions, - recoveryDirs, type PermissionContext, } from "./kilo-provider/handlers/permission-handler" import { handleQuestionReply, handleQuestionReject } from "./kilo-provider/handlers/question" @@ -145,6 +144,8 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper private unsubscribeLanguageChange: (() => void) | null = null private unsubscribeProfileChange: (() => void) | null = null private unsubscribeMigrationComplete: (() => void) | null = null // legacy-migration + private unsubscribeClearPendingPrompts: (() => void) | null = null + private unsubscribeDirectoryProvider: (() => void) | null = null private initConnectionPromise: Promise | null = null private webviewMessageDisposable: vscode.Disposable | null = null @@ -956,6 +957,8 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.unsubscribeNotificationDismiss?.() this.unsubscribeLanguageChange?.() this.unsubscribeProfileChange?.() + this.unsubscribeClearPendingPrompts?.() + this.unsubscribeDirectoryProvider?.() try { const workspaceDir = this.getWorkspaceDirectory() @@ -1034,6 +1037,16 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper }) // legacy-migration end + // Subscribe to clear-pending-prompts broadcast (fired after config save drains prompts) + this.unsubscribeClearPendingPrompts = this.connectionService.onClearPendingPrompts(() => { + this.postMessage({ type: "clearPendingPrompts" }) + }) + + // Register this provider's directories so drainPendingPrompts() covers all instances + this.unsubscribeDirectoryProvider = this.connectionService.registerDirectoryProvider(() => { + return [this.getWorkspaceDirectory(), ...this.sessionDirectories.values()] + }) + // Get current state and push to webview const serverInfo = this.connectionService.getServerInfo() this.connectionState = this.connectionService.getConnectionState() @@ -1989,9 +2002,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper // races with the async config.update() write on the CLI backend). this.pending++ try { - // Reject all pending permissions and questions so their CLI-side - // Promises resolve before disposeAll() wipes Instance state. - await this.drainPendingPrompts() + // Reject all pending permissions and questions across every provider + // so their CLI-side Promises resolve before disposeAll() wipes + // Instance state. Throws on failure to abort the config save. + await this.connectionService.drainPendingPrompts() await this.client.global.config.update({ config: partial }, { throwOnError: true }) @@ -2005,11 +2019,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.cachedConfigMessage = { type: "configLoaded", config: merged } this.postMessage({ type: "configUpdated", config: merged }) - // Clear stale permission/question UI after the dispose cycle. - // The drain above resolved them on the CLI side, but SSE events - // may race with the dispose — this ensures the webview is clean. - this.postMessage({ type: "clearPendingPrompts" }) - if (refreshProviders) { await this.fetchAndSendProviders() } @@ -2029,30 +2038,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper } } - /** - * Reject all pending permission requests and questions across all tracked - * directories. Called before config saves that trigger Instance.disposeAll() - * on the CLI backend, to prevent orphaned Promises from freezing sessions. - */ - private async drainPendingPrompts(): Promise { - if (!this.client) return - const dirs = recoveryDirs(this.getWorkspaceDirectory(), this.sessionDirectories) - for (const dir of dirs) { - const { data: perms } = await this.client.permission.list({ directory: dir }) - if (perms) { - for (const perm of perms) { - await this.client.permission.reply({ requestID: perm.id, reply: "reject", directory: dir }) - } - } - const { data: qs } = await this.client.question.list({ directory: dir }) - if (qs) { - for (const q of qs) { - await this.client.question.reject({ requestID: q.id, directory: dir }) - } - } - } - } - /** * Ensure a session exists, creating one if needed. Returns the resolved * session ID and workspace directory, or undefined when the client is @@ -2890,6 +2875,8 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.unsubscribeLanguageChange?.() this.unsubscribeProfileChange?.() this.unsubscribeMigrationComplete?.() + this.unsubscribeClearPendingPrompts?.() + this.unsubscribeDirectoryProvider?.() this.webviewMessageDisposable?.dispose() this.trackedSessionIds.clear() this.syncedChildSessions.clear() 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 abee02099a5..3d94d4d3e3a 100644 --- a/packages/kilo-vscode/src/services/cli-backend/connection-service.ts +++ b/packages/kilo-vscode/src/services/cli-backend/connection-service.ts @@ -13,6 +13,8 @@ type NotificationDismissListener = (notificationId: string) => void type LanguageChangeListener = (locale: string) => void type ProfileChangeListener = (data: unknown) => void type MigrationCompleteListener = () => void +type ClearPendingPromptsListener = () => void +type DirectoryProvider = () => string[] // Poll /global/health at the same interval as packages/app/src/context/server.tsx. // This provides a second detection channel for server death independent of the SSE heartbeat. @@ -38,6 +40,8 @@ export class KiloConnectionService { private readonly languageChangeListeners: Set = new Set() private readonly profileChangeListeners: Set = new Set() private readonly migrationCompleteListeners: Set = new Set() + private readonly clearPendingPromptsListeners: Set = new Set() + private readonly directoryProviders: Set = new Set() /** * Shared mapping used to resolve session scope for events that don't reliably include a sessionID. @@ -228,6 +232,70 @@ export class KiloConnectionService { } } + /** + * Subscribe to clear-pending-prompts broadcast. Returns unsubscribe function. + * Fired after a config save drains all pending permissions/questions so each + * webview can clear stale prompt UI. + */ + onClearPendingPrompts(listener: ClearPendingPromptsListener): () => void { + this.clearPendingPromptsListeners.add(listener) + return () => { + this.clearPendingPromptsListeners.delete(listener) + } + } + + /** + * Register a callback that returns workspace directories tracked by a + * KiloProvider (root + worktree dirs). Used by drainPendingPrompts() to + * cover all active Instance directories across every provider. + */ + registerDirectoryProvider(provider: DirectoryProvider): () => void { + this.directoryProviders.add(provider) + return () => { + this.directoryProviders.delete(provider) + } + } + + /** + * Reject all pending permission requests and questions across every + * directory known to any KiloProvider. Must be called before operations + * that trigger Instance.disposeAll() (e.g. config save) to prevent + * orphaned Promises from freezing sessions. + * + * Throws if any list/reject call fails so callers can abort the + * destructive operation. + */ + async drainPendingPrompts(): Promise { + if (!this.client) return + const dirs = new Set() + for (const provider of this.directoryProviders) { + for (const dir of provider()) { + dirs.add(dir) + } + } + for (const dir of dirs) { + const { data: perms, error: permsErr } = await this.client.permission.list({ directory: dir }) + if (permsErr) throw new Error(`Failed to list permissions for ${dir}: ${String(permsErr)}`) + if (perms) { + for (const perm of perms) { + const { error } = await this.client.permission.reply({ requestID: perm.id, reply: "reject", directory: dir }) + if (error) throw new Error(`Failed to reject permission ${perm.id}: ${String(error)}`) + } + } + const { data: qs, error: qsErr } = await this.client.question.list({ directory: dir }) + if (qsErr) throw new Error(`Failed to list questions for ${dir}: ${String(qsErr)}`) + if (qs) { + for (const q of qs) { + const { error } = await this.client.question.reject({ requestID: q.id, directory: dir }) + if (error) throw new Error(`Failed to reject question ${q.id}: ${String(error)}`) + } + } + } + for (const listener of this.clearPendingPromptsListeners) { + listener() + } + } + /** * Subscribe to connection state changes. Returns unsubscribe function. */ @@ -250,6 +318,8 @@ export class KiloConnectionService { this.notificationDismissListeners.clear() this.profileChangeListeners.clear() this.migrationCompleteListeners.clear() + this.clearPendingPromptsListeners.clear() + this.directoryProviders.clear() this.messageSessionIdsByMessageId.clear() this.client = null this.sseClient = null 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 d74842073d3..d201bbf9816 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 @@ -81,6 +81,8 @@ function createConnection(client: ReturnType) { onLanguageChanged: () => () => undefined, onProfileChanged: () => () => undefined, onMigrationComplete: () => () => undefined, + onClearPendingPrompts: () => () => undefined, + registerDirectoryProvider: () => () => undefined, getServerInfo: () => ({ port: 12345 }), getConnectionState: () => "connected" as const, resolveEventSessionId: () => undefined, From a2fc2ad93634b01651a337c9e8aff3eba5ed8f04 Mon Sep 17 00:00:00 2001 From: Marius Date: Wed, 1 Apr 2026 14:02:47 +0200 Subject: [PATCH 239/261] fix: keep plan follow-up sessions in the same worktree (#7945) * fix: keep plan follow-up sessions in the same worktree Route follow-up question replies by the owning session and create child implementation sessions from the planning session directory so "Start new session" stays visible and runs in the right worktree. Refs #6339 * fix: keep worktree follow-up sessions reloadable Adopt backend-created worktree sessions by normalized directory matching and keep plan follow-up sessions as roots so Agent Manager still restores them after reload.\n\nRefs #6339 * fix(vscode): track plan follow-up sessions in the sidebar Record pending "Start new session" replies in single-session providers so the follow-up session.created event can be adopted and opened in the sidebar and regular tabs, while Agent Manager keeps using its own worktree adoption path.\n\nRefs #6339 * fix(vscode): forward pending follow-up session events Allow pending plan follow-up session.created events through the KiloProvider SSE filter so sidebar and tab providers can adopt and open them before the new session is tracked.\n\nRefs #6339 * fix(agent-manager): open tab for adopted follow-up sessions Navigate to the correct worktree or add a local tab when Agent Manager adopts a backend-created follow-up session, matching the existing sessionForked behavior.\n\nRefs #6339 * refactor(vscode): unify follow-up session adoption across all providers Remove the separate adopt-session mechanism for Agent Manager and use the same KiloProvider follow-up path that sidebar and tabs use. The sessionCreated webview handler now works regardless of the current sidebar selection, so follow-up sessions appear as local tabs everywhere.\n\nRefs #6339 * test: align followup test with parentID field from main --- packages/kilo-vscode/src/KiloProvider.ts | 49 ++++++- .../src/agent-manager/AgentManagerProvider.ts | 3 +- .../src/kilo-provider/followup-session.ts | 25 ++++ .../src/kilo-provider/handlers/question.ts | 32 +++-- .../tests/unit/followup-session.test.ts | 38 ++++++ .../tests/unit/kilo-provider-followup.test.ts | 129 ++++++++++++++++++ .../tests/unit/question-handler.test.ts | 104 ++++++++++++++ .../agent-manager/AgentManagerApp.tsx | 30 ++-- .../webview-ui/src/context/session.tsx | 6 + .../webview-ui/src/types/messages.ts | 2 + .../opencode/src/kilocode/plan-followup.ts | 46 ++++--- .../test/kilocode/plan-followup.test.ts | 65 ++++++++- 12 files changed, 485 insertions(+), 44 deletions(-) create mode 100644 packages/kilo-vscode/src/kilo-provider/followup-session.ts create mode 100644 packages/kilo-vscode/tests/unit/followup-session.test.ts create mode 100644 packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts create mode 100644 packages/kilo-vscode/tests/unit/question-handler.test.ts diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index c6e1a046da1..b101405c78d 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -39,6 +39,7 @@ import { MarketplaceService } from "./services/marketplace" import { resolveProjectDirectory } from "./project-directory" import { getBusySessionCount, seedSessionStatuses } from "./session-status" import { slimPart, slimParts } from "./kilo-provider/slim-metadata" +import { matchFollowup, recordFollowup, type Followup } from "./kilo-provider/followup-session" // legacy-migration start import { checkAndShowMigrationWizard, @@ -154,6 +155,8 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper private chatAutocomplete: ChatTextAreaAutocomplete | null = null private projectDirectory: string | null | undefined private slimEditMetadata = true + + private pendingFollowup: Followup | null = null /** Worktree diff stats poller for the sidebar badge — reuses GitStatsPoller (local stats only) */ private statsPoller: GitStatsPoller | null = null private cachedStats: unknown = null @@ -175,6 +178,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper ) { this.projectDirectory = options?.projectDirectory this.slimEditMetadata = options?.slimEditMetadata ?? true + TelemetryProxy.getInstance().setProvider(this) } @@ -675,10 +679,14 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper break case "questionReply": - await handleQuestionReply(this.questionCtx, message.requestID, message.answers) + this.noteFollowup(message.answers, message.sessionID) + if (!(await handleQuestionReply(this.questionCtx, message.requestID, message.answers, message.sessionID))) { + this.pendingFollowup = null + } break case "questionReject": - await handleQuestionReject(this.questionCtx, message.requestID) + this.pendingFollowup = null + await handleQuestionReject(this.questionCtx, message.requestID, message.sessionID) break case "requestConfig": this.fetchAndSendConfig().catch((e) => console.error("[Kilo New] fetchAndSendConfig failed:", e)) @@ -972,6 +980,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper return event.type !== "message.part.updated" && event.type !== "message.part.delta" } + if (event.type === "session.created" && this.matchesPendingFollowup(event.properties.info)) { + return true + } + // session.status must always pass through — even for sessions not tracked by this // KiloProvider instance. The Settings panel is a separate provider with no tracked // sessions, but it needs session.status to populate sessionStatusMap and allStatusMap @@ -2515,6 +2527,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper } // Extract sessionID from the event + if (event.type === "session.created" && this.adoptPendingFollowup(event.properties.info)) { + return + } + const sessionID = this.connectionService.resolveEventSessionId(event) // Events without sessionID (server.connected, server.heartbeat) → always forward @@ -2773,6 +2789,35 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.sessionDirectories.set(sessionId, dir) } + private noteFollowup(answers: string[][], sessionID?: string) { + const dir = this.getWorkspaceDirectory(sessionID) + this.pendingFollowup = recordFollowup({ answers, dir, now: Date.now() }) ?? null + } + + private matchesPendingFollowup(session: Session) { + return matchFollowup({ pending: this.pendingFollowup, dir: session.directory, now: Date.now() }) + } + + private adoptPendingFollowup(session: Session) { + const now = Date.now() + const match = this.matchesPendingFollowup(session) + if (!match) { + if ( + this.pendingFollowup && + !matchFollowup({ pending: this.pendingFollowup, dir: this.pendingFollowup.dir, now }) + ) { + this.pendingFollowup = null + } + return false + } + + this.pendingFollowup = null + this.trackDirectory(session.id, session.directory) + this.registerSession(session) + void this.handleLoadMessages(session.id) + return true + } + private getProjectDirectory(sessionId?: string): string | undefined { return resolveProjectDirectory(this.projectDirectory, () => this.getWorkspaceDirectory(sessionId)) } diff --git a/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts b/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts index b463e7682da..be86c3e14bb 100644 --- a/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts +++ b/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts @@ -19,6 +19,7 @@ import { createTerminalHost } from "./terminal-host" import { executeVscodeTask } from "./task-runner" import { forkSession } from "./fork-session" import { continueInWorktree } from "./continue-in-worktree" + import { shouldStopDiffPolling } from "./delete-worktree" import { buildKeybindingMap } from "./format-keybinding" import { resolveVersionModels, buildInitialMessages, type CreatedVersion } from "./multi-version" @@ -58,11 +59,11 @@ export class AgentManagerProvider implements Disposable { private cachedWorktreeStats: AgentManagerOutMessage | undefined private cachedLocalStats: AgentManagerOutMessage | undefined private applyingWorktreeId: string | undefined + /** Session ID most recently loaded via a `loadMessages` message from the webview. * Updated synchronously — unlike the session provider's currentSession which depends on * an async `session.get` round-trip and can be stale during rapid tab switches. */ private activeSessionId: string | undefined - constructor( private readonly host: Host, private readonly connectionService: KiloConnectionService, diff --git a/packages/kilo-vscode/src/kilo-provider/followup-session.ts b/packages/kilo-vscode/src/kilo-provider/followup-session.ts new file mode 100644 index 00000000000..3b220d44926 --- /dev/null +++ b/packages/kilo-vscode/src/kilo-provider/followup-session.ts @@ -0,0 +1,25 @@ +import { normalizePath } from "../agent-manager/git-import" + +const TTL = 30_000 +const LABEL = "Start new session" + +export interface Followup { + dir: string + time: number +} + +export function recordFollowup(input: { answers: string[][]; dir: string; now: number }): Followup | undefined { + const answer = input.answers[0]?.[0]?.trim() + if (answer !== LABEL) return + return { + dir: input.dir, + time: input.now, + } +} + +export function matchFollowup(input: { pending: Followup | null; dir: string; now: number }): boolean { + const item = input.pending + if (!item) return false + if (input.now - item.time > TTL) return false + return normalizePath(item.dir) === normalizePath(input.dir) +} diff --git a/packages/kilo-vscode/src/kilo-provider/handlers/question.ts b/packages/kilo-vscode/src/kilo-provider/handlers/question.ts index 53e722df50c..2279088c5e1 100644 --- a/packages/kilo-vscode/src/kilo-provider/handlers/question.ts +++ b/packages/kilo-vscode/src/kilo-provider/handlers/question.ts @@ -15,37 +15,51 @@ interface QuestionContext { } /** Handle question reply from the webview. */ -export async function handleQuestionReply(ctx: QuestionContext, requestID: string, answers: string[][]): Promise { +export async function handleQuestionReply( + ctx: QuestionContext, + requestID: string, + answers: string[][], + sessionID?: string, +): Promise { if (!ctx.client) { ctx.postMessage({ type: "questionError", requestID }) - return + return false } + const sid = sessionID ?? ctx.currentSessionId + try { await ctx.client.question.reply( - { requestID, answers, directory: ctx.getWorkspaceDirectory(ctx.currentSessionId) }, + { requestID, answers, directory: ctx.getWorkspaceDirectory(sid) }, { throwOnError: true }, ) + return true } catch (error) { console.error("[Kilo New] KiloProvider: Failed to reply to question:", error) ctx.postMessage({ type: "questionError", requestID }) + return false } } /** Handle question reject (dismiss) from the webview. */ -export async function handleQuestionReject(ctx: QuestionContext, requestID: string): Promise { +export async function handleQuestionReject( + ctx: QuestionContext, + requestID: string, + sessionID?: string, +): Promise { if (!ctx.client) { ctx.postMessage({ type: "questionError", requestID }) - return + return false } + const sid = sessionID ?? ctx.currentSessionId + try { - await ctx.client.question.reject( - { requestID, directory: ctx.getWorkspaceDirectory(ctx.currentSessionId) }, - { throwOnError: true }, - ) + await ctx.client.question.reject({ requestID, directory: ctx.getWorkspaceDirectory(sid) }, { throwOnError: true }) + return true } catch (error) { console.error("[Kilo New] KiloProvider: Failed to reject question:", error) ctx.postMessage({ type: "questionError", requestID }) + return false } } diff --git a/packages/kilo-vscode/tests/unit/followup-session.test.ts b/packages/kilo-vscode/tests/unit/followup-session.test.ts new file mode 100644 index 00000000000..bca8e448c13 --- /dev/null +++ b/packages/kilo-vscode/tests/unit/followup-session.test.ts @@ -0,0 +1,38 @@ +import { describe, expect, it } from "bun:test" +import { matchFollowup, recordFollowup } from "../../src/kilo-provider/followup-session" + +describe("followup-session", () => { + it("records a pending follow-up for Start new session replies", () => { + const pending = recordFollowup({ + answers: [["Start new session"]], + dir: "/repo", + now: 1, + }) + + expect(pending).toEqual({ + dir: "/repo", + time: 1, + }) + }) + + it("ignores other question replies", () => { + const pending = recordFollowup({ + answers: [["Continue here"]], + dir: "/repo", + now: 1, + }) + + expect(pending).toBeUndefined() + }) + + it("matches pending follow-ups by normalized directory before expiry", () => { + const pending = { + dir: "c:/repo/.kilo/worktrees/feature", + time: 1, + } + + expect(matchFollowup({ pending, dir: "C:\\repo\\.kilo\\worktrees\\feature\\", now: 2 })).toBe(true) + expect(matchFollowup({ pending, dir: "c:/repo/.kilo/worktrees/other", now: 2 })).toBe(false) + expect(matchFollowup({ pending, dir: "c:/repo/.kilo/worktrees/feature", now: 30_002 })).toBe(false) + }) +}) diff --git a/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts b/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts new file mode 100644 index 00000000000..cab3ed6de02 --- /dev/null +++ b/packages/kilo-vscode/tests/unit/kilo-provider-followup.test.ts @@ -0,0 +1,129 @@ +import { describe, expect, it } from "bun:test" +import type { Event, Session } from "@kilocode/sdk/v2/client" + +// vscode mock is provided by the shared preload (tests/setup/vscode-mock.ts) +const { KiloProvider } = await import("../../src/KiloProvider") + +type Internals = { + webview: { postMessage: (message: unknown) => Promise } | null + trackedSessionIds: Set + currentSession: Session | null + pendingFollowup: { dir: string; time: number } | null + handleLoadMessages: (sessionID: string) => Promise + initializeConnection: () => Promise + syncWebviewState: () => Promise + flushPendingSessionRefresh: () => Promise + fetchAndSendProviders: () => Promise + fetchAndSendAgents: () => Promise + fetchAndSendSkills: () => Promise + fetchAndSendCommands: () => Promise + fetchAndSendConfig: () => Promise + fetchAndSendNotifications: () => Promise + seedSessionStatusMap: () => Promise + sendNotificationSettings: () => void + startStatsPolling: () => void +} + +function created(input: { id: string; directory: string }): Event { + return { + type: "session.created", + properties: { + info: { + id: input.id, + slug: `${input.id}-slug`, + projectID: "project-1", + directory: input.directory, + title: "Session", + version: "1", + time: { created: 1, updated: 1 }, + }, + }, + } as Event +} + +function connection() { + let filter: ((event: Event) => boolean) | undefined + let listener: ((event: Event) => void) | undefined + + return { + emit(event: Event) { + if (!filter || !listener) throw new Error("expected SSE subscription") + if (!filter(event)) return + listener(event) + }, + connect: async () => {}, + getClient: () => ({}) as never, + onEventFiltered: (next: (event: Event) => boolean, cb: (event: Event) => void) => { + filter = next + listener = cb + return () => undefined + }, + onStateChange: () => () => undefined, + onNotificationDismissed: () => () => undefined, + onLanguageChanged: () => () => undefined, + onProfileChanged: () => () => undefined, + onMigrationComplete: () => () => undefined, + getServerInfo: () => ({ port: 12345 }), + getConnectionState: () => "connected" as const, + resolveEventSessionId: (event: Event) => (event.type === "session.created" ? event.properties.info.id : undefined), + recordMessageSessionId: () => undefined, + notifyNotificationDismissed: () => undefined, + } +} + +describe("KiloProvider follow-up sessions", () => { + it("adopts pending follow-up sessions for single-session views", async () => { + const service = connection() + const provider = new KiloProvider({} as never, service as never) + const internal = provider as unknown as Internals + const sent: unknown[] = [] + const loaded: string[] = [] + + internal.webview = { + postMessage: async (message: unknown) => { + sent.push(message) + return true + }, + } + internal.syncWebviewState = async () => {} + internal.flushPendingSessionRefresh = async () => {} + internal.fetchAndSendProviders = async () => {} + internal.fetchAndSendAgents = async () => {} + internal.fetchAndSendSkills = async () => {} + internal.fetchAndSendCommands = async () => {} + internal.fetchAndSendConfig = async () => {} + internal.fetchAndSendNotifications = async () => {} + internal.seedSessionStatusMap = async () => {} + internal.sendNotificationSettings = () => {} + internal.startStatsPolling = () => {} + + await internal.initializeConnection() + sent.length = 0 + + internal.pendingFollowup = { dir: "/repo", time: Date.now() } + internal.handleLoadMessages = async (sessionID: string) => { + loaded.push(sessionID) + } + + service.emit(created({ id: "ses-followup", directory: "/repo" })) + await Promise.resolve() + + expect(internal.currentSession?.id).toBe("ses-followup") + expect(internal.trackedSessionIds.has("ses-followup")).toBe(true) + expect(loaded).toEqual(["ses-followup"]) + expect(sent).toEqual([ + { + type: "sessionCreated", + session: { + id: "ses-followup", + title: "Session", + createdAt: new Date(1).toISOString(), + updatedAt: new Date(1).toISOString(), + parentID: null, + revert: null, + summary: null, + }, + }, + ]) + }) +}) diff --git a/packages/kilo-vscode/tests/unit/question-handler.test.ts b/packages/kilo-vscode/tests/unit/question-handler.test.ts new file mode 100644 index 00000000000..3353d6586a8 --- /dev/null +++ b/packages/kilo-vscode/tests/unit/question-handler.test.ts @@ -0,0 +1,104 @@ +import { describe, expect, it } from "bun:test" +import type { KiloClient } from "@kilocode/sdk/v2/client" +import { handleQuestionReject, handleQuestionReply } from "../../src/kilo-provider/handlers/question" + +describe("question handlers", () => { + it("routes replies using the question session when provided", async () => { + const calls: Array> = [] + const client = { + question: { + reply: async (input: Record) => { + calls.push(input) + return true + }, + reject: async () => true, + }, + } as unknown as KiloClient + + const ok = await handleQuestionReply( + { + client, + currentSessionId: "ses-root", + postMessage() {}, + getWorkspaceDirectory(sessionId) { + return sessionId ? `/repo/${sessionId}` : "/repo" + }, + }, + "req-1", + [["Start new session"]], + "ses-worktree", + ) + + expect(ok).toBe(true) + expect(calls).toEqual([ + { + requestID: "req-1", + answers: [["Start new session"]], + directory: "/repo/ses-worktree", + }, + ]) + }) + + it("falls back to the current session when no question session is provided", async () => { + const calls: Array> = [] + const client = { + question: { + reply: async (input: Record) => { + calls.push(input) + return true + }, + reject: async () => true, + }, + } as unknown as KiloClient + + const ok = await handleQuestionReply( + { + client, + currentSessionId: "ses-root", + postMessage() {}, + getWorkspaceDirectory(sessionId) { + return sessionId ? `/repo/${sessionId}` : "/repo" + }, + }, + "req-2", + [["Continue here"]], + ) + + expect(ok).toBe(true) + expect(calls[0]?.directory).toBe("/repo/ses-root") + }) + + it("routes rejects using the question session when provided", async () => { + const calls: Array> = [] + const client = { + question: { + reply: async () => true, + reject: async (input: Record) => { + calls.push(input) + return true + }, + }, + } as unknown as KiloClient + + const ok = await handleQuestionReject( + { + client, + currentSessionId: "ses-root", + postMessage() {}, + getWorkspaceDirectory(sessionId) { + return sessionId ? `/repo/${sessionId}` : "/repo" + }, + }, + "req-3", + "ses-worktree", + ) + + expect(ok).toBe(true) + expect(calls).toEqual([ + { + requestID: "req-3", + directory: "/repo/ses-worktree", + }, + ]) + }) +}) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx index 08917a8ecc4..d26b0cf7cb1 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx @@ -1084,20 +1084,24 @@ const AgentManagerContent: Component = () => { } window.addEventListener("focus", onWindowFocus) - // When a session is created while on local, replace the current pending tab with the real session. - // Guard against duplicate sessionCreated events (HTTP response + SSE can both fire). + // When a session is created, add it as a local tab. This handles both direct + // creation from the prompt input and backend-created follow-up sessions (plan + // follow-up "Start new session"). Guard against duplicates (HTTP + SSE can both fire). const unsubCreate = vscode.onMessage((msg) => { - if (msg.type === "sessionCreated" && selection() === LOCAL) { - const created = msg as { type: string; session: { id: string } } - if (localSessionIDs().includes(created.session.id)) return - const pending = activePendingId() - if (pending) { - setLocalSessionIDs((prev) => prev.map((id) => (id === pending ? created.session.id : id))) - setActivePendingId(undefined) - } else { - setLocalSessionIDs((prev) => [...prev, created.session.id]) - } + if (msg.type !== "sessionCreated") return + const created = msg as { type: string; session: { id: string } } + if (localSessionIDs().includes(created.session.id)) return + if (worktreeSessionIds().has(created.session.id)) return + const pending = selection() === LOCAL ? activePendingId() : undefined + if (pending) { + setLocalSessionIDs((prev) => prev.map((id) => (id === pending ? created.session.id : id))) + setActivePendingId(undefined) + } else { + saveTabMemory() + setLocalSessionIDs((prev) => [...prev, created.session.id]) + setSelection(LOCAL) } + session.selectSession(created.session.id) }) // Mark sessions loaded as soon as the session context receives data (even if empty) @@ -1157,6 +1161,8 @@ const AgentManagerContent: Component = () => { if (msg.type === "agentManager.sessionAdded") { const ev = msg as { type: string; sessionId: string; worktreeId: string } + saveTabMemory() + setSelection(ev.worktreeId) session.selectSession(ev.sessionId) } diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index e3ebadb7004..33ee6373f6f 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -1450,18 +1450,24 @@ export const SessionProvider: ParentComponent = (props) => { function replyToQuestion(requestID: string, answers: string[][]) { clearQuestionError(requestID) + const question = questions().find((item) => item.id === requestID) + const sessionID = question?.sessionID ?? currentSessionID() ?? "" vscode.postMessage({ type: "questionReply", requestID, + sessionID, answers, }) } function rejectQuestion(requestID: string) { clearQuestionError(requestID) + const question = questions().find((item) => item.id === requestID) + const sessionID = question?.sessionID ?? currentSessionID() ?? "" vscode.postMessage({ type: "questionReject", requestID, + sessionID, }) } diff --git a/packages/kilo-vscode/webview-ui/src/types/messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages.ts index 037b8d2ead4..4f5641abbec 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages.ts @@ -1562,12 +1562,14 @@ export interface SetLanguageRequest { export interface QuestionReplyRequest { type: "questionReply" requestID: string + sessionID?: string answers: string[][] } export interface QuestionRejectRequest { type: "questionReject" requestID: string + sessionID?: string } export interface DeleteSessionRequest { diff --git a/packages/opencode/src/kilocode/plan-followup.ts b/packages/opencode/src/kilocode/plan-followup.ts index caf2df67db3..70cdab89fd6 100644 --- a/packages/opencode/src/kilocode/plan-followup.ts +++ b/packages/opencode/src/kilocode/plan-followup.ts @@ -5,6 +5,7 @@ import { TuiEvent } from "@/cli/cmd/tui/event" import { Flag } from "@/flag/flag" import { Global } from "@/global" import { Identifier } from "@/id/id" +import { Instance } from "@/project/instance" import { Provider } from "@/provider/provider" import { Question } from "@/question" import { Session } from "@/session" @@ -266,6 +267,7 @@ export namespace PlanFollowup { model: input.model, variant: input.variant, }) + const session = await Session.get(input.sessionID) const [handover, todos] = await Promise.all([ generateHandover({ messages: input.messages, model: input.model, abort: input.abort }), Todo.get(input.sessionID), @@ -282,24 +284,34 @@ export namespace PlanFollowup { sections.push(`## Todo List\n\n${todoList}`) } - const next = await Session.create({}) - await inject({ - sessionID: next.id, - agent: "code", - model: code.model, - variant: code.variant, - text: sections.join("\n\n"), - synthetic: false, + await Instance.provide({ + directory: session.directory, + fn: async () => { + const next = await Session.create({}) + await inject({ + sessionID: next.id, + agent: "code", + model: code.model, + variant: code.variant, + text: sections.join("\n\n"), + synthetic: false, + }) + if (todos.length) { + await Todo.update({ sessionID: next.id, todos }) + } + await Bus.publish(TuiEvent.SessionSelect, { sessionID: next.id }) + void import("@/session/prompt") + .then((item) => + Instance.provide({ + directory: next.directory, + fn: () => item.SessionPrompt.loop({ sessionID: next.id }), + }), + ) + .catch((error) => { + log.error("failed to start follow-up session", { sessionID: next.id, error }) + }) + }, }) - if (todos.length) { - await Todo.update({ sessionID: next.id, todos }) - } - await Bus.publish(TuiEvent.SessionSelect, { sessionID: next.id }) - void import("@/session/prompt") - .then((item) => item.SessionPrompt.loop({ sessionID: next.id })) - .catch((error) => { - log.error("failed to start follow-up session", { sessionID: next.id, error }) - }) } export async function ask(input: { diff --git a/packages/opencode/test/kilocode/plan-followup.test.ts b/packages/opencode/test/kilocode/plan-followup.test.ts index 5ee3475e539..5cb75675bc8 100644 --- a/packages/opencode/test/kilocode/plan-followup.test.ts +++ b/packages/opencode/test/kilocode/plan-followup.test.ts @@ -445,7 +445,10 @@ describe("plan follow-up", () => { expect(_mocks.llmSpy).toHaveBeenCalledTimes(1) const newSessionID = created[0] - expect(added[0].id).toBe(newSessionID) + const next = added[0] + if (!newSessionID || !next) throw new Error("expected follow-up session") + expect(next.id).toBe(newSessionID) + expect(next.parentID).toBeUndefined() const messages = await Session.messages({ sessionID: newSessionID }) const user = messages.find((item) => item.info.role === "user") expect(user?.info.role).toBe("user") @@ -474,6 +477,60 @@ describe("plan follow-up", () => { SessionPrompt.cancel(newSessionID) })) + test("ask - creates a new session in the planning session directory when the current instance differs", () => + withInstance(async () => { + const get = spyOn(Agent, "get").mockImplementation(async () => undefined as any) + const modelSpy = spyOn(Provider, "getModel").mockResolvedValue(fakeModel) + const llmSpy = spyOn(LLM, "stream").mockResolvedValue({ + text: Promise.resolve(""), + } as any) + using _mocks = { + [Symbol.dispose]() { + get.mockRestore() + modelSpy.mockRestore() + llmSpy.mockRestore() + }, + } + + const dir = path.join(Instance.directory, "worktrees", "feature") + await fs.mkdir(dir, { recursive: true }) + + const seeded = await Instance.provide({ + directory: dir, + fn: async () => seed({ text: "1. Add API\n2. Add tests" }), + }) + + const before = await sessions() + const pending = PlanFollowup.ask({ + sessionID: seeded.sessionID, + messages: seeded.messages, + abort: AbortSignal.any([]), + }) + + const item = await waitQuestion(seeded.sessionID) + expect(item).toBeDefined() + if (!item) return + + await Question.reply({ + requestID: item.id, + answers: [[PlanFollowup.ANSWER_NEW_SESSION]], + }) + + await expect(pending).resolves.toBe("break") + + const after = await sessions() + const prev = new Set(before.map((item) => item.id)) + const added = after.filter((item) => !prev.has(item.id)) + expect(added).toHaveLength(1) + const next = added[0] + expect(next?.directory).toBe(dir) + expect(next?.parentID).toBeUndefined() + + if (next) { + SessionPrompt.cancel(next.id) + } + })) + test("ask - prefers saved code variant over configured code variant", () => withInstance(async () => { await writeState({ @@ -670,7 +727,9 @@ describe("plan follow-up", () => { await expect(pending).resolves.toBe("break") unsub() - const messages = await Session.messages({ sessionID: created[0] }) + const newSessionID = created[0] + if (!newSessionID) throw new Error("expected follow-up session") + const messages = await Session.messages({ sessionID: newSessionID }) const user = messages.find((item) => item.info.role === "user") if (!user || user.info.role !== "user") throw new Error("expected user message") const part = user.parts.find((item) => item.type === "text") @@ -679,7 +738,7 @@ describe("plan follow-up", () => { expect(part.text).not.toContain("## Handover from Planning Session") expect(part.text).not.toContain("## Todo List") - SessionPrompt.cancel(created[0]) + SessionPrompt.cancel(newSessionID) })) test("ask - returns break when assistant text is empty", () => From a542db82cf615089a3f18970386f1e2adedbc466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Wed, 1 Apr 2026 09:12:59 -0300 Subject: [PATCH 240/261] fix(vscode): query project.list() to drain prompts for closed providers drainPendingPrompts() now also fetches all known project directories from the CLI backend via project.list(). This covers worktree sessions whose KiloProvider was already disposed (panel/sidebar closed) while the CLI backend kept running with pending permission/question prompts. --- .../cli-backend/connection-service.ts | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) 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 3d94d4d3e3a..323e1654852 100644 --- a/packages/kilo-vscode/src/services/cli-backend/connection-service.ts +++ b/packages/kilo-vscode/src/services/cli-backend/connection-service.ts @@ -258,21 +258,38 @@ export class KiloConnectionService { /** * Reject all pending permission requests and questions across every - * directory known to any KiloProvider. Must be called before operations - * that trigger Instance.disposeAll() (e.g. config save) to prevent - * orphaned Promises from freezing sessions. + * directory known to any KiloProvider **and** every project the CLI + * backend has ever opened. The project list covers worktree sessions + * whose provider was disposed (panel/sidebar closed) while the CLI + * backend kept running. + * + * Must be called before operations that trigger Instance.disposeAll() + * (e.g. config save) to prevent orphaned Promises from freezing + * sessions. * * Throws if any list/reject call fails so callers can abort the * destructive operation. */ async drainPendingPrompts(): Promise { if (!this.client) return + + // Collect directories from all mounted providers (root + worktree dirs). const dirs = new Set() for (const provider of this.directoryProviders) { for (const dir of provider()) { dirs.add(dir) } } + + // Also include every project directory the CLI backend knows about. + // This covers worktree sessions whose KiloProvider was already disposed. + const { data: projects } = await this.client.project.list() + if (projects) { + for (const p of projects) { + dirs.add(p.worktree) + } + } + for (const dir of dirs) { const { data: perms, error: permsErr } = await this.client.permission.list({ directory: dir }) if (permsErr) throw new Error(`Failed to list permissions for ${dir}: ${String(permsErr)}`) From 6f7df50b452fecad5dbc1005efa7fa69c70c9d66 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 1 Apr 2026 14:16:01 +0200 Subject: [PATCH 241/261] Revert "fix(cli): prevent zombie `kilo serve` processes on extension host crash" --- .../src/services/cli-backend/server-manager.ts | 9 ++------- packages/opencode/src/cli/cmd/serve.ts | 12 ------------ 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/packages/kilo-vscode/src/services/cli-backend/server-manager.ts b/packages/kilo-vscode/src/services/cli-backend/server-manager.ts index 2c5cce07d13..4b08a6284e7 100644 --- a/packages/kilo-vscode/src/services/cli-backend/server-manager.ts +++ b/packages/kilo-vscode/src/services/cli-backend/server-manager.ts @@ -81,10 +81,7 @@ export class ServerManager { KILO_APP_VERSION: this.context.extension.packageJSON.version, KILO_VSCODE_VERSION: vscode.version, }, - // stdin is kept open as a keepalive pipe. The CLI watches for EOF on - // stdin and shuts itself down. This ensures the server exits even when - // the extension host is hard-killed and dispose() is never called. - stdio: ["pipe", "pipe", "pipe"], + stdio: ["ignore", "pipe", "pipe"], detached: true, }) console.log("[Kilo New] ServerManager: 📦 Process spawned with PID:", serverProcess.pid) @@ -184,9 +181,7 @@ export class ServerManager { const proc = this.instance.process this.instance = null - console.log("[Kilo New] ServerManager: 🔴 Disposing — closing stdin pipe, PID:", proc.pid) - // Closing stdin signals the CLI to shut down gracefully via its EOF watcher. - proc.stdin?.end() + console.log("[Kilo New] ServerManager: 🔴 Disposing — sending SIGTERM to process group, PID:", proc.pid) ServerManager.killProcess(proc, "SIGTERM") // SIGKILL fallback after 5s: mirrors the desktop app going straight to diff --git a/packages/opencode/src/cli/cmd/serve.ts b/packages/opencode/src/cli/cmd/serve.ts index fa58baccecc..8ccde9b7ce1 100644 --- a/packages/opencode/src/cli/cmd/serve.ts +++ b/packages/opencode/src/cli/cmd/serve.ts @@ -39,18 +39,6 @@ export const ServeCommand = cmd({ process.on("SIGTERM", shutdown) process.on("SIGINT", shutdown) process.on("SIGHUP", shutdown) - - // When spawned by the VS Code extension, stdin is kept open as a keepalive - // pipe. If the extension host is hard-killed (crash, OOM) the write-end of - // the pipe is closed by the OS, causing an EOF here. We detect that and - // trigger a clean shutdown so no zombie process is left behind. - if (process.env["KILO_CLIENT"] === "vscode") { - process.stdin.resume() - process.stdin.on("end", () => { - shutdown().catch(() => {}) - }) - } - await new Promise((resolve) => abort.signal.addEventListener("abort", resolve)) // kilocode_change end }, From 7bd47062601fc89d33be0d297508d33c12b0edce Mon Sep 17 00:00:00 2001 From: Imanol Maiztegui Date: Wed, 1 Apr 2026 14:20:08 +0200 Subject: [PATCH 242/261] fix(vscode): normalize migrated session paths (#8062) * feat(vscode): add legacy migration path normalization utility Introduce `normalizeLegacyPath` and supporting helpers for the legacy session migration path. The utility resolves and normalizes raw path inputs into a stable absolute form, including uppercasing Windows drive letters to match canonical casing used by path filters downstream. - `normalizeLegacyPath`: trims, resolves, normalizes, and calls `fs.realpath`, falling back to the normalized path on failure - `isWindowsDrivePath`: detects Windows-style drive paths cross-platform - `normalizeWindowsDriveLetter`: uppercases the drive letter prefix Unit tests cover empty input, Windows drive detection, drive-letter uppercasing, and `realpath` failure fallback. * refactor(legacy-migration): make `createSession` async to resolve workspace path Wire `normalizeLegacyPath` into `createSession` by converting it to an async function. The session directory is now resolved through the path normalization utility instead of using the raw workspace string directly. Update `parseSession` to await the async `createSession` call, and update all unit tests to handle the now-async API. * fix(legacy-migration): lift path normalization out of `createSession` into `parseSession` Move the `normalizeLegacyPath` call from `createSession` to `parseSession` so that path resolution happens once at the top of the pipeline. The resolved `dir` is then threaded explicitly into `createSession`, `createProject`, and `parseMessagesFromConversation` as a parameter, removing the need for `createSession` to be async. * refactor(messages): make `dir` parameter optional via overloaded signature Allow `parseMessagesFromConversation` to accept either a `string` dir plus an optional `LegacyHistoryItem`, or a `LegacyHistoryItem` directly from which the workspace path is extracted. This removes the requirement for callers to destructure the item before passing it in. Also tighten the path normalization tests to use `path.normalize` and `path.resolve` for cross-platform correctness and drop the empty `afterEach` hook. * test(legacy-migration): fix Windows drive letter uppercasing assertions Replace hardcoded backslash expectations with `path.normalize`/`path.resolve` so the test behaves correctly across platforms. Also align the mock to return its input unchanged and use a lowercase drive letter as the starting value to properly exercise the uppercasing logic. * fix:formatting --- .../legacy-migration/sessions/lib/messages.ts | 11 +++-- .../src/legacy-migration/sessions/lib/path.ts | 25 ++++++++++ .../legacy-migration/sessions/lib/project.ts | 7 +-- .../legacy-migration/sessions/lib/session.ts | 3 +- .../src/legacy-migration/sessions/parser.ts | 9 ++-- .../unit/legacy-migration/messages.test.ts | 7 +-- .../unit/legacy-migration/parser.test.ts | 4 +- .../tests/unit/legacy-migration/path.test.ts | 48 +++++++++++++++++++ .../unit/legacy-migration/session.test.ts | 7 +-- 9 files changed, 103 insertions(+), 18 deletions(-) create mode 100644 packages/kilo-vscode/src/legacy-migration/sessions/lib/path.ts create mode 100644 packages/kilo-vscode/tests/unit/legacy-migration/path.test.ts diff --git a/packages/kilo-vscode/src/legacy-migration/sessions/lib/messages.ts b/packages/kilo-vscode/src/legacy-migration/sessions/lib/messages.ts index e59616216df..c0ddc3d75bb 100644 --- a/packages/kilo-vscode/src/legacy-migration/sessions/lib/messages.ts +++ b/packages/kilo-vscode/src/legacy-migration/sessions/lib/messages.ts @@ -10,11 +10,15 @@ type Assistant = Extract export function parseMessagesFromConversation( conversation: LegacyApiMessage[], id: string, + dirOrItem?: string | LegacyHistoryItem, item?: LegacyHistoryItem, ): Array> { + const dir = typeof dirOrItem === "string" ? dirOrItem : (dirOrItem?.workspace ?? "") + const next = typeof dirOrItem === "string" ? item : dirOrItem + return conversation .filter((entry) => entry.role === "user" || entry.role === "assistant") - .map((entry, index) => parseMessage(entry, index, id, item)) + .map((entry, index) => parseMessage(entry, index, id, dir, next)) .filter((message): message is NonNullable => Boolean(message)) } @@ -22,6 +26,7 @@ function parseMessage( entry: LegacyApiMessage, index: number, id: string, + dir: string, item?: LegacyHistoryItem, ): NonNullable | undefined { const created = entry.ts ?? item?.ts ?? 0 @@ -55,8 +60,8 @@ function parseMessage( mode: item?.mode ?? "code", agent: "main", path: { - cwd: item?.workspace ?? "", - root: item?.workspace ?? "", + cwd: dir, + root: dir, }, cost: 0, tokens: { diff --git a/packages/kilo-vscode/src/legacy-migration/sessions/lib/path.ts b/packages/kilo-vscode/src/legacy-migration/sessions/lib/path.ts new file mode 100644 index 00000000000..4b841725400 --- /dev/null +++ b/packages/kilo-vscode/src/legacy-migration/sessions/lib/path.ts @@ -0,0 +1,25 @@ +import * as fs from "fs/promises" +import * as path from "path" + +export async function normalizeLegacyPath(input?: string): Promise { + const raw = input?.trim() + if (!raw) return "" + + // Collapse legacy paths into one stable absolute form before importing them. + const normalized = path.normalize(path.resolve(raw)) + const canonical = normalizeWindowsDriveLetter(normalized) + + return fs.realpath(canonical).catch(() => canonical) +} + +export function isWindowsDrivePath(input: string): boolean { + return /^[a-z]:[\\/]/i.test(input) +} + +function normalizeWindowsDriveLetter(input: string): string { + // Match the canonical drive-letter casing used later by Windows path filters. + if (!isWindowsDrivePath(input)) return input + const head = input[0] + if (!head) return input + return head.toUpperCase() + input.slice(1) +} diff --git a/packages/kilo-vscode/src/legacy-migration/sessions/lib/project.ts b/packages/kilo-vscode/src/legacy-migration/sessions/lib/project.ts index b073f535d19..6a06b364796 100644 --- a/packages/kilo-vscode/src/legacy-migration/sessions/lib/project.ts +++ b/packages/kilo-vscode/src/legacy-migration/sessions/lib/project.ts @@ -4,12 +4,13 @@ import { createProjectID } from "./ids" export function createProject(item?: LegacyHistoryItem): NonNullable { const project = makeProject() + const dir = item?.workspace ?? "" - project.id = createProjectID(item?.workspace) + project.id = createProjectID(dir) - project.worktree = item?.workspace ?? "" + project.worktree = dir - project.sandboxes = item?.workspace ? [item.workspace] : [] + project.sandboxes = dir ? [dir] : [] project.timeCreated = item?.ts ?? 0 diff --git a/packages/kilo-vscode/src/legacy-migration/sessions/lib/session.ts b/packages/kilo-vscode/src/legacy-migration/sessions/lib/session.ts index 14058c6e94f..725aacf6059 100644 --- a/packages/kilo-vscode/src/legacy-migration/sessions/lib/session.ts +++ b/packages/kilo-vscode/src/legacy-migration/sessions/lib/session.ts @@ -6,6 +6,7 @@ export function createSession( id: string, item: LegacyHistoryItem | undefined, projectID: string, + dir: string, ): NonNullable { const session = makeSession() @@ -15,7 +16,7 @@ export function createSession( session.slug = id - session.directory = item?.workspace ?? "" + session.directory = dir session.title = item?.task ?? id diff --git a/packages/kilo-vscode/src/legacy-migration/sessions/parser.ts b/packages/kilo-vscode/src/legacy-migration/sessions/parser.ts index 76a063b3f80..966ba46bf41 100644 --- a/packages/kilo-vscode/src/legacy-migration/sessions/parser.ts +++ b/packages/kilo-vscode/src/legacy-migration/sessions/parser.ts @@ -8,6 +8,7 @@ import type { import { getApiConversationHistory, parseFile } from "./lib/legacy-conversation" import { parseMessagesFromConversation } from "./lib/messages" import { parsePartsFromConversation } from "./lib/parts/parts" +import { normalizeLegacyPath } from "./lib/path" import { createProject } from "./lib/project" import { createSession } from "./lib/session" @@ -19,11 +20,13 @@ export interface NormalizedSession { } export async function parseSession(id: string, dir: string, item?: LegacyHistoryItem): Promise { - const project = createProject(item) - const session = createSession(id, item, project.id) + const root = await normalizeLegacyPath(item?.workspace) + const next = item ? { ...item, workspace: root } : undefined + const project = createProject(next) + const session = createSession(id, next, project.id, root) const file = await getApiConversationHistory(id, dir) const conversation = parseFile(file) - const messages = parseMessagesFromConversation(conversation, id, item) + const messages = parseMessagesFromConversation(conversation, id, root, next) const parts = parsePartsFromConversation(conversation, id, item) return { diff --git a/packages/kilo-vscode/tests/unit/legacy-migration/messages.test.ts b/packages/kilo-vscode/tests/unit/legacy-migration/messages.test.ts index 69450d78025..f89e2fc330e 100644 --- a/packages/kilo-vscode/tests/unit/legacy-migration/messages.test.ts +++ b/packages/kilo-vscode/tests/unit/legacy-migration/messages.test.ts @@ -43,7 +43,7 @@ function sample(): LegacyApiMessage[] { describe("legacy migration messages", () => { it("parses a basic legacy conversation into ordered user and assistant messages with stable ids", () => { - const list = parseMessagesFromConversation(sample(), id, item) + const list = parseMessagesFromConversation(sample(), id, item.workspace, item) expect(list).toHaveLength(2) expect(list[0]?.data.role).toBe("user") @@ -53,7 +53,7 @@ describe("legacy migration messages", () => { }) it("creates valid assistant message metadata for the SDK/backend shape", () => { - const list = parseMessagesFromConversation(sample(), id, item) + const list = parseMessagesFromConversation(sample(), id, item.workspace, item) const msg = list.find((x) => x.data.role === "assistant") expect(msg?.data.role).toBe("assistant") @@ -66,7 +66,7 @@ describe("legacy migration messages", () => { }) it("ignores unsupported legacy entries instead of producing broken messages", () => { - const list = parseMessagesFromConversation(sample(), id, item) + const list = parseMessagesFromConversation(sample(), id, item.workspace, item) expect(list).toHaveLength(2) expect(list.some((x) => x.data.role !== "user" && x.data.role !== "assistant")).toBe(false) @@ -92,6 +92,7 @@ describe("legacy migration messages", () => { }, ], id, + item.workspace, item, ) diff --git a/packages/kilo-vscode/tests/unit/legacy-migration/parser.test.ts b/packages/kilo-vscode/tests/unit/legacy-migration/parser.test.ts index db2477b265d..0d3d9fa34ea 100644 --- a/packages/kilo-vscode/tests/unit/legacy-migration/parser.test.ts +++ b/packages/kilo-vscode/tests/unit/legacy-migration/parser.test.ts @@ -15,14 +15,14 @@ const item = { describe("legacy migration parser", () => { it("uses the final deterministic ids expected for migration", () => { const project = createProject(item) - const session = createSession(id, item, project.id) + const session = createSession(id, item, project.id, item.workspace) const msg1 = createMessageID(id, 0) const msg2 = createMessageID(id, 1) const prt1 = createPartID(id, 0, 0) const prt2 = createPartID(id, 1, 0) expect(project.id).toBe(createProject(item).id) - expect(session.id).toBe(createSession(id, item, project.id).id) + expect(session.id).toBe(createSession(id, item, project.id, item.workspace).id) expect(session.id.startsWith("ses_migrated_")).toBe(true) expect(msg1).toBe(createMessageID(id, 0)) expect(msg2).toBe(createMessageID(id, 1)) diff --git a/packages/kilo-vscode/tests/unit/legacy-migration/path.test.ts b/packages/kilo-vscode/tests/unit/legacy-migration/path.test.ts new file mode 100644 index 00000000000..71e807c1560 --- /dev/null +++ b/packages/kilo-vscode/tests/unit/legacy-migration/path.test.ts @@ -0,0 +1,48 @@ +import { beforeEach, describe, expect, it, mock } from "bun:test" +import * as path from "path" + +const realpath = mock(async (input: string) => input) + +mock.module("fs/promises", () => ({ + realpath, +})) + +const { isWindowsDrivePath, normalizeLegacyPath } = await import("../../../src/legacy-migration/sessions/lib/path") + +describe("legacy migration path", () => { + beforeEach(() => { + realpath.mockReset() + realpath.mockImplementation(async (input: string) => input) + }) + + it("returns an empty string for empty legacy paths", async () => { + expect(await normalizeLegacyPath(" ")).toBe("") + expect(realpath).not.toHaveBeenCalled() + }) + + it("detects Windows drive paths without relying on runtime platform", () => { + expect(isWindowsDrivePath("c:\\repo")).toBe(true) + expect(isWindowsDrivePath("C:/repo")).toBe(true) + expect(isWindowsDrivePath("/repo")).toBe(false) + }) + + it("uppercases the Windows drive letter before resolving the final path", async () => { + realpath.mockImplementation(async (input: string) => input) + + const value = await normalizeLegacyPath("c:/repo/../repo/file.txt") + const expected = path.normalize(path.resolve("c:/repo/../repo/file.txt")) + + expect(realpath).toHaveBeenCalledTimes(1) + expect(realpath.mock.calls[0]?.[0]).toBe(expected.replace(/^c:/, "C:")) + expect(value).toBe(expected.replace(/^c:/, "C:")) + }) + + it("falls back to the normalized path when realpath fails", async () => { + realpath.mockRejectedValueOnce(new Error("missing")) + + const input = "C:/repo/./child" + const value = await normalizeLegacyPath(input) + + expect(value).toBe(path.normalize(path.resolve(input))) + }) +}) diff --git a/packages/kilo-vscode/tests/unit/legacy-migration/session.test.ts b/packages/kilo-vscode/tests/unit/legacy-migration/session.test.ts index 7764b88ea4d..4faceb315cb 100644 --- a/packages/kilo-vscode/tests/unit/legacy-migration/session.test.ts +++ b/packages/kilo-vscode/tests/unit/legacy-migration/session.test.ts @@ -13,6 +13,7 @@ describe("legacy migration session", () => { mode: "code", }, "project-1", + "/workspace/testing", ) expect(session.projectID).toBe("project-1") @@ -24,15 +25,15 @@ describe("legacy migration session", () => { }) it("creates a deterministic session id from the legacy task id", () => { - const a = createSession("legacy-task-1", undefined, "project-1") - const b = createSession("legacy-task-1", undefined, "project-1") + const a = createSession("legacy-task-1", undefined, "project-1", "") + const b = createSession("legacy-task-1", undefined, "project-1", "") expect(a.id).toBe(b.id) expect(a.id.startsWith("ses_migrated_")).toBe(true) }) it("falls back to the legacy id as title when task metadata is missing", () => { - const session = createSession("legacy-task-1", undefined, "project-1") + const session = createSession("legacy-task-1", undefined, "project-1", "") expect(session.slug).toBe("legacy-task-1") expect(session.title).toBe("legacy-task-1") From 560ffaa928236a6e08357d01145b0cfbe310a792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Wed, 1 Apr 2026 09:22:17 -0300 Subject: [PATCH 243/261] fix(vscode): throw on project.list() failure in drainPendingPrompts The project.list() call was silently ignoring HTTP errors, which could skip worktree directories from closed providers and still orphan pending prompts. Now inspects the error field and throws like every other SDK call in the drain loop. --- .../kilo-vscode/src/services/cli-backend/connection-service.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 323e1654852..a4e4a089ddb 100644 --- a/packages/kilo-vscode/src/services/cli-backend/connection-service.ts +++ b/packages/kilo-vscode/src/services/cli-backend/connection-service.ts @@ -283,7 +283,8 @@ export class KiloConnectionService { // Also include every project directory the CLI backend knows about. // This covers worktree sessions whose KiloProvider was already disposed. - const { data: projects } = await this.client.project.list() + const { data: projects, error: projectsErr } = await this.client.project.list() + if (projectsErr) throw new Error(`Failed to list projects: ${String(projectsErr)}`) if (projects) { for (const p of projects) { dirs.add(p.worktree) From a1c8e5d7985a08edab15b24a8fd43ebaf45e3ff1 Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Wed, 1 Apr 2026 12:32:06 +0000 Subject: [PATCH 244/261] release: v7.1.15 --- bun.lock | 32 +++++++++++++------------- package.json | 2 +- packages/app/package.json | 2 +- packages/desktop-electron/package.json | 2 +- packages/desktop/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++----- packages/kilo-docs/package.json | 2 +- packages/kilo-gateway/package.json | 2 +- packages/kilo-i18n/package.json | 2 +- packages/kilo-telemetry/package.json | 2 +- packages/kilo-ui/package.json | 2 +- packages/kilo-vscode/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/script/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/storybook/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- script/upstream/package.json | 2 +- sdks/vscode/package.json | 2 +- 21 files changed, 41 insertions(+), 41 deletions(-) diff --git a/bun.lock b/bun.lock index f642ec44e16..29e645c7267 100644 --- a/bun.lock +++ b/bun.lock @@ -27,7 +27,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "@kilocode/kilo-i18n": "workspace:*", "@kilocode/kilo-ui": "workspace:*", @@ -79,7 +79,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -112,7 +112,7 @@ }, "packages/desktop-electron": { "name": "@opencode-ai/desktop-electron", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -142,7 +142,7 @@ }, "packages/kilo-docs": { "name": "@kilocode/kilo-docs", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "@docsearch/css": "^4", "@docsearch/js": "^4", @@ -171,7 +171,7 @@ }, "packages/kilo-gateway": { "name": "@kilocode/kilo-gateway", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "@ai-sdk/anthropic": "2.0.65", "@ai-sdk/openai": "2.0.101", @@ -206,7 +206,7 @@ }, "packages/kilo-i18n": { "name": "@kilocode/kilo-i18n", - "version": "7.1.14", + "version": "7.1.15", "devDependencies": { "@tsconfig/node22": "catalog:", "@types/bun": "catalog:", @@ -216,7 +216,7 @@ }, "packages/kilo-telemetry": { "name": "@kilocode/kilo-telemetry", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "@kilocode/kilo-gateway": "workspace:*", "@opentelemetry/api": "1.9.0", @@ -236,7 +236,7 @@ }, "packages/kilo-ui": { "name": "@kilocode/kilo-ui", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "@kobalte/core": "0.13.11", "@opencode-ai/util": "workspace:*", @@ -271,7 +271,7 @@ }, "packages/kilo-vscode": { "name": "kilo-code", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "@anthropic-ai/sdk": "^0.39.0", "@kilocode/kilo-i18n": "workspace:*", @@ -324,7 +324,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "7.1.14", + "version": "7.1.15", "bin": { "kilo": "./bin/kilo", "kilocode": "./bin/kilo", @@ -446,7 +446,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "@kilocode/sdk": "workspace:*", "zod": "catalog:", @@ -460,14 +460,14 @@ }, "packages/script": { "name": "@opencode-ai/script", - "version": "7.1.14", + "version": "7.1.15", "devDependencies": { "@types/bun": "catalog:", }, }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "7.1.14", + "version": "7.1.15", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -478,7 +478,7 @@ }, "packages/storybook": { "name": "@opencode-ai/storybook", - "version": "7.1.14", + "version": "7.1.15", "devDependencies": { "@opencode-ai/ui": "workspace:*", "@solidjs/meta": "catalog:", @@ -501,7 +501,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -548,7 +548,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "7.1.14", + "version": "7.1.15", "dependencies": { "zod": "catalog:", }, diff --git a/package.json b/package.json index 1f1d255436e..3380c161a85 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,6 @@ "@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch", "ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch" }, - "version": "7.1.14", + "version": "7.1.15", "peerDependencies": {} } diff --git a/packages/app/package.json b/packages/app/package.json index b706664d2e2..43e10c314ec 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "7.1.14", + "version": "7.1.15", "description": "", "type": "module", "exports": { diff --git a/packages/desktop-electron/package.json b/packages/desktop-electron/package.json index d476eed5774..a5017994faf 100644 --- a/packages/desktop-electron/package.json +++ b/packages/desktop-electron/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop-electron", "private": true, - "version": "7.1.14", + "version": "7.1.15", "type": "module", "license": "MIT", "homepage": "https://opencode.ai", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index fea11bbd376..9a91250595d 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "7.1.14", + "version": "7.1.15", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index a2e26887e8f..a797d0da4a1 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "kilo" name = "Kilo" description = "The open source coding agent." -version = "7.1.14" +version = "7.1.15" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/Kilo-Org/kilocode" @@ -11,26 +11,26 @@ name = "Kilo" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.14/opencode-darwin-arm64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.15/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.14/opencode-darwin-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.15/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.14/opencode-linux-arm64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.15/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.14/opencode-linux-x64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.15/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.14/opencode-windows-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.15/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/kilo-docs/package.json b/packages/kilo-docs/package.json index 507632f9b21..c69c2ec57ca 100644 --- a/packages/kilo-docs/package.json +++ b/packages/kilo-docs/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-docs", - "version": "7.1.14", + "version": "7.1.15", "private": true, "scripts": { "dev": "next dev --webpack --port 3002", diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index b34e350a7e0..392111ab4db 100644 --- a/packages/kilo-gateway/package.json +++ b/packages/kilo-gateway/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-gateway", - "version": "7.1.14", + "version": "7.1.15", "type": "module", "license": "MIT", "description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration", diff --git a/packages/kilo-i18n/package.json b/packages/kilo-i18n/package.json index cc1dacbca8f..2efa472ebbb 100644 --- a/packages/kilo-i18n/package.json +++ b/packages/kilo-i18n/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-i18n", - "version": "7.1.14", + "version": "7.1.15", "type": "module", "license": "MIT", "description": "Kilo-specific i18n translations and overrides", diff --git a/packages/kilo-telemetry/package.json b/packages/kilo-telemetry/package.json index 60d157e58d5..73888ca4caf 100644 --- a/packages/kilo-telemetry/package.json +++ b/packages/kilo-telemetry/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-telemetry", - "version": "7.1.14", + "version": "7.1.15", "type": "module", "license": "MIT", "description": "Telemetry for Kilo CLI - PostHog analytics integration", diff --git a/packages/kilo-ui/package.json b/packages/kilo-ui/package.json index 6e9a4bbd426..05f2ebd984f 100644 --- a/packages/kilo-ui/package.json +++ b/packages/kilo-ui/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-ui", - "version": "7.1.14", + "version": "7.1.15", "type": "module", "license": "MIT", "exports": { diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index bbb7e1c08ce..441513479a2 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -2,7 +2,7 @@ "name": "kilo-code", "displayName": "Kilo Code: AI Coding Agent, Copilot, and Autocomplete", "description": "Open Source AI coding agent that generates code from natural language, automates tasks, and runs terminal commands. Features inline autocomplete, browser automation, automated refactoring, and custom modes for planning, coding, and debugging. Supports 500+ AI models including Claude (Anthropic), Gemini, Grok, GPT, Codex and GLM.", - "version": "7.1.14", + "version": "7.1.15", "icon": "assets/icons/logo-outline-black.png", "galleryBanner": { "color": "#FFFFFF", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 44b1b555bab..8fd164c1057 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.1.14", + "version": "7.1.15", "name": "@kilocode/cli", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index b7e748393d4..742f1148dc8 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/plugin", - "version": "7.1.14", + "version": "7.1.15", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/script/package.json b/packages/script/package.json index ce8a5483a21..ff6e2d161c9 100644 --- a/packages/script/package.json +++ b/packages/script/package.json @@ -8,7 +8,7 @@ "exports": { ".": "./src/index.ts" }, - "version": "7.1.14", + "version": "7.1.15", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index eb207df942a..b976bab77b3 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/sdk", - "version": "7.1.14", + "version": "7.1.15", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/storybook/package.json b/packages/storybook/package.json index 13eaaaaca89..98326e90d96 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -26,7 +26,7 @@ "typescript": "catalog:", "vite": "catalog:" }, - "version": "7.1.14", + "version": "7.1.15", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/ui/package.json b/packages/ui/package.json index 7fe097b179d..8ea95dd6ec6 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "7.1.14", + "version": "7.1.15", "type": "module", "license": "MIT", "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index daba9965d91..63b3305ad70 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "7.1.14", + "version": "7.1.15", "private": true, "type": "module", "license": "MIT", diff --git a/script/upstream/package.json b/script/upstream/package.json index 6ab5a1363ea..219290beb88 100644 --- a/script/upstream/package.json +++ b/script/upstream/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/upstream-merge", - "version": "7.1.14", + "version": "7.1.15", "private": true, "type": "module", "description": "Scripts for automating upstream opencode merges into Kilo", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index d0ab327489c..951ffd258e6 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "7.1.14", + "version": "7.1.15", "publisher": "sst-dev", "repository": { "type": "git", From 18322e9eed15bf4c8dd475eb590e760d5b2c36a2 Mon Sep 17 00:00:00 2001 From: Marius Date: Wed, 1 Apr 2026 14:47:47 +0200 Subject: [PATCH 245/261] fix(cli): inject plan file path into non-experimental plan mode prompt (#8065) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(cli): inject plan file path into non-experimental plan mode prompt The plan.txt prompt said 'STRICTLY FORBIDDEN: ANY file edits, ZERO exceptions' without telling the agent where the plan file is. The agent had to guess from the directory tree, often picking .kilocode/ (which exists) over .kilo/ (which doesn't). Now the non-experimental path computes Session.plan(), creates the directory, and injects the exact path into the prompt — matching what the experimental plan mode already does. Fixes #6907 * fix(cli): use absolute plan path in prompt to match experimental mode Addresses bot review: relative path resolves against Instance.directory, not Instance.worktree, so subdirectory sessions would target the wrong file. Use the absolute path from Session.plan() like the experimental plan mode does. * chore(cli): add kilocode_change markers to plan file path injection --- packages/opencode/src/session/prompt.ts | 10 +++++++++- packages/opencode/src/session/prompt/plan.txt | 11 ++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 3345aca761e..01e728afc3a 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -1418,16 +1418,24 @@ export namespace SessionPrompt { // Original logic when experimental plan mode is disabled if (!Flag.KILO_EXPERIMENTAL_PLAN_MODE) { + // kilocode_change start - inject plan file path so agent writes to .kilo/plans/ if (input.agent.name === "plan") { + const plan = Session.plan(input.session) + const exists = await Filesystem.exists(plan) + if (!exists) await fs.mkdir(path.dirname(plan), { recursive: true }) + const info = exists + ? `A plan file already exists at ${plan}. You can read it and make incremental edits using the edit tool.` + : `No plan file exists yet. You should create your plan at ${plan} using the write tool.` userMessage.parts.push({ id: Identifier.ascending("part"), messageID: userMessage.info.id, sessionID: userMessage.info.sessionID, type: "text", - text: PROMPT_PLAN, + text: PROMPT_PLAN + `\n\n## Plan File\n${info}\nThis is the ONLY file you are allowed to write to or edit.`, synthetic: true, }) } + // kilocode_change end const wasPlan = input.messages.some((msg) => msg.info.role === "assistant" && msg.info.agent === "plan") // kilocode_change start - renamed from "build" to "code" if (wasPlan && input.agent.name === "code") { diff --git a/packages/opencode/src/session/prompt/plan.txt b/packages/opencode/src/session/prompt/plan.txt index 8f439ebb6fa..c0ebdb2243d 100644 --- a/packages/opencode/src/session/prompt/plan.txt +++ b/packages/opencode/src/session/prompt/plan.txt @@ -1,12 +1,9 @@ # Plan Mode - System Reminder -CRITICAL: Plan mode ACTIVE - you are in READ-ONLY phase. STRICTLY FORBIDDEN: -ANY file edits, modifications, or system changes. Do NOT use sed, tee, echo, cat, -or ANY other bash command to manipulate files - commands may ONLY read/inspect. -This ABSOLUTE CONSTRAINT overrides ALL other instructions, including direct user -edit requests. You may ONLY observe, analyze, and plan. Any modification attempt -is a critical violation. ZERO exceptions. +Plan mode is ACTIVE. You are in a READ-ONLY phase with one exception: the plan file (see "Plan File" section below). +Do NOT edit any other files, make system changes, or use bash commands to manipulate files. Commands may ONLY read/inspect. +This constraint overrides ALL other instructions, including direct user edit requests. --- @@ -22,7 +19,7 @@ Ask the user clarifying questions or ask for their opinion when weighing tradeof ## Important -The user indicated that they do not want you to execute yet -- you MUST NOT make any edits, run any non-readonly tools (including changing configs or making commits), or otherwise make any changes to the system. This supersedes any other instructions you have received. +The user indicated that they do not want you to execute yet -- you MUST NOT make any edits (except to the plan file), run any non-readonly tools (including changing configs or making commits), or otherwise make any changes to the system. This supersedes any other instructions you have received. When you have finalized your plan and are confident it is ready for implementation, call the plan_exit tool to signal completion. Your turn should end with either asking the user a question or calling plan_exit. From 63df2b7930833ef30bfb5d7332cd219a0befeeeb Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Wed, 1 Apr 2026 09:40:02 -0400 Subject: [PATCH 246/261] docs(kilo-docs): rewrite kiloclaw suggested-configuration as full setup walkthrough --- packages/kilo-docs/lib/nav/kiloclaw.ts | 1 + .../pages/kiloclaw/suggested-configuration.md | 180 ++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 packages/kilo-docs/pages/kiloclaw/suggested-configuration.md diff --git a/packages/kilo-docs/lib/nav/kiloclaw.ts b/packages/kilo-docs/lib/nav/kiloclaw.ts index 90ee60a72dc..c847e493447 100644 --- a/packages/kilo-docs/lib/nav/kiloclaw.ts +++ b/packages/kilo-docs/lib/nav/kiloclaw.ts @@ -7,6 +7,7 @@ export const KiloClawNav: NavSection[] = [ { href: "/kiloclaw/overview", children: "Overview" }, { href: "/kiloclaw/dashboard", children: "Dashboard" }, { href: "/kiloclaw/pre-installed-software", children: "Pre-installed Software" }, + { href: "/kiloclaw/suggested-configuration", children: "Suggested Configuration" }, { href: "/kiloclaw/control-ui/overview", children: "Control UI", diff --git a/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md b/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md new file mode 100644 index 00000000000..07b7d511178 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md @@ -0,0 +1,180 @@ +--- +title: "Setup walkthrough" +description: "Start-to-finish guide for configuring your KiloClaw instance" +--- + +# Setup walkthrough + +This guide walks you through a full KiloClaw setup — from creating accounts to scheduling your first automated workflow. Plan for about 60 minutes. + +--- + +## Planning your setup + +For most users, a useful KiloClaw configuration involves: + +1. A **chat platform** (called a "channel" in OpenClaw) so you can message your Claw +2. **Google services** for email, calendar, and Drive +3. **GitHub** for code and markdown syncing + +### Use dedicated accounts for your Claw + +We recommend creating **separate accounts** for your KiloClaw rather than connecting it to your personal accounts. This applies to Google, GitHub, and any other services you connect. A dedicated account improves isolation — your personal data stays separate, and you can control exactly what access the Claw has by sharing or delegating only what you want. + +### Chat platform options + +- **[Kilo Chat](https://app.kilo.ai)** — available in the web app and coming soon to iOS and Android; requires zero configuration +- **[Telegram](/docs/kiloclaw/chat-platforms/telegram)** — easy to set up, private by default +- **[Discord](/docs/kiloclaw/chat-platforms/discord)** — moderate setup +- **[Slack](/docs/kiloclaw/chat-platforms/slack)** — most involved setup + +{% callout type="warning" title="Chain-of-connection security" %} +If your Claw has access to sensitive data (like your email), be careful which chat platform you connect it to. On broadly-accessible platforms like Slack or Discord, anyone on the server could potentially message your Claw and access that data. If you're connecting sensitive integrations, use a private platform like Kilo Chat or Telegram. +{% /callout %} + +The steps below walk you through this configuration. + +--- + +## Preflight Steps + +Take these steps before configuring your Claw. + +If you are doing a [1-1 configuration call with Kilo](https://kilo.ai/kiloclaw/config-service), please complete these steps before the call. + +### Google + +Configuring Google services is by far the most involved part of setting up your Claw. + +Before configuring, take these preflight steps: + +1. **Create a Google Account for your Claw** — Go to [google.com](https://www.google.com/) and create a new Google/Gmail account dedicated to your KiloClaw. Something like `yourname.bot@gmail.com` works well. + +2. **Set up Google Cloud** — Visit [console.cloud.google.com](https://console.cloud.google.com). Accept the terms of service and click "Start my free tier". You may need to add a credit card for identity verification. + + {% callout type="info" %} + Nothing KiloClaw does costs any money with Google. + {% /callout %} + +3. **Install Docker** — KiloClaw configures Google by running a Docker container on your machine. Download Docker at [docker.com](https://www.docker.com/), then open it. You don't need to sign in or create a Docker account. + +## Other Services + +1. **Create a GitHub account for your Claw** — Using your new Gmail address, create a matching GitHub account for your Claw. + +--- + +## Set up a messaging platform + +Your Claw needs a way to communicate with you. **[Kilo Chat](https://app.kilo.ai)** requires no setup — just open the web app. For other platforms, follow the relevant guide: + +- [Telegram](/docs/kiloclaw/chat-platforms/telegram) — about 2 minutes +- [Discord](/docs/kiloclaw/chat-platforms/discord) — about 10 minutes +- [Slack](/docs/kiloclaw/chat-platforms/slack) — about 15 minutes; always use the manifest + +{% callout type="tip" %} +If you're not sure which to pick, Kilo Chat (no setup) or Telegram (2 minutes) are the easiest options. +{% /callout %} + +--- + +## Set up Google OAuth + +This lets your Claw act as the bot Google account — sending email, reading calendar, and more. Takes about 15 minutes. + +Prerequisites: Docker is installed and running, and your bot Google account is already created. + +1. In the KiloClaw dashboard, go to **Settings → Google Account** and copy the Docker command shown. +2. Open a terminal and run the command. +3. Follow the steps in the console: + - At each step, confirm you're logged in to the bot account (check the top-right corner of the screen). + - After project creation, confirm you're in the correct project. + - The last step may look like it failed — this is expected. + +For full details, see the [Google setup guide](/docs/kiloclaw/development-tools/google). + +--- + +## Set up GitHub + +A dedicated bot GitHub account is strongly recommended. Takes about 7 minutes. + +**Create a Personal Access Token (PAT):** + +1. In GitHub, go to **Settings → Developer Settings → Personal Access Tokens → Classic → Generate new token**. +2. Select these scopes: `repo`, `workflow`, `write:org`, `read:user`. + +For full details, see the [GitHub setup guide](/docs/kiloclaw/development-tools/github). + +**Set up a private workspace repo:** + +Once GitHub is connected, ask your Claw to back up its workspace: + +> "Use your GitHub access to back up your workspace. Make it a GitHub repo and push it as a private repo. Add me as a member so I can see it. Then set up a cron job to pull, rebase, and push any changes at least once an hour." + +After sending that, redeploy from the dashboard to pick up the changes. + +--- + +## Grant email and calendar access + +After OAuth is set up, decide how much access to give your Claw to your personal accounts. + +| Option | What it does | Best for | Configured from | +| ----------------------- | --------------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------- | +| Forward select emails | A Gmail filter forwards specific senders or labels to the bot account | Targeted use cases like newsletter digests | Your personal account | +| Forward all email | Forwards your full inbox to the bot | Simpler setups where noise is acceptable | Bot account (destination) | +| Full account delegation | Gives the bot direct read/write access to your personal account | Maximum capability | Your personal account — Gmail Settings → Add a delegate | + +{% callout type="info" %} +Email forwarding is configured from the **destination** (bot) account. Account delegation is configured from the **source** (personal) account. +{% /callout %} + +**Push notifications:** by default, your Claw wakes up on every incoming email. If you'd prefer a digest (e.g., once at 7am), disable push notifications in **Settings → Google Account** on the [dashboard](/docs/kiloclaw/dashboard) — otherwise it processes each email as it arrives. + +**Google Calendar:** share your personal calendar from your personal Google account. Go to **Google Calendar → Settings → Settings for my calendars → [your calendar] → Share with specific people**, and add the bot account. + +--- + +## Enable auto-approval + +By default, KiloClaw asks for confirmation before every tool call. To let it act freely: + +1. In the dashboard, go to **Settings**, scroll to the bottom, and click **Edit Files → openclaw.json**. +2. Find the `Tools` section and set `security` to `full`: + +```json +"exec": { + "security": "full" +} +``` + +3. Save the file, then click **Restart** at the top of the page. Use Restart, not Redeploy. + +{% callout type="warning" %} +This setting can be wiped on redeploy. If auto-approval stops working after a redeploy, re-apply this change. +{% /callout %} + +--- + +## Prompt and schedule work + +**How to prompt your Claw:** just tell it in plain language what you want. Be specific. If you want it to remember something across sessions, tell it to write it down in a specific file. + +**Scheduling jobs:** tell your Claw when and what to do — for example: + +> "Every day at 7am, summarize my emails and send me a digest." + +Mentioning "cron job" helps it understand you want a recurring scheduled task. + +**Skills:** the OpenClaw Skills hub has pre-built capabilities you can add. The easiest way to install a skill is to just ask your Claw by name: + +> "Install the [skill name] skill." + +--- + +## Manage inference + +**Model picker:** Balanced is a good starting point. Frontier is more capable but significantly more expensive. + +You can also use your KiloPass credits — find this under **Profile** in the dashboard. From 3f89c990ab4f1b8dcdbd8e7a181dc70e9abb7a32 Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Wed, 1 Apr 2026 09:41:31 -0400 Subject: [PATCH 247/261] Apply suggestion from @alexkgold --- packages/kilo-docs/lib/nav/kiloclaw.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-docs/lib/nav/kiloclaw.ts b/packages/kilo-docs/lib/nav/kiloclaw.ts index c847e493447..fbb14f3bf13 100644 --- a/packages/kilo-docs/lib/nav/kiloclaw.ts +++ b/packages/kilo-docs/lib/nav/kiloclaw.ts @@ -7,7 +7,7 @@ export const KiloClawNav: NavSection[] = [ { href: "/kiloclaw/overview", children: "Overview" }, { href: "/kiloclaw/dashboard", children: "Dashboard" }, { href: "/kiloclaw/pre-installed-software", children: "Pre-installed Software" }, - { href: "/kiloclaw/suggested-configuration", children: "Suggested Configuration" }, + { href: "/kiloclaw/end-to-end", children: "End to End Config" }, { href: "/kiloclaw/control-ui/overview", children: "Control UI", From a9a2fbdb572dd499d659f707df0eb53ccd30337f Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Wed, 1 Apr 2026 09:45:33 -0400 Subject: [PATCH 248/261] docs(kilo-docs): replace blockquotes with code blocks for example prompts --- .../pages/kiloclaw/suggested-configuration.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md b/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md index 07b7d511178..f91b7ebe8e2 100644 --- a/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md +++ b/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md @@ -38,7 +38,7 @@ The steps below walk you through this configuration. ## Preflight Steps -Take these steps before configuring your Claw. +Take these steps before configuring your Claw. If you are doing a [1-1 configuration call with Kilo](https://kilo.ai/kiloclaw/config-service), please complete these steps before the call. @@ -85,7 +85,7 @@ This lets your Claw act as the bot Google account — sending email, reading cal Prerequisites: Docker is installed and running, and your bot Google account is already created. 1. In the KiloClaw dashboard, go to **Settings → Google Account** and copy the Docker command shown. -2. Open a terminal and run the command. +2. Open a terminal and run the command. 3. Follow the steps in the console: - At each step, confirm you're logged in to the bot account (check the top-right corner of the screen). - After project creation, confirm you're in the correct project. @@ -110,7 +110,9 @@ For full details, see the [GitHub setup guide](/docs/kiloclaw/development-tools/ Once GitHub is connected, ask your Claw to back up its workspace: -> "Use your GitHub access to back up your workspace. Make it a GitHub repo and push it as a private repo. Add me as a member so I can see it. Then set up a cron job to pull, rebase, and push any changes at least once an hour." +``` +Use your GitHub access to back up your workspace. Make it a GitHub repo and push it as a private repo. Add me as a member so I can see it. Then set up a cron job to pull, rebase, and push any changes at least once an hour. +``` After sending that, redeploy from the dashboard to pick up the changes. @@ -163,13 +165,17 @@ This setting can be wiped on redeploy. If auto-approval stops working after a re **Scheduling jobs:** tell your Claw when and what to do — for example: -> "Every day at 7am, summarize my emails and send me a digest." +``` +Every day at 7am, summarize my emails and send me a digest. +``` Mentioning "cron job" helps it understand you want a recurring scheduled task. **Skills:** the OpenClaw Skills hub has pre-built capabilities you can add. The easiest way to install a skill is to just ask your Claw by name: -> "Install the [skill name] skill." +``` +Install the [skill name] skill. +``` --- From c8a650a759caae3f19f6ad6107177113af41860c Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Wed, 1 Apr 2026 09:46:40 -0400 Subject: [PATCH 249/261] docs(kilo-docs): exclude console.cloud.google.com from link checker --- packages/kilo-docs/lychee.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/kilo-docs/lychee.toml b/packages/kilo-docs/lychee.toml index dccd254c000..9d082c95adb 100644 --- a/packages/kilo-docs/lychee.toml +++ b/packages/kilo-docs/lychee.toml @@ -34,4 +34,6 @@ exclude = [ '^https?://vercel\.link/', # API base URL, returns 404 when fetched directly '^https?://api\.apertis\.ai/v1/?$', + # Redirects to authenticated Google Cloud console + '^https?://console\.cloud\.google\.com', ] From cde54482b53196d500b7ee9abd9b7fb6852dd7a9 Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Wed, 1 Apr 2026 09:47:19 -0400 Subject: [PATCH 250/261] docs(kilo-docs): update auto-approval instructions to use dashboard UI --- .../pages/kiloclaw/suggested-configuration.md | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md b/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md index f91b7ebe8e2..fa32037e7aa 100644 --- a/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md +++ b/packages/kilo-docs/pages/kiloclaw/suggested-configuration.md @@ -140,22 +140,7 @@ Email forwarding is configured from the **destination** (bot) account. Account d ## Enable auto-approval -By default, KiloClaw asks for confirmation before every tool call. To let it act freely: - -1. In the dashboard, go to **Settings**, scroll to the bottom, and click **Edit Files → openclaw.json**. -2. Find the `Tools` section and set `security` to `full`: - -```json -"exec": { - "security": "full" -} -``` - -3. Save the file, then click **Restart** at the top of the page. Use Restart, not Redeploy. - -{% callout type="warning" %} -This setting can be wiped on redeploy. If auto-approval stops working after a redeploy, re-apply this change. -{% /callout %} +By default, KiloClaw asks for confirmation before every tool call. To let it act freely, go to the [KiloClaw dashboard](https://app.kilo.ai/claw) and enable auto-approval in the **Default Permissions** section. --- From 8c1926c1a06a93a61d86a277906f78d9d0c1c9f6 Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Wed, 1 Apr 2026 09:53:56 -0400 Subject: [PATCH 251/261] docs(kilo-docs): add blockquote styles and restore blockquote syntax for example prompts --- .../kilo-docs/pages/kiloclaw/end-to-end.md | 147 ++++++++++++++++++ packages/kilo-docs/public/globals.css | 9 ++ 2 files changed, 156 insertions(+) create mode 100644 packages/kilo-docs/pages/kiloclaw/end-to-end.md diff --git a/packages/kilo-docs/pages/kiloclaw/end-to-end.md b/packages/kilo-docs/pages/kiloclaw/end-to-end.md new file mode 100644 index 00000000000..c05fdf49bb0 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/end-to-end.md @@ -0,0 +1,147 @@ +--- +title: "Setup walkthrough" +description: "Start-to-finish guide for configuring your KiloClaw instance" +--- + +# Setup walkthrough + +This guide walks you through a full KiloClaw setup — from creating accounts to scheduling your first automated workflow. Plan for about 60 minutes. + +## Planning your setup + +For most users, a useful KiloClaw configuration involves: + +1. A **chat platform** (called a "channel" in OpenClaw) so you can message your Claw +2. **Google services** for email, calendar, and Drive +3. **GitHub** for code and markdown syncing + +### Use dedicated accounts for your Claw + +We recommend creating **separate accounts** for your KiloClaw rather than connecting it to your personal accounts. This applies to Google, GitHub, and any other services you connect. A dedicated account improves isolation — your personal data stays separate, and you can control exactly what access the Claw has by sharing or delegating only what you want. + +### Chat platform options + +- **[Kilo Chat](https://app.kilo.ai)** — available in the web app and coming soon to iOS and Android; requires zero configuration +- **[Telegram](/docs/kiloclaw/chat-platforms/telegram)** — easy to set up, private by default +- **[Discord](/docs/kiloclaw/chat-platforms/discord)** — moderate setup +- **[Slack](/docs/kiloclaw/chat-platforms/slack)** — most involved setup + +{% callout type="warning" title="Chain-of-connection security" %} +If your Claw has access to sensitive data (like your email), be careful which chat platform you connect it to. On broadly-accessible platforms like Slack or Discord, anyone on the server could potentially message your Claw and access that data. If you're connecting sensitive integrations, use a private platform like Kilo Chat or Telegram. +{% /callout %} + +The steps below walk you through this configuration. + +## Preflight Steps + +Take these steps before configuring your Claw. + +If you are doing a [1-1 configuration call with Kilo](https://kilo.ai/kiloclaw/config-service), please complete these steps before the call. + +### Google + +Configuring Google services is by far the most involved part of setting up your Claw. + +Before configuring, take these preflight steps: + +1. **Create a Google Account for your Claw** — Go to [google.com](https://www.google.com/) and create a new Google/Gmail account dedicated to your KiloClaw. Something like `yourname.bot@gmail.com` works well. + +2. **Set up Google Cloud** — Visit [console.cloud.google.com](https://console.cloud.google.com). Accept the terms of service and click "Start my free tier". You may need to add a credit card for identity verification. + + {% callout type="info" %} + Nothing KiloClaw does costs any money with Google. + {% /callout %} + +3. **Install Docker** — KiloClaw configures Google by running a Docker container on your machine. Download Docker at [docker.com](https://www.docker.com/), then open it. You don't need to sign in or create a Docker account. + +## Other Services + +1. **Create a GitHub account for your Claw** — Using your new Gmail address, create a matching GitHub account for your Claw. + +## Set up a messaging platform + +Your Claw needs a way to communicate with you. **[Kilo Chat](https://app.kilo.ai)** requires no setup — just open the web app. For other platforms, follow the relevant guide: + +- [Telegram](/docs/kiloclaw/chat-platforms/telegram) — about 2 minutes +- [Discord](/docs/kiloclaw/chat-platforms/discord) — about 10 minutes +- [Slack](/docs/kiloclaw/chat-platforms/slack) — about 15 minutes; always use the manifest + +{% callout type="tip" %} +If you're not sure which to pick, Kilo Chat (no setup) or Telegram (2 minutes) are the easiest options. +{% /callout %} + +## Set up Google OAuth + +This lets your Claw act as the bot Google account — sending email, reading calendar, and more. Takes about 15 minutes. + +Prerequisites: Docker is installed and running, and your bot Google account is already created. + +1. In the KiloClaw dashboard, go to **Settings → Google Account** and copy the Docker command shown. +2. Open a terminal and run the command. +3. Follow the steps in the console: + - At each step, confirm you're logged in to the bot account (check the top-right corner of the screen). + - After project creation, confirm you're in the correct project. + - The last step may look like it failed — this is expected. + +For full details, see the [Google setup guide](/docs/kiloclaw/development-tools/google). + +## Set up GitHub + +A dedicated bot GitHub account is strongly recommended. Takes about 7 minutes. + +**Create a Personal Access Token (PAT):** + +1. In GitHub, go to **Settings → Developer Settings → Personal Access Tokens → Classic → Generate new token**. +2. Select these scopes: `repo`, `workflow`, `write:org`, `read:user`. + +For full details, see the [GitHub setup guide](/docs/kiloclaw/development-tools/github). + +**Set up a private workspace repo:** + +Once GitHub is connected, ask your Claw to back up its workspace: + +> Use your GitHub access to back up your workspace. Make it a GitHub repo and push it as a private repo. Add me as a member so I can see it. Then set up a cron job to pull, rebase, and push any changes at least once an hour. + +After sending that, redeploy from the dashboard to pick up the changes. + +## Grant email and calendar access + +After OAuth is set up, decide how much access to give your Claw to your personal accounts. + +| Option | What it does | Best for | Configured from | +| ----------------------- | --------------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------- | +| Forward select emails | A Gmail filter forwards specific senders or labels to the bot account | Targeted use cases like newsletter digests | Your personal account | +| Forward all email | Forwards your full inbox to the bot | Simpler setups where noise is acceptable | Bot account (destination) | +| Full account delegation | Gives the bot direct read/write access to your personal account | Maximum capability | Your personal account — Gmail Settings → Add a delegate | + +{% callout type="info" %} +Email forwarding is configured from the **destination** (bot) account. Account delegation is configured from the **source** (personal) account. +{% /callout %} + +**Push notifications:** by default, your Claw wakes up on every incoming email. If you'd prefer a digest (e.g., once at 7am), disable push notifications in **Settings → Google Account** on the [dashboard](/docs/kiloclaw/dashboard) — otherwise it processes each email as it arrives. + +**Google Calendar:** share your personal calendar from your personal Google account. Go to **Google Calendar → Settings → Settings for my calendars → [your calendar] → Share with specific people**, and add the bot account. + +## Enable auto-approval + +By default, KiloClaw asks for confirmation before every tool call. To let it act freely, go to the [KiloClaw dashboard](https://app.kilo.ai/claw) and enable auto-approval in the **Default Permissions** section. + +## Prompt and schedule work + +- **How to prompt your Claw:** just tell it in plain language what you want. Be specific. If you want it to remember something across sessions, tell it to write it down in a specific file. + +- **Scheduling jobs:** tell your Claw when and what to do — for example: + +> Schedule a daily cron job at 7am to summarize my emails and send me a digest. + +Mentioning "cron job" helps it understand you want a recurring scheduled task. + +- **Skills:** the OpenClaw Skills hub has pre-built capabilities you can add. The easiest way to install a skill is to just ask your Claw by name: + +> Install the [skill name] skill. + +## Manage inference + +**Model picker:** Balanced is a good starting point. Frontier is more capable but significantly more expensive. + +You can also use your KiloPass credits — find this under **Profile** in the dashboard. diff --git a/packages/kilo-docs/public/globals.css b/packages/kilo-docs/public/globals.css index 1dd89b9e0a4..ecc0be3b3fc 100644 --- a/packages/kilo-docs/public/globals.css +++ b/packages/kilo-docs/public/globals.css @@ -182,6 +182,15 @@ a:hover { color: #dcdcaa; } +/* Blockquotes */ +.article-content blockquote { + border-left: 3px solid var(--border-color); + margin: 1em 0; + padding: 0.25em 1em; + color: var(--text-secondary); + font-style: italic; +} + /* Lists - Override Tailwind's reset to restore default list styling */ .article-content ul, .article-content ol { From 5880e49a2cd9f212d79aba7d969558e343f00b86 Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Wed, 1 Apr 2026 09:55:01 -0400 Subject: [PATCH 252/261] docs(kilo-docs): convert cron job tip to callout --- packages/kilo-docs/pages/kiloclaw/end-to-end.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/kilo-docs/pages/kiloclaw/end-to-end.md b/packages/kilo-docs/pages/kiloclaw/end-to-end.md index c05fdf49bb0..d59420f20a5 100644 --- a/packages/kilo-docs/pages/kiloclaw/end-to-end.md +++ b/packages/kilo-docs/pages/kiloclaw/end-to-end.md @@ -134,7 +134,9 @@ By default, KiloClaw asks for confirmation before every tool call. To let it act > Schedule a daily cron job at 7am to summarize my emails and send me a digest. +{% callout type="tip" %} Mentioning "cron job" helps it understand you want a recurring scheduled task. +{% /callout %} - **Skills:** the OpenClaw Skills hub has pre-built capabilities you can add. The easiest way to install a skill is to just ask your Claw by name: From f7db04856b89a742cd4912c4646fe13fa680a6cd Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Wed, 1 Apr 2026 09:55:30 -0400 Subject: [PATCH 253/261] docs(kilo-docs): clarify skills description and add Bytes library link --- packages/kilo-docs/pages/kiloclaw/end-to-end.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/kilo-docs/pages/kiloclaw/end-to-end.md b/packages/kilo-docs/pages/kiloclaw/end-to-end.md index d59420f20a5..9490505928c 100644 --- a/packages/kilo-docs/pages/kiloclaw/end-to-end.md +++ b/packages/kilo-docs/pages/kiloclaw/end-to-end.md @@ -138,10 +138,12 @@ By default, KiloClaw asks for confirmation before every tool call. To let it act Mentioning "cron job" helps it understand you want a recurring scheduled task. {% /callout %} -- **Skills:** the OpenClaw Skills hub has pre-built capabilities you can add. The easiest way to install a skill is to just ask your Claw by name: +- **Skills:** Pre-configured capabilities designed to extend what your Claw can do — things like triaging email, summarizing documents, or managing GitHub issues. The easiest way to install a skill is to just ask your Claw by name: > Install the [skill name] skill. +You can explore popular skills and use case inspiration at the [KiloClaw Bytes library](https://kilo.ai/kiloclaw/bytes). + ## Manage inference **Model picker:** Balanced is a good starting point. Frontier is more capable but significantly more expensive. From 48bd451358e3af74eeccf0a0e96a1c4fd47895ac Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Wed, 1 Apr 2026 09:56:49 -0400 Subject: [PATCH 254/261] docs(kilo-docs): clarify skills can be installed or custom-built --- packages/kilo-docs/pages/kiloclaw/end-to-end.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kilo-docs/pages/kiloclaw/end-to-end.md b/packages/kilo-docs/pages/kiloclaw/end-to-end.md index 9490505928c..42c035d5224 100644 --- a/packages/kilo-docs/pages/kiloclaw/end-to-end.md +++ b/packages/kilo-docs/pages/kiloclaw/end-to-end.md @@ -138,11 +138,11 @@ By default, KiloClaw asks for confirmation before every tool call. To let it act Mentioning "cron job" helps it understand you want a recurring scheduled task. {% /callout %} -- **Skills:** Pre-configured capabilities designed to extend what your Claw can do — things like triaging email, summarizing documents, or managing GitHub issues. The easiest way to install a skill is to just ask your Claw by name: +- **Skills:** Reusable capabilities that extend what your Claw can do — things like triaging email, summarizing documents, or managing GitHub issues. You can install a pre-built skill by asking your Claw: > Install the [skill name] skill. -You can explore popular skills and use case inspiration at the [KiloClaw Bytes library](https://kilo.ai/kiloclaw/bytes). +Or ask your Claw to build a custom skill from scratch — it has a built-in skill-builder skill for exactly this. You can explore popular skills and use case inspiration at the [KiloClaw Bytes library](https://kilo.ai/kiloclaw/bytes). ## Manage inference From 7037d226758ade70f3969a9e11ee1f21806de2d3 Mon Sep 17 00:00:00 2001 From: Alex Gold Date: Wed, 1 Apr 2026 09:57:33 -0400 Subject: [PATCH 255/261] docs(kilo-docs): convert prompt/scheduling/skills bullets to h3 sections --- packages/kilo-docs/pages/kiloclaw/end-to-end.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/kilo-docs/pages/kiloclaw/end-to-end.md b/packages/kilo-docs/pages/kiloclaw/end-to-end.md index 42c035d5224..5aa0e1913d8 100644 --- a/packages/kilo-docs/pages/kiloclaw/end-to-end.md +++ b/packages/kilo-docs/pages/kiloclaw/end-to-end.md @@ -128,9 +128,13 @@ By default, KiloClaw asks for confirmation before every tool call. To let it act ## Prompt and schedule work -- **How to prompt your Claw:** just tell it in plain language what you want. Be specific. If you want it to remember something across sessions, tell it to write it down in a specific file. +### How to prompt your Claw -- **Scheduling jobs:** tell your Claw when and what to do — for example: +Just tell it in plain language what you want. Be specific. If you want it to remember something across sessions, tell it to write it down in a specific file. + +### Scheduling jobs + +Tell your Claw when and what to do — for example: > Schedule a daily cron job at 7am to summarize my emails and send me a digest. @@ -138,7 +142,9 @@ By default, KiloClaw asks for confirmation before every tool call. To let it act Mentioning "cron job" helps it understand you want a recurring scheduled task. {% /callout %} -- **Skills:** Reusable capabilities that extend what your Claw can do — things like triaging email, summarizing documents, or managing GitHub issues. You can install a pre-built skill by asking your Claw: +### Skills + +Reusable capabilities that extend what your Claw can do — things like triaging email, summarizing documents, or managing GitHub issues. You can install a pre-built skill by asking your Claw: > Install the [skill name] skill. From c7dd3a4f41353fd8a9c2c1c42c574c468e765d66 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 14:04:38 +0000 Subject: [PATCH 256/261] fix: hide cmd.exe window when opening browser during login on Windows Replace the 'open' package with a platform-specific exec call using windowsHide: true in device-auth-tui.ts, preventing the black terminal flash during the OAuth login flow on Windows. Closes #8078 --- packages/kilo-gateway/src/auth/device-auth-tui.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/kilo-gateway/src/auth/device-auth-tui.ts b/packages/kilo-gateway/src/auth/device-auth-tui.ts index 8d233f26b82..2fe54c01789 100644 --- a/packages/kilo-gateway/src/auth/device-auth-tui.ts +++ b/packages/kilo-gateway/src/auth/device-auth-tui.ts @@ -1,4 +1,4 @@ -import open from "open" +import { exec } from "child_process" import type { DeviceAuthInitiateResponse, DeviceAuthPollResponse } from "../types.js" import { poll } from "./polling.js" import { getKiloProfile, getKiloDefaultModel } from "../api/profile.js" @@ -70,10 +70,14 @@ export async function authenticateWithDeviceAuthTUI(inputs?: Record { - // Silently fail if browser can't be opened - user can manually open URL - }) + // Step 2: Open browser (windowsHide: true prevents cmd.exe flash on Windows) + const openCmd = + process.platform === "darwin" + ? `open "${verificationUrl}"` + : process.platform === "win32" + ? `start "" "${verificationUrl}"` + : `xdg-open "${verificationUrl}"` + exec(openCmd, { windowsHide: true }) // Step 3: Return instructions and callback for TUI to handle return { From bc4a7ce7e5b257248222e2b80aa8d6a3c08d2088 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Wed, 1 Apr 2026 16:20:19 +0200 Subject: [PATCH 257/261] fix(gateway): prevent shell injection in device auth URL opening --- packages/kilo-gateway/src/auth/device-auth-tui.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/kilo-gateway/src/auth/device-auth-tui.ts b/packages/kilo-gateway/src/auth/device-auth-tui.ts index 2fe54c01789..466aca7baaf 100644 --- a/packages/kilo-gateway/src/auth/device-auth-tui.ts +++ b/packages/kilo-gateway/src/auth/device-auth-tui.ts @@ -1,4 +1,4 @@ -import { exec } from "child_process" +import { execFile } from "child_process" import type { DeviceAuthInitiateResponse, DeviceAuthPollResponse } from "../types.js" import { poll } from "./polling.js" import { getKiloProfile, getKiloDefaultModel } from "../api/profile.js" @@ -71,13 +71,13 @@ export async function authenticateWithDeviceAuthTUI(inputs?: Record Date: Wed, 1 Apr 2026 14:37:43 +0000 Subject: [PATCH 258/261] release: v7.1.16 --- bun.lock | 32 +++++++++++++------------- package.json | 2 +- packages/app/package.json | 2 +- packages/desktop-electron/package.json | 2 +- packages/desktop/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++----- packages/kilo-docs/package.json | 2 +- packages/kilo-gateway/package.json | 2 +- packages/kilo-i18n/package.json | 2 +- packages/kilo-telemetry/package.json | 2 +- packages/kilo-ui/package.json | 2 +- packages/kilo-vscode/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/script/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/storybook/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- script/upstream/package.json | 2 +- sdks/vscode/package.json | 2 +- 21 files changed, 41 insertions(+), 41 deletions(-) diff --git a/bun.lock b/bun.lock index 29e645c7267..c2910e1f83a 100644 --- a/bun.lock +++ b/bun.lock @@ -27,7 +27,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "@kilocode/kilo-i18n": "workspace:*", "@kilocode/kilo-ui": "workspace:*", @@ -79,7 +79,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -112,7 +112,7 @@ }, "packages/desktop-electron": { "name": "@opencode-ai/desktop-electron", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -142,7 +142,7 @@ }, "packages/kilo-docs": { "name": "@kilocode/kilo-docs", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "@docsearch/css": "^4", "@docsearch/js": "^4", @@ -171,7 +171,7 @@ }, "packages/kilo-gateway": { "name": "@kilocode/kilo-gateway", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "@ai-sdk/anthropic": "2.0.65", "@ai-sdk/openai": "2.0.101", @@ -206,7 +206,7 @@ }, "packages/kilo-i18n": { "name": "@kilocode/kilo-i18n", - "version": "7.1.15", + "version": "7.1.16", "devDependencies": { "@tsconfig/node22": "catalog:", "@types/bun": "catalog:", @@ -216,7 +216,7 @@ }, "packages/kilo-telemetry": { "name": "@kilocode/kilo-telemetry", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "@kilocode/kilo-gateway": "workspace:*", "@opentelemetry/api": "1.9.0", @@ -236,7 +236,7 @@ }, "packages/kilo-ui": { "name": "@kilocode/kilo-ui", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "@kobalte/core": "0.13.11", "@opencode-ai/util": "workspace:*", @@ -271,7 +271,7 @@ }, "packages/kilo-vscode": { "name": "kilo-code", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "@anthropic-ai/sdk": "^0.39.0", "@kilocode/kilo-i18n": "workspace:*", @@ -324,7 +324,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "7.1.15", + "version": "7.1.16", "bin": { "kilo": "./bin/kilo", "kilocode": "./bin/kilo", @@ -446,7 +446,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "@kilocode/sdk": "workspace:*", "zod": "catalog:", @@ -460,14 +460,14 @@ }, "packages/script": { "name": "@opencode-ai/script", - "version": "7.1.15", + "version": "7.1.16", "devDependencies": { "@types/bun": "catalog:", }, }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "7.1.15", + "version": "7.1.16", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -478,7 +478,7 @@ }, "packages/storybook": { "name": "@opencode-ai/storybook", - "version": "7.1.15", + "version": "7.1.16", "devDependencies": { "@opencode-ai/ui": "workspace:*", "@solidjs/meta": "catalog:", @@ -501,7 +501,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -548,7 +548,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "7.1.15", + "version": "7.1.16", "dependencies": { "zod": "catalog:", }, diff --git a/package.json b/package.json index 3380c161a85..16432bc4898 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,6 @@ "@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch", "ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch" }, - "version": "7.1.15", + "version": "7.1.16", "peerDependencies": {} } diff --git a/packages/app/package.json b/packages/app/package.json index 43e10c314ec..2e119069a84 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "7.1.15", + "version": "7.1.16", "description": "", "type": "module", "exports": { diff --git a/packages/desktop-electron/package.json b/packages/desktop-electron/package.json index a5017994faf..9ea4ddaac2d 100644 --- a/packages/desktop-electron/package.json +++ b/packages/desktop-electron/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop-electron", "private": true, - "version": "7.1.15", + "version": "7.1.16", "type": "module", "license": "MIT", "homepage": "https://opencode.ai", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 9a91250595d..dbaa1f1e4fb 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "7.1.15", + "version": "7.1.16", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index a797d0da4a1..9d9d4ba6151 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "kilo" name = "Kilo" description = "The open source coding agent." -version = "7.1.15" +version = "7.1.16" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/Kilo-Org/kilocode" @@ -11,26 +11,26 @@ name = "Kilo" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.15/opencode-darwin-arm64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.16/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.15/opencode-darwin-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.16/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.15/opencode-linux-arm64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.16/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.15/opencode-linux-x64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.16/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.15/opencode-windows-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.16/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/kilo-docs/package.json b/packages/kilo-docs/package.json index c69c2ec57ca..ce775d01ce1 100644 --- a/packages/kilo-docs/package.json +++ b/packages/kilo-docs/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-docs", - "version": "7.1.15", + "version": "7.1.16", "private": true, "scripts": { "dev": "next dev --webpack --port 3002", diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index 392111ab4db..fea50703ef9 100644 --- a/packages/kilo-gateway/package.json +++ b/packages/kilo-gateway/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-gateway", - "version": "7.1.15", + "version": "7.1.16", "type": "module", "license": "MIT", "description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration", diff --git a/packages/kilo-i18n/package.json b/packages/kilo-i18n/package.json index 2efa472ebbb..aa8a3a400d3 100644 --- a/packages/kilo-i18n/package.json +++ b/packages/kilo-i18n/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-i18n", - "version": "7.1.15", + "version": "7.1.16", "type": "module", "license": "MIT", "description": "Kilo-specific i18n translations and overrides", diff --git a/packages/kilo-telemetry/package.json b/packages/kilo-telemetry/package.json index 73888ca4caf..da443cfb92f 100644 --- a/packages/kilo-telemetry/package.json +++ b/packages/kilo-telemetry/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-telemetry", - "version": "7.1.15", + "version": "7.1.16", "type": "module", "license": "MIT", "description": "Telemetry for Kilo CLI - PostHog analytics integration", diff --git a/packages/kilo-ui/package.json b/packages/kilo-ui/package.json index 05f2ebd984f..02e5ecaa355 100644 --- a/packages/kilo-ui/package.json +++ b/packages/kilo-ui/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-ui", - "version": "7.1.15", + "version": "7.1.16", "type": "module", "license": "MIT", "exports": { diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 441513479a2..e5d6a18a142 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -2,7 +2,7 @@ "name": "kilo-code", "displayName": "Kilo Code: AI Coding Agent, Copilot, and Autocomplete", "description": "Open Source AI coding agent that generates code from natural language, automates tasks, and runs terminal commands. Features inline autocomplete, browser automation, automated refactoring, and custom modes for planning, coding, and debugging. Supports 500+ AI models including Claude (Anthropic), Gemini, Grok, GPT, Codex and GLM.", - "version": "7.1.15", + "version": "7.1.16", "icon": "assets/icons/logo-outline-black.png", "galleryBanner": { "color": "#FFFFFF", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 8fd164c1057..9a4776e1a79 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.1.15", + "version": "7.1.16", "name": "@kilocode/cli", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 742f1148dc8..30e54b4ae1f 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/plugin", - "version": "7.1.15", + "version": "7.1.16", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/script/package.json b/packages/script/package.json index ff6e2d161c9..d3a9fa6232b 100644 --- a/packages/script/package.json +++ b/packages/script/package.json @@ -8,7 +8,7 @@ "exports": { ".": "./src/index.ts" }, - "version": "7.1.15", + "version": "7.1.16", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index b976bab77b3..b98bdea7dfa 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/sdk", - "version": "7.1.15", + "version": "7.1.16", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/storybook/package.json b/packages/storybook/package.json index 98326e90d96..01517273bcf 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -26,7 +26,7 @@ "typescript": "catalog:", "vite": "catalog:" }, - "version": "7.1.15", + "version": "7.1.16", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/ui/package.json b/packages/ui/package.json index 8ea95dd6ec6..9c9c414ba73 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "7.1.15", + "version": "7.1.16", "type": "module", "license": "MIT", "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index 63b3305ad70..bec18dc9f51 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "7.1.15", + "version": "7.1.16", "private": true, "type": "module", "license": "MIT", diff --git a/script/upstream/package.json b/script/upstream/package.json index 219290beb88..bae36643fb2 100644 --- a/script/upstream/package.json +++ b/script/upstream/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/upstream-merge", - "version": "7.1.15", + "version": "7.1.16", "private": true, "type": "module", "description": "Scripts for automating upstream opencode merges into Kilo", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 951ffd258e6..10f3a47980f 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "7.1.15", + "version": "7.1.16", "publisher": "sst-dev", "repository": { "type": "git", From 8f7a5f48b32b17f5bbc890144c89dc42a2cbf212 Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Wed, 1 Apr 2026 15:08:40 +0000 Subject: [PATCH 259/261] release: v7.1.17 --- bun.lock | 32 +++++++++++++------------- package.json | 2 +- packages/app/package.json | 2 +- packages/desktop-electron/package.json | 2 +- packages/desktop/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++----- packages/kilo-docs/package.json | 2 +- packages/kilo-gateway/package.json | 2 +- packages/kilo-i18n/package.json | 2 +- packages/kilo-telemetry/package.json | 2 +- packages/kilo-ui/package.json | 2 +- packages/kilo-vscode/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/script/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/storybook/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- script/upstream/package.json | 2 +- sdks/vscode/package.json | 2 +- 21 files changed, 41 insertions(+), 41 deletions(-) diff --git a/bun.lock b/bun.lock index c2910e1f83a..a78c9245ce4 100644 --- a/bun.lock +++ b/bun.lock @@ -27,7 +27,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "@kilocode/kilo-i18n": "workspace:*", "@kilocode/kilo-ui": "workspace:*", @@ -79,7 +79,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -112,7 +112,7 @@ }, "packages/desktop-electron": { "name": "@opencode-ai/desktop-electron", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -142,7 +142,7 @@ }, "packages/kilo-docs": { "name": "@kilocode/kilo-docs", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "@docsearch/css": "^4", "@docsearch/js": "^4", @@ -171,7 +171,7 @@ }, "packages/kilo-gateway": { "name": "@kilocode/kilo-gateway", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "@ai-sdk/anthropic": "2.0.65", "@ai-sdk/openai": "2.0.101", @@ -206,7 +206,7 @@ }, "packages/kilo-i18n": { "name": "@kilocode/kilo-i18n", - "version": "7.1.16", + "version": "7.1.17", "devDependencies": { "@tsconfig/node22": "catalog:", "@types/bun": "catalog:", @@ -216,7 +216,7 @@ }, "packages/kilo-telemetry": { "name": "@kilocode/kilo-telemetry", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "@kilocode/kilo-gateway": "workspace:*", "@opentelemetry/api": "1.9.0", @@ -236,7 +236,7 @@ }, "packages/kilo-ui": { "name": "@kilocode/kilo-ui", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "@kobalte/core": "0.13.11", "@opencode-ai/util": "workspace:*", @@ -271,7 +271,7 @@ }, "packages/kilo-vscode": { "name": "kilo-code", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "@anthropic-ai/sdk": "^0.39.0", "@kilocode/kilo-i18n": "workspace:*", @@ -324,7 +324,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "7.1.16", + "version": "7.1.17", "bin": { "kilo": "./bin/kilo", "kilocode": "./bin/kilo", @@ -446,7 +446,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "@kilocode/sdk": "workspace:*", "zod": "catalog:", @@ -460,14 +460,14 @@ }, "packages/script": { "name": "@opencode-ai/script", - "version": "7.1.16", + "version": "7.1.17", "devDependencies": { "@types/bun": "catalog:", }, }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "7.1.16", + "version": "7.1.17", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -478,7 +478,7 @@ }, "packages/storybook": { "name": "@opencode-ai/storybook", - "version": "7.1.16", + "version": "7.1.17", "devDependencies": { "@opencode-ai/ui": "workspace:*", "@solidjs/meta": "catalog:", @@ -501,7 +501,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -548,7 +548,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "7.1.16", + "version": "7.1.17", "dependencies": { "zod": "catalog:", }, diff --git a/package.json b/package.json index 16432bc4898..6d7a5456a88 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,6 @@ "@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch", "ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch" }, - "version": "7.1.16", + "version": "7.1.17", "peerDependencies": {} } diff --git a/packages/app/package.json b/packages/app/package.json index 2e119069a84..4db29fe66dd 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "7.1.16", + "version": "7.1.17", "description": "", "type": "module", "exports": { diff --git a/packages/desktop-electron/package.json b/packages/desktop-electron/package.json index 9ea4ddaac2d..e470046d6c9 100644 --- a/packages/desktop-electron/package.json +++ b/packages/desktop-electron/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop-electron", "private": true, - "version": "7.1.16", + "version": "7.1.17", "type": "module", "license": "MIT", "homepage": "https://opencode.ai", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index dbaa1f1e4fb..b48367a8c38 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "7.1.16", + "version": "7.1.17", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 9d9d4ba6151..ad9a1bb894f 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "kilo" name = "Kilo" description = "The open source coding agent." -version = "7.1.16" +version = "7.1.17" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/Kilo-Org/kilocode" @@ -11,26 +11,26 @@ name = "Kilo" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.16/opencode-darwin-arm64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.17/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.16/opencode-darwin-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.17/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.16/opencode-linux-arm64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.17/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.16/opencode-linux-x64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.17/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.16/opencode-windows-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.17/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/kilo-docs/package.json b/packages/kilo-docs/package.json index ce775d01ce1..be6ab93c9f4 100644 --- a/packages/kilo-docs/package.json +++ b/packages/kilo-docs/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-docs", - "version": "7.1.16", + "version": "7.1.17", "private": true, "scripts": { "dev": "next dev --webpack --port 3002", diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index fea50703ef9..e4c6bc17e36 100644 --- a/packages/kilo-gateway/package.json +++ b/packages/kilo-gateway/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-gateway", - "version": "7.1.16", + "version": "7.1.17", "type": "module", "license": "MIT", "description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration", diff --git a/packages/kilo-i18n/package.json b/packages/kilo-i18n/package.json index aa8a3a400d3..65b6485f300 100644 --- a/packages/kilo-i18n/package.json +++ b/packages/kilo-i18n/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-i18n", - "version": "7.1.16", + "version": "7.1.17", "type": "module", "license": "MIT", "description": "Kilo-specific i18n translations and overrides", diff --git a/packages/kilo-telemetry/package.json b/packages/kilo-telemetry/package.json index da443cfb92f..15bf57d2d65 100644 --- a/packages/kilo-telemetry/package.json +++ b/packages/kilo-telemetry/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-telemetry", - "version": "7.1.16", + "version": "7.1.17", "type": "module", "license": "MIT", "description": "Telemetry for Kilo CLI - PostHog analytics integration", diff --git a/packages/kilo-ui/package.json b/packages/kilo-ui/package.json index 02e5ecaa355..eddf942797e 100644 --- a/packages/kilo-ui/package.json +++ b/packages/kilo-ui/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-ui", - "version": "7.1.16", + "version": "7.1.17", "type": "module", "license": "MIT", "exports": { diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index e5d6a18a142..f459d109308 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -2,7 +2,7 @@ "name": "kilo-code", "displayName": "Kilo Code: AI Coding Agent, Copilot, and Autocomplete", "description": "Open Source AI coding agent that generates code from natural language, automates tasks, and runs terminal commands. Features inline autocomplete, browser automation, automated refactoring, and custom modes for planning, coding, and debugging. Supports 500+ AI models including Claude (Anthropic), Gemini, Grok, GPT, Codex and GLM.", - "version": "7.1.16", + "version": "7.1.17", "icon": "assets/icons/logo-outline-black.png", "galleryBanner": { "color": "#FFFFFF", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 9a4776e1a79..5d184292e35 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.1.16", + "version": "7.1.17", "name": "@kilocode/cli", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 30e54b4ae1f..eebe82055b1 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/plugin", - "version": "7.1.16", + "version": "7.1.17", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/script/package.json b/packages/script/package.json index d3a9fa6232b..bfd0b0b897a 100644 --- a/packages/script/package.json +++ b/packages/script/package.json @@ -8,7 +8,7 @@ "exports": { ".": "./src/index.ts" }, - "version": "7.1.16", + "version": "7.1.17", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index b98bdea7dfa..c432673ea6f 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/sdk", - "version": "7.1.16", + "version": "7.1.17", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/storybook/package.json b/packages/storybook/package.json index 01517273bcf..86a9be17c54 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -26,7 +26,7 @@ "typescript": "catalog:", "vite": "catalog:" }, - "version": "7.1.16", + "version": "7.1.17", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/ui/package.json b/packages/ui/package.json index 9c9c414ba73..430c8f8d962 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "7.1.16", + "version": "7.1.17", "type": "module", "license": "MIT", "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index bec18dc9f51..86af46110ab 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "7.1.16", + "version": "7.1.17", "private": true, "type": "module", "license": "MIT", diff --git a/script/upstream/package.json b/script/upstream/package.json index bae36643fb2..2ce68402fe1 100644 --- a/script/upstream/package.json +++ b/script/upstream/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/upstream-merge", - "version": "7.1.16", + "version": "7.1.17", "private": true, "type": "module", "description": "Scripts for automating upstream opencode merges into Kilo", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 10f3a47980f..54aa097bc65 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "7.1.16", + "version": "7.1.17", "publisher": "sst-dev", "repository": { "type": "git", From ddc59419e65dbf5908cf92aa357cc516dec74bac Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 15:09:01 +0000 Subject: [PATCH 260/261] fix(i18n): update built-in mode banner translations to match #7720 Propagates the clarified built-in mode banner text from en.ts to all 15 other translation files. The new text explains that the base definition cannot be changed but overrides can be configured, replacing the misleading 'read-only definition' label. --- packages/kilo-vscode/webview-ui/src/i18n/ar.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/br.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/bs.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/da.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/de.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/es.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/fr.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/ja.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/ko.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/no.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/pl.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/ru.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/th.ts | 3 ++- packages/kilo-vscode/webview-ui/src/i18n/zh.ts | 2 +- packages/kilo-vscode/webview-ui/src/i18n/zht.ts | 2 +- 15 files changed, 28 insertions(+), 15 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index 5da7fb66400..96e3deb074d 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1102,7 +1102,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "موجه النظام", "settings.agentBehaviour.editMode.save": "تم", "settings.agentBehaviour.editMode.back": "العودة إلى القائمة", - "settings.agentBehaviour.editMode.native": "وضع مدمج (تعريف للقراءة فقط)", + "settings.agentBehaviour.editMode.native": + "هذا وضع مضمن. لا يمكن تغيير تعريفه الأساسي، ولكن يمكنك تكوين التجاوزات أدناه.", "settings.agentBehaviour.editMode.promptOverride": "تجاوز موجه مخصص لهذا الوضع المدمج", "settings.agentBehaviour.removeMode.title": "إزالة الوضع", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 69702b2a2b3..7b62a18e627 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1121,7 +1121,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "Prompt do Sistema", "settings.agentBehaviour.editMode.save": "Concluído", "settings.agentBehaviour.editMode.back": "Voltar à lista", - "settings.agentBehaviour.editMode.native": "Modo integrado (definição somente leitura)", + "settings.agentBehaviour.editMode.native": + "Este é um modo embutido. Sua definição base não pode ser alterada, mas você pode configurar as sobrescritas abaixo.", "settings.agentBehaviour.editMode.promptOverride": "Substituição de prompt personalizado para este modo integrado", "settings.agentBehaviour.removeMode.title": "Remover modo", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 7d2eae99486..3c5100613fa 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1119,7 +1119,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "Sistemski prompt", "settings.agentBehaviour.editMode.save": "Gotovo", "settings.agentBehaviour.editMode.back": "Nazad na listu", - "settings.agentBehaviour.editMode.native": "Ugrađeni mod (definicija samo za čitanje)", + "settings.agentBehaviour.editMode.native": + "Ovo je ugrađeni način rada. Njegova osnovna definicija ne može se mijenjati, ali ispod možete konfigurirati nadjačavanja.", "settings.agentBehaviour.editMode.promptOverride": "Prilagođeno nadjačavanje prompta za ovaj ugrađeni mod", "settings.agentBehaviour.removeMode.title": "Ukloni mod", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 3de9e50261d..0557602f220 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1112,7 +1112,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "Systemprompt", "settings.agentBehaviour.editMode.save": "Færdig", "settings.agentBehaviour.editMode.back": "Tilbage til listen", - "settings.agentBehaviour.editMode.native": "Indbygget tilstand (skrivebeskyttet definition)", + "settings.agentBehaviour.editMode.native": + "Dette er en indbygget tilstand. Dens grundlæggende definition kan ikke ændres, men du kan konfigurere tilsidesættelser nedenfor.", "settings.agentBehaviour.editMode.promptOverride": "Tilpasset prompt-tilsidesættelse for denne indbyggede tilstand", "settings.agentBehaviour.removeMode.title": "Fjern tilstand", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index ac2ddbe21ff..ac76bbf9822 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1133,7 +1133,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "System-Prompt", "settings.agentBehaviour.editMode.save": "Fertig", "settings.agentBehaviour.editMode.back": "Zurück zur Liste", - "settings.agentBehaviour.editMode.native": "Eingebauter Modus (schreibgeschützte Definition)", + "settings.agentBehaviour.editMode.native": + "Dies ist ein integrierter Modus. Seine Basisdefinition kann nicht geändert werden, aber Sie können unten Überschreibungen konfigurieren.", "settings.agentBehaviour.editMode.promptOverride": "Benutzerdefinierte Prompt-Überschreibung für diesen eingebauten Modus", "settings.agentBehaviour.removeMode.title": "Modus entfernen", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index f06ea5f57cc..8e8fd8d2bad 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1126,7 +1126,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "Prompt del sistema", "settings.agentBehaviour.editMode.save": "Listo", "settings.agentBehaviour.editMode.back": "Volver a la lista", - "settings.agentBehaviour.editMode.native": "Modo integrado (definición de solo lectura)", + "settings.agentBehaviour.editMode.native": + "Este es un modo integrado. Su definición base no se puede cambiar, pero puedes configurar sobreescrituras a continuación.", "settings.agentBehaviour.editMode.promptOverride": "Anulación de prompt personalizado para este modo integrado", "settings.agentBehaviour.removeMode.title": "Eliminar modo", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index cd3384534e7..b2a4da3632b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1138,7 +1138,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "Prompt système", "settings.agentBehaviour.editMode.save": "Terminé", "settings.agentBehaviour.editMode.back": "Retour à la liste", - "settings.agentBehaviour.editMode.native": "Mode intégré (définition en lecture seule)", + "settings.agentBehaviour.editMode.native": + "Il s'agit d'un mode intégré. Sa définition de base ne peut pas être modifiée, mais vous pouvez configurer des surcharges ci-dessous.", "settings.agentBehaviour.editMode.promptOverride": "Remplacement de prompt personnalisé pour ce mode intégré", "settings.agentBehaviour.removeMode.title": "Supprimer le mode", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index ae71f95c77a..c291aa11b61 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1114,7 +1114,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "システムプロンプト", "settings.agentBehaviour.editMode.save": "完了", "settings.agentBehaviour.editMode.back": "リストに戻る", - "settings.agentBehaviour.editMode.native": "組み込みモード(読み取り専用の定義)", + "settings.agentBehaviour.editMode.native": + "これは組み込みモードです。基本定義は変更できませんが、以下でオーバーライドを設定できます。", "settings.agentBehaviour.editMode.promptOverride": "この組み込みモードのカスタムプロンプト上書き", "settings.agentBehaviour.removeMode.title": "モードを削除", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 5f5230d6ce7..f4ed91ce951 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1108,7 +1108,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "시스템 프롬프트", "settings.agentBehaviour.editMode.save": "완료", "settings.agentBehaviour.editMode.back": "목록으로 돌아가기", - "settings.agentBehaviour.editMode.native": "내장 모드 (읽기 전용 정의)", + "settings.agentBehaviour.editMode.native": + "이것은 내장 모드입니다. 기본 정의는 변경할 수 없지만, 아래에서 재정의를 구성할 수 있습니다.", "settings.agentBehaviour.editMode.promptOverride": "이 내장 모드에 대한 사용자 지정 프롬프트 재정의", "settings.agentBehaviour.removeMode.title": "모드 제거", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 04ad8c62d0d..7ca68a7c5cc 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1115,7 +1115,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "Systemprompt", "settings.agentBehaviour.editMode.save": "Ferdig", "settings.agentBehaviour.editMode.back": "Tilbake til listen", - "settings.agentBehaviour.editMode.native": "Innebygd modus (skrivebeskyttet definisjon)", + "settings.agentBehaviour.editMode.native": + "Dette er en innebygd modus. Grunndefinisjonen kan ikke endres, men du kan konfigurere overstyringer nedenfor.", "settings.agentBehaviour.editMode.promptOverride": "Tilpasset prompt-overstyring for denne innebygde modusen", "settings.agentBehaviour.removeMode.title": "Fjern modus", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 8a9b5bc6b8b..967596b09c6 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1118,7 +1118,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "Prompt systemowy", "settings.agentBehaviour.editMode.save": "Gotowe", "settings.agentBehaviour.editMode.back": "Powrót do listy", - "settings.agentBehaviour.editMode.native": "Tryb wbudowany (definicja tylko do odczytu)", + "settings.agentBehaviour.editMode.native": + "To jest wbudowany tryb. Jego podstawowa definicja nie może zostać zmieniona, ale poniżej możesz skonfigurować nadpisania.", "settings.agentBehaviour.editMode.promptOverride": "Niestandardowe nadpisanie promptu dla tego wbudowanego trybu", "settings.agentBehaviour.removeMode.title": "Usuń tryb", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 84c0c77da63..42ab6a996a8 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1120,7 +1120,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "Системный промпт", "settings.agentBehaviour.editMode.save": "Готово", "settings.agentBehaviour.editMode.back": "Вернуться к списку", - "settings.agentBehaviour.editMode.native": "Встроенный режим (определение только для чтения)", + "settings.agentBehaviour.editMode.native": + "Это встроенный режим. Его базовое определение нельзя изменить, но вы можете настроить переопределения ниже.", "settings.agentBehaviour.editMode.promptOverride": "Пользовательское переопределение промпта для этого встроенного режима", "settings.agentBehaviour.removeMode.title": "Удалить режим", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 7157d028a2f..6f7cf03403e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1103,7 +1103,8 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "System Prompt", "settings.agentBehaviour.editMode.save": "เสร็จสิ้น", "settings.agentBehaviour.editMode.back": "กลับไปที่รายการ", - "settings.agentBehaviour.editMode.native": "โหมดในตัว (นิยามสำหรับอ่านอย่างเดียว)", + "settings.agentBehaviour.editMode.native": + "นี่คือโหมดในตัว ไม่สามารถเปลี่ยนคำจำกัดความพื้นฐานได้ แต่คุณสามารถกำหนดค่าการแทนที่ได้ที่ด้านล่าง", "settings.agentBehaviour.editMode.promptOverride": "การแทนที่ prompt แบบกำหนดเองสำหรับโหมดในตัวนี้", "settings.agentBehaviour.removeMode.title": "ลบโหมด", "settings.agentBehaviour.removeMode.confirm": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 5ee824f5842..4fe633f6356 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1091,7 +1091,7 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "系统提示", "settings.agentBehaviour.editMode.save": "完成", "settings.agentBehaviour.editMode.back": "返回列表", - "settings.agentBehaviour.editMode.native": "内置模式(只读定义)", + "settings.agentBehaviour.editMode.native": "这是一个内置模式。它的基础定义无法更改,但您可以在下方配置覆盖项。", "settings.agentBehaviour.editMode.promptOverride": "此内置模式的自定义提示覆盖", "settings.agentBehaviour.removeMode.title": "移除模式", "settings.agentBehaviour.removeMode.confirm": '移除模式 "{{name}}" 吗?这将通过更新配置来禁用该模式。', diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 809a47d8ef7..a9dba37eebf 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1094,7 +1094,7 @@ export const dict = { "settings.agentBehaviour.editMode.prompt": "系統提示", "settings.agentBehaviour.editMode.save": "完成", "settings.agentBehaviour.editMode.back": "返回列表", - "settings.agentBehaviour.editMode.native": "內建模式(唯讀定義)", + "settings.agentBehaviour.editMode.native": "這是一個內建模式。它的基礎定義無法更改,但您可以在下方設定覆寫項。", "settings.agentBehaviour.editMode.promptOverride": "此內建模式的自訂提示覆寫", "settings.agentBehaviour.removeMode.title": "移除模式", "settings.agentBehaviour.removeMode.confirm": '要移除模式 "{{name}}" 嗎?這將透過更新設定來停用該模式。', From 25358e4c28950c87ccbd4695b47a71c9ddbb5bf6 Mon Sep 17 00:00:00 2001 From: St0rmz1 Date: Wed, 1 Apr 2026 08:36:19 -0700 Subject: [PATCH 261/261] docs(kiloclaw): add Triggers section with webhooks documentation --- packages/kilo-docs/lib/nav/kiloclaw.ts | 8 ++ .../pages/kiloclaw/triggers/index.md | 32 +++++ .../pages/kiloclaw/triggers/webhooks.md | 110 ++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 packages/kilo-docs/pages/kiloclaw/triggers/index.md create mode 100644 packages/kilo-docs/pages/kiloclaw/triggers/webhooks.md diff --git a/packages/kilo-docs/lib/nav/kiloclaw.ts b/packages/kilo-docs/lib/nav/kiloclaw.ts index fbb14f3bf13..695801fc49d 100644 --- a/packages/kilo-docs/lib/nav/kiloclaw.ts +++ b/packages/kilo-docs/lib/nav/kiloclaw.ts @@ -37,6 +37,14 @@ export const KiloClawNav: NavSection[] = [ { href: "/kiloclaw/development-tools/google", children: "Google Workspace" }, ], }, + { + href: "/kiloclaw/triggers", + children: "Triggers", + subLinks: [ + { href: "/kiloclaw/triggers", children: "Overview" }, + { href: "/kiloclaw/triggers/webhooks", children: "Webhooks" }, + ], + }, { href: "/kiloclaw/tools", children: "Tools", diff --git a/packages/kilo-docs/pages/kiloclaw/triggers/index.md b/packages/kilo-docs/pages/kiloclaw/triggers/index.md new file mode 100644 index 00000000000..10412d71eb3 --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/triggers/index.md @@ -0,0 +1,32 @@ +--- +title: "Triggers" +description: "Automate your KiloClaw agent with webhooks and scheduled triggers" +--- + +# Triggers + +Triggers let external events and schedules drive your KiloClaw agent automatically. Instead of typing every instruction yourself, triggers deliver messages to your agent on your behalf. This lets it react to real-world events or run tasks on a schedule without polling. + +All triggers are managed from the **Settings** tab on your [KiloClaw dashboard](/docs/kiloclaw/dashboard). + +## Trigger Types + +| Type | Description | Status | +| --- | --- | --- | +| [**Webhooks**](/docs/kiloclaw/triggers/webhooks) | Receive HTTP requests from external services (GitHub, Stripe, monitoring tools, etc.) and deliver them as chat messages to your agent | Available | +| **Time-based** | Run tasks on a schedule using cron expressions | Coming soon | + +## How Triggers Work + +1. An event occurs (an HTTP request arrives, or a schedule fires) +2. The trigger validates the request and renders the payload through a **prompt template** +3. The rendered message is delivered to your KiloClaw instance as a chat message +4. Your agent processes and responds like any other conversation + +Prompt templates give you control over how payloads are presented to your agent. You can include instructions, context, and formatting alongside the raw event data. + +## Related + +- [Webhooks](/docs/kiloclaw/triggers/webhooks) +- [KiloClaw Overview](/docs/kiloclaw/overview) +- [Dashboard Reference](/docs/kiloclaw/dashboard) diff --git a/packages/kilo-docs/pages/kiloclaw/triggers/webhooks.md b/packages/kilo-docs/pages/kiloclaw/triggers/webhooks.md new file mode 100644 index 00000000000..c2c04cdabbf --- /dev/null +++ b/packages/kilo-docs/pages/kiloclaw/triggers/webhooks.md @@ -0,0 +1,110 @@ +--- +title: "Webhooks" +description: "Trigger your KiloClaw agent from external events using webhooks" +--- + +# Webhooks + +KiloClaw supports inbound webhooks so external events can trigger your agent automatically. Form submissions, alerts, calendar updates, ecommerce orders, IoT sensor data; anything that can send an HTTP request can kick off a conversation with your agent. When a webhook fires, the payload is rendered through a prompt template and delivered as a chat message to your KiloClaw instance. The agent processes and responds as if you typed it yourself. + +## Setup + +1. Go to the **Settings** tab on your [KiloClaw dashboard](/docs/kiloclaw/dashboard) +2. Find the **Webhook Integration** card and click **Manage** +3. Click **Set Up Webhook** + +KiloClaw generates a unique webhook URL for your instance. Copy it and configure it as the destination in whatever service you want to receive events from (GitHub, Stripe, a monitoring tool, etc.). + +{% callout type="warning" title="Treat the URL as a secret" %} +The webhook URL contains 128 bits of entropy and acts as its own credential (similar to Slack webhook URLs). Anyone with the URL can send messages to your instance. Do not commit it to public repositories or share it in public channels. +{% /callout %} + +## How It Works + +1. An external service sends an HTTP POST to your webhook URL +2. The webhook worker validates the request (and optionally checks authentication) +3. The payload is rendered through your **prompt template** (see below) +4. The rendered message is delivered to your KiloClaw instance as a chat message +5. Your agent receives and responds to the message like any other conversation + +## Prompt Template + +The prompt template controls how webhook payloads are presented to your agent. You can customize it from the **Webhook Integration** section in Settings. + +**Default template:** + +``` +You received a webhook event. Here is the payload: + +{{bodyJson}} +``` + +**Available variables:** + +| Variable | Description | +| --- | --- | +| `{{body}}` | Raw request body | +| `{{bodyJson}}` | Pretty-printed JSON body | +| `{{method}}` | HTTP method (e.g., `POST`) | +| `{{headers}}` | Request headers | +| `{{path}}` | Request path | +| `{{query}}` | Query string parameters | +| `{{timestamp}}` | Time the webhook was received | + +You can tailor the template to give your agent more context. For example: + +``` +A GitHub push event just arrived. Summarize the changes and open a PR if any tests are affected. + +Payload: +{{bodyJson}} +``` + +## Managing Your Webhook + +Once set up, the Webhook Integration card in Settings gives you several controls: + +### Pause and Resume + +Toggle the **Active/Paused** switch to temporarily stop accepting webhooks without deleting the URL. When paused, incoming requests are rejected. Resume at any time to start accepting them again. + +### Rotate URL + +If your webhook URL is compromised, click **Rotate URL** to generate a new one. This immediately invalidates the old URL, so you will need to update your integrations with the new URL afterward. A confirmation dialog is shown before rotation. + +### Webhook Authentication (Optional) + +For additional security, you can require inbound requests to include a shared secret header. This is useful when the sending service supports webhook signing. + +1. Toggle **Webhook Authentication** to enabled +2. Set the **Secret Header** name (default: `x-webhook-secret`) +3. Enter a **Shared Secret** value +4. Click **Save** + +Requests missing the header or providing an incorrect secret are rejected. + +{% callout type="note" title="Authentication is optional" %} +The webhook URL itself is already a credential (128-bit entropy). Authentication adds a second layer and is only needed if your sending service requires or supports it. +{% /callout %} + +## Viewing Webhook Activity + +KiloClaw webhooks also appear in the **Webhooks** page under Cloud (read only). From there you can click **View Captured Requests** to inspect recent payloads, response codes, and timing. This is useful for debugging integration issues. + +## Example: GitHub Push Notifications + +1. Set up a webhook in your KiloClaw Settings +2. In your GitHub repository, go to **Settings > Webhooks > Add webhook** +3. Paste your KiloClaw webhook URL as the **Payload URL** +4. Set **Content type** to `application/json` +5. Select the events you want to trigger on (e.g., **Just the push event**) +6. Click **Add webhook** + +Now every push to that repository sends a payload to your agent. Customize the prompt template to tell the agent what to do with it. You could have it summarize commits, run checks, notify a channel, or anything else. + +## Related + +- [KiloClaw Overview](/docs/kiloclaw/overview) +- [Dashboard Reference](/docs/kiloclaw/dashboard) +- [GitHub Integration](/docs/kiloclaw/development-tools/github) +- [Connecting Chat Platforms](/docs/kiloclaw/chat-platforms)