diff --git a/.github/workflows/auto-docs.yml b/.github/workflows/auto-docs.yml index 5e55c94c099..4364ee87480 100644 --- a/.github/workflows/auto-docs.yml +++ b/.github/workflows/auto-docs.yml @@ -7,9 +7,9 @@ on: jobs: call-webhook: if: > - github.event.pull_request.merged == true && - (startsWith(github.event.pull_request.title, 'feat:') || - startsWith(github.event.pull_request.title, 'feat(')) + github.event.pull_request.merged == true && + (startsWith(github.event.pull_request.title, 'feat:') || + startsWith(github.event.pull_request.title, 'feat(')) runs-on: ubuntu-latest steps: - name: Send webhook safely diff --git a/AGENTS.md b/AGENTS.md index 5e238eea946..a8323860822 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,6 +16,7 @@ Kilo CLI is an open source AI coding agent that generates code from natural lang - **Single test**: `bun test test/tool/tool.test.ts` from `packages/opencode/` - **SDK regen**: After changing server endpoints in `packages/opencode/src/server/`, run `./script/generate.ts` from root to regenerate `packages/sdk/js/` - **Knip** (unused exports): `bun run knip` from `packages/kilo-vscode/`. CI runs this — all exported types/functions must be imported somewhere. Remove or unexport unused exports before pushing. +- **Source links**: After adding or changing URLs in `packages/kilo-vscode/`, `packages/kilo-vscode/webview-ui/`, or `packages/opencode/src/`, run `bun run script/extract-source-links.ts` from the repo root and commit the updated `packages/kilo-docs/source-links.md`. CI runs this check — the build fails if the file is stale. - **kilocode_change check**: `bun run check-kilocode-change` from `packages/kilo-vscode/`. CI runs this — `kilocode_change` is a marker for upstream merge conflicts and must not appear in `packages/kilo-vscode/` or `packages/kilo-ui/` (these are entirely Kilo Code additions). Remove the markers before pushing. ## Products diff --git a/README.md b/README.md index 31d9e5cf348..0c39fb0bbe2 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@

- VS Code Marketplace - X (Twitter) - Substack Blog - Discord - Reddit + VS Code Marketplace + X (Twitter) + Substack Blog + Discord + Reddit

# 🚀 Kilo diff --git a/bun.lock b/bun.lock index 54a2892e862..9de6aeed81e 100644 --- a/bun.lock +++ b/bun.lock @@ -27,7 +27,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { "@kilocode/kilo-i18n": "workspace:*", "@kilocode/kilo-ui": "workspace:*", @@ -79,7 +79,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -112,7 +112,7 @@ }, "packages/desktop-electron": { "name": "@opencode-ai/desktop-electron", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -142,7 +142,7 @@ }, "packages/kilo-docs": { "name": "@kilocode/kilo-docs", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { "@docsearch/css": "^4", "@docsearch/js": "^4", @@ -171,8 +171,11 @@ }, "packages/kilo-gateway": { "name": "@kilocode/kilo-gateway", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { + "@ai-sdk/anthropic": "2.0.65", + "@ai-sdk/openai": "2.0.101", + "@ai-sdk/openai-compatible": "1.0.32", "@clack/prompts": "1.0.0-alpha.1", "@kilocode/plugin": "workspace:*", "@kilocode/sdk": "workspace:*", @@ -203,7 +206,7 @@ }, "packages/kilo-i18n": { "name": "@kilocode/kilo-i18n", - "version": "7.1.2", + "version": "7.1.8", "devDependencies": { "@tsconfig/node22": "catalog:", "@types/bun": "catalog:", @@ -213,7 +216,7 @@ }, "packages/kilo-telemetry": { "name": "@kilocode/kilo-telemetry", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { "@kilocode/kilo-gateway": "workspace:*", "@opentelemetry/api": "1.9.0", @@ -233,7 +236,7 @@ }, "packages/kilo-ui": { "name": "@kilocode/kilo-ui", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { "@kobalte/core": "0.13.11", "@opencode-ai/util": "workspace:*", @@ -268,7 +271,7 @@ }, "packages/kilo-vscode": { "name": "kilo-code", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { "@anthropic-ai/sdk": "^0.39.0", "@kilocode/kilo-i18n": "workspace:*", @@ -321,7 +324,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "7.1.2", + "version": "7.1.8", "bin": { "kilo": "./bin/kilo", "kilocode": "./bin/kilo", @@ -341,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", @@ -443,7 +446,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { "@kilocode/sdk": "workspace:*", "zod": "catalog:", @@ -457,14 +460,14 @@ }, "packages/script": { "name": "@opencode-ai/script", - "version": "7.1.2", + "version": "7.1.8", "devDependencies": { "@types/bun": "catalog:", }, }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "7.1.2", + "version": "7.1.8", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -475,7 +478,7 @@ }, "packages/storybook": { "name": "@opencode-ai/storybook", - "version": "7.1.2", + "version": "7.1.8", "devDependencies": { "@opencode-ai/ui": "workspace:*", "@solidjs/meta": "catalog:", @@ -498,7 +501,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -545,7 +548,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "7.1.2", + "version": "7.1.8", "dependencies": { "zod": "catalog:", }, @@ -662,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=="], @@ -4354,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=="], @@ -4378,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=="], @@ -4832,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=="], @@ -5596,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/nix/hashes.json b/nix/hashes.json index 2009eae3304..80015c18486 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-h4RHYUp03Kpy2GCPv5B7pjfcHxZ9M9R475svzkwzpH4=", - "aarch64-linux": "sha256-zLCL5Z5NRvWBfsxnjdMGEWAYBNU120G2/YQ0KFaq+ZA=", - "aarch64-darwin": "sha256-KZPpNosE6S3rW0RSCiADi26ysPIt74TeULQdYF7dDOE=", - "x86_64-darwin": "sha256-XkEYBrRiD1DRhWtQ73afzBNRk0bZHRFpxqAcwnsraE8=" + "x86_64-linux": "sha256-YjB3YfaA79nztpZoYEAlFBakS//G/Guprlqk4BYFgOA=", + "aarch64-linux": "sha256-ru470M8RVwyOPNGr6I4VfApQRHhYFFMPjOBneTRBJtc=", + "aarch64-darwin": "sha256-M6LIPBHnYH9AtIRAKyW44VN71Kb28nztzFteCkL0588=", + "x86_64-darwin": "sha256-HURoot79BFHYwoEp0XqVdI6cRdV7KGvmRRqOf+hUa9Q=" } } diff --git a/package.json b/package.json index c5aa660df26..963b46f01af 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.2", + "version": "7.1.8", "peerDependencies": {} } diff --git a/packages/app/package.json b/packages/app/package.json index f5814dc83e3..d30c14b44a2 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "7.1.2", + "version": "7.1.8", "description": "", "type": "module", "exports": { diff --git a/packages/app/src/context/language.tsx b/packages/app/src/context/language.tsx index b49e68aa93f..9bf9d504c8c 100644 --- a/packages/app/src/context/language.tsx +++ b/packages/app/src/context/language.tsx @@ -127,7 +127,7 @@ const INTL: Record = { th: "th", bs: "bs", nl: "nl", - + tr: "tr", } @@ -149,7 +149,6 @@ const LABEL_KEY: Record = { th: "language.th", bs: "language.bs", nl: "language.nl", - tr: "language.tr", } diff --git a/packages/app/src/i18n/ar.ts b/packages/app/src/i18n/ar.ts index c8183928cac..6e5d16775b9 100644 --- a/packages/app/src/i18n/ar.ts +++ b/packages/app/src/i18n/ar.ts @@ -136,8 +136,7 @@ export const dict = { "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.visit.suffix": " وأدخل الرمز أدناه لتوصيل حسابك واستخدام نماذج {{provider}} في Kilo.", "provider.connect.oauth.auto.confirmationCode": "رمز التأكيد", "provider.connect.toast.connected.title": "تم توصيل {{provider}}", "provider.connect.toast.connected.description": "نماذج {{provider}} متاحة الآن للاستخدام.", diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts index 7319472bcd1..f0d7724ef01 100644 --- a/packages/app/src/i18n/fr.ts +++ b/packages/app/src/i18n/fr.ts @@ -389,8 +389,7 @@ export const dict = { "toast.session.unshare.failed.description": "Une erreur s'est produite lors de l'annulation du partage de la session", "toast.session.listFailed.title": "Échec du chargement des sessions pour {{project}}", "toast.update.title": "Mise à jour disponible", - "toast.update.description": - "Une nouvelle version d'Kilo ({{version}}) est maintenant disponible pour installation.", + "toast.update.description": "Une nouvelle version d'Kilo ({{version}}) est maintenant disponible pour installation.", "toast.update.action.installRestart": "Installer et redémarrer", "toast.update.action.notYet": "Pas encore", "error.page.title": "Quelque chose s'est mal passé", @@ -525,8 +524,7 @@ export const dict = { "sidebar.workspaces.enable": "Activer les espaces de travail", "sidebar.workspaces.disable": "Désactiver les espaces de travail", "sidebar.gettingStarted.title": "Commencer", - "sidebar.gettingStarted.line1": - "Kilo inclut des modèles gratuits pour que vous puissiez commencer immédiatement.", + "sidebar.gettingStarted.line1": "Kilo inclut des modèles gratuits pour que vous puissiez commencer immédiatement.", "sidebar.gettingStarted.line2": "Connectez n'importe quel fournisseur pour utiliser des modèles, y compris Claude, GPT, Gemini etc.", "sidebar.project.recentSessions": "Sessions récentes", diff --git a/packages/app/src/i18n/th.ts b/packages/app/src/i18n/th.ts index 3d3ccd4e04c..3243b5d322b 100644 --- a/packages/app/src/i18n/th.ts +++ b/packages/app/src/i18n/th.ts @@ -148,8 +148,7 @@ export const dict = { "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.visit.suffix": " และป้อนรหัสด้านล่างเพื่อเชื่อมต่อบัญชีและใช้โมเดล {{provider}} ใน Kilo", "provider.connect.oauth.auto.confirmationCode": "รหัสยืนยัน", "provider.connect.toast.connected.title": "{{provider}} ที่เชื่อมต่อแล้ว", "provider.connect.toast.connected.description": "โมเดล {{provider}} พร้อมใช้งานแล้ว", diff --git a/packages/app/src/i18n/tr.ts b/packages/app/src/i18n/tr.ts index 76b4b283d7d..762ab6f2330 100644 --- a/packages/app/src/i18n/tr.ts +++ b/packages/app/src/i18n/tr.ts @@ -143,8 +143,7 @@ export const dict = { "provider.connect.opencodeZen.visit.prefix": "", "provider.connect.opencodeZen.visit.link": "opencode.ai/zen", "provider.connect.opencodeZen.visit.suffix": " adresini ziyaret ederek API anahtarınızı alın.", - "provider.connect.oauth.code.visit.prefix": - "Hesabınızı bağlamak ve Kilo'da {{provider}} modellerini kullanmak için ", + "provider.connect.oauth.code.visit.prefix": "Hesabınızı bağlamak ve Kilo'da {{provider}} modellerini kullanmak için ", "provider.connect.oauth.code.visit.link": "bu bağlantıya", "provider.connect.oauth.code.visit.suffix": " tıklayarak yetkilendirme kodunuzu alın.", "provider.connect.oauth.code.label": "{{method}} yetkilendirme kodu", diff --git a/packages/app/src/i18n/zht.ts b/packages/app/src/i18n/zht.ts index 0d810b5f826..c77f6fd52d8 100644 --- a/packages/app/src/i18n/zht.ts +++ b/packages/app/src/i18n/zht.ts @@ -149,8 +149,7 @@ export const dict = { "provider.connect.oauth.code.invalid": "授權碼無效", "provider.connect.oauth.auto.visit.prefix": "造訪 ", "provider.connect.oauth.auto.visit.link": "此連結", - "provider.connect.oauth.auto.visit.suffix": - " 並輸入以下程式碼,以連線你的帳戶並在 Kilo 中使用 {{provider}} 模型。", + "provider.connect.oauth.auto.visit.suffix": " 並輸入以下程式碼,以連線你的帳戶並在 Kilo 中使用 {{provider}} 模型。", "provider.connect.oauth.auto.confirmationCode": "確認碼", "provider.connect.toast.connected.title": "{{provider}} 已連線", "provider.connect.toast.connected.description": "現在可以使用 {{provider}} 模型了。", diff --git a/packages/app/src/pages/layout/sidebar-items.tsx b/packages/app/src/pages/layout/sidebar-items.tsx index f78f27a8541..9160ca397be 100644 --- a/packages/app/src/pages/layout/sidebar-items.tsx +++ b/packages/app/src/pages/layout/sidebar-items.tsx @@ -43,9 +43,7 @@ export const ProjectIcon = (props: { project: LocalProject; class?: string; noti
+ {legacy ? "\u24D8" : "\u2728"} + + {legacy + ? "This page applies to the legacy VSCode extension." + : "This page applies to the current VSCode extension & CLI."} + + + +
+ ) +} diff --git a/packages/kilo-docs/components/SideNav.tsx b/packages/kilo-docs/components/SideNav.tsx index 1960fa1f842..2897576d3fb 100644 --- a/packages/kilo-docs/components/SideNav.tsx +++ b/packages/kilo-docs/components/SideNav.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react" import { useRouter } from "next/router" import Link from "next/link" -import { SectionNav } from "../lib/types" +import { Platform, SectionNav } from "../lib/types" import { Nav } from "../lib/nav" // Define navigation items for each major section @@ -67,6 +67,16 @@ const ChevronLeft = () => ( ) +function PlatformBadge({ platform }: { platform?: Platform }) { + if (!platform || platform === "all") return null + const label = platform === "legacy" ? "Legacy" : "New" + return ( + + {label} + + ) +} + interface SideNavProps { isMobileOpen?: boolean onMobileClose?: () => void @@ -268,6 +278,7 @@ export function SideNav({ isMobileOpen = false, onMobileClose }: SideNavProps) {
{link.children} +
) diff --git a/packages/kilo-docs/components/Tabs.tsx b/packages/kilo-docs/components/Tabs.tsx index 43fe16707ca..6cc69abda61 100644 --- a/packages/kilo-docs/components/Tabs.tsx +++ b/packages/kilo-docs/components/Tabs.tsx @@ -27,16 +27,16 @@ export function Tabs({ children }: TabsProps) { ) const indexFromHash = () => { - if (typeof window === "undefined") return 0 const hash = window.location.hash.slice(1) if (!hash) return 0 const found = tabs.findIndex((tab) => slugify(tab.props.label) === hash) return found >= 0 ? found : 0 } - const [activeIndex, setActiveIndex] = useState(indexFromHash) + const [activeIndex, setActiveIndex] = useState(0) useEffect(() => { + setActiveIndex(indexFromHash()) const onHashChange = () => setActiveIndex(indexFromHash()) window.addEventListener("hashchange", onHashChange) return () => window.removeEventListener("hashchange", onHashChange) diff --git a/packages/kilo-docs/components/TopNav.tsx b/packages/kilo-docs/components/TopNav.tsx index 677cd82615e..3d458227c40 100644 --- a/packages/kilo-docs/components/TopNav.tsx +++ b/packages/kilo-docs/components/TopNav.tsx @@ -336,9 +336,8 @@ export function TopNav({ onMobileMenuToggle, isMobileMenuOpen = false, showMobil {/* Announcement banner */}

- We're replatforming our extensions on the new Kilo CLI. - Contribute to the new CLI and pre-release extensions at{" "} - Kilo-Org/kilocode. + We've replatformed our extensions on the new Kilo CLI. + Contribute at Kilo-Org/kilocode.

diff --git a/packages/kilo-docs/components/index.js b/packages/kilo-docs/components/index.js index 9bb2cc21b24..9297d31ab0e 100644 --- a/packages/kilo-docs/components/index.js +++ b/packages/kilo-docs/components/index.js @@ -7,6 +7,7 @@ export * from "./Icon" export * from "./Image" export * from "./KiloCodeIcon" export * from "./PageFooter" +export * from "./PageVersionSwitcher" export * from "./SideNav" export * from "./Table" export * from "./TableOfContents" diff --git a/packages/kilo-docs/lib/nav/getting-started.ts b/packages/kilo-docs/lib/nav/getting-started.ts index 38132a38eb0..45d16d25fcc 100644 --- a/packages/kilo-docs/lib/nav/getting-started.ts +++ b/packages/kilo-docs/lib/nav/getting-started.ts @@ -30,8 +30,12 @@ export const GettingStartedNav: NavSection[] = [ children: "Settings", subLinks: [ { href: "/getting-started/settings/auto-approving-actions", children: "Auto-Approving Actions" }, - { href: "/getting-started/settings/auto-cleanup", children: "Auto Cleanup" }, - { href: "/getting-started/settings/system-notifications", children: "System Notifications" }, + { href: "/getting-started/settings/auto-cleanup", children: "Auto Cleanup", platform: "legacy" }, + { + href: "/getting-started/settings/system-notifications", + children: "System Notifications", + platform: "legacy", + }, ], }, { href: "/getting-started/adding-credits", children: "Adding Credits" }, diff --git a/packages/kilo-docs/lib/types.ts b/packages/kilo-docs/lib/types.ts index 7e5fdf7a22e..5feef035784 100644 --- a/packages/kilo-docs/lib/types.ts +++ b/packages/kilo-docs/lib/types.ts @@ -1,6 +1,9 @@ +export type Platform = "legacy" | "new" | "all" + export interface NavLink { href: string children: string + platform?: Platform // "legacy" = stable VSCode only, "new" = new VSCode + CLI only, omitted = universal subLinks?: NavLink[] // Optional nested links for second-level navigation } diff --git a/packages/kilo-docs/markdoc/partials/install-jetbrains.md b/packages/kilo-docs/markdoc/partials/install-jetbrains.md index 7dce539d9a8..a64c1c1974e 100644 --- a/packages/kilo-docs/markdoc/partials/install-jetbrains.md +++ b/packages/kilo-docs/markdoc/partials/install-jetbrains.md @@ -18,7 +18,7 @@ Before installing the Kilo Code plugin, ensure you have: 1. If you don't have a JetBrains IDE installed, download one from [jetbrains.com](https://www.jetbrains.com/) 2. Then, you can click the button below to install Kilo Code directly from the JetBrains Marketplace: -[![Install Kilo Code](https://img.shields.io/badge/Install%20Kilo%20Code-F8F674?style=for-the-badge)](https://plugins.jetbrains.com/plugin/28350-kilo-code) +[![Install Kilo Code](https://raster.shields.io/badge/Install%20Kilo%20Code-F8F674?style=for-the-badge)](https://plugins.jetbrains.com/plugin/28350-kilo-code) ### Install from JetBrains Marketplace diff --git a/packages/kilo-docs/markdoc/partials/install-vscode.md b/packages/kilo-docs/markdoc/partials/install-vscode.md index 54a22e5adbd..1edf8af2dc9 100644 --- a/packages/kilo-docs/markdoc/partials/install-vscode.md +++ b/packages/kilo-docs/markdoc/partials/install-vscode.md @@ -3,7 +3,7 @@ 1. If you don't have VS Code installed, download it from [code.visualstudio.com](https://code.visualstudio.com/) 2. Then, you can click the button below to install Kilo Code directly from the VS Code Marketplace: -[![Install Kilo Code](https://img.shields.io/badge/Install%20Kilo%20Code-F8F674?style=for-the-badge)](vscode:extension/kilocode.kilo-code) +[![Install Kilo Code](https://raster.shields.io/badge/Install%20Kilo%20Code-F8F674?style=for-the-badge)](vscode:extension/kilocode.kilo-code) ### Install from VS Code Marketplace diff --git a/packages/kilo-docs/package.json b/packages/kilo-docs/package.json index e14fa6df803..e72b4ef414c 100644 --- a/packages/kilo-docs/package.json +++ b/packages/kilo-docs/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-docs", - "version": "7.1.2", + "version": "7.1.8", "private": true, "scripts": { "dev": "next dev --webpack --port 3002", diff --git a/packages/kilo-docs/pages/_app.tsx b/packages/kilo-docs/pages/_app.tsx index 6d45a81782c..245ab29af70 100644 --- a/packages/kilo-docs/pages/_app.tsx +++ b/packages/kilo-docs/pages/_app.tsx @@ -3,7 +3,7 @@ import Head from "next/head" import { useRouter } from "next/router" import posthog from "posthog-js" -import { CopyPageButton, PageFooter, SideNav, TableOfContents, TopNav } from "../components" +import { CopyPageButton, PageFooter, PageVersionSwitcher, SideNav, TableOfContents, TopNav } from "../components" import "prismjs" import "prismjs/components/prism-bash.min" @@ -129,6 +129,8 @@ export default function MyApp({ Component, pageProps }: AppProps) { const toc = pageProps.markdoc?.content ? collectHeadings(pageProps.markdoc.content) : [] + const platform = markdoc?.frontmatter?.platform + return ( <> @@ -179,6 +181,7 @@ export default function MyApp({ Component, pageProps }: AppProps) {
+ {markdoc && } {markdoc && }
diff --git a/packages/kilo-docs/pages/code-with-ai/agents/auto-model.md b/packages/kilo-docs/pages/code-with-ai/agents/auto-model.md index ce89c2efb24..94a48c21970 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/auto-model.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/auto-model.md @@ -45,28 +45,28 @@ That's it. No configuration needed. ## Auto Balanced -`kilo-auto/balanced` follows the same mode-based routing structure as Frontier but uses more cost-effective models — Kimi K2.5 for reasoning-heavy modes and Minimax M2.5 (Free) for implementation modes. +`kilo-auto/balanced` follows the same mode-based routing structure as Frontier but uses more cost-effective models — Kimi K2.5 for reasoning-heavy modes and Minimax M2.7 for implementation modes. ### Mode-to-Model Mapping -| Mode | Model Used | Best For | -| -------------- | ------------------- | ---------------------------- | -| `architect` | Kimi K2.5 | System design, planning | -| `orchestrator` | Kimi K2.5 | Multi-step task coordination | -| `ask` | Kimi K2.5 | Questions, explanations | -| `plan` | Kimi K2.5 | Planning, reasoning | -| `general` | Kimi K2.5 | General assistance | -| `debug` | Kimi K2.5 | Debugging and fixing issues | -| `code` | Minimax M2.5 (Free) | Writing and editing code | -| `build` | Minimax M2.5 (Free) | Implementation tasks | -| `explore` | Minimax M2.5 (Free) | Codebase exploration | +| Mode | Model Used | Best For | +| -------------- | ------------ | ---------------------------- | +| `architect` | Kimi K2.5 | System design, planning | +| `orchestrator` | Kimi K2.5 | Multi-step task coordination | +| `ask` | Kimi K2.5 | Questions, explanations | +| `plan` | Kimi K2.5 | Planning, reasoning | +| `general` | Kimi K2.5 | General assistance | +| `debug` | Kimi K2.5 | Debugging and fixing issues | +| `code` | Minimax M2.7 | Writing and editing code | +| `build` | Minimax M2.7 | Implementation tasks | +| `explore` | Minimax M2.7 | Codebase exploration | **Planning and reasoning tasks** use Kimi K2.5, a strong open-weight reasoning model from Moonshot AI. -**Implementation tasks** use Minimax M2.5, which provides fast, capable code generation at a fraction of frontier model costs. +**Implementation tasks** use Minimax M2.7, which provides fast, capable code generation at a fraction of frontier model costs. {% callout type="info" title="Image support" %} -Auto Balanced does not support image inputs, since Minimax M2.5 does not have vision capabilities. +Auto Balanced does not support image inputs, since Minimax M2.7 does not have vision capabilities. {% /callout %} ## Benefits diff --git a/packages/kilo-docs/pages/gateway/models-and-providers.md b/packages/kilo-docs/pages/gateway/models-and-providers.md index aa5c7cf8c01..1a902b2c392 100644 --- a/packages/kilo-docs/pages/gateway/models-and-providers.md +++ b/packages/kilo-docs/pages/gateway/models-and-providers.md @@ -82,11 +82,11 @@ Routes to the most capable paid models optimizing for cost, performance, and cap Follows the same mode-based routing as Frontier but uses more cost-effective models. -| Mode | Resolved Model | -| -------------------------------------------------------------- | --------------------------- | -| `plan`, `general`, `architect`, `orchestrator`, `ask`, `debug` | `moonshotai/kimi-k2.5` | -| `build`, `explore`, `code` | `minimax/minimax-m2.5:free` | -| Default (no mode specified) | `minimax/minimax-m2.5:free` | +| Mode | Resolved Model | +| -------------------------------------------------------------- | ---------------------- | +| `plan`, `general`, `architect`, `orchestrator`, `ask`, `debug` | `moonshotai/kimi-k2.5` | +| `build`, `explore`, `code` | `minimax/minimax-m2.7` | +| Default (no mode specified) | `minimax/minimax-m2.7` | ### `kilo-auto/free` diff --git a/packages/kilo-docs/pages/getting-started/byok.md b/packages/kilo-docs/pages/getting-started/byok.md index 3df9aff13e1..24ed48bf863 100644 --- a/packages/kilo-docs/pages/getting-started/byok.md +++ b/packages/kilo-docs/pages/getting-started/byok.md @@ -20,10 +20,11 @@ Kilo Gateway currently supports BYOK keys for these providers: - Anthropic - AWS Bedrock -- OpenAI - Google AI Studio +- Inception - Minimax - Mistral AI +- OpenAI - xAI - Z.AI diff --git a/packages/kilo-docs/pages/getting-started/installing.md b/packages/kilo-docs/pages/getting-started/installing.md index f3693d1b7c6..e63c864adb5 100644 --- a/packages/kilo-docs/pages/getting-started/installing.md +++ b/packages/kilo-docs/pages/getting-started/installing.md @@ -14,54 +14,16 @@ Get started with Kilo Code by installing it on your preferred platform. Choose y ## VS Code Extension -{% partial file="install-vscode.md" /%} - -{% /tab %} -{% tab label="VS Code (Preview)" %} - -## VS Code Preview Extension - -{% callout type="info" %} -We're rebuilding Kilo Code from the ground up on the new [Kilo CLI](https://github.com/Kilo-Org/kilocode). The pre-release extension is available for users who want to try the latest architecture and provide feedback, and don't mind some missing features and rough edges. -{% /callout %} - -The pre-release extension is a complete rebuild featuring: - -- A new Solid.js-based UI -- Deep integration with the Kilo CLI backend -- Improved session management and model switching - -### Current Status - -This is an early pre-release. Core features like chat, markdown rendering, authentication, and model/mode switching are working. Some features from the stable extension are still being implemented. - -For the full feature status, see the [feature parity tracking document](https://github.com/Kilo-Org/kilocode/blob/main/packages/kilo-vscode/docs/opencode-migration-plan.md). - -### Installing the Pre-Release +The current Kilo Code extension is built on the [Kilo CLI](https://github.com/Kilo-Org/kilocode) and is distributed as the **pre-release version** on the VS Code Marketplace. 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** -### Switching Back to Stable - -If you need to return to the stable version: - -1. Open Extensions in VS Code -2. Find Kilo Code -3. Click the dropdown and select **Switch to Release Version** - -### Feedback and Issues - -Report issues or provide feedback in the [Kilo-Org/kilocode repository](https://github.com/Kilo-Org/kilocode/issues). - -{% /tab %} -{% tab label="JetBrains" %} - -## JetBrains IDEs - -{% partial file="install-jetbrains.md" /%} +{% callout type="info" %} +The "pre-release" label is a VS Code Marketplace distribution channel — the extension is stable and recommended for all users. +{% /callout %} {% /tab %} {% tab label="CLI" %} @@ -70,6 +32,27 @@ Report issues or provide feedback in the [Kilo-Org/kilocode repository](https:// {% partial file="install-cli.md" /%} +{% /tab %} +{% tab label="VS Code (Legacy)" %} + +## VS Code Legacy Extension + +The legacy extension is the previous version of Kilo Code for VS Code. It is still available but is no longer actively developed. We recommend installing the current extension (see the **VS Code** tab). + +To install or switch back to the legacy version: + +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 **Switch to Release Version** + +{% /tab %} +{% tab label="JetBrains" %} + +## JetBrains IDEs + +{% partial file="install-jetbrains.md" /%} + {% /tab %} {% tab label="Slack" %} diff --git a/packages/kilo-docs/pages/getting-started/quickstart.md b/packages/kilo-docs/pages/getting-started/quickstart.md index 3258a77a4d8..5a1a82f2229 100644 --- a/packages/kilo-docs/pages/getting-started/quickstart.md +++ b/packages/kilo-docs/pages/getting-started/quickstart.md @@ -5,12 +5,112 @@ description: "Get up and running with Kilo Code in minutes" # Quickstart +After you [set up Kilo Code](/docs/getting-started/setup-authentication), follow the guide for your platform below. + +{% tabs %} +{% tab label="VSCode" %} + +## Step by Step Guide + +### Step 1: Open Kilo Code + +Click the Kilo Code icon in the VS Code Primary Side Bar to open the chat panel. If you don't see the icon, verify the [extension is installed](/docs/getting-started/installing). + +### Step 2: Type Your Task + +Type a clear, concise description of what you want Kilo Code to do in the chat box. The same examples work here: + +- "Create a file named `hello.txt` containing 'Hello, world!'." +- "Write a Python function that adds two numbers." +- "Create an HTML file for a simple website with the title 'Kilo test'" + +No special commands or syntax needed—just use plain English. + +### Step 3: Send Your Task + +Press **Enter** to send. + +### Step 4: Review & Approve Actions + +Kilo Code analyzes your request and proposes actions. By default, most tools are auto-approved — only shell commands, external directory access, and sensitive file reads will prompt for confirmation. You'll see the tool name, arguments, and can approve or reject each action. + +To change which actions require approval, open **Settings** (gear icon) and go to the **Auto-Approve** tab. You can set each tool to Allow, Ask, or Deny. See [Auto-Approving Actions](/docs/getting-started/settings/auto-approving-actions) for details. + +### Step 5: Iterate + +Kilo Code works iteratively. Continue giving feedback or follow-up instructions until your task is complete. + +### Key Differences from Legacy + +- **Settings** are managed via `kilo.jsonc` config files (the Settings webview reads and writes the same files) +- **Permissions** use a granular per-tool system instead of broad approval categories +- **Modes** are called "agents" and configured as `.md` files or via the `agent` config key +- **Autocomplete** uses FIM (Fill-in-the-Middle) with Codestral + +{% /tab %} +{% tab label="CLI" %} + +## CLI Quickstart + +### Step 1: Open a Terminal + +Navigate to your project directory: + +```bash +cd /path/to/your/project +``` + +### Step 2: Launch Kilo + +Run the `kilo` command to start the interactive TUI (terminal user interface): + +```bash +kilo +``` + +If this is your first time, run `kilo auth login` first to authenticate (see [Setup & Authentication](/docs/getting-started/setup-authentication)). + +### Step 3: Type Your Task + +Type your request in natural language at the prompt. The same examples work here: + +- "Create a file named `hello.txt` containing 'Hello, world!'." +- "Write a Python function that adds two numbers." +- "Create an HTML file for a simple website with the title 'Kilo test'" + +Press **Enter** to send. + +### Step 4: Review & Approve Actions + +Kilo analyzes your request and proposes actions. By default, most tools are auto-approved — only shell commands, external directory access, and sensitive file reads will prompt for confirmation. You'll see the tool name, arguments, and can approve or reject each action. + +To change permission defaults, configure the `permission` key in your `kilo.jsonc` config file. See [Auto-Approving Actions](/docs/getting-started/settings/auto-approving-actions) for details. + +### Step 5: Iterate + +Kilo works iteratively. Continue giving feedback or follow-up instructions until your task is complete. + +### One-Shot Mode + +For quick, non-interactive tasks, use `kilo run`: + +```bash +kilo run "add error handling to src/api.ts" +``` + +Add `--auto` to auto-approve all permissions (use carefully): + +```bash +kilo run --auto "fix the failing tests in test/auth.test.ts" +``` + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + ## Video Tour {% youtube url="https://www.youtube.com/watch?v=pO7zRLQS-p0" caption="This quick tour shows how Kilo Code handles a simple request from start to finish" /%} -After you [set up Kilo Code](/docs/getting-started/setup-authentication), follow these steps: - ## Step by Step Guide ### Step 1: Open Kilo Code @@ -66,6 +166,9 @@ Kilo Code works iteratively. After each action, it waits for your feedback befor {% image src="/docs/img/your-first-task/your-first-task-8.png" alt="Final result of a completed task showing the iteration process" width="500" caption="After completing the task, Kilo Code shows the final result and awaits your next instruction." /%} +{% /tab %} +{% /tabs %} + ## Conclusion You've completed your first task. Along the way you learned: diff --git a/packages/kilo-docs/pages/getting-started/settings/auto-approving-actions.md b/packages/kilo-docs/pages/getting-started/settings/auto-approving-actions.md index c071327ebc1..10e4a9d0044 100644 --- a/packages/kilo-docs/pages/getting-started/settings/auto-approving-actions.md +++ b/packages/kilo-docs/pages/getting-started/settings/auto-approving-actions.md @@ -9,7 +9,243 @@ description: "Configure automatic approval settings for Kilo Code operations" **Security Warning:** Auto-approve settings bypass confirmation prompts, giving Kilo Code direct access to your system. This can result in data loss, file corruption, or worse. Command line access is particularly dangerous, as it can potentially execute harmful operations that could damage your system or compromise security. Only enable auto-approval for actions you fully trust. {% /callout %} -Auto-approve settings speed up your workflow by eliminating repetitive confirmation prompts, but they significantly increase security risks. +Auto-approve settings speed up your workflow by eliminating repetitive confirmation prompts, but they significantly increase security risks. The **VSCode (Legacy)**, **VSCode**, and **CLI** versions each handle permissions differently — choose the tab that matches your setup. + +{% tabs %} +{% tab label="VSCode" %} + +## Overview + +The extension uses a granular, per-tool permission system. You can configure permissions through the **Settings → Auto Approve** tab, which provides a UI with per-tool **Allow / Ask / Deny** dropdowns. + +The UI reads and writes to the same `kilo.jsonc` config files used by the CLI, so changes made in either place are reflected in both. + +## Permission Levels + +Each tool permission can be set to one of three values: + +| Value | Behavior | +| --------- | --------------------------------------------------------- | +| `"allow"` | The tool runs automatically without prompting | +| `"ask"` | Kilo pauses and asks for approval before running the tool | +| `"deny"` | The tool is blocked entirely | + +When no rule matches a permission check, the default action is `ask`. + +## Available Tool Permissions + +The Auto Approve tab lists the following tool-specific permissions. Some tools are grouped together in the UI and share a single permission level: + +| Permission | Controls | +| -------------------------- | ------------------------------------------------------ | +| `external_directory` | Accessing files outside the project directory | +| `bash` | Executing shell commands | +| `read` | Reading file contents | +| `edit` | Editing existing files | +| `glob` | File pattern matching / searching by name | +| `grep` | Searching file contents by regex | +| `list` | Listing directory contents | +| `task` | Launching sub-agents | +| `skill` | Loading specialized skills | +| `lsp` | Language server protocol operations | +| `todoread` / `todowrite` | Reading and updating the todo list | +| `websearch` / `codesearch` | Performing web or code searches | +| `webfetch` | Fetching content from URLs | +| `doom_loop` | Allowing the agent to continue after repeated failures | + +## Runtime Permission Requests + +When a tool is set to `"ask"`, Kilo pauses and displays a permission prompt with two options: + +| Option | Behavior | +| -------- | ------------------------------ | +| **Run** | Allow this specific invocation | +| **Deny** | Block this specific invocation | + +Expand **Manage Auto-Approve Rules** to add commands or patterns to your allowed or denied lists. These rules are then appended to the bottom of the approval rules in settings and the config file. + +## Defaults + +Most tools default to `"*": "allow"` for a smooth out-of-the-box experience. Notable exceptions that prompt by default: + +- **`.env` files** — reading `.env` files prompts for approval. Files matching `*.env.*` (e.g., `.env.local`, `.env.production`) also trigger an ask, while `*.env.example` is explicitly allowed. +- **`external_directory`** — accessing files outside the project prompts for approval +- **`doom_loop`** — prompts when the agent enters a repeated failure cycle + +{% /tab %} +{% tab label="CLI" %} + +## Overview + +The CLI uses a granular, per-tool permission system configured in `kilo.jsonc`. Instead of broad categories like "read" or "write," each tool has its own permission level with glob-pattern rules for fine-grained control. + +## Permission Levels + +Each tool permission can be set to one of three values: + +| Value | Behavior | +| --------- | --------------------------------------------------------- | +| `"allow"` | The tool runs automatically without prompting | +| `"ask"` | Kilo pauses and asks for approval before running the tool | +| `"deny"` | The tool is blocked entirely | + +When no rule matches a permission check, the default action is `ask`. + +## Available Tool Permissions + +Permissions are configured under the `permission` key in `kilo.jsonc`. The following tool-specific permission levels are available: + +| Permission | Controls | +| -------------------------- | ------------------------------------------------------ | +| `external_directory` | Accessing files outside the project directory | +| `bash` | Executing shell commands | +| `read` | Reading file contents | +| `edit` | Editing existing files | +| `glob` | File pattern matching / searching by name | +| `grep` | Searching file contents by regex | +| `list` | Listing directory contents | +| `task` | Launching sub-agents | +| `skill` | Loading specialized skills | +| `lsp` | Language server protocol operations | +| `todoread` / `todowrite` | Reading and updating the todo list | +| `websearch` / `codesearch` | Performing web or code searches | +| `webfetch` | Fetching content from URLs | +| `doom_loop` | Allowing the agent to continue after repeated failures | + +## Glob-Pattern Rules + +Instead of a simple `"allow"` or `"deny"`, each tool can use glob-pattern rules for granular control. Patterns are matched against the tool's arguments (command strings, file paths, etc.), and the last matching rule wins. + +### Example: Shell Commands + +Allow git commands automatically, but prompt for everything else: + +```json +{ + "permission": { + "bash": { + "git *": "allow", + "*": "ask" + } + } +} +``` + +### Example: File Reading + +Prompt before reading `.env` files, but allow all other reads: + +```json +{ + "permission": { + "read": { + "*.env": "ask", + "*": "allow" + } + } +} +``` + +### Example: Blocking Dangerous Commands + +Deny `rm -rf` commands, allow common dev commands, and ask for anything else: + +```json +{ + "permission": { + "bash": { + "rm -rf *": "deny", + "npm *": "allow", + "bun *": "allow", + "git *": "allow", + "*": "ask" + } + } +} +``` + +## Per-Agent Permission Overrides + +Different agents can have different permission levels. Override the default permissions for a specific agent under the `agent..permission` key: + +```json +{ + "permission": { + "bash": { "*": "ask" } + }, + "agent": { + "code": { + "permission": { + "bash": { "git *": "allow", "*": "ask" } + } + }, + "plan": { + "permission": { + "bash": { "*": "deny" } + } + } + } +} +``` + +In this example, the `code` agent can run `git` commands automatically and asks for other shell commands, while the `plan` agent cannot run shell commands at all. + +## Runtime Permission Requests + +When a tool is set to `"ask"`, Kilo pauses and displays a permission prompt. You have three options: + +| Option | Behavior | +| ---------------- | -------------------------------------------------------- | +| **Allow once** | Allow this specific invocation only | +| **Allow always** | Allow this tool (or pattern) for the rest of the session | +| **Reject** | Block this specific invocation | + +## Defaults + +Most tools default to `"*": "allow"` for a smooth out-of-the-box experience. Notable exceptions that prompt by default: + +- **`.env` files** — reading `.env` files prompts for approval. Files matching `*.env.*` (e.g., `.env.local`, `.env.production`) also trigger an ask, while `*.env.example` is explicitly allowed. +- **`external_directory`** — accessing files outside the project prompts for approval +- **`doom_loop`** — prompts when the agent enters a repeated failure cycle + +## Full Configuration Example + +{% callout type="info" %} +This is a custom example showing the available configuration options — it does not represent the shipped defaults. +{% /callout %} + +```json +{ + "permission": { + "read": { "*.env": "ask", "*": "allow" }, + "edit": { "*.env": "ask", "*": "allow" }, + "glob": { "*": "allow" }, + "grep": { "*": "allow" }, + "list": { "*": "allow" }, + "bash": { "git *": "allow", "npm *": "allow", "*": "ask" }, + "task": { "*": "allow" }, + "skill": { "*": "allow" }, + "lsp": { "*": "allow" }, + "todoread": { "*": "allow" }, + "todowrite": { "*": "allow" }, + "webfetch": { "*": "allow" }, + "websearch": { "*": "allow" }, + "codesearch": { "*": "allow" }, + "external_directory": { "*": "ask" }, + "doom_loop": { "*": "ask" } + }, + "agent": { + "code": { + "permission": { + "bash": { "git *": "allow", "npm *": "allow", "*": "ask" } + } + } + } +} +``` + +{% /tab %} +{% tab label="VSCode (Legacy)" %} ## Quick Start Guide @@ -343,3 +579,6 @@ You can optionally enable an AI Safety Gatekeeper, which reviews every intended This is the fastest way to work with Kilo Code, but also the riskiest. Use it only when you fully trust the AI and are prepared for the consequences. {% /callout %} + +{% /tab %} +{% /tabs %} diff --git a/packages/kilo-docs/pages/getting-started/settings/auto-cleanup.md b/packages/kilo-docs/pages/getting-started/settings/auto-cleanup.md index 2dabb1c2c5e..c011f2c937e 100644 --- a/packages/kilo-docs/pages/getting-started/settings/auto-cleanup.md +++ b/packages/kilo-docs/pages/getting-started/settings/auto-cleanup.md @@ -1,3 +1,7 @@ +--- +platform: legacy +--- + # Auto Cleanup Auto Cleanup automatically manages your task history by removing old tasks to free up disk space and improve performance. Tasks are intelligently classified and retained based on their type and age, ensuring important work is preserved while temporary or experimental tasks are cleaned up. diff --git a/packages/kilo-docs/pages/getting-started/settings/index.md b/packages/kilo-docs/pages/getting-started/settings/index.md index 294831ca62e..00e1cc30a2a 100644 --- a/packages/kilo-docs/pages/getting-started/settings/index.md +++ b/packages/kilo-docs/pages/getting-started/settings/index.md @@ -5,13 +5,88 @@ description: "Configure Kilo Code settings and preferences" # Settings +The VS Code extension can be configured through the Settings window, opened by pressing the gear icon. Both the CLI and the extension can also be configured through interactions with the agent. The current VS Code extension and CLI share the same underlying settings, so changes in one are reflected in the other. + +## Managing Settings + +{% tabs %} +{% tab label="VSCode" %} + +The VS Code extension provides a **Settings webview UI** accessible from the extension sidebar by clicking the gear icon ({% codicon name="gear" /%}). The UI is organized into tabs including Providers, Auto-Approve, Models, and more. + +This UI reads and writes to the same underlying JSONC config files used by the CLI, so changes made in either place are reflected in both. + +### Config File Locations + +There are two primary config files: + +- **Global config:** `~/.config/kilo/kilo.jsonc` — applies to all projects. On Windows, this is `C:\Users\\.config\kilo\kilo.jsonc`. +- **Project config:** `kilo.jsonc` in your project root, or `.kilo/kilo.jsonc` for a cleaner setup. The `.kilo/` version takes priority if both exist. + +{% callout type="warning" %} +If you check config files into version control, make sure they do not contain API keys or other secrets (e.g., `provider.*.options.apiKey`). Use environment variables for credentials instead. +{% /callout %} + +### Export and Import + +Config files are plain-text and portable — copy them between machines and you're done. + +{% /tab %} +{% tab label="CLI" %} + +In the CLI, settings are managed via **JSONC config files** directly. Config files are plain-text and portable -- you can copy them between machines. + +{% callout type="warning" %} +If you check `kilo.jsonc` into version control, make sure it does not contain API keys or other secrets (e.g., `provider.*.options.apiKey`). Use environment variables for credentials instead. +{% /callout %} + +### Config File Locations + +There are two primary config files: + +- **Global config:** `~/.config/kilo/kilo.jsonc` -- applies to all projects. On Windows, this is `C:\Users\\.config\kilo\kilo.jsonc`. +- **Project config:** `kilo.jsonc` in the root of your project -- overrides global settings for that project. + +Both files use the [JSONC](https://code.visualstudio.com/docs/languages/json#_json-with-comments) format (JSON with comments). + +### Config File Precedence + +Settings are resolved through an 8-level precedence system (lowest to highest priority): + +1. **Legacy Kilocode** -- migrated settings from the VSCode extension +2. **Remote well-known** -- remotely fetched defaults +3. **Global** -- `~/.config/kilo/kilo.jsonc` +4. **Custom** -- additional custom config paths +5. **Project** -- `kilo.jsonc` in the project root +6. **`.kilo` directory** -- config from a `.kilo/` directory in the project +7. **Inline environment** -- environment variable overrides +8. **Managed / Enterprise** -- enterprise-managed configuration (highest priority) + +Higher-priority levels override lower ones. This allows organizations to enforce settings at the enterprise level while still letting individual developers customize their local environment. + +### Schema Auto-Injection + +When you create or open a `kilo.jsonc` file, the CLI automatically injects a `$schema` property pointing to the config JSON schema. This gives you **autocompletion and validation** in any editor that supports JSON Schema (VS Code, JetBrains, etc.). + +### Export and Import + +There is no traditional export/import of settings -- the JSONC config files themselves are portable. Copy `~/.config/kilo/kilo.jsonc` or `kilo.jsonc` to another machine and you're done. + +For **session** export and import, use the CLI commands: + +- `kilo export` -- export session data +- `kilo import` -- import session data + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + Kilo Code allows you to manage your configuration settings effectively through export, import, and reset options. These features are useful for backing up your setup, sharing configurations with others, or restoring default settings if needed. You can find these options at the bottom of the Kilo Code settings page, accessible via the gear icon ({% codicon name="gear" /%}) in the Kilo Code chat view. {% image src="/docs/img/settings-management/settings-management.png" alt="Export, Import, and Reset buttons in Kilo Code settings" width="800" caption="Export, Import, and Reset buttons" /%} -## Export Settings +### Export Settings Clicking the **Export** button saves your current Kilo Code settings to a JSON file. @@ -24,7 +99,7 @@ Clicking the **Export** button saves your current Kilo Code settings to a JSON f This creates a backup of your configuration or a file you can share. -## Import Settings +### Import Settings Clicking the **Import** button allows you to load settings from a previously exported JSON file. @@ -35,7 +110,7 @@ Clicking the **Import** button allows you to load settings from a previously exp - **Merging:** Importing settings **merges** the configurations. It adds new API profiles and updates existing ones and global settings based on the file content. It does **not** delete configurations present in your current setup but missing from the imported file. - **Validation:** Only valid settings matching the internal schema can be imported, preventing configuration errors. A success notification appears upon completion. -## Reset Settings +### Reset Settings Clicking the **Reset** button completely clears all Kilo Code configuration data and returns the extension to its default state. This is a destructive action intended for troubleshooting or starting fresh. @@ -57,8 +132,24 @@ Clicking the **Reset** button completely clears all Kilo Code configuration data Use this option only if you are certain you want to remove all Kilo Code data or if instructed during troubleshooting. Consider exporting your settings first if you might want to restore them later. +{% /tab %} +{% /tabs %} + ## Experimental Features +{% 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. + +{% /tab %} +{% tab label="CLI" %} + +The CLI does not currently expose the same experimental feature toggles as the **VSCode (Legacy)** version. Configuration of model behavior, file editing strategies, and other advanced options is handled directly in the JSONC config files. Refer to the auto-generated `$schema` in your `kilo.jsonc` for the full list of available options. + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + {% callout type="info" %} These features are experimental and may change in future releases. They provide advanced control over Kilo Code's behavior for specific use cases. {% /callout %} @@ -106,3 +197,6 @@ This setting controls the number of lines read from a file in one batch. To mana **Default:** Set in Advanced Settings You can find this setting in the Kilo Code settings under 'Advanced Settings'. + +{% /tab %} +{% /tabs %} diff --git a/packages/kilo-docs/pages/getting-started/settings/system-notifications.md b/packages/kilo-docs/pages/getting-started/settings/system-notifications.md index 0593577a0f6..477f88043d6 100644 --- a/packages/kilo-docs/pages/getting-started/settings/system-notifications.md +++ b/packages/kilo-docs/pages/getting-started/settings/system-notifications.md @@ -1,6 +1,7 @@ --- title: "System Notifications" description: "Configure native OS notifications for Kilo Code" +platform: legacy --- # System Notifications diff --git a/packages/kilo-docs/pages/getting-started/setup-authentication.md b/packages/kilo-docs/pages/getting-started/setup-authentication.md index 8697970b0bd..d6390faa5f8 100644 --- a/packages/kilo-docs/pages/getting-started/setup-authentication.md +++ b/packages/kilo-docs/pages/getting-started/setup-authentication.md @@ -9,6 +9,31 @@ When you install Kilo Code, you'll be prompted to sign in or create a free accou ## Quick Start with Kilo Account +{% tabs %} +{% tab label="VSCode" %} + +The extension prompts you to sign in when you first open the sidebar. Click **Sign In** and complete the browser-based flow. The extension communicates with the CLI backend, so authentication is shared between the CLI and extension. + +{% /tab %} +{% tab label="CLI" %} + +Run the auth command and follow the browser-based sign-in flow: + +```bash +kilo auth login +``` + +This may open your browser to complete authentication. Once signed in, your credentials are stored locally and used for all future sessions. + +To verify your auth status: + +```bash +kilo auth list +``` + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + 1. Click **"Try Kilo Code for Free"** in the extension 2. Sign in with your Google account 3. Allow VS Code to open the authorization URL @@ -17,6 +42,9 @@ When you install Kilo Code, you'll be prompted to sign in or create a free accou That's it! You're ready to [start your first task](/docs/getting-started/quickstart). +{% /tab %} +{% /tabs %} + {% callout type="tip" title="Bonus Credits" %} [Add credits to your account](https://app.kilo.ai/profile) and get $20 bonus credits, or sign up for [Kilo Pass](https://kilo.ai/features/kilo-pass). {% /callout %} @@ -75,12 +103,48 @@ Already have a ChatGPT subscription? You can use it with Kilo Code through the [ ### Configuring Your Provider +{% tabs %} +{% tab label="VSCode" %} + +1. Open the Kilo Code sidebar in VS Code +2. Click the gear icon ({% codicon name="gear" /%}) to open **Settings** +3. Go to the **Providers** tab +4. Select your provider and enter your API key +5. Choose your model + +You can also use `kilo auth login` for providers that support OAuth (like GitHub Copilot). The extension reads from the same underlying config files as the CLI, so provider settings are shared. + +{% /tab %} +{% tab label="CLI" %} + +Set the API key as an environment variable: + +```bash +export ANTHROPIC_API_KEY="sk-ant-..." +``` + +Or use `kilo auth login` for providers that support OAuth (like GitHub Copilot). + +To set a default model: + +```jsonc +{ + "model": "anthropic/claude-sonnet-4-20250514", +} +``` + +{% /tab %} +{% tab label="VSCode (Legacy)" %} + 1. Click the {% kilo-code-icon /%} icon in the VS Code sidebar 2. Select your API provider from the dropdown 3. Paste your API key -4. Choose your model: +4. Choose your model 5. Click **"Let's go!"** +{% /tab %} +{% /tabs %} + {% callout type="info" title="Need Help?" %} Reach out to our [support team](mailto:hi@kilo.ai) or join our [Discord community](https://kilo.ai/discord). {% /callout %} diff --git a/packages/kilo-docs/pages/kiloclaw/dashboard.md b/packages/kilo-docs/pages/kiloclaw/dashboard.md index 9904f07bc74..9e75225fdd0 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 visible 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 c3f07a9f0a0..e90f39738d2 100644 --- a/packages/kilo-docs/pages/kiloclaw/troubleshooting.md +++ b/packages/kilo-docs/pages/kiloclaw/troubleshooting.md @@ -77,11 +77,21 @@ You can access instance files in `/root/.openclaw/` directly from the [KiloClaw 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? +### Can I install tailscale on my KiloClaw instance? -Do **not** click **Update Now** inside the OpenClaw Control UI — this is not supported for KiloClaw instances and may break your setup. +Not at this time. -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). +### Can I update the version of Node on my instance? + +Not at this time. + +### How do I upgrade the OpenClaw version? Can I upgrade it myself? + +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. + +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 diff --git a/packages/kilo-docs/source-links.md b/packages/kilo-docs/source-links.md index 9938c82f3df..14b4571bff8 100644 --- a/packages/kilo-docs/source-links.md +++ b/packages/kilo-docs/source-links.md @@ -1,15 +1,16 @@ # Source Code Links - + - - - - +- + - - diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index a88041fe96f..7f405db613a 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.2", + "version": "7.1.8", "type": "module", "license": "MIT", "description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration", @@ -29,6 +29,9 @@ "dependencies": { "@kilocode/plugin": "workspace:*", "@kilocode/sdk": "workspace:*", + "@ai-sdk/anthropic": "2.0.65", + "@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", "ai": "catalog:", diff --git a/packages/kilo-gateway/src/api/constants.ts b/packages/kilo-gateway/src/api/constants.ts index 086aea7149f..f2f08dc92ad 100644 --- a/packages/kilo-gateway/src/api/constants.ts +++ b/packages/kilo-gateway/src/api/constants.ts @@ -69,3 +69,7 @@ export const HEADER_FEATURE = "X-KILOCODE-FEATURE" /** Environment variable name for feature override */ export const ENV_FEATURE = "KILOCODE_FEATURE" + +export const PROMPTS = ["codex", "gemini", "beast", "anthropic", "trinity", "anthropic_without_todo"] as const + +export const AI_SDK_PROVIDERS = ["anthropic", "openai", "openai-compatible", "openrouter"] as const diff --git a/packages/kilo-gateway/src/api/models.ts b/packages/kilo-gateway/src/api/models.ts index 5e62fedd644..8229966bf83 100644 --- a/packages/kilo-gateway/src/api/models.ts +++ b/packages/kilo-gateway/src/api/models.ts @@ -1,7 +1,7 @@ import { z } from "zod" import { getKiloUrlFromToken } from "../auth/token.js" import { DEFAULT_HEADERS } from "../headers.js" -import { KILO_API_BASE, KILO_OPENROUTER_BASE, MODELS_FETCH_TIMEOUT_MS } from "./constants.js" +import { KILO_API_BASE, KILO_OPENROUTER_BASE, MODELS_FETCH_TIMEOUT_MS, PROMPTS, AI_SDK_PROVIDERS } from "./constants.js" /** * OpenRouter model schema @@ -34,11 +34,9 @@ const openRouterModelSchema = z.object({ opencode: z .object({ family: z.string().optional(), - prompt: z - .enum(["codex", "gemini", "beast", "anthropic", "trinity", "anthropic_without_todo"]) - .optional() - .catch(undefined), + prompt: z.enum(PROMPTS).optional().catch(undefined), variants: z.record(z.string(), z.record(z.string(), z.any())).optional(), + ai_sdk_provider: z.enum(AI_SDK_PROVIDERS).optional().catch(undefined), }) .optional(), }) @@ -50,12 +48,15 @@ const openRouterModelsResponseSchema = z.object({ type OpenRouterModel = z.infer /** - * Parse API price string to number (e.g. "0.00001" -> 0.00001) + * Parse API price string to number, converting from per-token to per-million-tokens. + * The API returns prices in $/token, but downstream cost calculation (getUsage) + * divides by 1,000,000 expecting $/M tokens. */ function parseApiPrice(price: string | null | undefined): number | undefined { if (!price) return undefined const parsed = parseFloat(price) - return isNaN(parsed) ? undefined : parsed + if (isNaN(parsed)) return undefined + return parsed * 1_000_000 // Convert $/token → $/M tokens } /** @@ -162,6 +163,7 @@ function transformToModelDevFormat(model: OpenRouterModel): any { recommendedIndex: model.preferredIndex, variants: model.opencode?.variants, prompt: model.opencode?.prompt, + ai_sdk_provider: model.opencode?.ai_sdk_provider, tool_call: supportsTools, isFree: model.isFree, ...(inputPrice !== undefined && diff --git a/packages/kilo-gateway/src/api/modes.ts b/packages/kilo-gateway/src/api/modes.ts new file mode 100644 index 00000000000..18557ab50f4 --- /dev/null +++ b/packages/kilo-gateway/src/api/modes.ts @@ -0,0 +1,99 @@ +import { z } from "zod" +import { KILO_API_BASE, MODELS_FETCH_TIMEOUT_MS } from "./constants.js" +import { DEFAULT_HEADERS } from "../headers.js" + +/** + * Group entry in an organization mode config. + * Either a simple group name or a tuple for edit with file restrictions. + */ +const EditGroupConfigSchema = z.object({ + fileRegex: z.string().optional(), + description: z.string().optional(), +}) + +const GroupEntrySchema = z.union([z.string(), z.tuple([z.string(), EditGroupConfigSchema])]) + +const OrganizationModeConfigSchema = z.object({ + roleDefinition: z.string().optional(), + whenToUse: z.string().optional(), + description: z.string().optional(), + customInstructions: z.string().optional(), + groups: z.array(GroupEntrySchema).optional(), +}) + +const OrganizationModeSchema = z.object({ + id: z.string(), + organization_id: z.string(), + name: z.string(), + slug: z.string(), + created_by: z.string(), + created_at: z.string(), + updated_at: z.string(), + config: OrganizationModeConfigSchema, +}) + +const ResponseSchema = z.object({ + modes: z.array(OrganizationModeSchema), +}) + +export type OrganizationModeConfig = z.infer +export type OrganizationMode = z.infer + +/** + * In-memory cache for organization modes, keyed by organizationId. + */ +const cache = new Map() +const TTL = 5 * 60 * 1000 // 5 minutes + +/** + * Clear the organization modes cache. + * Should be called when switching organizations. + */ +export function clearModesCache() { + cache.clear() +} + +/** + * Fetch custom modes for an organization from the Kilo Cloud API. + * + * @param token - Bearer authentication token + * @param organizationId - Organization UUID + * @returns Array of organization modes, or empty array on error + */ +export async function fetchOrganizationModes(token: string, organizationId: string): Promise { + const cached = cache.get(organizationId) + if (cached && Date.now() - cached.timestamp < TTL) { + return cached.modes + } + + try { + const url = `${KILO_API_BASE}/api/organizations/${encodeURIComponent(organizationId)}/modes` + const response = await fetch(url, { + headers: { + ...DEFAULT_HEADERS, + Authorization: `Bearer ${token}`, + }, + signal: AbortSignal.timeout(MODELS_FETCH_TIMEOUT_MS), + }) + + if (!response.ok) { + console.warn(`[Kilo Gateway] Failed to fetch organization modes: ${response.status}`) + return [] + } + + const json = await response.json() + const parsed = ResponseSchema.safeParse(json) + + if (!parsed.success) { + console.warn("[Kilo Gateway] Organization modes response validation failed:", parsed.error.format()) + return [] + } + + const modes = parsed.data.modes + cache.set(organizationId, { modes, timestamp: Date.now() }) + return modes + } catch (err) { + console.warn("[Kilo Gateway] Error fetching organization modes:", err) + return [] + } +} diff --git a/packages/kilo-gateway/src/index.ts b/packages/kilo-gateway/src/index.ts index c2c2325ad59..c441cc5a6c1 100644 --- a/packages/kilo-gateway/src/index.ts +++ b/packages/kilo-gateway/src/index.ts @@ -34,6 +34,12 @@ export { promptOrganizationSelection, } from "./api/profile.js" export { fetchKiloModels } from "./api/models.js" +export { + fetchOrganizationModes, + clearModesCache, + type OrganizationMode, + type OrganizationModeConfig, +} from "./api/modes.js" export { fetchKilocodeNotifications, type KilocodeNotification } from "./api/notifications.js" // ============================================================================ @@ -60,6 +66,7 @@ export type { PollOptions, PollResult, // Provider types + KiloProvider, KiloProviderOptions, KiloMetadata, CustomLoaderResult, @@ -96,4 +103,6 @@ export { ENV_VERSION, TESTER_SUPPRESS_VALUE, ENV_FEATURE, + PROMPTS, + AI_SDK_PROVIDERS, } from "./api/constants.js" diff --git a/packages/kilo-gateway/src/provider.ts b/packages/kilo-gateway/src/provider.ts index 62c4ed80057..618360a4c35 100644 --- a/packages/kilo-gateway/src/provider.ts +++ b/packages/kilo-gateway/src/provider.ts @@ -1,6 +1,8 @@ import { createOpenRouter } from "@openrouter/ai-sdk-provider" -import type { Provider as SDK } from "ai" -import type { KiloProviderOptions } from "./types.js" +import { createAnthropic } from "@ai-sdk/anthropic" +import { createOpenAI } from "@ai-sdk/openai" +import { createOpenAICompatible } from "@ai-sdk/openai-compatible" +import type { KiloProvider, KiloProviderOptions } from "./types.js" import { getKiloUrlFromToken, getApiKey } from "./auth/token.js" import { buildKiloHeaders, DEFAULT_HEADERS } from "./headers.js" import { KILO_API_BASE, ANONYMOUS_API_KEY } from "./api/constants.js" @@ -21,7 +23,7 @@ import { KILO_API_BASE, ANONYMOUS_API_KEY } from "./api/constants.js" * const model = provider.languageModel("anthropic/claude-sonnet-4") * ``` */ -export function createKilo(options: KiloProviderOptions = {}): SDK { +export function createKilo(options: KiloProviderOptions = {}): KiloProvider { // Get API key from options or environment const apiKey = getApiKey(options) @@ -66,11 +68,36 @@ export function createKilo(options: KiloProviderOptions = {}): SDK { }) } - // Create OpenRouter provider with KiloCode configuration - return createOpenRouter({ + const sdkOptions = { baseURL: openRouterUrl, apiKey: apiKey ?? ANONYMOUS_API_KEY, headers: customHeaders, fetch: wrappedFetch as typeof fetch, - }) + } + + const openrouter = createOpenRouter(sdkOptions) + const anthropic = createAnthropic(sdkOptions) + const openai = createOpenAI(sdkOptions) + const openaiCompatible = createOpenAICompatible({ ...sdkOptions, name: "openaiCompatible" }) + + return { + languageModel(modelId) { + return openrouter(modelId) + }, + textEmbeddingModel(modelId) { + return openrouter.textEmbeddingModel(modelId) + }, + imageModel(modelId) { + return openrouter.imageModel(modelId) + }, + anthropic(modelId) { + return anthropic(modelId) + }, + openai(modelId) { + return openai(modelId) + }, + openaiCompatible(modelId) { + return openaiCompatible(modelId) + }, + } } diff --git a/packages/kilo-gateway/src/server/routes.ts b/packages/kilo-gateway/src/server/routes.ts index b5231f245af..79a27b7f5f5 100644 --- a/packages/kilo-gateway/src/server/routes.ts +++ b/packages/kilo-gateway/src/server/routes.ts @@ -7,6 +7,7 @@ import { fetchProfile, fetchBalance } from "../api/profile.js" import { fetchKilocodeNotifications, KilocodeNotificationSchema } from "../api/notifications.js" +import { fetchOrganizationModes, clearModesCache } from "../api/modes.js" import { KILO_API_BASE, HEADER_FEATURE } from "../api/constants.js" import { buildKiloHeaders } from "../headers.js" import type { ImportDeps, DrizzleDb } from "../cloud-sessions.js" @@ -204,10 +205,84 @@ export function createKiloRoutes(deps: KiloRoutesDeps) { }) ModelCache.clear("kilo") + clearModesCache() return c.json(true) }, ) + .get( + "/modes", + describeRoute({ + summary: "Get organization custom modes", + description: "Fetch custom modes defined for the current organization", + operationId: "kilo.modes", + responses: { + 200: { + description: "Organization modes list", + content: { + "application/json": { + schema: resolver( + z.object({ + modes: z.array( + z.object({ + id: z.string(), + organization_id: z.string(), + name: z.string(), + slug: z.string(), + created_by: z.string(), + created_at: z.string(), + updated_at: z.string(), + config: z.object({ + roleDefinition: z.string().optional(), + whenToUse: z.string().optional(), + description: z.string().optional(), + customInstructions: z.string().optional(), + groups: z + .array( + z.union([ + z.string(), + z.tuple([ + z.string(), + z.object({ fileRegex: z.string().optional(), description: z.string().optional() }), + ]), + ]), + ) + .optional(), + }), + }), + ), + }), + ), + }, + }, + }, + }, + }), + async (c: any) => { + const auth = await Auth.get("kilo") + + if (!auth || auth.type !== "oauth") { + return c.json({ modes: [] }) + } + + const token = auth.access + if (!token) { + return c.json({ modes: [] }) + } + + const orgId = auth.accountId + if (!orgId) { + return c.json({ modes: [] }) + } + + try { + const modes = await fetchOrganizationModes(token, orgId) + return c.json({ modes }) + } catch { + return c.json({ modes: [] }) + } + }, + ) .post( "/fim", describeRoute({ diff --git a/packages/kilo-gateway/src/types.ts b/packages/kilo-gateway/src/types.ts index 5afecffe09d..ccfc786081f 100644 --- a/packages/kilo-gateway/src/types.ts +++ b/packages/kilo-gateway/src/types.ts @@ -1,4 +1,4 @@ -import type { Provider as SDK } from "ai" +import type { LanguageModel, Provider, Provider as SDK } from "ai" import type { LanguageModelV2 } from "@openrouter/ai-sdk-provider" // ============================================================================ @@ -159,5 +159,11 @@ export interface ProviderInfo { models: Record } +export type KiloProvider = Provider & { + anthropic(modelId: string): LanguageModel + openai(modelId: string): LanguageModel + openaiCompatible(modelId: string): LanguageModel +} + // Re-export LanguageModelV2 for convenience export type { LanguageModelV2 } diff --git a/packages/kilo-i18n/package.json b/packages/kilo-i18n/package.json index fa58760b7e4..79bd3fef8a5 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.2", + "version": "7.1.8", "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 fd9a924f757..348c3889482 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.2", + "version": "7.1.8", "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 80f90256db6..3847808338d 100644 --- a/packages/kilo-ui/package.json +++ b/packages/kilo-ui/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-ui", - "version": "7.1.2", + "version": "7.1.8", "type": "module", "license": "MIT", "exports": { diff --git a/packages/kilo-ui/src/components/message-part.css b/packages/kilo-ui/src/components/message-part.css index cac42ad5f26..307ae9fccdd 100644 --- a/packages/kilo-ui/src/components/message-part.css +++ b/packages/kilo-ui/src/components/message-part.css @@ -150,15 +150,15 @@ html[data-theme="kilo-vscode"] [data-component="bash-output"] { margin-bottom: 0px; } -/* User message copy button: tiny reserved space, button overflows on hover. - * height:2px keeps layout stable; overflow:hidden clips the invisible button; - * on hover overflow:visible lets the button appear without shifting content. */ +/* User message copy button: collapse wrapper when idle, show on hover. + * The wrapper must be tall enough to fully contain the button (20px) + * so that hovering the button keeps [data-component="user-message"] + * hovered — otherwise :hover is lost and pointer-events/opacity revert. */ [data-component="user-message"] { [data-slot="user-message-copy-wrapper"] { min-height: 0; - height: 10px; + height: 20px; margin-top: 0; - overflow: hidden; [data-slot="user-message-meta-wrap"] { display: none; @@ -169,11 +169,6 @@ html[data-theme="kilo-vscode"] [data-component="bash-output"] { height: 20px; } } - - &:hover [data-slot="user-message-copy-wrapper"], - &:focus-within [data-slot="user-message-copy-wrapper"] { - overflow: visible; - } } [data-component="question-answers"] { @@ -291,3 +286,26 @@ html[data-theme="kilo-vscode"] [data-component="bash-output"] { opacity: 1; } } + +[data-component="tool-hint"] { + display: flex; + align-items: start; + gap: 6px; + padding: 4px 8px; + border-left: 2px solid var(--border-weak-base); + + [data-component="icon"] { + flex-shrink: 0; + color: var(--icon-weak-base); + margin-top: 1px; + } + + [data-slot="tool-hint-message"] { + font-family: var(--font-family-sans); + font-size: var(--font-size-small); + font-style: italic; + color: var(--text-weak); + opacity: 0.9; + line-height: var(--line-height-large); + } +} diff --git a/packages/kilo-ui/src/components/message-part.tsx b/packages/kilo-ui/src/components/message-part.tsx index d2fc659fad4..e4b6351e429 100644 --- a/packages/kilo-ui/src/components/message-part.tsx +++ b/packages/kilo-ui/src/components/message-part.tsx @@ -1077,6 +1077,20 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
) } + const hint = + cleaned.includes("before overwriting it. Use the Read tool first") || + cleaned.includes("has been modified since it was last read") || + cleaned.includes("oldString and newString are identical") || + cleaned.includes("must match exactly, including whitespace") || + cleaned.includes("Found multiple matches for oldString") + if (hint) { + return ( +
+ + {cleaned} +
+ ) + } const [title, ...rest] = cleaned.split(": ") return ( @@ -1292,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 ( @@ -1302,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} -
+
@@ -1993,8 +2016,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 @@ -2049,7 +2072,6 @@ ToolRegistry.register({ path={file().relativePath.includes("/") ? getDirectory(file().relativePath) : undefined} changes={{ additions: file().additions, deletions: file().deletions }} animate={reveal()} - soft onClick={ data.openFile && file().filePath ? (e: MouseEvent) => { @@ -2145,7 +2167,7 @@ ToolRegistry.register({ - +
} > -
- -
+ +
+ +
+
)} diff --git a/packages/kilo-ui/src/components/text-shimmer.tsx b/packages/kilo-ui/src/components/text-shimmer.tsx index 8a835e07cb7..382d1ec27d6 100644 --- a/packages/kilo-ui/src/components/text-shimmer.tsx +++ b/packages/kilo-ui/src/components/text-shimmer.tsx @@ -1 +1 @@ -export * from "@opencode-ai/ui/text-shimmer" \ No newline at end of file +export * from "@opencode-ai/ui/text-shimmer" diff --git a/packages/kilo-ui/src/components/tool-count-summary.tsx b/packages/kilo-ui/src/components/tool-count-summary.tsx index 63aed1c7710..52bc991829c 100644 --- a/packages/kilo-ui/src/components/tool-count-summary.tsx +++ b/packages/kilo-ui/src/components/tool-count-summary.tsx @@ -1 +1 @@ -export * from "@opencode-ai/ui/tool-count-summary" \ No newline at end of file +export * from "@opencode-ai/ui/tool-count-summary" diff --git a/packages/kilo-ui/src/hooks/create-auto-scroll.tsx b/packages/kilo-ui/src/hooks/create-auto-scroll.tsx index 99862e4ae73..6ea1f5d8ad0 100644 --- a/packages/kilo-ui/src/hooks/create-auto-scroll.tsx +++ b/packages/kilo-ui/src/hooks/create-auto-scroll.tsx @@ -7,7 +7,6 @@ const DEBOUNCE_MS = 100 export interface AutoScrollOptions { working: () => boolean onUserInteracted?: () => void - overflowAnchor?: "none" | "auto" | "dynamic" bottomThreshold?: number } @@ -15,10 +14,10 @@ export function createAutoScroll(options: AutoScrollOptions) { let scroll: HTMLElement | undefined let settling = false let settleTimer: ReturnType | undefined - let autoTimer: ReturnType | undefined let stopTimer: ReturnType | undefined let cleanup: (() => void) | undefined - let auto: { time: number } | undefined + let userInitiated = false + let lastScrollTop: number | undefined const threshold = () => options.bottomThreshold ?? 10 @@ -37,36 +36,18 @@ export function createAutoScroll(options: AutoScrollOptions) { return el.scrollHeight - el.clientHeight > 1 } - // Browsers can dispatch scroll events asynchronously. If new content arrives - // between us calling `scrollTo()` and the subsequent `scroll` event firing, - // the handler can see a non-zero `distanceFromBottom` and incorrectly assume - // the user scrolled. - const markAuto = (_el: HTMLElement) => { - auto = { time: Date.now() } - - if (autoTimer) clearTimeout(autoTimer) - autoTimer = setTimeout(() => { - auto = undefined - autoTimer = undefined - }, 250) - } - - const isAuto = (_el: HTMLElement) => { - const a = auto - if (!a) return false - - if (Date.now() - a.time > 250) { - auto = undefined - return false + const markUser = (e: Event) => { + if (e instanceof WheelEvent) { + const target = e.target instanceof Element ? e.target : undefined + const nested = target?.closest("[data-scrollable]") + if (scroll && nested && nested !== scroll) return } - - return true + userInitiated = true } const scrollToBottomNow = (behavior: ScrollBehavior) => { const el = scroll if (!el) return - markAuto(el) if (behavior === "smooth") { el.scrollTo({ top: el.scrollHeight, behavior }) return @@ -74,6 +55,7 @@ export function createAutoScroll(options: AutoScrollOptions) { // `scrollTop` assignment bypasses any CSS `scroll-behavior: smooth`. el.scrollTop = el.scrollHeight + lastScrollTop = el.scrollTop } const scrollToBottom = (force: boolean) => { @@ -121,19 +103,28 @@ export function createAutoScroll(options: AutoScrollOptions) { const el = scroll if (!el) return + const byUser = userInitiated + userInitiated = false + const distance = distanceFromBottom(el) + if (!canScroll(el)) { if (store.userScrolled) setStore("userScrolled", false) return } - if (distanceFromBottom(el) < threshold()) { + if (distance < threshold()) { if (store.userScrolled) setStore("userScrolled", false) + lastScrollTop = el.scrollTop return } - // Ignore scroll events triggered by our own scrollToBottom calls. - if (!store.userScrolled && isAuto(el)) { - scrollToBottom(false) + if (!store.userScrolled && !byUser) { + if (el.scrollTop < (lastScrollTop ?? el.scrollTop)) { + stop() + } else { + scrollToBottomNow("auto") + } + lastScrollTop = el.scrollTop return } @@ -145,7 +136,6 @@ export function createAutoScroll(options: AutoScrollOptions) { const cur = scroll if (!cur) return if (distanceFromBottom(cur) < threshold()) return - if (!store.userScrolled && isAuto(cur)) return stop() }, DEBOUNCE_MS) } @@ -155,22 +145,6 @@ export function createAutoScroll(options: AutoScrollOptions) { stop() } - const updateOverflowAnchor = (el: HTMLElement) => { - const mode = options.overflowAnchor ?? "dynamic" - - if (mode === "none") { - el.style.overflowAnchor = "none" - return - } - - if (mode === "auto") { - el.style.overflowAnchor = "auto" - return - } - - el.style.overflowAnchor = store.userScrolled ? "auto" : "none" - } - createResizeObserver( () => store.contentRef, () => { @@ -179,8 +153,16 @@ export function createAutoScroll(options: AutoScrollOptions) { if (store.userScrolled) setStore("userScrolled", false) return } - if (!active()) return - if (store.userScrolled) return + if (!active()) { + if (!store.userScrolled && el && distanceFromBottom(el) > threshold()) { + scrollToBottomNow("auto") + return + } + return + } + if (store.userScrolled) { + return + } // ResizeObserver fires after layout, before paint. // Keep the bottom locked in the same frame to avoid visible // "jump up then catch up" artifacts while streaming content. @@ -206,18 +188,8 @@ export function createAutoScroll(options: AutoScrollOptions) { }), ) - createEffect(() => { - // Track `userScrolled` even before `scrollRef` is attached, so we can - // update overflow anchoring once the element exists. - store.userScrolled - const el = scroll - if (!el) return - updateOverflowAnchor(el) - }) - onCleanup(() => { if (settleTimer) clearTimeout(settleTimer) - if (autoTimer) clearTimeout(autoTimer) if (stopTimer) clearTimeout(stopTimer) if (cleanup) cleanup() }) @@ -233,11 +205,19 @@ export function createAutoScroll(options: AutoScrollOptions) { if (!el) return - updateOverflowAnchor(el) + el.style.overflowAnchor = "auto" el.addEventListener("wheel", handleWheel, { passive: true }) + el.addEventListener("wheel", markUser, { passive: true, capture: true }) + el.addEventListener("pointerdown", markUser, { passive: true }) + el.addEventListener("keydown", markUser, { passive: true }) + el.addEventListener("touchstart", markUser, { passive: true }) cleanup = () => { el.removeEventListener("wheel", handleWheel) + el.removeEventListener("wheel", markUser, { capture: true }) + el.removeEventListener("pointerdown", markUser) + el.removeEventListener("keydown", markUser) + el.removeEventListener("touchstart", markUser) } }, contentRef: (el: HTMLElement | undefined) => setStore("contentRef", el), diff --git a/packages/kilo-ui/src/stories/basic-tool.stories.tsx b/packages/kilo-ui/src/stories/basic-tool.stories.tsx index ac8252e077e..255ea5fe13a 100644 --- a/packages/kilo-ui/src/stories/basic-tool.stories.tsx +++ b/packages/kilo-ui/src/stories/basic-tool.stories.tsx @@ -40,12 +40,7 @@ export const NoChildren: Story = { export const Locked: Story = { render: () => ( - +
{"Hello, world!"}
), diff --git a/packages/kilo-ui/src/stories/message-part.stories.tsx b/packages/kilo-ui/src/stories/message-part.stories.tsx index 112e29e236a..e67fe32b441 100644 --- a/packages/kilo-ui/src/stories/message-part.stories.tsx +++ b/packages/kilo-ui/src/stories/message-part.stories.tsx @@ -353,3 +353,91 @@ export const WithContextGroup: Story = { ), } + +// --- All 5 tool hint error types in a single screenshot --- + +const hintErrors: ToolPart[] = [ + { + id: "part-hint-001", + sessionID: SESSION_ID, + messageID: ASST_MSG_ID, + type: "tool", + callID: "call-hint-001", + tool: "write", + state: { + status: "error", + input: { filePath: "src/config.ts" }, + error: + "Error: File already exists — read it before overwriting it. Use the Read tool first to see its current contents.", + time: { start: now - 6000, end: now - 5500 }, + }, + }, + { + id: "part-hint-002", + sessionID: SESSION_ID, + messageID: ASST_MSG_ID, + type: "tool", + callID: "call-hint-002", + tool: "edit", + state: { + status: "error", + input: { filePath: "src/app.tsx" }, + error: "Error: File has been modified since it was last read. Please read it again before editing.", + time: { start: now - 5500, end: now - 5000 }, + }, + }, + { + id: "part-hint-003", + sessionID: SESSION_ID, + messageID: ASST_MSG_ID, + type: "tool", + callID: "call-hint-003", + tool: "edit", + state: { + status: "error", + input: { filePath: "src/utils.ts" }, + error: "Error: oldString and newString are identical. No changes were made.", + time: { start: now - 5000, end: now - 4500 }, + }, + }, + { + id: "part-hint-004", + sessionID: SESSION_ID, + messageID: ASST_MSG_ID, + type: "tool", + callID: "call-hint-004", + tool: "edit", + state: { + status: "error", + input: { filePath: "src/index.ts" }, + error: + "Error: oldString not found in file. The oldString must match exactly, including whitespace and indentation.", + time: { start: now - 4500, end: now - 4000 }, + }, + }, + { + id: "part-hint-005", + sessionID: SESSION_ID, + messageID: ASST_MSG_ID, + type: "tool", + callID: "call-hint-005", + tool: "edit", + state: { + status: "error", + input: { filePath: "src/counter.tsx" }, + error: + "Error: Found multiple matches for oldString. Provide more surrounding lines to identify the correct match.", + time: { start: now - 4000, end: now - 3500 }, + }, + }, +] + +const mockDataHintErrors = createMockData(hintErrors) + +export const ToolHintErrors: Story = { + render: () => ( + + + + ), +} diff --git a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/full-conversation-turn-chromium-linux.png b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/full-conversation-turn-chromium-linux.png index 6f383cb9019..27646a659da 100644 --- a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/full-conversation-turn-chromium-linux.png +++ b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/full-conversation-turn-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9cad4954b9ac5c0d1a245d14b3ab51836217479870c39589a55eb862c4247aa9 -size 18902 +oid sha256:81fd232992e804e8e0b3453c4e77d358f8c24dd7495b354b8d7de24c7a43724c +size 18986 diff --git a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/tool-hint-errors-chromium-linux.png b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/tool-hint-errors-chromium-linux.png new file mode 100644 index 00000000000..4650c65cafe --- /dev/null +++ b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/tool-hint-errors-chromium-linux.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:958b3b690c8e19c8c4ffc451da476954e9334f5619a1b8b40ce30da848240f6d +size 15354 diff --git a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/user-message-story-chromium-linux.png b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/user-message-story-chromium-linux.png index b68a8dc340c..c11138b36db 100644 --- a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/user-message-story-chromium-linux.png +++ b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-messagepart/user-message-story-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:876fba84b341bffa55bedb3c6d3384c5099c9a1d9336a3090b429b87e1256110 -size 4149 +oid sha256:4b690e1cba9e1a7a4eef86162c762092f5908f2d498f0d77f48c44fef1fd44ff +size 4242 diff --git a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/default-chromium-linux.png b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/default-chromium-linux.png index 4b660e94928..5e3dcecb255 100644 --- a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/default-chromium-linux.png +++ b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/default-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0fc349b25120ba40eaf3f6e6cb9adf268a0433c6a4b4e723f5a9957c555aec25 -size 29267 +oid sha256:71a4c5ce0d2bd00ac8428a65e3c4db6c0455720cac5467f8f483a9708cea8765 +size 29370 diff --git a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/with-steps-expanded-chromium-linux.png b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/with-steps-expanded-chromium-linux.png index 7adc3a5b82c..5e3dcecb255 100644 --- a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/with-steps-expanded-chromium-linux.png +++ b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/with-steps-expanded-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c67bd29525bc38133cc5271d0467e85e131a0bd41313a4033836e7a6bc5e02e2 -size 26312 +oid sha256:71a4c5ce0d2bd00ac8428a65e3c4db6c0455720cac5467f8f483a9708cea8765 +size 29370 diff --git a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/working-chromium-linux.png b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/working-chromium-linux.png index a69883f2758..6d44ffd8a25 100644 --- a/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/working-chromium-linux.png +++ b/packages/kilo-ui/tests/visual-regression.spec.ts-snapshots/components-sessionturn/working-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:640fabcec21e9e8e2251e1b347966790d347af9c0b438ca4dc9bc118819069f2 -size 4562 +oid sha256:4272e7e538d95ee3c7010dca5711a53643573c0efed2c527d6db58ef23d6c086 +size 4627 diff --git a/packages/kilo-vscode/AGENTS.md b/packages/kilo-vscode/AGENTS.md index 3604d6c14b4..ff630a3ac06 100644 --- a/packages/kilo-vscode/AGENTS.md +++ b/packages/kilo-vscode/AGENTS.md @@ -201,6 +201,16 @@ New webview features must use **`@kilocode/kilo-ui`** components instead of raw This package is entirely Kilo-specific — `kilocode_change` markers are NOT needed in any files under `packages/kilo-vscode/`. The markers are only necessary when modifying shared upstream opencode files. +## Process Spawning (Windows) + +On Windows, any `spawn`/`execFile`/`exec` call that does not set `windowsHide: true` will flash a cmd.exe console window at the user. To prevent this, **never import `spawn`, `execFile`, or `exec` from `child_process` directly**. Use the wrappers in `src/util/process.ts` instead — they enforce `windowsHide: true` automatically: + +```ts +import { spawn, exec } from "../util/process" +``` + +The `spawn` wrapper covers long-lived processes (e.g. `kilo serve`). The `exec` wrapper covers short commands (e.g. `git`, `tar`). If you need the raw callback form of `execFile` for some reason, pass `windowsHide: true` explicitly in the options object. + ## Style Follow monorepo root AGENTS.md style guide: diff --git a/packages/kilo-vscode/LICENSE b/packages/kilo-vscode/LICENSE new file mode 100644 index 00000000000..5cb50685f18 --- /dev/null +++ b/packages/kilo-vscode/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2025 Kilo Code +Copyright (c) 2025 opencode + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/kilo-vscode/README.md b/packages/kilo-vscode/README.md index aef1c95a4d2..e69a35887f8 100644 --- a/packages/kilo-vscode/README.md +++ b/packages/kilo-vscode/README.md @@ -1,9 +1,9 @@

- VS Code Marketplace - X (Twitter) - Substack Blog - Discord - Reddit + VS Code Marketplace + X (Twitter) + Substack Blog + Discord + Reddit

# 🚀 Kilo diff --git a/packages/kilo-vscode/docs/agent-behaviour/mcp-server-creation.md b/packages/kilo-vscode/docs/agent-behaviour/mcp-server-creation.md new file mode 100644 index 00000000000..7656a450dcb --- /dev/null +++ b/packages/kilo-vscode/docs/agent-behaviour/mcp-server-creation.md @@ -0,0 +1,59 @@ +# MCP Servers Sub-Tab Parity + +**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. + +## Side-by-Side Comparison + +| Feature | Legacy | New | +| ----------------------- | -------------------------------- | ------------------------------------------------------------- | +| View server list | Name + source badge + status dot | Name + command/URL | +| 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 | +| 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 | +| Edit Project MCP config | Button to open file | Not available | +| Network timeout | Per-server dropdown (15s–60min) | Not available | +| Server source badge | Shows "global" / "project" | Not displayed | +| Empty state | N/A | "No MCP servers configured. Edit the opencode config file..." | + +### Expandable Server Detail (Legacy Only) + +When a server was connected and enabled, expanding it showed 5 tabs: + +| Tab | Content | +| ------------ | --------------------------------------------------------------------- | +| Tools | List of MCP tools with tool count | +| Resources | List of resources + resource templates with count | +| Instructions | Server-provided instruction text (if present) | +| Logs | Error/log entries sorted by timestamp with count | +| Auth | OAuth debug info: auth status, token expiration, scopes, refresh info | + +The new extension has none of this expandable detail. + +## Remaining Work + +### Important (P2) + +- **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 + +### Nice to Have (P3) + +- **Expandable server detail**: Show tools, resources, instructions, and logs per server when expanded. Requires CLI to expose per-server tool/resource/log data +- **Network timeout per server**: If CLI supports per-server timeout config, expose it +- **Server source badge**: Display whether server comes from global or project config +- **OAuth/Auth tab**: Display auth status for OAuth-based MCP servers (depends on CLI support) + +## Notes + +The mcp-and-mcp-hub.md doc in `non-agent-features/` tracks MCP configuration as a broader feature. This doc focuses specifically on the MCP Servers sub-tab within the Agent Behaviour settings tab. The Marketplace covers MCP server discovery and installation from a registry. diff --git a/packages/kilo-vscode/docs/agent-behaviour/modes-subtab-parity.md b/packages/kilo-vscode/docs/agent-behaviour/modes-subtab-parity.md new file mode 100644 index 00000000000..3ce93fff942 --- /dev/null +++ b/packages/kilo-vscode/docs/agent-behaviour/modes-subtab-parity.md @@ -0,0 +1,93 @@ +# Modes / Agents Sub-Tab Parity + +**Priority:** P2 + +The legacy "Modes" sub-tab was a 1794-line component with comprehensive mode management. The new "Agents" sub-tab now covers core CRUD (create, edit, delete) after PR #7225 but is still missing several legacy features. + +## Side-by-Side Comparison + +### Mode/Agent CRUD + +| Feature | Legacy (Modes) | New (Agents) | +| ------------------------ | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| View modes/agents list | List with name + slug | Interactive clickable list with name + description + "custom" badges | +| Select mode to configure | Popover/Command searchable combobox | Click-to-edit in agent list | +| Create new mode | Full dialog: name, slug, save location, role definition, description, when-to-use, tool groups, custom instructions | "Create New Mode" button with form: name (validated), description, system prompt | +| Delete custom mode | Confirmation dialog | Delete button with confirmation dialog | +| Rename custom mode | Inline text field with save/cancel | Not available — name is immutable after creation | +| Export mode | Export to file button | Not available | +| Import mode | Import dialog (project/global) | Not available (marketplace handles this) | +| Edit modes config (JSON) | Dropdown: "Edit Global Modes" / "Edit Project Modes" | Not available | +| Marketplace button | Opens mode marketplace | Not available | + +### Per-Mode/Agent Settings + +| Setting | Legacy | New | +| ------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | +| API Configuration (provider profile) | `