From a7c537bfa229b1fe16eb2d71885d9e073fc9831c Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 12:17:35 +0000 Subject: [PATCH 1/8] docs(kilo-docs): drop 'Kilo' prefix from Auto Model tier names and add Auto Free data-handling disclosure Aligns tier names with the user-facing display names ('Auto Free', 'Auto Frontier', etc.). Adds a visible note near every Auto Free mention that prompts may be logged by upstream providers (including NVIDIA's free endpoints) and drops the obsolete ByteDance Dola Seed free model. --- .../pages/code-with-ai/agents/auto-model.md | 4 ++++ .../pages/code-with-ai/agents/model-selection.md | 2 +- .../contributing/architecture/auto-model-tiers.md | 9 ++++++--- .../kilo-docs/pages/gateway/models-and-providers.md | 7 +++++-- .../pages/getting-started/using-kilo-for-free.md | 12 ++++++++---- 5 files changed, 24 insertions(+), 10 deletions(-) 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 c52b8dd6509..1ed07cf5261 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 @@ -33,6 +33,10 @@ The underlying models behind each Auto Model tier are updated server-side as bet - **Balanced** — Routes to a cost-effective model for all modes. The specific model is selected based on the API interface in use, but does not vary by mode. A good default for most developers who want strong AI assistance without paying frontier prices. - **Free** — Routes to the best available free models on OpenRouter, splitting traffic across them. Because free model availability shifts over time as providers change promotional periods, the mapping is updated server-side — you always get the best free option without having to track what's currently available. Quality will be lower than paid tiers, and the models may change over time. +{% callout type="warning" title="Data handling for Auto Free" %} +Auto Free may route your requests to providers that log prompts and outputs and use them to improve their services. In particular, it may route to NVIDIA's free endpoints, which are provided under the [NVIDIA API Trial Terms of Service](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf) — trial use only, not for production or sensitive data. Do not submit personal or confidential data when using Auto Free. +{% /callout %} + ## Benefits ### Cost Optimization diff --git a/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md b/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md index cf5c2d3ae5b..167b4cda3a7 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md @@ -27,7 +27,7 @@ While the specifics change constantly, some principles stay consistent: - Use the **model selector** in the chat prompt area to pick a model for the current session. You can also type `/models` to open the model picker. - When the selected model supports variants, type `/variant` to open the reasoning effort selector. - Set per-agent defaults and a global default in the **Settings** panel (Models tab), or directly in the `kilo.jsonc` config file. -- **Model precedence:** Session override → Last picked per agent → Per-agent config → Global config → Kilo Auto (free). +- **Model precedence:** Session override → Last picked per agent → Per-agent config → Global config → Auto Free. - The model selector remembers the last model you picked for each agent — switching agents restores your previous choice. A manual pick always beats config settings; use the **reset button** (visible when your active model differs from config) to go back to the config default. {% /tab %} diff --git a/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md b/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md index 4ecc42b1de0..bbe02b5cc86 100644 --- a/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md +++ b/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md @@ -1,13 +1,13 @@ --- title: "Auto Model Tiers" -description: "Architecture of Kilo Auto — a family of smart model tiers that match users to the right models without requiring AI expertise" +description: "Architecture of the Auto Model tiers — a family of smart model tiers that match users to the right models without requiring AI expertise" --- # Auto Model Tiers ## Overview -Kilo Auto is a model routing system that automatically selects the optimal AI model based on the user's current mode (Code, Architect, Debug, etc.). It comes in multiple tiers so that every user — regardless of budget, preference, or expertise — gets a "just works" experience without needing to understand the AI model landscape. +Auto Model is a routing system that automatically selects the optimal AI model based on the user's current mode (Code, Architect, Debug, etc.). It comes in multiple tiers so that every user — regardless of budget, preference, or expertise — gets a "just works" experience without needing to understand the AI model landscape. Three tiers are user-facing, and one is internal: @@ -68,6 +68,8 @@ For the current mode-to-model mappings, see the [Auto Model user docs](/docs/cod **Constraints**: Free models do not vary by mode — the same model is used for every mode within a session. Quality will be lower than Frontier or Balanced tiers — this is a tradeoff users accept by choosing free. +**Data handling**: Auto Free may route to providers that log prompts and outputs and use them to improve their services, including NVIDIA's free endpoints (governed by the [NVIDIA API Trial Terms of Service](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf)). This is surfaced to users alongside Auto Free mentions in the user-facing docs. + ### Auto: Small (internal) **Who it's for**: Not user-facing. Used internally by Kilo for lightweight background tasks (session titles, commit messages, conversation summaries). @@ -170,7 +172,8 @@ The client-side chain works as follows: ## Data and compliance - **Frontier**: Uses Anthropic models with no training on user data. -- **Balanced and Free**: The underlying models may have different data handling policies depending on the provider. This should be documented per-tier so enterprise users can make informed choices. +- **Balanced**: The underlying models may have different data handling policies depending on the provider. This should be documented per-tier so enterprise users can make informed choices. +- **Free**: May route to providers that log prompts and outputs and use them to improve their services, including NVIDIA's free endpoints (see [NVIDIA API Trial Terms of Service](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf)). Users should avoid submitting personal or confidential data. Surface this disclosure in proximity to every user-facing Auto Free mention. - **Small**: Same concern as Balanced/Free — the model selected depends on credit status, which may route to providers with different policies. ## Features for the future diff --git a/packages/kilo-docs/pages/gateway/models-and-providers.md b/packages/kilo-docs/pages/gateway/models-and-providers.md index a34767b01f5..fc692771c85 100644 --- a/packages/kilo-docs/pages/gateway/models-and-providers.md +++ b/packages/kilo-docs/pages/gateway/models-and-providers.md @@ -60,7 +60,6 @@ Several models are available at no cost, subject to rate limits: | Model ID | Description | |---|---| -| `bytedance-seed/dola-seed-2.0-pro:free` | ByteDance Dola Seed 2.0 Pro | | `x-ai/grok-code-fast-1:optimized:free` | xAI Grok Code Fast 1 Optimized | | `nvidia/nemotron-3-super-120b-a12b:free` | NVIDIA Nemotron 3 Super 120B | | `arcee-ai/trinity-large-thinking:free` | Arcee Trinity Large | @@ -74,7 +73,7 @@ Provided under the [NVIDIA API Trial Terms of Service](https://assets.ngc.nvidia ## Auto models -Kilo Auto virtual models automatically select the best underlying model based on the task type. The selection is controlled by the `x-kilocode-mode` request header. +Auto virtual models automatically select the best underlying model based on the task type. The selection is controlled by the `x-kilocode-mode` request header. {% callout type="info" title="Underlying models can change" %} The mappings below reflect the current routing. The underlying models behind each `kilo-auto/*` tier are updated server-side as better options become available or as providers change pricing and availability — the tier IDs themselves remain stable. @@ -104,6 +103,10 @@ Great balance of price and capability. The resolved model depends on the API int Free with limited capability. No credits required. The resolved model is selected dynamically per session from a curated set of available free models; the mapping updates server-side as free model availability shifts. +{% callout type="warning" title="Data handling for Auto Free" %} +Auto Free may route your requests to providers that log prompts and outputs and use them to improve their services — including NVIDIA's free endpoints, which are provided under the [NVIDIA API Trial Terms of Service](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf) (trial use only, not for production or sensitive data). Do not submit personal or confidential data when using Auto Free. +{% /callout %} + ### `kilo-auto/small` Automatically routes to a small, fast model for lightweight background tasks (session titles, commit messages, summaries). diff --git a/packages/kilo-docs/pages/getting-started/using-kilo-for-free.md b/packages/kilo-docs/pages/getting-started/using-kilo-for-free.md index 00a189c0ebd..60f0d97aa48 100644 --- a/packages/kilo-docs/pages/getting-started/using-kilo-for-free.md +++ b/packages/kilo-docs/pages/getting-started/using-kilo-for-free.md @@ -1,6 +1,6 @@ --- title: "Using Kilo for Free" -description: "How to use Kilo Code for free — Auto Model Free, finding free models, free autocomplete, and free background tasks" +description: "How to use Kilo Code for free — Auto Free, finding free models, free autocomplete, and free background tasks" --- # Using Kilo for Free @@ -19,9 +19,13 @@ Each of these consumes credits by default. **To use Kilo entirely for free, conf Kilo provides free models for coding tasks through the Kilo Gateway and partner providers. -### Auto Model Free +### Auto Free -The easiest way to get started is [**Auto Model Free**](/docs/code-with-ai/agents/auto-model) (`kilo-auto/free`). This is a Kilo-provided model tier that automatically routes your requests to the best available free models — no configuration needed. +The easiest way to get started is [**Auto Free**](/docs/code-with-ai/agents/auto-model) (`kilo-auto/free`). This is a Kilo-provided model tier that automatically routes your requests to the best available free models — no configuration needed. + +{% callout type="warning" title="Data handling for Auto Free" %} +Auto Free may route your requests to providers that log prompts and outputs and use them to improve their services — including NVIDIA's free endpoints, which are provided under the [NVIDIA API Trial Terms of Service](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf) (trial use only, not for production or sensitive data). Do not submit personal or confidential data when using Auto Free. +{% /callout %} ### Finding Other Free Models @@ -65,7 +69,7 @@ See the [Mistral Setup Guide](/docs/code-with-ai/features/autocomplete/mistral-s ## Free Background Tasks -Kilo uses a small model in the background for tasks like session titling. By default this is Kilo Auto Small, which consumes credits. If the small model is unavailable, Kilo falls back to your primary model — which may also consume credits if it's a paid model. +Kilo uses a small model in the background for tasks like session titling. By default this is Auto Small, which consumes credits. If the small model is unavailable, Kilo falls back to your primary model — which may also consume credits if it's a paid model. To avoid credit usage for background tasks, set the small model to a free model: From 51fe5472e214aad168775d71b9803741d1bdc4b4 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 12:20:59 +0000 Subject: [PATCH 2/8] docs(kilo-docs): link Auto Free fallback to data-handling disclosure --- packages/kilo-docs/pages/code-with-ai/agents/model-selection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md b/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md index 167b4cda3a7..b0f7c227cec 100644 --- a/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md +++ b/packages/kilo-docs/pages/code-with-ai/agents/model-selection.md @@ -27,7 +27,7 @@ While the specifics change constantly, some principles stay consistent: - Use the **model selector** in the chat prompt area to pick a model for the current session. You can also type `/models` to open the model picker. - When the selected model supports variants, type `/variant` to open the reasoning effort selector. - Set per-agent defaults and a global default in the **Settings** panel (Models tab), or directly in the `kilo.jsonc` config file. -- **Model precedence:** Session override → Last picked per agent → Per-agent config → Global config → Auto Free. +- **Model precedence:** Session override → Last picked per agent → Per-agent config → Global config → [Auto Free](/docs/code-with-ai/agents/auto-model#tiers) (note: Auto Free may route to providers that log prompts — see the Auto Model page for details). - The model selector remembers the last model you picked for each agent — switching agents restores your previous choice. A manual pick always beats config settings; use the **reset button** (visible when your active model differs from config) to go back to the config default. {% /tab %} From 8c0f27698cd11ecf901bcaa8ddd900849a44078f Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 12:28:18 +0000 Subject: [PATCH 3/8] docs(kilo-docs): clarify enterprise data-handling expectations for Auto Balanced --- .../pages/contributing/architecture/auto-model-tiers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md b/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md index bbe02b5cc86..8d4e3a6cffb 100644 --- a/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md +++ b/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md @@ -172,7 +172,7 @@ The client-side chain works as follows: ## Data and compliance - **Frontier**: Uses Anthropic models with no training on user data. -- **Balanced**: The underlying models may have different data handling policies depending on the provider. This should be documented per-tier so enterprise users can make informed choices. +- **Balanced**: As a paid tier, the underlying providers are curated to offer enterprise-grade data handling — no training on customer prompts or outputs, limited retention for abuse monitoring only, and contractual data-processing terms. When selecting or updating the providers Balanced routes to, prefer those with zero-retention or opt-out-by-default policies and clear enterprise DPAs. Per-provider policies should be documented so enterprise users can make informed choices. - **Free**: May route to providers that log prompts and outputs and use them to improve their services, including NVIDIA's free endpoints (see [NVIDIA API Trial Terms of Service](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf)). Users should avoid submitting personal or confidential data. Surface this disclosure in proximity to every user-facing Auto Free mention. - **Small**: Same concern as Balanced/Free — the model selected depends on credit status, which may route to providers with different policies. From 3d4048b59b174088f09165c1b8d9e921dcf01be5 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 12:29:29 +0000 Subject: [PATCH 4/8] docs(kilo-docs): soften Auto Balanced data-handling wording --- .../pages/contributing/architecture/auto-model-tiers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md b/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md index 8d4e3a6cffb..e956eccaa3a 100644 --- a/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md +++ b/packages/kilo-docs/pages/contributing/architecture/auto-model-tiers.md @@ -172,7 +172,7 @@ The client-side chain works as follows: ## Data and compliance - **Frontier**: Uses Anthropic models with no training on user data. -- **Balanced**: As a paid tier, the underlying providers are curated to offer enterprise-grade data handling — no training on customer prompts or outputs, limited retention for abuse monitoring only, and contractual data-processing terms. When selecting or updating the providers Balanced routes to, prefer those with zero-retention or opt-out-by-default policies and clear enterprise DPAs. Per-provider policies should be documented so enterprise users can make informed choices. +- **Balanced**: As a paid tier, underlying providers are selected with data-handling policies suitable for professional use. Prefer providers with stronger privacy posture when updating the routing. - **Free**: May route to providers that log prompts and outputs and use them to improve their services, including NVIDIA's free endpoints (see [NVIDIA API Trial Terms of Service](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf)). Users should avoid submitting personal or confidential data. Surface this disclosure in proximity to every user-facing Auto Free mention. - **Small**: Same concern as Balanced/Free — the model selected depends on credit status, which may route to providers with different policies. From 7ad1bf66d072770e80641caccd336aafce073fd1 Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 4 May 2026 10:40:15 +0200 Subject: [PATCH 5/8] docs(cli): expand config skill with agent manager workflows (#9813) --- .../opencode/src/kilocode/skills/builtin.ts | 2 +- .../src/kilocode/skills/kilo-config.md | 54 ++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/kilocode/skills/builtin.ts b/packages/opencode/src/kilocode/skills/builtin.ts index 96accd8f5ad..23275d040a3 100644 --- a/packages/opencode/src/kilocode/skills/builtin.ts +++ b/packages/opencode/src/kilocode/skills/builtin.ts @@ -15,7 +15,7 @@ export const BUILTIN_SKILLS: BuiltinSkill[] = [ { name: "kilo-config", description: - "Guide for configuring Kilo CLI and locating config, command, agent, and skill paths (global, project, legacy), plus MCP servers, permissions, instructions, plugins, providers, kilo.json fields, and TUI settings (themes, appearance, keybinds, ctrl+p commands). Use when the user asks about configuring Kilo, where it loads things from, or how to change settings.", + "Guide for Kilo configuration: config paths, kilo.json fields, commands, agents, skills, permissions, MCPs, providers, TUI settings, plus Agent Manager worktree setup/run scripts, workflows, and state. Use for Kilo config questions, locating loaded config, changing settings, or Agent Manager questions about run/setup scripts, worktree setup/workflows, apply/merge/PR/conflicts, missing sessions/worktrees, and agent-manager.json recovery.", content: KILO_CONFIG, }, ] diff --git a/packages/opencode/src/kilocode/skills/kilo-config.md b/packages/opencode/src/kilocode/skills/kilo-config.md index dd006777c21..2f35f31301b 100644 --- a/packages/opencode/src/kilocode/skills/kilo-config.md +++ b/packages/opencode/src/kilocode/skills/kilo-config.md @@ -2,7 +2,7 @@ All config lives in `kilo.json` (or `kilo.jsonc`). Precedence low-to-high: remote well-known, global (`~/.config/kilo/kilo.json`), env `KILO_CONFIG`, project `./kilo.json`, `.kilo/kilo.json`, `KILO_CONFIG_CONTENT`, managed (see Config File Locations). Deep-merged; later wins. -This also covers where Kilo looks for config files, commands, agents, and skills across project, global, and legacy paths such as `.kilo/`, `.kilocode/`, `.opencode/`, and `~/.config/kilo/`. +This also covers where Kilo looks for config files, commands, agents, and skills across project, global, and legacy paths such as `.kilo/`, `.kilocode/`, `.opencode/`, and `~/.config/kilo/`, plus Agent Manager setup/run scripts in the VS Code extension. ## Commands (`.kilo/command/*.md`) @@ -67,6 +67,58 @@ System prompt for this agent. Markdown files in `.kilo/workflows/` or `.kilocode/workflows/` (project-level) and `~/.kilo/workflows/` or `~/.kilocode/workflows/` (global). These are automatically converted to commands at startup. The filename (minus `.md`) becomes the command name. Project workflows override global ones with the same name. +## Agent Manager Setup And Run Scripts + +Agent Manager setup/run scripts are project files in the main repository's `.kilo/` directory. They are not `kilo.json` settings and should not be configured inside generated `.kilo/worktrees//` checkouts. + +Agent Manager worktrees usually live under `.kilo/worktrees/`. Think of each worktree as a separate checkout on its own branch: it enables parallel edits, but dependencies, build output, caches, databases, and generated files can consume significant disk space across many worktrees. + +### Worktree workflow and conflicts + +To bring changes back, choose one path: Agent Manager Apply for selected changes, merge the worktree branch into the target branch, or create/update a PR from the worktree. Agent Manager has native PR support and shows PR status on worktrees. + +For conflict-heavy work, resolve inside the worktree before integration: merge or rebase the original/base branch into that worktree, ask the agent there to resolve conflicts and run checks, then apply, merge, or update the PR. Do not use `git stash` or autostash because stashes are shared across worktrees. + +Agent Manager does not fully orchestrate dependencies across worktrees; users usually choose and sequence worktrees themselves. For larger parallel efforts, suggest stabilizing shared contracts, schemas, interfaces, routes, file layout, or test shape on the original/base branch before creating separate worktrees. + +### Setup script + +Setup scripts run once when a managed worktree is created, imported, or promoted, before the agent session starts. Use them for nested env files, local config, dependencies, databases, certificates, or other per-worktree setup. + +| Platform | Filenames checked in order | +|---|---| +| macOS / Linux | `.kilo/setup-script`, `.kilo/setup-script.sh` | +| Windows | `.kilo/setup-script.ps1`, `.kilo/setup-script.cmd`, `.kilo/setup-script.bat` | + +Behavior: runs from the worktree directory with `WORKTREE_PATH` set to the absolute worktree path and `REPO_PATH` set to the main repository root. Agent Manager copies root-level `.env` and `.env.*` files before setup without overwriting existing files; nested env files or other project-specific local files need setup script handling. Setup has a 5 minute timeout, and failures leave the worktree available for inspection. + +### Run script + +Run scripts start or stop the user's project for the selected Agent Manager context. Use them for dev servers, watchers, emulators, queues, or other commands behind the Run button. + +| Platform | Filenames checked in order | +|---|---| +| macOS / Linux | `.kilo/run-script`, `.kilo/run-script.sh` | +| Windows | `.kilo/run-script.ps1`, `.kilo/run-script.cmd`, `.kilo/run-script.bat` | + +Behavior: runs from the selected worktree directory, or the main repo root when `LOCAL` is selected. Receives `WORKTREE_PATH` as the current run directory and `REPO_PATH` as the main repository root. If no valid run script exists, Run opens or creates the default script template instead of running. Run status is in memory only and is not persisted in `.kilo/agent-manager.json`. + +When the project supports it, avoid fixed global resources across worktrees by deriving ports, caches, Docker Compose project names, emulators, or databases from `WORKTREE_PATH` or the branch. + +### Troubleshooting scripts + +- If Run opens configuration instead of running, no valid run script exists for the current platform. +- If a script is ignored, verify the platform-specific filename from the tables above. +- For port conflicts (`EADDRINUSE`, browser/tests hitting the wrong worktree), inspect the app's dev-server config as well as `.kilo/run-script`. If fixing it requires application changes, ask whether the user wants the app made configurable or only wants a run-script workaround. +- If commands are missing, inspect how VS Code was launched. Run scripts load the user shell environment, but setup scripts only receive explicit `WORKTREE_PATH` and `REPO_PATH` from the task adapter, so `PATH` can differ. +- If setup times out, keep setup under 5 minutes or move long-running work into the run script or manual setup. +- If output is not visible in the Agent Manager chat terminal, explain that setup/run scripts write to VS Code task terminals. Ask the user for that output if it is needed for debugging. +- If unrelated conflicts appear, check for `git stash` usage. If stash caused it, suggest adding `AGENTS.md`, skill, or prompt guidance to avoid stash-based worktree merge flows. + +### `agent-manager.json` + +Agent Manager persists UI, worktree, and session state in `.kilo/agent-manager.json`. Treat this file as diagnostic or recovery state for lost sessions, stale worktrees, missing UI state, or external worktree deletion/movement. It can be large, so inspect it selectively. It does not store script contents, run status, live tasks, or terminal mappings, and should not be edited to configure run/setup behavior. + ## Permissions Scalar form applies to all patterns. Object form maps glob patterns to actions. Evaluated top-to-bottom; first match wins. From b8b915739cb52afce9e899f76bbc8f6ec571dbd5 Mon Sep 17 00:00:00 2001 From: "kilo-code-bot[bot]" <240665456+kilo-code-bot[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 10:55:19 +0200 Subject: [PATCH 6/8] refactor(prompts): hoist Kilo model-specific prompt checks to the front (#9815) * refactor(cli): hoist Kilo model-specific prompt checks to the front Extract the Kilo metadata-driven prompt selection into a dedicated kiloPrompt() helper and invoke it with an early return at the top of provider(). This ensures Kilo-specific prompt routing takes priority over upstream heuristics and leaves the upstream if-chain untouched, reducing future merge conflicts when opencode adjusts its own model-specific prompt branching. No behavior change. * fix(cli): preserve Ling prompt fallback precedence * fix(cli): keep prompt annotations scoped --------- Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> Co-authored-by: marius-kilocode --- packages/opencode/src/session/system.ts | 40 +++++++++++-------- .../test/kilocode/system-prompt.test.ts | 19 +++++++++ 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/packages/opencode/src/session/system.ts b/packages/opencode/src/session/system.ts index 8b610e48865..7b30357d791 100644 --- a/packages/opencode/src/session/system.ts +++ b/packages/opencode/src/session/system.ts @@ -37,24 +37,30 @@ export function soul() { export function provider(model: Provider.Model) { // kilocode_change start - switch (model.prompt) { - case "anthropic": - return [PROMPT_ANTHROPIC] - case "anthropic_without_todo": - return [PROMPT_DEFAULT] - case "beast": - return [PROMPT_BEAST] - case "codex": - return [PROMPT_CODEX] - case "gemini": - return [PROMPT_GEMINI] - case "gpt55": - return [PROMPT_GPT55] - case "ling": - return [PROMPT_LING] - case "trinity": - return [PROMPT_TRINITY] + function prompt() { + switch (model.prompt) { + case "anthropic": + return [PROMPT_ANTHROPIC] + case "anthropic_without_todo": + return [PROMPT_DEFAULT] + case "beast": + return [PROMPT_BEAST] + case "codex": + return [PROMPT_CODEX] + case "gemini": + return [PROMPT_GEMINI] + case "gpt55": + return [PROMPT_GPT55] + case "ling": + return [PROMPT_LING] + case "trinity": + return [PROMPT_TRINITY] + } + return undefined } + + const kilo = prompt() + if (kilo) return kilo // kilocode_change end if (model.api.id.includes("gpt-4") || model.api.id.includes("o1") || model.api.id.includes("o3")) diff --git a/packages/opencode/test/kilocode/system-prompt.test.ts b/packages/opencode/test/kilocode/system-prompt.test.ts index d54b94dc03b..4945204e622 100644 --- a/packages/opencode/test/kilocode/system-prompt.test.ts +++ b/packages/opencode/test/kilocode/system-prompt.test.ts @@ -9,6 +9,7 @@ import PROMPT_CODEX from "../../src/session/prompt/codex.txt" import PROMPT_GEMINI from "../../src/session/prompt/gemini.txt" import PROMPT_GPT from "../../src/session/prompt/gpt.txt" import PROMPT_GPT55 from "../../src/session/prompt/kilocode-gpt-5.5.txt" +import PROMPT_LING from "../../src/session/prompt/ling.txt" import PROMPT_TRINITY from "../../src/session/prompt/trinity.txt" describe("SystemPrompt.provider", () => { @@ -78,6 +79,24 @@ describe("SystemPrompt.provider", () => { expect(result).toEqual([PROMPT_ANTHROPIC]) }) + test("Ling fallback runs after upstream model id heuristics", () => { + const model = ProviderTest.model({ + prompt: undefined, + api: { id: "gpt-5-ling", url: "https://example.com", npm: "@ai-sdk/openai" }, + }) + const result = SystemPrompt.provider(model) + expect(result).toEqual([PROMPT_GPT]) + }) + + test("Ling fallback is selected after upstream heuristics miss", () => { + const model = ProviderTest.model({ + prompt: undefined, + api: { id: "ling-2", url: "https://example.com", npm: "@ai-sdk/openai" }, + }) + const result = SystemPrompt.provider(model) + expect(result).toEqual([PROMPT_LING]) + }) + test("GPT-5.5 model ids are not prompt-special without metadata", () => { const model = ProviderTest.model({ prompt: undefined, From c8494f2f25c17f68455230feec146775d6707090 Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 4 May 2026 11:01:50 +0200 Subject: [PATCH 7/8] fix(vscode): persist auto-approve toggle preference (#9816) --- .changeset/quiet-shields-remember.md | 5 +++ packages/kilo-vscode/package.json | 5 +++ .../src/commands/toggle-auto-approve.ts | 35 +++++++++++++++++-- .../src/components/chat/PromptInput.tsx | 1 + 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 .changeset/quiet-shields-remember.md diff --git a/.changeset/quiet-shields-remember.md b/.changeset/quiet-shields-remember.md new file mode 100644 index 00000000000..6664eb33ae9 --- /dev/null +++ b/.changeset/quiet-shields-remember.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Remember the main auto-approve toggle preference across VS Code reloads and extension restarts. diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index aa7acdcca2b..82fe789dbf2 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -781,6 +781,11 @@ "default": false, "description": "Load CLAUDE.md instructions and skills from your Claude Code configuration directory into Kilo sessions. Enable this if you want Kilo to use your Claude Code instructions and skills." }, + "kilo-code.new.autoApprove.enabled": { + "type": "boolean", + "default": false, + "description": "Start Kilo Code with the main auto-approve toggle enabled. When enabled, permission prompts are approved automatically." + }, "kilo-code.new.browserAutomation.enabled": { "type": "boolean", "default": false, diff --git a/packages/kilo-vscode/src/commands/toggle-auto-approve.ts b/packages/kilo-vscode/src/commands/toggle-auto-approve.ts index ea5439d89d2..ee892312884 100644 --- a/packages/kilo-vscode/src/commands/toggle-auto-approve.ts +++ b/packages/kilo-vscode/src/commands/toggle-auto-approve.ts @@ -20,6 +20,9 @@ export interface AutoApproveController { onChange(listener: (active: boolean) => void): { dispose(): void } } +const CONFIG = "kilo-code.new.autoApprove" +const KEY = "enabled" + /** * Runtime auto-accept toggle for permissions. * @@ -34,7 +37,7 @@ export function registerToggleAutoApprove( resolve: DirectoryResolver, directories: AllDirectories, ): AutoApproveController { - let active = false + let active = readActive() // Bumped on disable to invalidate in-flight enable drains let generation = 0 const listeners = new Set<(active: boolean) => void>() @@ -43,10 +46,15 @@ export function registerToggleAutoApprove( for (const listener of listeners) listener(active) } - const toggle = async () => { - active = !active + const setActive = async (next: boolean) => { + active = next generation++ notify() + await vscode.workspace.getConfiguration(CONFIG).update(KEY, active, target()) + } + + const toggle = async () => { + await setActive(!active) const snapshot = generation if (!active) { @@ -88,6 +96,16 @@ export function registerToggleAutoApprove( }) context.subscriptions.push({ dispose: unsubscribe }) + context.subscriptions.push( + vscode.workspace.onDidChangeConfiguration((event) => { + if (!event.affectsConfiguration(`${CONFIG}.${KEY}`)) return + const next = readActive() + if (next === active) return + active = next + generation++ + notify() + }), + ) context.subscriptions.push(vscode.commands.registerCommand("kilo-code.new.toggleAutoApprove", toggle)) @@ -108,6 +126,17 @@ export function registerToggleAutoApprove( } } +function readActive(): boolean { + return vscode.workspace.getConfiguration(CONFIG).get(KEY, false) +} + +function target(): vscode.ConfigurationTarget { + const info = vscode.workspace.getConfiguration(CONFIG).inspect(KEY) + if (info?.workspaceFolderValue !== undefined) return vscode.ConfigurationTarget.WorkspaceFolder + if (info?.workspaceValue !== undefined) return vscode.ConfigurationTarget.Workspace + return vscode.ConfigurationTarget.Global +} + function tryGetClient(connectionService: KiloConnectionService): KiloClient | undefined { try { return connectionService.getClient() diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx index ce720517433..f1c28a9966b 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx @@ -1017,6 +1017,7 @@ export const PromptInput: Component = (props) => { ? language.t("prompt.action.autoApprove.disable") : language.t("prompt.action.autoApprove.enable") } + aria-pressed={autoApprove()} class={`prompt-auto-approve-button ${autoApprove() ? "prompt-auto-approve-button--active" : ""}`} > From a858f001ba8b2de561c69ba8a42d9d3347b1e66f Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 4 May 2026 11:42:47 +0200 Subject: [PATCH 8/8] fix(cli): warn on output length stops (#9820) * fix(cli): warn on reasoning-only length stops * fix(cli): warn on output length stops --- .changeset/quiet-ollamas-think.md | 5 + .../src/kilocode/session/processor.ts | 17 ++ packages/opencode/src/session/message-v2.ts | 2 +- packages/opencode/src/session/processor.ts | 22 +++ ...session-processor-empty-tool-calls.test.ts | 165 ++++++++++++++++++ 5 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 .changeset/quiet-ollamas-think.md diff --git a/.changeset/quiet-ollamas-think.md b/.changeset/quiet-ollamas-think.md new file mode 100644 index 00000000000..cb8b17b9611 --- /dev/null +++ b/.changeset/quiet-ollamas-think.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Warn when a model hits its output limit before finishing a response. diff --git a/packages/opencode/src/kilocode/session/processor.ts b/packages/opencode/src/kilocode/session/processor.ts index 9ca328cf2b7..ed7770d1ed6 100644 --- a/packages/opencode/src/kilocode/session/processor.ts +++ b/packages/opencode/src/kilocode/session/processor.ts @@ -10,6 +10,9 @@ import { Flag } from "@/flag/flag" export namespace KiloSessionProcessor { const log = Log.create({ service: "session.processor.kilo" }) + export const OUTPUT_LENGTH_WARNING = "The model hit its output limit, so this response may be incomplete." + export const REASONING_LENGTH_WARNING = + "The model hit its output limit while reasoning and produced no actionable output. Try disabling reasoning or increasing the output limit." /** * Track LLM completion telemetry for a finished step. @@ -122,4 +125,18 @@ export namespace KiloSessionProcessor { msg.finish = "stop" } } + + export function lengthWarning(input: { + msg: MessageV2.Assistant + step: { reasoning: boolean; text: boolean; tool: boolean } + }) { + if (input.msg.summary) return + if (input.msg.finish !== "length") return + if (input.step.reasoning && !input.step.text && !input.step.tool) { + log.warn("reasoning-only length stop", { messageID: input.msg.id }) + return REASONING_LENGTH_WARNING + } + log.warn("length stop", { messageID: input.msg.id }) + return OUTPUT_LENGTH_WARNING + } } diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index 1de74a39f0a..f83906fed78 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -909,7 +909,7 @@ export const toModelMessagesEffect = Effect.fnUntraced(function* ( parts: [], } for (const part of msg.parts) { - if (part.type === "text") + if (part.type === "text" && !part.ignored) // kilocode_change - keep local UI warnings out of future prompts assistantMessage.parts.push({ type: "text", text: part.text, diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts index 67f3418e9b0..75dfc10c450 100644 --- a/packages/opencode/src/session/processor.ts +++ b/packages/opencode/src/session/processor.ts @@ -75,6 +75,7 @@ interface ProcessorContext extends Input { currentText: MessageV2.TextPart | undefined reasoningMap: Record stepStart: number // kilocode_change + step: { reasoning: boolean; text: boolean; tool: boolean } // kilocode_change } type StreamEvent = Event @@ -126,6 +127,7 @@ export const layer: Layer.Layer< currentText: undefined, reasoningMap: {}, stepStart: 0, // kilocode_change + step: { reasoning: false, text: false, tool: false }, // kilocode_change } let aborted = false const ac = new AbortController() // kilocode_change — abort controller for offline handler @@ -249,6 +251,7 @@ export const layer: Layer.Layer< case "reasoning-start": if (value.id in ctx.reasoningMap) return + ctx.step.reasoning = true // kilocode_change ctx.reasoningMap[value.id] = { id: PartID.ascending(), messageID: ctx.assistantMessage.id, @@ -288,6 +291,7 @@ export const layer: Layer.Layer< if (ctx.assistantMessage.summary) { throw new Error(`Tool call not allowed while generating summary: ${value.toolName}`) } + ctx.step.tool = true // kilocode_change const part = yield* session.updatePart({ id: ctx.toolcalls[value.id]?.partID ?? PartID.ascending(), messageID: ctx.assistantMessage.id, @@ -316,6 +320,7 @@ export const layer: Layer.Layer< if (ctx.assistantMessage.summary) { throw new Error(`Tool call not allowed while generating summary: ${value.toolName}`) } + ctx.step.tool = true // kilocode_change // kilocode_change start — create tool part if tool-input-start was never emitted if (!ctx.toolcalls[value.toolCallId]) { log.warn("tool-call without prior tool-input-start", { @@ -401,6 +406,7 @@ export const layer: Layer.Layer< case "start-step": ctx.stepStart = performance.now() // kilocode_change + ctx.step = { reasoning: false, text: false, tool: false } // kilocode_change if (!ctx.snapshot) ctx.snapshot = yield* snapshot.track() yield* session.updatePart({ id: PartID.ascending(), @@ -442,6 +448,19 @@ export const layer: Layer.Layer< tokens: usage.tokens, cost: usage.cost, }) + // kilocode_change start - surface output limit stops, with a stronger message for reasoning-only stops + const warn = KiloSessionProcessor.lengthWarning({ msg: ctx.assistantMessage, step: ctx.step }) + if (warn) { + yield* session.updatePart({ + id: PartID.ascending(), + messageID: ctx.assistantMessage.id, + sessionID: ctx.assistantMessage.sessionID, + type: "text", + text: warn, + ignored: true, + }) + } + // kilocode_change end yield* session.updateMessage(ctx.assistantMessage) if (ctx.snapshot) { const patch = yield* snapshot.patch(ctx.snapshot) @@ -488,6 +507,7 @@ export const layer: Layer.Layer< case "text-delta": if (!ctx.currentText) return ctx.currentText.text += value.text + if (value.text.trim()) ctx.step.text = true // kilocode_change if (value.providerMetadata) ctx.currentText.metadata = value.providerMetadata yield* session.updatePartDelta({ sessionID: ctx.currentText.sessionID, @@ -511,6 +531,7 @@ export const layer: Layer.Layer< }, { text: ctx.currentText.text }, )).text + if (ctx.currentText.text.trim()) ctx.step.text = true // kilocode_change { const end = Date.now() ctx.currentText.time = { start: ctx.currentText.time?.start ?? end, end } @@ -618,6 +639,7 @@ export const layer: Layer.Layer< yield* Effect.gen(function* () { ctx.currentText = undefined ctx.reasoningMap = {} + ctx.step = { reasoning: false, text: false, tool: false } // kilocode_change const stream = llm.stream(streamInput) yield* stream.pipe( diff --git a/packages/opencode/test/kilocode/session-processor-empty-tool-calls.test.ts b/packages/opencode/test/kilocode/session-processor-empty-tool-calls.test.ts index 276edaefa40..41c8b0fc76a 100644 --- a/packages/opencode/test/kilocode/session-processor-empty-tool-calls.test.ts +++ b/packages/opencode/test/kilocode/session-processor-empty-tool-calls.test.ts @@ -18,6 +18,7 @@ import { MessageID, PartID, SessionID } from "../../src/session/schema" import { SessionStatus } from "../../src/session/status" import { SessionSummary } from "../../src/session/summary" import { Snapshot } from "../../src/snapshot" +import { KiloSessionProcessor } from "../../src/kilocode/session/processor" import { Log } from "../../src/util" import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner" import { provideTmpdirInstance } from "../fixture/fixture" @@ -183,6 +184,170 @@ describe("session processor empty tool-calls", () => { ), ) + it.effect("adds warning when model stops after reasoning-only length finish", () => + provideTmpdirInstance( + (dir) => + Effect.gen(function* () { + const test = yield* TestLLM + const processors = yield* SessionProcessor.Service + const session = yield* Session.Service + + yield* test.reply( + { type: "start" }, + { type: "start-step" } as LLM.Event, + { type: "reasoning-start", id: "reasoning", providerMetadata: undefined } as LLM.Event, + { type: "reasoning-delta", id: "reasoning", text: "thinking", providerMetadata: undefined } as LLM.Event, + { type: "reasoning-end", id: "reasoning", providerMetadata: undefined } as LLM.Event, + { + type: "finish-step", + finishReason: "length", + usage: usage(), + providerMetadata: undefined, + } as LLM.Event, + { type: "finish" } as LLM.Event, + ) + + const chat = yield* session.create({}) + const parent = yield* session.updateMessage({ + id: MessageID.ascending(), + role: "user", + sessionID: chat.id, + agent: "code", + model: ref, + time: { created: Date.now() }, + }) + const msg: MessageV2.Assistant = { + id: MessageID.ascending(), + role: "assistant", + sessionID: chat.id, + parentID: parent.id, + mode: "code", + agent: "code", + path: { cwd: path.resolve(dir), root: path.resolve(dir) }, + cost: 0, + tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }, + modelID: ref.modelID, + providerID: ref.providerID, + time: { created: Date.now() }, + } + yield* session.updateMessage(msg) + + const mdl = model() + const handle = yield* processors.create({ + assistantMessage: msg, + sessionID: chat.id, + model: mdl, + }) + + const input: LLM.StreamInput = { + user: parent as MessageV2.User, + sessionID: chat.id, + model: mdl, + agent: { name: "code", mode: "primary", permission: [], options: {} } as any, + system: [], + messages: [], + tools: {}, + } + + yield* handle.process(input) + const parts = MessageV2.parts(msg.id) + const warning = parts.find( + (part): part is MessageV2.TextPart => + part.type === "text" && part.text === KiloSessionProcessor.REASONING_LENGTH_WARNING, + ) + + expect(warning?.ignored).toBe(true) + + const modelMsgs = yield* MessageV2.toModelMessagesEffect([{ info: handle.message, parts }], mdl) + expect(JSON.stringify(modelMsgs)).not.toContain(KiloSessionProcessor.REASONING_LENGTH_WARNING) + }), + { git: true }, + ), + ) + + it.effect("adds generic warning when model stops after text length finish", () => + provideTmpdirInstance( + (dir) => + Effect.gen(function* () { + const test = yield* TestLLM + const processors = yield* SessionProcessor.Service + const session = yield* Session.Service + + yield* test.reply( + { type: "start" }, + { type: "start-step" } as LLM.Event, + { type: "text-start", id: "text", providerMetadata: undefined } as LLM.Event, + { type: "text-delta", id: "text", text: "partial answer", providerMetadata: undefined } as LLM.Event, + { type: "text-end", id: "text", providerMetadata: undefined } as LLM.Event, + { + type: "finish-step", + finishReason: "length", + usage: usage(), + providerMetadata: undefined, + } as LLM.Event, + { type: "finish" } as LLM.Event, + ) + + const chat = yield* session.create({}) + const parent = yield* session.updateMessage({ + id: MessageID.ascending(), + role: "user", + sessionID: chat.id, + agent: "code", + model: ref, + time: { created: Date.now() }, + }) + const msg: MessageV2.Assistant = { + id: MessageID.ascending(), + role: "assistant", + sessionID: chat.id, + parentID: parent.id, + mode: "code", + agent: "code", + path: { cwd: path.resolve(dir), root: path.resolve(dir) }, + cost: 0, + tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }, + modelID: ref.modelID, + providerID: ref.providerID, + time: { created: Date.now() }, + } + yield* session.updateMessage(msg) + + const mdl = model() + const handle = yield* processors.create({ + assistantMessage: msg, + sessionID: chat.id, + model: mdl, + }) + + const input: LLM.StreamInput = { + user: parent as MessageV2.User, + sessionID: chat.id, + model: mdl, + agent: { name: "code", mode: "primary", permission: [], options: {} } as any, + system: [], + messages: [], + tools: {}, + } + + yield* handle.process(input) + const parts = MessageV2.parts(msg.id) + const warning = parts.find( + (part): part is MessageV2.TextPart => + part.type === "text" && part.text === KiloSessionProcessor.OUTPUT_LENGTH_WARNING, + ) + + expect(warning?.ignored).toBe(true) + + const modelMsgs = yield* MessageV2.toModelMessagesEffect([{ info: handle.message, parts }], mdl) + const json = JSON.stringify(modelMsgs) + expect(json).toContain("partial answer") + expect(json).not.toContain(KiloSessionProcessor.OUTPUT_LENGTH_WARNING) + }), + { git: true }, + ), + ) + it.live("ignores deleted session during cost reconciliation", () => provideTmpdirInstance( (dir) =>