mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
Merge branch 'main' into fix/indexing-model-validation
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Inherit the current model and reasoning variant when Agent Manager starts sessions without explicit overrides.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Fix the reasoning-variant and mode dropdowns being clipped inside the New Worktree dialog. The dialog's scroll-container overflow escape now covers all inline selector popovers, not just the model picker, so dropdowns render fully above the prompt input.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Make session model usage easier to scan with collapsible summary rows and aligned steps and cost columns.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Fix cloud session fork commands so they import cloud sessions before validating the local session.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Harden config credential substitution against untrusted project config. Environment references (`{env:VAR}`) now resolve only in trusted config (global config, `KILO_CONFIG`, `KILO_CONFIG_CONTENT`, and org/MDM-managed config); a project-committed `kilo.json` / `opencode.json` can no longer use them. File references (`{file:...}`) still work in project config but are confined to the project root, so absolute paths, `../` traversal, and symlink escapes are rejected. This closes a path where a malicious repository could exfiltrate local secrets to an attacker-controlled `baseURL`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-console": patch
|
||||
---
|
||||
|
||||
Replace the hardcoded "K" letter in the Kilo Console navbar with the real Kilo logo, and drop the redundant "Kilo" wordmark since the logo already carries the name.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-web-ui": patch
|
||||
---
|
||||
|
||||
Show trailing external-link icons for Kilo Console profile links that open in a new tab.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Speed up VS Code settings saves by draining pending prompts and disposing worktree instances concurrently.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Fix Amazon Bedrock models returning no output. A smithy dependency version-skew made the Bedrock event-stream decoder silently fail under the browser build condition, so every Bedrock request completed with an empty response.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Resolve AWS Bedrock credentials from SSO profiles in packaged CLI builds.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Fix prompt submission in JetBrains IDEs when sending messages with file or git-change mentions.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Fix unreliable clicks on inline action buttons (Connect, OAuth, Disconnect, Enable) in the JetBrains provider, agent, and MCP settings lists so the whole button is clickable.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Fix multiline bidirectional prompt input rendering and file mention arrow navigation.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Show a focus outline around the JetBrains prompt input.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Hide gpt-5.5-pro from the model picker when using ChatGPT OAuth login, since Codex rejects it with HTTP 400.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"kilo-code": minor
|
||||
---
|
||||
|
||||
Render images inline in the chat view when the agent reads an image file. Images appear below the read tool card and can be clicked to open a full-size preview.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Return keyboard focus to the JetBrains prompt after clicking inline session dialog actions.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Reduce JetBrains plugin size by downloading the Kilo Core release on first connect.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Show subagent tool activity inline in JetBrains session transcripts.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Stop orphaned Kilo CLI processes when JetBrains IDEs close, including binaries that ignore graceful shutdown.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Fix JetBrains prompt pickers so reasoning effort opens above the button and expanded model details still allow one-click model selection.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Hide the JetBrains editor floating toolbar from the Kilo prompt input.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Refresh the JetBrains prompt input chrome when switching IDE themes.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Polish JetBrains prompt focus and copy toolbar positioning.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Remove old JetBrains CLI binaries so they no longer accumulate in the IDE cache. Only the active version is kept, the downloaded archive is deleted after extraction, and reinstalling re-downloads a fresh binary.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Show rollback/redo progress inline (on the message and redo controls) with a cancel action instead of a full-screen loading overlay.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Support rollback and redo controls in JetBrains sessions and clarify when reverted changes can be redone.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Clarify in JetBrains rollback that only the conversation was reverted when snapshots are disabled.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Balance JetBrains shell command tooltip padding when a horizontal scrollbar is present.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Increase JetBrains todo checklist inner padding.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Polish JetBrains session message toolbar alignment, rollback icon, and copy tooltips.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Use the standard transcript font for JetBrains prompt text and custom question responses.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Increase spacing before non-initial user prompts in the JetBrains session transcript.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-web-ui": patch
|
||||
---
|
||||
|
||||
Use the same font stack as Kilo Cloud (Inter variable for sans, Roboto Mono variable for mono, JetBrains Mono variable as the alt-mono token) in Kilo Console. Fonts are now self-hosted as woff2 in `@kilocode/kilo-web-ui`, so Inter no longer relies on the OS having it installed.
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
"@kilocode/cli": minor
|
||||
"@kilocode/sdk": minor
|
||||
"@kilocode/kilo-memory": minor
|
||||
---
|
||||
|
||||
Add opt-in project memory commands, tools, automatic capture, and public API support.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"kilo-code": minor
|
||||
---
|
||||
|
||||
Integrate project memory into the VS Code extension: memory status and controls in the Context settings tab, task-header and assistant-message affordances, the `/memory` prompt command, and Show/Toggle Project Memory command-palette entries.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Load expanded diff previews consistently when opening a review.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Allow Shift+Arrow selections in the prompt input to shrink back across file mentions.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Show effective permission defaults and clarify external-directory approvals in VS Code.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"@kilocode/cli": minor
|
||||
"kilo-code": minor
|
||||
---
|
||||
|
||||
Add a reload action that reboots the per-directory instance, picking up config, skills, agents, commands, and MCP prompts changed on disk. Sessions and history are preserved. Surfaces: `/reload` in the CLI palette and editor chat, a reload button in the task header and settings panel, the `Kilo Code: Reload Config and Skills` command, and a `POST /instance/reload` HTTP endpoint. The endpoint returns 409 while a session is actively running.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/cli": minor
|
||||
---
|
||||
|
||||
Support provider-aware model discovery and selection for remote Cloud sessions.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Show the Remote badge in the TUI prompt status area when remote session relay is enabled.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Stop explicitly directing GPT and Codex models to delegate tasks to subagents.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Fix the model usage panel showing just "free" for auto-routed sessions. The routed model id (e.g. `tencent/hy3:free`) is now displayed correctly instead of being collapsed to its `:free` suffix.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Show sandbox controls only after sandboxing is enabled in settings.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Widen the Additional Writable Paths input in the Sandboxing settings so longer filesystem paths are easier to read while typing.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Shut down the headless `kilo serve` process automatically when the editor client that launched it exits without a clean signal, preventing orphaned CLI processes.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Show live session spend in the TUI sidebar while an assistant turn is still running.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/cli": minor
|
||||
---
|
||||
|
||||
Add vim modal editing to the CLI prompt input. Enable it with `"vim": true` in `tui.jsonc`, the `Toggle vim mode` command in the command palette, or the `/vim` slash command. Supports NORMAL-mode motions (h/j/k/l, w/b/e, 0/^/$, gg/G, counts), edits (x, dd, dw, cw, D, C, r, yy/p, u, Ctrl+r), insert transitions (i/a/A/I/o/O), and VISUAL / VISUAL-LINE mode (v/V with selection-extending motions, d/x/c/s/y, o to swap ends), with a mode indicator and matching cursor shape.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Preserve the selected mode when sending the first message in a new VS Code task so the chosen model is paired with the correct agent instructions.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Wait for microphone capture to start before showing voice input as recording.
|
||||
@@ -33,7 +33,10 @@ runs:
|
||||
shell: bash
|
||||
run: echo "dir=$(bun pm cache)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Restoring and extracting the ~1 GB cache took 2m23s on Windows, while a # kilocode_change
|
||||
# fresh install took 1m27s. Keep Windows off this cache until that reverses. # kilocode_change
|
||||
- name: Restore Bun dependencies
|
||||
if: runner.os != 'Windows' # kilocode_change
|
||||
id: bun-cache
|
||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
@@ -84,16 +87,24 @@ runs:
|
||||
|
||||
# Workaround for patched peer variants
|
||||
# e.g. ./patches/ for standard-openapi
|
||||
# https://github.com/oven-sh/bun/issues/28147
|
||||
# https://github.com/oven-sh/bun/issues/28147 # kilocode_change
|
||||
if [ "$RUNNER_OS" = "Windows" ]; then
|
||||
bun install --linker hoisted ${{ inputs.install-flags }}
|
||||
# kilocode_change start
|
||||
if ! bun install --frozen-lockfile --linker hoisted ${{ inputs.install-flags }}; then
|
||||
echo "::warning::Bun install failed on Windows; retrying with conservative extraction"
|
||||
sleep 5
|
||||
BUN_FEATURE_FLAG_DISABLE_STREAMING_INSTALL=1 \
|
||||
bun install --frozen-lockfile --linker hoisted --network-concurrency 16 ${{ inputs.install-flags }}
|
||||
fi
|
||||
# kilocode_change end
|
||||
else
|
||||
bun install ${{ inputs.install-flags }}
|
||||
bun install --frozen-lockfile ${{ inputs.install-flags }} # kilocode_change
|
||||
fi
|
||||
shell: bash
|
||||
|
||||
# Do not upload a Windows cache that Windows jobs intentionally never restore. # kilocode_change
|
||||
- name: Save Bun dependencies
|
||||
if: steps.bun-cache.outputs.cache-hit != 'true' && github.event_name != 'pull_request' && github.event_name != 'pull_request_target'
|
||||
if: runner.os != 'Windows' && steps.bun-cache.outputs.cache-hit != 'true' && github.event_name != 'pull_request' && github.event_name != 'pull_request_target' # kilocode_change
|
||||
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: ${{ steps.cache.outputs.dir }}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# kilocode_change - new file
|
||||
name: "Setup Linux Sandbox"
|
||||
description: "Build the Linux bubblewrap helper"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Setup Zig
|
||||
run: |
|
||||
curl --fail --location --retry 3 \
|
||||
https://ziglang.org/download/0.14.0/zig-linux-x86_64-0.14.0.tar.xz \
|
||||
--output "$RUNNER_TEMP/zig.tar.xz"
|
||||
echo "473ec26806133cf4d1918caf1a410f8403a13d979726a9045b421b685031a982 $RUNNER_TEMP/zig.tar.xz" | sha256sum --check --status
|
||||
tar -xJf "$RUNNER_TEMP/zig.tar.xz" -C "$RUNNER_TEMP"
|
||||
echo "$RUNNER_TEMP/zig-linux-x86_64-0.14.0" >> "$GITHUB_PATH"
|
||||
shell: bash
|
||||
|
||||
- name: Build bubblewrap helper
|
||||
run: |
|
||||
bun packages/opencode/script/kilocode/bubblewrap.ts --arch x64 --output "$RUNNER_TEMP/bwrap"
|
||||
echo "KILO_BWRAP_PATH=$RUNNER_TEMP/bwrap" >> "$GITHUB_ENV"
|
||||
shell: bash
|
||||
@@ -39,6 +39,12 @@ jobs:
|
||||
distribution: temurin
|
||||
java-version: "21"
|
||||
|
||||
- name: Free disk space for CodeQL
|
||||
shell: bash
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android /usr/local/share/boost
|
||||
docker system prune --all --force || true
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
|
||||
@@ -35,7 +35,9 @@ concurrency: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.version || inpu
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
issues: write # kilocode_change - label automated JetBrains CLI pin bump PRs
|
||||
packages: write
|
||||
pull-requests: write # kilocode_change - create automated JetBrains CLI pin bump PRs
|
||||
|
||||
jobs:
|
||||
version:
|
||||
|
||||
+82
-33
@@ -30,6 +30,7 @@ jobs:
|
||||
pull-requests: read
|
||||
outputs:
|
||||
settings: ${{ steps.matrix.outputs.settings }}
|
||||
general: ${{ steps.matrix.outputs.general }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
@@ -57,14 +58,16 @@ jobs:
|
||||
env:
|
||||
GENERAL: ${{ github.event_name != 'pull_request' || steps.filter.outputs.general == 'true' }}
|
||||
run: |
|
||||
if [ "$GENERAL" = "true" ]; then
|
||||
echo 'settings=[{"name":"linux","host":"blacksmith-4vcpu-ubuntu-2404","run":true},{"name":"macos","host":"macos-15","run":true},{"name":"windows","host":"blacksmith-4vcpu-windows-2025","run":true}]' >> "$GITHUB_OUTPUT"
|
||||
if [ "$GENERAL" != "true" ]; then
|
||||
echo 'general=false' >> "$GITHUB_OUTPUT"
|
||||
echo 'settings=[{"os":"linux","index":1,"total":1,"host":"blacksmith-4vcpu-ubuntu-2404","run":false,"packages":false}]' >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
echo 'settings=[{"name":"linux","host":"blacksmith-4vcpu-ubuntu-2404","run":false}]' >> "$GITHUB_OUTPUT"
|
||||
echo 'general=true' >> "$GITHUB_OUTPUT"
|
||||
echo 'settings=[{"os":"linux","index":1,"total":2,"host":"blacksmith-4vcpu-ubuntu-2404","run":true,"packages":true},{"os":"linux","index":2,"total":2,"host":"blacksmith-4vcpu-ubuntu-2404","run":true,"packages":false},{"os":"macos","index":1,"total":1,"host":"macos-15","run":true,"packages":true},{"os":"windows","index":1,"total":4,"host":"blacksmith-4vcpu-windows-2025","run":true,"packages":true},{"os":"windows","index":2,"total":4,"host":"blacksmith-4vcpu-windows-2025","run":true,"packages":false},{"os":"windows","index":3,"total":4,"host":"blacksmith-4vcpu-windows-2025","run":true,"packages":false},{"os":"windows","index":4,"total":4,"host":"blacksmith-4vcpu-windows-2025","run":true,"packages":false}]' >> "$GITHUB_OUTPUT"
|
||||
|
||||
unit:
|
||||
name: unit (${{ matrix.settings.name }})
|
||||
name: ${{ !matrix.settings.run && 'unit (unchanged)' || matrix.settings.total > 1 && format('unit ({0}, {1}/{2})', matrix.settings.os, matrix.settings.index, matrix.settings.total) || format('unit ({0})', matrix.settings.os) }}
|
||||
needs: changes
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -107,21 +110,9 @@ jobs:
|
||||
uses: ./.github/actions/setup-bun
|
||||
|
||||
# kilocode_change start
|
||||
- name: Setup Zig for Linux sandbox helper
|
||||
- name: Setup Linux sandbox helper
|
||||
if: matrix.settings.run && runner.os == 'Linux'
|
||||
run: |
|
||||
curl --fail --location --retry 3 \
|
||||
https://ziglang.org/download/0.14.0/zig-linux-x86_64-0.14.0.tar.xz \
|
||||
--output "$RUNNER_TEMP/zig.tar.xz"
|
||||
echo "473ec26806133cf4d1918caf1a410f8403a13d979726a9045b421b685031a982 $RUNNER_TEMP/zig.tar.xz" | sha256sum --check --status
|
||||
tar -xJf "$RUNNER_TEMP/zig.tar.xz" -C "$RUNNER_TEMP"
|
||||
echo "$RUNNER_TEMP/zig-linux-x86_64-0.14.0" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Build Linux sandbox helper
|
||||
if: matrix.settings.run && runner.os == 'Linux'
|
||||
run: |
|
||||
bun packages/opencode/script/kilocode/bubblewrap.ts --arch x64 --output "$RUNNER_TEMP/bwrap"
|
||||
echo "KILO_BWRAP_PATH=$RUNNER_TEMP/bwrap" >> "$GITHUB_ENV"
|
||||
uses: ./.github/actions/setup-linux-sandbox
|
||||
# kilocode_change end
|
||||
- name: Configure git identity
|
||||
if: matrix.settings.run
|
||||
@@ -133,32 +124,31 @@ jobs:
|
||||
if: matrix.settings.run
|
||||
uses: actions/cache@v5 # kilocode_change
|
||||
with:
|
||||
path: node_modules/.cache/turbo
|
||||
key: turbo-${{ runner.os }}-${{ hashFiles('turbo.json', '**/package.json') }}-${{ github.sha }}
|
||||
path: .turbo/cache # kilocode_change
|
||||
key: turbo-${{ runner.os }}-${{ hashFiles('turbo.json', 'bun.lock') }}-${{ matrix.settings.os }}-${{ matrix.settings.index }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
turbo-${{ runner.os }}-${{ hashFiles('turbo.json', '**/package.json') }}-
|
||||
turbo-${{ runner.os }}-${{ hashFiles('turbo.json', 'bun.lock') }}-${{ matrix.settings.os }}-${{ matrix.settings.index }}-
|
||||
turbo-${{ runner.os }}-${{ hashFiles('turbo.json', 'bun.lock') }}-
|
||||
turbo-${{ runner.os }}-
|
||||
|
||||
- name: Run unit tests
|
||||
- name: Run non-CLI unit tests
|
||||
if: matrix.settings.run && matrix.settings.packages
|
||||
run: bun turbo test:ci --filter='!@kilocode/cli' --filter='!@kilocode/kilo-jetbrains'
|
||||
|
||||
- name: Run CLI unit tests
|
||||
if: matrix.settings.run
|
||||
run: bun turbo test:ci --filter='!@kilocode/kilo-jetbrains'
|
||||
run: bun turbo test:ci --filter='@kilocode/cli'
|
||||
env:
|
||||
KILO_EXPERIMENTAL_DISABLE_FILEWATCHER: ${{ runner.os == 'Windows' && 'true' || 'false' }}
|
||||
KILO_TEST_PROFILE: ${{ runner.os == 'macOS' && github.event_name == 'pull_request' && 'darwin' || '' }} # kilocode_change
|
||||
|
||||
# kilocode_change start
|
||||
- name: Run HttpApi exerciser gates
|
||||
if: matrix.settings.run && runner.os == 'Linux'
|
||||
working-directory: packages/opencode
|
||||
run: bun run test:httpapi
|
||||
# kilocode_change end
|
||||
KILO_TEST_PROFILE: ${{ matrix.settings.os == 'macos' && 'darwin' || '' }}
|
||||
KILO_TEST_SHARD: ${{ format('{0}/{1}', matrix.settings.index, matrix.settings.total) }}
|
||||
|
||||
- name: Publish unit reports # kilocode_change
|
||||
if: always() && matrix.settings.run
|
||||
uses: mikepenz/action-junit-report@bccf2e31636835cf0874589931c4116687171386 # v6.4.0
|
||||
with:
|
||||
report_paths: packages/*/.artifacts/unit/junit.xml
|
||||
check_name: "unit results (${{ matrix.settings.name }})"
|
||||
annotate_only: true
|
||||
detailed_summary: true
|
||||
include_time_in_summary: true
|
||||
fail_on_failure: false
|
||||
@@ -167,13 +157,52 @@ jobs:
|
||||
if: always() && matrix.settings.run
|
||||
uses: actions/upload-artifact@v7 # kilocode_change
|
||||
with:
|
||||
name: unit-${{ matrix.settings.name }}-${{ github.run_attempt }}
|
||||
name: unit-${{ matrix.settings.os }}-${{ matrix.settings.index }}-${{ github.run_attempt }}
|
||||
include-hidden-files: true
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
path: packages/*/.artifacts/unit/junit.xml
|
||||
# kilocode_change end
|
||||
|
||||
# kilocode_change start
|
||||
httpapi:
|
||||
name: HttpApi exerciser
|
||||
needs: changes
|
||||
if: needs.changes.outputs.general == 'true'
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
timeout-minutes: 15
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
|
||||
- name: Setup Linux sandbox helper
|
||||
uses: ./.github/actions/setup-linux-sandbox
|
||||
|
||||
- name: Configure git identity
|
||||
run: |
|
||||
git config --global user.email "kilo-maintainer[bot]@users.noreply.github.com"
|
||||
git config --global user.name "kilo-maintainer[bot]"
|
||||
|
||||
- name: Cache Turbo
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .turbo/cache
|
||||
key: turbo-${{ runner.os }}-${{ hashFiles('turbo.json', 'bun.lock') }}-httpapi-${{ github.sha }}
|
||||
restore-keys: |
|
||||
turbo-${{ runner.os }}-${{ hashFiles('turbo.json', 'bun.lock') }}-httpapi-
|
||||
turbo-${{ runner.os }}-${{ hashFiles('turbo.json', 'bun.lock') }}-
|
||||
turbo-${{ runner.os }}-
|
||||
|
||||
- name: Run HttpApi exerciser gates
|
||||
run: bun turbo test:httpapi --filter='@kilocode/cli'
|
||||
# kilocode_change end
|
||||
|
||||
# kilocode_change start
|
||||
jetbrains:
|
||||
name: jetbrains
|
||||
@@ -185,18 +214,38 @@ jobs:
|
||||
# kilocode_change end
|
||||
|
||||
# kilocode_change start
|
||||
unit-required:
|
||||
name: unit (linux)
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
needs:
|
||||
- unit
|
||||
if: always()
|
||||
steps:
|
||||
- name: Verify unit matrix passed
|
||||
run: |
|
||||
echo "unit=${{ needs.unit.result }}"
|
||||
test "${{ needs.unit.result }}" = "success"
|
||||
|
||||
required:
|
||||
name: test (linux)
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
needs:
|
||||
- changes
|
||||
- unit
|
||||
- httpapi
|
||||
- jetbrains
|
||||
if: always()
|
||||
steps:
|
||||
- name: Verify upstream test jobs passed
|
||||
run: |
|
||||
echo "unit=${{ needs.unit.result }}"
|
||||
echo "httpapi=${{ needs.httpapi.result }}"
|
||||
echo "jetbrains=${{ needs.jetbrains.result }}"
|
||||
test "${{ needs.unit.result }}" = "success"
|
||||
if [ "${{ needs.changes.outputs.general }}" = "true" ]; then
|
||||
test "${{ needs.httpapi.result }}" = "success"
|
||||
else
|
||||
test "${{ needs.httpapi.result }}" = "skipped"
|
||||
fi
|
||||
test "${{ needs.jetbrains.result }}" = "success"
|
||||
# kilocode_change end
|
||||
|
||||
@@ -5,6 +5,10 @@ on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
check-paths:
|
||||
name: Check changed paths
|
||||
@@ -42,9 +46,10 @@ jobs:
|
||||
- name: Check baseline auto-commit permissions
|
||||
id: autocommit-check
|
||||
env:
|
||||
BOT_PAT: ${{ secrets.BOT_PAT }}
|
||||
MAINTAINER_APP_ID: ${{ secrets.KILO_MAINTAINER_APP_ID }}
|
||||
MAINTAINER_APP_SECRET: ${{ secrets.KILO_MAINTAINER_APP_SECRET }}
|
||||
run: |
|
||||
if [ "${{ steps.fork-check.outputs.is_fork }}" != "true" ] && [ -n "$BOT_PAT" ]; then
|
||||
if [ "${{ steps.fork-check.outputs.is_fork }}" != "true" ] && [ -n "$MAINTAINER_APP_ID" ] && [ -n "$MAINTAINER_APP_SECRET" ]; then
|
||||
echo "can_autocommit=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "can_autocommit=false" >> "$GITHUB_OUTPUT"
|
||||
@@ -63,8 +68,8 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
lfs: true
|
||||
# use BOT_PAT only when later baseline pushes are allowed; github.token is read-only on Dependabot PRs.
|
||||
token: ${{ secrets.BOT_PAT }}
|
||||
# Use github.token for LFS access. The maintainer app is used only for generated commits.
|
||||
token: ${{ github.token }}
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Checkout (read-only)
|
||||
@@ -171,25 +176,33 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Commit and push new baselines (if any)
|
||||
- name: Check for baseline updates
|
||||
if: needs.check-paths.outputs.can_autocommit == 'true' && steps.check-baseline-commit.outputs.is_baseline_update != 'true'
|
||||
id: commit-baselines
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.BOT_PAT }}
|
||||
id: baseline-changes
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add packages/kilo-docs/public/img/screenshot-tests/kilo-ui/
|
||||
if git diff --cached --quiet; then
|
||||
echo "No new baselines — nothing to commit."
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
git commit -m "chore: update visual regression baselines"
|
||||
git lfs push --all origin
|
||||
git push --no-verify
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Setup Git Committer
|
||||
if: steps.baseline-changes.outputs.changed == 'true'
|
||||
uses: ./.github/actions/setup-git-committer
|
||||
with:
|
||||
kilo-maintainer-app-id: ${{ secrets.KILO_MAINTAINER_APP_ID }}
|
||||
kilo-maintainer-app-secret: ${{ secrets.KILO_MAINTAINER_APP_SECRET }}
|
||||
|
||||
- name: Commit and push new baselines (if any)
|
||||
if: steps.baseline-changes.outputs.changed == 'true'
|
||||
id: commit-baselines
|
||||
run: |
|
||||
git commit -m "chore: update visual regression baselines"
|
||||
git lfs push --all origin
|
||||
git push --no-verify origin "HEAD:${GITHUB_HEAD_REF}"
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Fail if baselines changed
|
||||
if: needs.check-paths.outputs.can_autocommit == 'true' && steps.commit-baselines.outputs.changed == 'true'
|
||||
run: |
|
||||
@@ -219,8 +232,8 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
lfs: true
|
||||
# use BOT_PAT only when later baseline pushes are allowed; github.token is read-only on Dependabot PRs.
|
||||
token: ${{ secrets.BOT_PAT }}
|
||||
# Use github.token for LFS access. The maintainer app is used only for generated commits.
|
||||
token: ${{ github.token }}
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Checkout (read-only)
|
||||
@@ -357,25 +370,33 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Commit and push new baselines (if any)
|
||||
- name: Check for baseline updates
|
||||
if: needs.check-paths.outputs.can_autocommit == 'true' && steps.check-baseline-commit-vscode.outputs.is_baseline_update != 'true'
|
||||
id: commit-baselines-vscode
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.BOT_PAT }}
|
||||
id: baseline-changes-vscode
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/
|
||||
if git diff --cached --quiet; then
|
||||
echo "No new baselines — nothing to commit."
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
git commit -m "chore: update kilo-vscode visual regression baselines"
|
||||
git lfs push --all origin
|
||||
git push --no-verify
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Setup Git Committer
|
||||
if: steps.baseline-changes-vscode.outputs.changed == 'true'
|
||||
uses: ./.github/actions/setup-git-committer
|
||||
with:
|
||||
kilo-maintainer-app-id: ${{ secrets.KILO_MAINTAINER_APP_ID }}
|
||||
kilo-maintainer-app-secret: ${{ secrets.KILO_MAINTAINER_APP_SECRET }}
|
||||
|
||||
- name: Commit and push new baselines (if any)
|
||||
if: steps.baseline-changes-vscode.outputs.changed == 'true'
|
||||
id: commit-baselines-vscode
|
||||
run: |
|
||||
git commit -m "chore: update kilo-vscode visual regression baselines"
|
||||
git lfs push --all origin
|
||||
git push --no-verify origin "HEAD:${GITHUB_HEAD_REF}"
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Fail if baselines changed
|
||||
if: needs.check-paths.outputs.can_autocommit == 'true' && steps.commit-baselines-vscode.outputs.changed == 'true'
|
||||
run: |
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
# Prompt Rollback + Redo — JetBrains Parity
|
||||
|
||||
Bring the VS Code "rollback / redo" (CLI `revert` / `unrevert`) feature to the JetBrains plugin, and fix the misleading VS Code hint string. Implementation-capable agent required — this plan touches source and tests.
|
||||
|
||||
## Context (verified)
|
||||
|
||||
- CLI already exposes everything needed; no CLI release or SDK regen required. Pinned CLI version is `7.4.1` (`packages/kilo-jetbrains/package.json`).
|
||||
- `POST /session/{id}/revert` body `{ messageID, partID? }`, `POST /session/{id}/unrevert`.
|
||||
- `Session.revert?: { messageID, partID?, snapshot?, diff? }` — `packages/sdk/js/src/gen/types.gen.ts:554`. Pushed via `session.updated` SSE.
|
||||
- VS Code entry points: `RevertBanner.tsx`, `VscodeSessionTurn.tsx`, `session.tsx` context. Per-user-message rollback restores reverted prompt text into the input; redo banner shows count + per-file diff stats + Redo / Redo All + hint; reverted messages/parts hidden (`id >= revert.messageID`, partID partial-turn boundary).
|
||||
- JetBrains split-mode packages differ from AGENTS.md's stated `ai.kilocode.jetbrains`; actual source roots are:
|
||||
- shared → `packages/kilo-jetbrains/shared/src/main/kotlin/ai/kilocode/rpc/`
|
||||
- backend → `packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/`
|
||||
- frontend → `packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/`
|
||||
- All target files confirmed to exist: `SessionDto.kt`, `KiloSessionRpcApi.kt`, `KiloBackendChatManager.kt`, `KiloSessionRpcApiImpl.kt`, `KiloSessionService.kt`, `SessionController.kt`, `SessionModel.kt`, `SessionModelEvent.kt`, `SessionView.kt`, `MessageView.kt`, `MessageToolbar.kt`, `PromptPanel.kt`, `PromptEditorTextField.kt`, plus reuse targets `DiffStatBadge.kt`, `HoverIcon.kt`, `PermissionDiffView.kt`.
|
||||
|
||||
## Decisions
|
||||
|
||||
- **Reuse `DiffStatBadge`** (already the shared per-file +/- renderer used by `PermissionDiffView`) for the banner's per-file diff rows. No new diff-stat component.
|
||||
- **Reuse the existing user-prompt hover toolbar (`MessageToolbar`)** for the per-message rollback control.
|
||||
- **Reuse the existing `session.updated → model.setSession(...)` pipeline** for the revert boundary; no new SSE handling.
|
||||
- **Stale non-English hint strings: reset all to the new English value** and flag for re-translation (applies to VS Code locales; JetBrains base bundle only, others fall back).
|
||||
|
||||
## Part A — VS Code string fix
|
||||
|
||||
File: `packages/kilo-vscode/webview-ui/src/i18n/en.ts:138`
|
||||
|
||||
- Change `revert.banner.hint` from `"Send a new message to make this permanent"` to `"You can redo these changes until you send a new message"`.
|
||||
- In the 19 non-English locale files under `packages/kilo-vscode/webview-ui/src/i18n/` (ar, br, bs, da, de, es, fr, it, ja, ko, nl, no, pl, ru, th, tr, uk, zh, zht), overwrite `revert.banner.hint` with the identical new English string; leave a note that these need re-translation.
|
||||
- Do not touch the other revert keys (`revert.banner.count_one`, `revert.banner.count_other`, `revert.banner.redo`, `revert.banner.redo.all`, `revert.disabled.agentBusy`) — only the hint changes meaning.
|
||||
|
||||
## Part B — JetBrains implementation
|
||||
|
||||
### 1. Shared (DTO + RPC contract)
|
||||
|
||||
- `shared/.../rpc/dto/SessionDto.kt`: add `val revert: SessionRevertDto? = null`; add `@Serializable data class SessionRevertDto(val messageID: String, val partID: String? = null, val snapshot: String? = null, val diff: String? = null)`. Field names must match CLI JSON for kotlinx auto-mapping through `session.updated`.
|
||||
- `shared/.../rpc/KiloSessionRpcApi.kt`: add
|
||||
- `suspend fun revert(id: String, directory: String, messageID: String, partID: String?)`
|
||||
- `suspend fun unrevert(id: String, directory: String)`
|
||||
|
||||
### 2. Backend (RPC impl + HTTP)
|
||||
|
||||
- `backend/.../app/KiloBackendChatManager.kt`: add `revert(id, dir, messageID, partID?)` → `POST /session/$id/revert?directory=…` with `{messageID, partID?}` body, and `unrevert(id, dir)` → `POST /session/$id/unrevert?directory=…`. Mirror the existing `compact()` OkHttp pattern; add JSON body builders to `KiloCliDataParser`.
|
||||
- `backend/.../rpc/KiloSessionRpcApiImpl.kt`: implement both, resolve worktree dir via `sessions.getDirectory(id, directory)`, wrap in `ready { }` like `compact`/`abort`.
|
||||
|
||||
### 3. Frontend service
|
||||
|
||||
- `frontend/.../app/KiloSessionService.kt`: add `suspend revert(...)` / `unrevert(...)` wrappers over the RPC, using `durable {}` per split-mode rules.
|
||||
|
||||
### 4. Frontend controller (`session/controller/SessionController.kt`)
|
||||
|
||||
- Add EDT-entry actions dispatched to the coroutine scope:
|
||||
- `revert(messageID, partID?)`
|
||||
- `unrevert()`
|
||||
- `redo()` — mirror `RevertBanner.handleRedo`: find the next user message after the boundary and revert to it; `unrevert()` if none.
|
||||
- `redoAll()` → `unrevert()`.
|
||||
- Revert boundary already arrives via `is ChatEventDto.SessionUpdated -> model.setSession(...)` — no new SSE handling.
|
||||
- On revert, restore the reverted user prompt text into the input (`session/ui/prompt/PromptPanel.kt` / `PromptEditorTextField`); on full redo (`redoAll` / final `unrevert`), clear it — matching VS Code and TUI.
|
||||
|
||||
### 5. Frontend model (`session/model/SessionModel.kt`, `SessionModelEvent.kt`)
|
||||
|
||||
- Add `SessionModelEvent.RevertChanged(revert: SessionRevertDto?)` with a stable `toString()`, fired from `setSession()` when the revert value changes. Reset in `loadHistory()` and `clear()`.
|
||||
- Add derived helpers: `revert(): SessionRevertDto?` and `revertedCount()` (count of user messages with `id >= boundary`, mirroring `session.tsx`).
|
||||
- Transcript hiding: expose whether a message id is hidden by the boundary (`id >= revert.messageID`, with partID partial-turn handling), applied both to newly-arriving messages and on `RevertChanged`.
|
||||
- Follow the AGENTS.md "Adding a New Event" checklist (event subclass → model field + mutation + resets → controller handling → `-> Unit` stubs in exhaustive `when` blocks).
|
||||
|
||||
### 6. Frontend views
|
||||
|
||||
- New `session/ui/RevertBanner.kt` Swing view, built once and mutated via `update()` per retained-Swing rules. Listens to `RevertChanged` + `DiffUpdated`. Contents:
|
||||
- arrow-left icon + count label (localized count.one/other),
|
||||
- per-file diff rows reusing `ai.kilocode.client.ui.DiffStatBadge` fed from `model.diff` (`DiffFileDto.additions/deletions`),
|
||||
- Redo button → `controller.redo()`, Redo All (only when count > 1) → `controller.redoAll()`,
|
||||
- hint label (same new wording as Part A).
|
||||
- Placed in `session/ui/SessionView.kt` at the bottom of the transcript, above the prompt input; shown only when `revert != null`.
|
||||
- Per-user-message rollback control in `session/views/MessageView.kt`: user prompt bubbles already carry a hover `promptToolbar` (`MessageToolbar` with copy) + `promptHover` state. Add a rollback `HoverIcon` (arrow-left) alongside copy for user messages, wired through `SessionView → controller.revert(msgId)`. Disable/hide while the agent is busy or when there are no assistant messages after it, with the `revert.disabled.agentBusy` tooltip — mirroring `VscodeSessionTurn` `onRevert` + `data-revert-disabled`. Extend `MessageToolbar.kt` to host the extra action (or add a sibling control).
|
||||
- Apply transcript hiding: `SessionView`/`TurnView` toggle `MessageView` visibility on `RevertChanged` (prefer visibility toggle over rebuild, per Swing lifecycle guidance).
|
||||
|
||||
### 7. i18n (`frontend/src/main/resources/messages/KiloBundle*.properties`)
|
||||
|
||||
- Add to base `KiloBundle.properties`: `revert.banner.count.one`, `revert.banner.count.other`, `revert.banner.redo`, `revert.banner.redo.all`, `revert.banner.hint` (new wording), `revert.disabled.agentBusy`.
|
||||
- Other locale bundles fall back to base until translated; do not add stale translations.
|
||||
|
||||
### 8. Tests
|
||||
|
||||
- Backend: extend `KiloSessionRpcApiImplTest` / a `KiloBackendChatManager` test against `MockCliServer` asserting the exact HTTP path + JSON body for `revert`/`unrevert`, and that a session carrying `revert` deserializes into `SessionRevertDto`.
|
||||
- Frontend controller (`SessionControllerTestBase` + `FakeSessionRpcApi`, add revert/unrevert call tracking): `revert()`/`unrevert()`/`redo()`/`redoAll()` hit the right RPC; `RevertChanged` fires; count logic; reverted messages hidden and restored; prompt-text restore on revert / clear on full redo.
|
||||
- Frontend views (`BasePlatformTestCase`): `RevertBanner` renders count + per-file `DiffStatBadge` + redo buttons (Redo All only when count > 1); `MessageView` shows the rollback control on user messages and disables it while busy; retained-component assertions (`assertSame`, bounded count) per Swing lifecycle rules.
|
||||
|
||||
## Deliverables
|
||||
|
||||
| Area | Files |
|
||||
|---|---|
|
||||
| VS Code string | `webview-ui/src/i18n/en.ts` + 19 non-English locale hints reset |
|
||||
| Shared | `SessionDto.kt` (+`SessionRevertDto`), `KiloSessionRpcApi.kt` |
|
||||
| Backend | `KiloBackendChatManager.kt`, `KiloCliDataParser`, `KiloSessionRpcApiImpl.kt` |
|
||||
| Frontend service/controller/model | `KiloSessionService.kt`, `SessionController.kt`, `SessionModel.kt`, `SessionModelEvent.kt` |
|
||||
| Frontend views | new `RevertBanner.kt` (reusing `DiffStatBadge`), `MessageView.kt`, `MessageToolbar.kt`, `SessionView.kt`, `PromptPanel.kt` |
|
||||
| i18n | `KiloBundle.properties` |
|
||||
| Tests | backend RPC/chat-manager, frontend controller + view tests, `FakeSessionRpcApi` |
|
||||
|
||||
## Validation
|
||||
|
||||
- VS Code string change: `bun run typecheck` from repo root (or from `packages/kilo-vscode/`).
|
||||
- JetBrains: `./gradlew typecheck` and `./gradlew test` from `packages/kilo-jetbrains/` (Java 21).
|
||||
- Manual: `./gradlew runIde` (or split mode) to exercise rollback → redo → redo-all and reverted-transcript hiding.
|
||||
|
||||
## Risks / Notes
|
||||
|
||||
- Confirm no `kilocode_change` markers are needed for the VS Code i18n edits (Kilo-owned webview path — none required).
|
||||
- Reset (not delete) is chosen for VS Code locale hints, so the fallback path is not relied upon; flag the 19 files for re-translation.
|
||||
- Keep new Kotlin identifiers single-word per repo style; annotate EDT/model-touching methods with `@RequiresEdt`; wrap frontend RPC in `durable {}`.
|
||||
@@ -0,0 +1,199 @@
|
||||
# JetBrains Rollback Feature — Hardening Plan
|
||||
|
||||
Harden the new JetBrains rollback/redo feature: (1) communicate when only messages were
|
||||
reverted because snapshots are disabled, and (2–4) close the code-duplication, testing,
|
||||
end-to-end, and AGENTS-conformance gaps.
|
||||
|
||||
All work is inside `packages/kilo-jetbrains/`. No shared `packages/opencode/` files change,
|
||||
so no `kilocode_change` markers are needed.
|
||||
|
||||
## Context an implementer needs
|
||||
|
||||
- Revert flow: user clicks the per-message Rollback button (`MessageToolbar`/`MessageView`)
|
||||
→ `SessionController.revert()` aborts a busy turn then POSTs `/session/:id/revert`
|
||||
→ CLI sets a revert marker → `SessionUpdated` event → `SessionModel.setRevert()` →
|
||||
`RevertBanner` shows + reverted messages hidden. `redo()`/`redoAll()` drive
|
||||
`/session/:id/revert` (next user msg) and `/session/:id/unrevert`.
|
||||
- Snapshot signal: `SessionRevertDto.snapshot` (`shared/.../rpc/dto/SessionDto.kt:22`) is
|
||||
`null` exactly when the server did NOT restore files (snapshots disabled: `config.snapshot
|
||||
=== false`, non-git worktree, or ACP). It is already parsed and reaches the frontend via
|
||||
`SessionModel.revert()`. When `snapshot == null` the diff is also empty, so the banner shows
|
||||
no file rows today. This is the reliable, no-new-API signal for "history only".
|
||||
- Test harnesses already exist: frontend `SessionControllerTestBase` + `FakeSessionRpcApi`
|
||||
(already tracks `rpc.reverts` and `rpc.unreverts`); backend `MockCliServer` +
|
||||
`KiloBackendChatManagerTest`. Banner tests instantiate `RevertBanner(model, redo, redoAll)`
|
||||
and read components via `components(banner)`.
|
||||
|
||||
## Key files
|
||||
|
||||
- `frontend/.../session/ui/RevertBanner.kt`
|
||||
- `frontend/.../session/controller/SessionController.kt` (`revert`, `unrevert`, `redo`, `redoAll`, `capture`, `sessionProps`)
|
||||
- `frontend/.../session/model/SessionModel.kt` (`revert()`, `revertedCount()`, `isRevertedMessage()`)
|
||||
- `frontend/src/main/resources/messages/KiloBundle.properties` (+ translated `KiloBundle_*.properties`)
|
||||
- `backend/.../app/KiloBackendChatManager.kt` (`revert`/`unrevert`), `backend/.../cli/KiloCliDataParser.kt` (`buildRevertJson`)
|
||||
- `backend/.../app/KiloBackendSessionManager.kt` (`revertDto` duplication)
|
||||
- Tests: `frontend/.../session/controller/TurnLifecycleTest.kt` (or new `RevertFlowTest.kt`),
|
||||
`frontend/.../session/ui/SessionMessageListPanelTest.kt`,
|
||||
`frontend/.../session/model/SessionModelTest.kt`,
|
||||
`backend/.../testing/MockCliServer.kt`, `backend/.../app/KiloBackendChatManagerTest.kt`,
|
||||
`backend/.../cli/KiloCliDataParserTest.kt`
|
||||
|
||||
## Resolved decisions
|
||||
|
||||
- **Do NOT hide/disable the Rollback button when snapshots are off.** This matches VS Code and
|
||||
keeps history-only revert usable. We only add messaging.
|
||||
- **Detect "files not restored" via `model.revert()?.snapshot == null`.** No new config/API,
|
||||
no shared-code change.
|
||||
- **Message it in the `RevertBanner`** with a distinct localized line, shown only when
|
||||
`snapshot == null`.
|
||||
- Proactively warning on the button before a revert (needs `config.snapshot`/`vcs` exposed to
|
||||
the frontend) is **out of scope**.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Communicate history-only revert (snapshots disabled)
|
||||
|
||||
1. Add bundle key in `KiloBundle.properties` (place near the other `revert.banner.*` keys):
|
||||
- `revert.banner.filesNotRestored=Snapshots are off — only the conversation was reverted; your files were not changed.`
|
||||
- Add the same key to every translated `KiloBundle_*.properties` file. If translations are
|
||||
not available, copy the English value (mirror how the other `revert.banner.*` keys were
|
||||
seeded across bundles) so no key is missing.
|
||||
2. In `RevertBanner.kt`:
|
||||
- Add a retained `JBLabel` field `notice` styled like `hint` (`JBFont.small()`), created
|
||||
once in `init` and added to `body` after `hint`.
|
||||
- In `update()`, after computing `revert`, set
|
||||
`notice.isVisible = revert.snapshot == null` and its text to
|
||||
`KiloBundle.message("revert.banner.filesNotRestored")`.
|
||||
- Color it via a theme API in `applyStyle` (use `UIUtil.getContextHelpForeground()` to match
|
||||
the secondary `hint`; do not hardcode a color). Re-evaluate in `applyStyle` alongside
|
||||
`hint.foreground`.
|
||||
- Keep the existing empty-diff behavior (no file rows) — the notice replaces the missing
|
||||
information rather than adding chrome.
|
||||
3. Remove the redundant `isOpaque = false` on the `body` and `files` `Stack`s (see Phase 4);
|
||||
do this while editing the file.
|
||||
|
||||
## Phase 2 — Close code-duplication gaps
|
||||
|
||||
4. In `KiloBackendSessionManager.kt`, collapse the two identical `revertDto(...)` overloads
|
||||
(`SessionRevert` and `GlobalSessionRevert`) into a single private helper that maps the four
|
||||
fields (`messageID`, `partID`, `snapshot`, `diff`) from a small shared shape. Simplest
|
||||
approach: one private `fun revertDto(messageID: String?, partID: String?, snapshot: String?,
|
||||
diff: String?)` returning `SessionRevertDto?` (null when `messageID` is null), and have both
|
||||
call sites extract fields from their respective model type. Keep behavior identical; this is
|
||||
a pure refactor covered by existing `KiloBackendSessionManagerTest` parsing assertions.
|
||||
|
||||
## Phase 3 — Fill testing + end-to-end gaps
|
||||
|
||||
### Frontend controller/model logic
|
||||
|
||||
5. `SessionModelTest.kt` — add direct model tests:
|
||||
- `revertedCount()` returns the number of user messages from the marker to the end
|
||||
(build entries `u1,a1,u2,a2`; marker at `u1` → 2; marker at `u2` → 1; marker id absent → 0).
|
||||
- `isRevertedMessage()` true for the marker message and everything after, false before.
|
||||
- `snapshot`-null marker still yields a non-zero `revertedCount()` (history-only case).
|
||||
6. `TurnLifecycleTest.kt` (or new `RevertFlowTest.kt`) — add controller tests using `prompted()`:
|
||||
- `redo()` reverts to the NEXT user message: seed `u1,a1,u2,a2`, apply marker at `u1`,
|
||||
`edt { m.redo() }`, flush → assert `rpc.reverts` last call targets `u2`.
|
||||
- `redo()` at the last user message calls unrevert: marker at `u2` → `redo()` → assert
|
||||
`rpc.unreverts` recorded and no new revert call.
|
||||
- `redoAll()` calls unrevert: assert `rpc.unreverts` contains `("ses_test","/test")`.
|
||||
- `unrevert()` clears via RPC: assert `rpc.unreverts` populated.
|
||||
|
||||
### Frontend banner → controller wiring (end-to-end within the UI layer)
|
||||
|
||||
7. `SessionMessageListPanelTest.kt` — add wiring + history-only tests:
|
||||
- Redo button click invokes the controller: build `RevertBanner(model, redo = { redo++ },
|
||||
redoAll = { all++ })`, set a marker, `banner...first { text == redo }.doClick()` → assert
|
||||
the redo lambda fired; same for Redo All when `revertedCount > 1`.
|
||||
- History-only notice: marker with `SessionRevertDto("u1", snapshot = null)` → assert the
|
||||
`revert.banner.filesNotRestored` label is visible and no file rows are present.
|
||||
- Snapshot-present: marker with `snapshot = "snap1"` → assert the notice label is hidden.
|
||||
|
||||
### Full round-trip end-to-end (frontend)
|
||||
|
||||
8. Add one `RevertFlowTest` case that exercises the whole loop through `SessionControllerTestBase`:
|
||||
- Seed a multi-turn session, `edt { m.revert(userMsgId) }`, flush → assert busy-abort
|
||||
ordering + `rpc.reverts`.
|
||||
- `emit(SessionUpdated(..., revert = SessionRevertDto(userMsgId, snapshot = "s1")))` →
|
||||
assert `model.isRevertedMessage(userMsgId)` and reverted views hidden.
|
||||
- Drive Redo All via `m.redoAll()`; `emit(SessionUpdated(..., revert = null))` → assert
|
||||
messages restored (`isRevertedMessage` false) and marker cleared.
|
||||
Use existing `emit`/`flush` helpers; no timeouts.
|
||||
|
||||
### Backend HTTP contract
|
||||
|
||||
9. `MockCliServer.kt` — add routing + capture fields (the current generic `/session/ses_*`
|
||||
regexes are full-match and won't catch the `/revert` suffix, so new cases are safe):
|
||||
- Fields: `lastRevertPath`, `lastRevertBody`, `lastUnrevertPath`, `lastUnrevertBody`
|
||||
(`@Volatile var ... : String? = null`).
|
||||
- Cases (place beside the `summarize`/`prompt_async` cases):
|
||||
- `bare.matches(Regex("/session/ses_[^/]+/revert")) && method == "POST"` → store path+body,
|
||||
`respond(output, 200, sessionCreate)`.
|
||||
- `bare.matches(Regex("/session/ses_[^/]+/unrevert")) && method == "POST"` → store path+body,
|
||||
`respond(output, 200, sessionCreate)`.
|
||||
10. `KiloBackendChatManagerTest.kt` — mirror the existing `compact posts summarize request` test:
|
||||
- `revert posts messageID and partID to revert endpoint`: call
|
||||
`chat.revert("ses_abc", "/test/project", "msg1", "prt1")`; assert
|
||||
`requestCount("/session/ses_abc/revert") == 1`, path starts with
|
||||
`/session/ses_abc/revert?directory=`, body == `{"messageID":"msg1","partID":"prt1"}`.
|
||||
- `revert omits partID when null`: body == `{"messageID":"msg1"}`.
|
||||
- `unrevert posts empty body to unrevert endpoint`: body == `{}` and path prefix asserted.
|
||||
11. `KiloCliDataParserTest.kt` — add `buildRevertJson` unit tests:
|
||||
- `buildRevertJson("m1", null) == {"messageID":"m1"}`.
|
||||
- `buildRevertJson("m1", "p1") == {"messageID":"m1","partID":"p1"}`.
|
||||
- Escaping: an id containing a quote/backslash is JSON-escaped (reuse the parser's `escape`).
|
||||
|
||||
## Phase 4 — AGENTS conformance cleanup
|
||||
|
||||
12. Remove the unused bundle key `revert.disabled.agentBusy` from `KiloBundle.properties` and all
|
||||
translated bundles (grep confirms it is referenced nowhere in Kotlin). Alternatively, if the
|
||||
team wants VS Code parity, wire it as a disabled-state tooltip on the Rollback button — but
|
||||
the recommended, lower-risk action is removal, since JetBrains intentionally aborts the busy
|
||||
turn instead of disabling the button.
|
||||
13. Remove redundant `isOpaque = false` on the transparent `Stack`s in `RevertBanner.kt`
|
||||
(`body`, `files`) — `Stack` is already a no-color panel. Keep `isOpaque = false` on the
|
||||
`BorderLayoutPanel` root only if it visibly overlays the session surface; otherwise remove it
|
||||
too and rely on the default.
|
||||
14. Add usage metrics for the new user-facing actions in `SessionController.kt`, using the
|
||||
existing `capture(event, props)` + `sessionProps(id)` helpers:
|
||||
- In `revert()` (on the success path, after `sessions.revert`): `capture("Session Rollback",
|
||||
sessionProps(id))`.
|
||||
- In `redo()`/`redoAll()`/`unrevert()`: `capture("Session Redo", sessionProps(id))` /
|
||||
`capture("Session Redo All", ...)` as appropriate. Keep names consistent with existing
|
||||
event naming; do not add PII.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Exposing `config.snapshot`/`vcs` to the frontend to proactively warn before a revert.
|
||||
- Changing the retained-vs-rebuild strategy of `RevertBanner.files` (low-frequency update;
|
||||
acceptable as-is).
|
||||
- Replacing the full-project `ACTION_SYNCHRONIZE` in `synchronizeFromDisk` with a scoped VFS
|
||||
refresh (only revisit if it shows up as a perf problem).
|
||||
- Any VS Code webview parity changes beyond the shared i18n strings already present.
|
||||
|
||||
## Validation
|
||||
|
||||
Run from `packages/kilo-jetbrains/`:
|
||||
|
||||
- `./gradlew typecheck` — compiles all Kotlin including generated client.
|
||||
- `./gradlew test` — runs frontend + backend suites, including the new tests. Requires Java 21;
|
||||
only check Java if Gradle reports a Java error.
|
||||
- Targeted while iterating: run the touched test classes (`TurnLifecycleTest`/`RevertFlowTest`,
|
||||
`SessionMessageListPanelTest`, `SessionModelTest`, `KiloBackendChatManagerTest`,
|
||||
`KiloCliDataParserTest`).
|
||||
|
||||
Manual smoke (optional, `./gradlew runIde`): trigger a rollback in a non-git directory (or with
|
||||
`snapshot: false`) and confirm the banner shows the "files not changed" notice with no file rows;
|
||||
trigger one in a git repo and confirm the notice is hidden and file rows appear.
|
||||
|
||||
## Changeset
|
||||
|
||||
Add `.changeset/<slug>.md` (`"@kilocode/kilo-jetbrains": patch`) describing the user-facing
|
||||
change, e.g. "Clarify in JetBrains rollback that only the conversation was reverted when
|
||||
snapshots are disabled." Test-only and refactor tasks do not need their own changeset.
|
||||
|
||||
## Suggested order
|
||||
|
||||
Phase 3 backend tests (9–11) and model tests (5) are independent and can be done first to lock
|
||||
behavior. Then Phase 1 (user-facing messaging) with its banner tests (7). Then Phase 2 refactor,
|
||||
Phase 4 cleanups, controller tests (6, 8), and the changeset last.
|
||||
@@ -38,36 +38,67 @@ Show the resolved `version`, `kind`, and default `fromTagDefault` to the user.
|
||||
|
||||
## CLI Pin Verification
|
||||
|
||||
Before dispatching prepare, verify the JetBrains plugin is pinned to the intended Kilo Core release. The plugin downloads the CLI version from `packages/kilo-jetbrains/package.json`, not from the JetBrains plugin version.
|
||||
Before dispatching prepare, verify the JetBrains plugin is pinned to the intended Kilo Core release. The plugin downloads the CLI version from `packages/kilo-jetbrains/package.json`, not from the JetBrains plugin version. Prepare tags `origin/main`, so the authoritative pin is the value on `origin/main`, not a local edit.
|
||||
|
||||
Read the pinned CLI version:
|
||||
Run the pin preflight:
|
||||
|
||||
```bash
|
||||
bun -e 'const p=require("./packages/kilo-jetbrains/package.json"); console.log(p.version)'
|
||||
bun .kilo/skills/release-jetbrains/script/check-pin.ts
|
||||
```
|
||||
|
||||
Verify the matching GitHub Release exists and includes every runtime asset the backend may download:
|
||||
The script prints:
|
||||
|
||||
| Field | Meaning |
|
||||
|---|---|
|
||||
| `pinMain` | CLI version that `origin/main` will lock into the release tag. |
|
||||
| `pinLocal` | CLI version in the current worktree, useful for catching stale local checkouts. |
|
||||
| `latestCli` | Latest stable `v*` Kilo CLI GitHub release. |
|
||||
| `prevJetbrainsCli` | CLI pin used by the latest `jetbrains/v*` release tag, for reviewing the jump. |
|
||||
| `pinnedMain` / `pinnedLocal` | Whether `kilo.cli.pinned=true`; `false` means repo CLI dev mode. |
|
||||
| `assetsOk` / `missingAssets` | Whether the pinned CLI release has every runtime asset. |
|
||||
| `drift` | `up-to-date`, `behind`, `worktree-behind-main`, `repo-mode-on-main`, `repo-mode-local`, or `assets-missing`. |
|
||||
|
||||
Interpretation:
|
||||
|
||||
| Drift | Action |
|
||||
|---|---|
|
||||
| `up-to-date` | Continue after user confirmation. |
|
||||
| `behind` | Stop and show `pinMain`, `latestCli`, and `prevJetbrainsCli`; ask whether to cancel, bump + test, or proceed anyway. |
|
||||
| `worktree-behind-main` | Explain that prepare tags `origin/main`; refresh the worktree or rely on `pinMain` in the confirmation. |
|
||||
| `repo-mode-on-main` | Stop. `kilo.cli.pinned=false` is dev-only and must be reset to `true` on `main` before release. |
|
||||
| `repo-mode-local` | Stop or reset local `kilo.cli.pinned=true`; release checks should run from a releasable local state. |
|
||||
| `assets-missing` | Stop. The pinned CLI release is incomplete and would fail runtime download. |
|
||||
|
||||
Show the resolved JetBrains plugin version, release kind, default `fromTagDefault`, `pinMain`, `latestCli`, `prevJetbrainsCli`, and `assetsOk` to the user, then ask for confirmation before continuing. If the user wants a different CLI pin, use the bump workflow below and do not dispatch prepare until the bump is merged to `main`.
|
||||
|
||||
## Bump the CLI Pin
|
||||
|
||||
Use this only when the user wants to test or release with a different CLI than `origin/main` currently pins. The helper refuses versions whose GitHub release or runtime assets are missing.
|
||||
|
||||
Local test edit only:
|
||||
|
||||
```bash
|
||||
cli_version="7.4.1"
|
||||
gh release view "v${cli_version}" --repo Kilo-Org/kilocode --json assets \
|
||||
--jq '.assets[].name' | sort
|
||||
bun .kilo/skills/release-jetbrains/script/set-pin.ts --latest
|
||||
# or
|
||||
bun .kilo/skills/release-jetbrains/script/set-pin.ts --version 7.4.1
|
||||
```
|
||||
|
||||
Expected assets:
|
||||
Then test from `packages/kilo-jetbrains/`:
|
||||
|
||||
```text
|
||||
kilo-darwin-arm64.zip
|
||||
kilo-darwin-x64.zip
|
||||
kilo-linux-arm64.tar.gz
|
||||
kilo-linux-x64.tar.gz
|
||||
kilo-windows-arm64.zip
|
||||
kilo-windows-x64.zip
|
||||
```bash
|
||||
./gradlew typecheck
|
||||
./gradlew test
|
||||
```
|
||||
|
||||
If the pin is stale or the release assets are missing, stop and ask the user to update `packages/kilo-jetbrains/package.json` on `main` before dispatching prepare. The prepare workflow tags `origin/main`, so the pin must already be reviewed and merged before the release tag is created.
|
||||
If the user confirms the tested pin should be released, open or update a pin bump PR to `main`:
|
||||
|
||||
Show the resolved JetBrains plugin version, release kind, default `fromTagDefault`, pinned CLI version, and CLI release asset status to the user, then ask for confirmation before continuing.
|
||||
```bash
|
||||
bun .kilo/skills/release-jetbrains/script/set-pin.ts --latest --pr
|
||||
# or
|
||||
bun .kilo/skills/release-jetbrains/script/set-pin.ts --version 7.4.1 --pr
|
||||
```
|
||||
|
||||
After that PR merges to `main`, re-run `resolve-version.ts`, re-run `check-pin.ts`, confirm `drift=up-to-date`, then dispatch prepare. Do not dispatch prepare from a local-only pin edit; the prepare workflow tags `origin/main`.
|
||||
|
||||
## Prepare Workflow
|
||||
|
||||
@@ -200,6 +231,7 @@ Report the Marketplace channel and GitHub Release URL. RC versions publish to th
|
||||
|
||||
- If prepare created the tag but failed before creating a PR, rerun prepare for the same version. The existing workflow reuses the tag if it points to the same commit.
|
||||
- If a tag points to an unexpected SHA, stop and inspect manually. Do not move or delete release tags casually.
|
||||
- If prepare tagged an unintended CLI pin, do not move the tag. Land the intended pin on `main`, resolve the next JetBrains version, and create a new release tag.
|
||||
- If release PR checks fail from an apparent flake, use `gh run rerun <run-id> --failed`, then `gh run watch <run-id> --exit-status` before publishing.
|
||||
- If publish fails after merge, rerun the failed workflow only if Marketplace did not already accept the version.
|
||||
- If Marketplace succeeds but GitHub Release upload fails, manually create or edit the GitHub Release for `jetbrains/v<version>` using the reviewed changelog.
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
import { $ } from "bun"
|
||||
import semver from "semver"
|
||||
import { parseArgs } from "util"
|
||||
import { latest, missing } from "./pin-common"
|
||||
|
||||
const repo = process.env.GH_REPO ?? process.env.GITHUB_REPOSITORY ?? "Kilo-Org/kilocode"
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: Bun.argv.slice(2),
|
||||
options: {
|
||||
help: { type: "boolean", short: "h", default: false },
|
||||
},
|
||||
})
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
Usage: bun .kilo/skills/release-jetbrains/script/check-pin.ts
|
||||
|
||||
Checks the CLI pin that a JetBrains release would lock. Prepare tags origin/main,
|
||||
so this reads packages/kilo-jetbrains/package.json from origin/main and compares
|
||||
it with the latest published Kilo CLI release plus the local worktree pin.
|
||||
|
||||
Exit codes:
|
||||
0 Pin is release-ready.
|
||||
2 Pin drift, repo CLI mode, or missing CLI assets require maintainer review.
|
||||
`)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
await $`git fetch origin main --tags`.quiet()
|
||||
|
||||
const pinMain = JSON.parse(await $`git show origin/main:packages/kilo-jetbrains/package.json`.text()).version as string
|
||||
const pinLocal = (await Bun.file("packages/kilo-jetbrains/package.json").json()).version as string
|
||||
const propsMain = await $`git show origin/main:packages/kilo-jetbrains/gradle.properties`.text()
|
||||
const propsLocal = await Bun.file("packages/kilo-jetbrains/gradle.properties").text()
|
||||
const pinnedMain = pinned(propsMain)
|
||||
const pinnedLocal = pinned(propsLocal)
|
||||
const latestCli = await latest(repo)
|
||||
const prevJetbrainsCli = await previous()
|
||||
const missingAssets = await missing(repo, pinMain)
|
||||
const assetsOk = missingAssets.length === 0
|
||||
const drift = (() => {
|
||||
if (!pinnedMain) return "repo-mode-on-main"
|
||||
if (!pinnedLocal) return "repo-mode-local"
|
||||
if (pinLocal !== pinMain) return "worktree-behind-main"
|
||||
if (!assetsOk) return "assets-missing"
|
||||
if (latestCli && semver.lt(pinMain, latestCli)) return "behind"
|
||||
return "up-to-date"
|
||||
})()
|
||||
|
||||
console.log(JSON.stringify({
|
||||
pinMain,
|
||||
pinLocal,
|
||||
latestCli,
|
||||
prevJetbrainsCli,
|
||||
pinnedMain,
|
||||
pinnedLocal,
|
||||
assetsOk,
|
||||
missingAssets,
|
||||
drift,
|
||||
}, null, 2))
|
||||
|
||||
if (drift !== "up-to-date") process.exit(2)
|
||||
|
||||
async function previous() {
|
||||
const text = await $`git tag --list ${"jetbrains/v*"}`.text()
|
||||
const tag = text
|
||||
.split(/\r?\n/)
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean)
|
||||
.map((tag) => ({ tag, version: tag.replace(/^jetbrains\/v/, "") }))
|
||||
.filter((item) => semver.valid(item.version))
|
||||
.sort((a, b) => semver.rcompare(a.version, b.version))[0]?.tag
|
||||
if (!tag) return null
|
||||
const res = await $`git show ${tag}:packages/kilo-jetbrains/package.json`.nothrow().text()
|
||||
if (!res.trim()) return null
|
||||
return JSON.parse(res).version as string
|
||||
}
|
||||
|
||||
function pinned(text: string) {
|
||||
const value = text.split(/\r?\n/).flatMap((line) => {
|
||||
const [key, value] = line.split("=", 2)
|
||||
if (key.trim() !== "kilo.cli.pinned") return []
|
||||
return [value?.trim().toLowerCase()]
|
||||
})[0]
|
||||
return value == null || value === "true"
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { $ } from "bun"
|
||||
import semver from "semver"
|
||||
|
||||
export const assets = [
|
||||
"kilo-darwin-arm64.zip",
|
||||
"kilo-darwin-x64.zip",
|
||||
"kilo-linux-arm64.tar.gz",
|
||||
"kilo-linux-x64.tar.gz",
|
||||
"kilo-windows-arm64.zip",
|
||||
"kilo-windows-x64.zip",
|
||||
]
|
||||
|
||||
export async function latest(repo: string) {
|
||||
const list = (await $`gh release list --repo ${repo} --limit 100 --json tagName,isDraft,isPrerelease`.json()) as {
|
||||
tagName: string
|
||||
isDraft: boolean
|
||||
isPrerelease: boolean
|
||||
}[]
|
||||
return list
|
||||
.filter((item) => /^v\d+\.\d+\.\d+$/.test(item.tagName) && !item.isDraft && !item.isPrerelease)
|
||||
.map((item) => item.tagName.slice(1))
|
||||
.sort(semver.rcompare)[0] ?? null
|
||||
}
|
||||
|
||||
export async function missing(repo: string, version: string) {
|
||||
const res = await $`gh release view ${`v${version}`} --repo ${repo} --json assets --jq ${".assets[].name"}`.quiet().nothrow()
|
||||
if (res.exitCode !== 0) return assets
|
||||
const names = res.stdout.toString().split(/\r?\n/).map((item) => item.trim()).filter(Boolean)
|
||||
return assets.filter((item) => !names.includes(item))
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
import { $ } from "bun"
|
||||
import semver from "semver"
|
||||
import { parseArgs } from "util"
|
||||
import { latest, missing } from "./pin-common"
|
||||
|
||||
const repo = process.env.GH_REPO ?? process.env.GITHUB_REPOSITORY ?? "Kilo-Org/kilocode"
|
||||
const file = "packages/kilo-jetbrains/package.json"
|
||||
const label = "jetbrains-cli-pin-bump"
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: Bun.argv.slice(2),
|
||||
options: {
|
||||
version: { type: "string" },
|
||||
latest: { type: "boolean", default: false },
|
||||
pr: { type: "boolean", default: false },
|
||||
help: { type: "boolean", short: "h", default: false },
|
||||
},
|
||||
})
|
||||
|
||||
if (values.help) {
|
||||
console.log(`
|
||||
Usage: bun .kilo/skills/release-jetbrains/script/set-pin.ts (--latest | --version <x.y.z>) [--pr]
|
||||
|
||||
Without --pr, rewrites ${file} in the local worktree so you can test a CLI pin.
|
||||
With --pr, opens or updates a PR against main using the GitHub API; prepare tags
|
||||
origin/main, so the pin bump must merge there before a JetBrains release starts.
|
||||
|
||||
Examples:
|
||||
bun .kilo/skills/release-jetbrains/script/set-pin.ts --latest
|
||||
bun .kilo/skills/release-jetbrains/script/set-pin.ts --version 7.4.1
|
||||
bun .kilo/skills/release-jetbrains/script/set-pin.ts --latest --pr
|
||||
`)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
if (values.latest && values.version) throw new Error("Pass either --latest or --version, not both")
|
||||
const version = values.latest ? await latest(repo) : values.version?.replace(/^v/, "")
|
||||
if (!version || !semver.valid(version) || semver.prerelease(version)) {
|
||||
throw new Error("Pass a stable CLI version with --version x.y.z or use --latest")
|
||||
}
|
||||
|
||||
const miss = await missing(repo, version)
|
||||
if (miss.length > 0) {
|
||||
throw new Error(`CLI release v${version} is missing required assets: ${miss.join(", ")}`)
|
||||
}
|
||||
|
||||
if (values.pr) {
|
||||
await pr(version)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const pkg = await Bun.file(file).json()
|
||||
const previous = pkg.version as string
|
||||
pkg.version = version
|
||||
await Bun.write(file, `${JSON.stringify(pkg, null, 2)}\n`)
|
||||
if (previous === version) {
|
||||
console.log(`${file} already pins CLI v${version}`)
|
||||
} else {
|
||||
console.log(`Pinned JetBrains CLI ${previous} -> ${version} in ${file}`)
|
||||
}
|
||||
console.log("Test locally with: cd packages/kilo-jetbrains && ./gradlew typecheck && ./gradlew test")
|
||||
console.log("When satisfied, run this script again with --pr so the bump lands on main before prepare tags it.")
|
||||
|
||||
async function pr(version: string) {
|
||||
await $`git fetch origin main`.quiet()
|
||||
const branch = `chore/jetbrains-cli-pin-v${version}`
|
||||
const main = (await $`git rev-parse origin/main`.text()).trim()
|
||||
const text = await $`git show origin/main:${file}`.text()
|
||||
const pkg = JSON.parse(text)
|
||||
const previous = pkg.version as string
|
||||
if (previous === version) {
|
||||
console.log(`origin/main already pins CLI v${version}; no PR needed.`)
|
||||
return
|
||||
}
|
||||
pkg.version = version
|
||||
const body = `${JSON.stringify(pkg, null, 2)}\n`
|
||||
await ensure(branch, main)
|
||||
const current = (await $`gh api ${`repos/${repo}/contents/${file}?ref=${branch}`}`.json()) as { sha: string }
|
||||
await $`gh api --method PUT ${`repos/${repo}/contents/${file}`} -f message=${`chore(jetbrains): bump CLI pin to v${version}`} -f content=${Buffer.from(body).toString("base64")} -f branch=${branch} -f sha=${current.sha}`.quiet()
|
||||
|
||||
const title = `chore(jetbrains): bump CLI pin to v${version}`
|
||||
const desc = [
|
||||
`Bumps the JetBrains CLI pin from v${previous} to v${version}.`,
|
||||
"",
|
||||
"Prepare tags origin/main, so this PR must merge before dispatching a JetBrains release that should lock this CLI.",
|
||||
"",
|
||||
"After merging, re-run:",
|
||||
"",
|
||||
"```bash",
|
||||
"bun .kilo/skills/release-jetbrains/script/check-pin.ts",
|
||||
"```",
|
||||
].join("\n")
|
||||
const view = await $`gh pr view ${branch} --repo ${repo} --json url --jq .url`.quiet().nothrow()
|
||||
if (view.exitCode === 0 && view.stdout.toString().trim()) {
|
||||
await $`gh pr edit ${branch} --repo ${repo} --title ${title} --body ${desc}`
|
||||
await tag(branch)
|
||||
console.log(view.stdout.toString().trim())
|
||||
return
|
||||
}
|
||||
const url = await $`gh pr create --repo ${repo} --base main --head ${branch} --title ${title} --body ${desc}`.text()
|
||||
await tag(branch)
|
||||
console.log(url.trim())
|
||||
}
|
||||
|
||||
async function ensure(branch: string, sha: string) {
|
||||
const ref = `repos/${repo}/git/refs/heads/${branch}`
|
||||
const exists = await $`gh api ${ref}`.nothrow().quiet()
|
||||
if (exists.exitCode === 0) {
|
||||
await $`gh api --method PATCH ${ref} -f sha=${sha} -F force=true`.quiet()
|
||||
return
|
||||
}
|
||||
await $`gh api --method POST ${`repos/${repo}/git/refs`} -f ref=${`refs/heads/${branch}`} -f sha=${sha}`.quiet()
|
||||
}
|
||||
|
||||
async function tag(branch: string) {
|
||||
await $`gh label create ${label} --repo ${repo} --color 1D76DB --description ${"JetBrains pinned CLI version bump"}`.quiet().nothrow()
|
||||
const result = await $`gh pr edit ${branch} --repo ${repo} --add-label ${label}`.quiet().nothrow()
|
||||
if (result.exitCode !== 0) {
|
||||
console.warn(`Warning: failed to add ${label} label to ${branch}`)
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@opencode-ai/core",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
@@ -93,7 +93,7 @@
|
||||
},
|
||||
"packages/effect-drizzle-sqlite": {
|
||||
"name": "@opencode-ai/effect-drizzle-sqlite",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"drizzle-orm": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -107,7 +107,7 @@
|
||||
},
|
||||
"packages/http-recorder": {
|
||||
"name": "@opencode-ai/http-recorder",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@effect/platform-node": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -120,7 +120,7 @@
|
||||
},
|
||||
"packages/kilo-console": {
|
||||
"name": "@kilocode/kilo-console",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@kilocode/kilo-web-ui": "workspace:*",
|
||||
"@kilocode/sdk": "workspace:*",
|
||||
@@ -142,7 +142,7 @@
|
||||
},
|
||||
"packages/kilo-docs": {
|
||||
"name": "@kilocode/kilo-docs",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@docsearch/css": "^4",
|
||||
"@docsearch/js": "^4",
|
||||
@@ -172,7 +172,7 @@
|
||||
},
|
||||
"packages/kilo-gateway": {
|
||||
"name": "@kilocode/kilo-gateway",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@ai-sdk/alibaba": "1.0.17",
|
||||
"@ai-sdk/anthropic": "3.0.71",
|
||||
@@ -208,7 +208,7 @@
|
||||
},
|
||||
"packages/kilo-i18n": {
|
||||
"name": "@kilocode/kilo-i18n",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"devDependencies": {
|
||||
"@tsconfig/node22": "catalog:",
|
||||
"@types/bun": "catalog:",
|
||||
@@ -218,7 +218,7 @@
|
||||
},
|
||||
"packages/kilo-indexing": {
|
||||
"name": "@kilocode/kilo-indexing",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-bedrock-runtime": "3.1005.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.972.31",
|
||||
@@ -250,11 +250,11 @@
|
||||
},
|
||||
"packages/kilo-jetbrains": {
|
||||
"name": "@kilocode/kilo-jetbrains",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
},
|
||||
"packages/kilo-memory": {
|
||||
"name": "@kilocode/kilo-memory",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"effect": "catalog:",
|
||||
"zod": "catalog:",
|
||||
@@ -268,7 +268,7 @@
|
||||
},
|
||||
"packages/kilo-sandbox": {
|
||||
"name": "@kilocode/sandbox",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"effect": "catalog:",
|
||||
},
|
||||
@@ -281,7 +281,7 @@
|
||||
},
|
||||
"packages/kilo-telemetry": {
|
||||
"name": "@kilocode/kilo-telemetry",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@kilocode/kilo-gateway": "workspace:*",
|
||||
"posthog-node": "4.4.0",
|
||||
@@ -295,7 +295,7 @@
|
||||
},
|
||||
"packages/kilo-ui": {
|
||||
"name": "@kilocode/kilo-ui",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@kilocode/sdk": "workspace:*",
|
||||
"@kobalte/core": "0.13.11",
|
||||
@@ -332,7 +332,7 @@
|
||||
},
|
||||
"packages/kilo-vscode": {
|
||||
"name": "kilo-code",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.39.0",
|
||||
"@kilocode/kilo-gateway": "workspace:*",
|
||||
@@ -401,7 +401,7 @@
|
||||
},
|
||||
"packages/kilo-web-ui": {
|
||||
"name": "@kilocode/kilo-web-ui",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@kilocode/kilo-ui": "workspace:*",
|
||||
"@kobalte/core": "catalog:",
|
||||
@@ -418,7 +418,7 @@
|
||||
},
|
||||
"packages/llm": {
|
||||
"name": "@opencode-ai/llm",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@smithy/eventstream-codec": "4.2.14",
|
||||
"@smithy/util-utf8": "4.2.2",
|
||||
@@ -436,7 +436,7 @@
|
||||
},
|
||||
"packages/opencode": {
|
||||
"name": "@kilocode/cli",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"bin": {
|
||||
"kilo": "./bin/kilo",
|
||||
"kilocode": "./bin/kilo",
|
||||
@@ -500,7 +500,6 @@
|
||||
"@secretlint/secretlint-rule-preset-recommend": "10.2.2",
|
||||
"@silvia-odwyer/photon-node": "0.3.4",
|
||||
"@solid-primitives/event-bus": "1.1.2",
|
||||
"@solid-primitives/scheduled": "1.5.2",
|
||||
"@types/ws": "8.18.1",
|
||||
"@zip.js/zip.js": "2.7.62",
|
||||
"ai": "catalog:",
|
||||
@@ -587,7 +586,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@kilocode/plugin",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@kilocode/sdk": "workspace:*",
|
||||
"effect": "catalog:",
|
||||
@@ -615,7 +614,7 @@
|
||||
},
|
||||
"packages/plugin-atomic-chat": {
|
||||
"name": "@kilocode/plugin-atomic-chat",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@kilocode/plugin": "workspace:*",
|
||||
},
|
||||
@@ -629,7 +628,7 @@
|
||||
},
|
||||
"packages/script": {
|
||||
"name": "@opencode-ai/script",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"semver": "^7.6.3",
|
||||
},
|
||||
@@ -640,7 +639,7 @@
|
||||
},
|
||||
"packages/sdk/js": {
|
||||
"name": "@kilocode/sdk",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"cross-spawn": "catalog:",
|
||||
},
|
||||
@@ -655,7 +654,7 @@
|
||||
},
|
||||
"packages/storybook": {
|
||||
"name": "@opencode-ai/storybook",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"devDependencies": {
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
"@solidjs/meta": "catalog:",
|
||||
@@ -678,7 +677,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"dependencies": {
|
||||
"@kilocode/sdk": "workspace:*",
|
||||
"@kobalte/core": "catalog:",
|
||||
@@ -739,7 +738,6 @@
|
||||
"@opentui/core": "catalog:",
|
||||
"@opentui/keymap": "catalog:",
|
||||
"@opentui/solid": "catalog:",
|
||||
"@smithy/util-buffer-from": "4.2.2",
|
||||
"@types/bun": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"@xmldom/xmldom": ">=0.8.12",
|
||||
@@ -1899,7 +1897,7 @@
|
||||
|
||||
"@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-jUH1Eth7Sgn4KPBX5OKYDRpNjzul7AzsIhxKXT1rHXPTSfY00/7Kb9RtNil5SDAlPPsxaUiesR/rql2wjackmw=="],
|
||||
|
||||
"@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.4.5", "", { "dependencies": { "@smithy/core": "^3.29.0", "tslib": "^2.6.2" } }, "sha512-OTu6rqRA5jcUDVOf2atiMdh+UmZ8GB2gzSdZPElZJAG0hS8lqak0jlvTcrmaR/FNIlP68r5EDUZ+cq1ZLKjq6g=="],
|
||||
"@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
|
||||
"@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-nfpYCrzSFAgfIXmIHFTjOGNeTV3DVF5E5rfi3ZuNfsOjKSpePBOJF3rjyXlWYND0anvxVoqioIwClWCNdKt4Og=="],
|
||||
|
||||
@@ -1935,7 +1933,7 @@
|
||||
|
||||
"@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-T15zTQJ/xKYdS0/3CFckhz1QBbhxmhk/xjL6FKvHKgkJPN4E985If2FI9CcV2kh2v0sfiWMfXVEOKFbqgw4m4w=="],
|
||||
|
||||
"@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.2", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q=="],
|
||||
"@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-sms/ty2CJwHOiGzEaAVWizTVK5KusXpAYqCUeXIa+hWtNKLwjimH4z11mc07d0Fe3DT3lmZJIZWOMcVQ/N4hBQ=="],
|
||||
|
||||
"@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.4.6", "", { "dependencies": { "@smithy/core": "^3.24.6", "tslib": "^2.6.2" } }, "sha512-dRCZKu05AL7KQWrVuRJPotfjCRnvGkCjV56XNP067CRfyTtvgi/Ygu44qrBKb814Hsa52bWwDJ+Vt3pd04BjPA=="],
|
||||
|
||||
@@ -1975,8 +1973,6 @@
|
||||
|
||||
"@solid-primitives/rootless": ["@solid-primitives/rootless@1.5.2", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-9HULb0QAzL2r47CCad0M+NKFtQ+LrGGNHZfteX/ThdGvKIg2o2GYhBooZubTCd/RTu2l2+Nw4s+dEfiDGvdrrQ=="],
|
||||
|
||||
"@solid-primitives/scheduled": ["@solid-primitives/scheduled@1.5.2", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-/j2igE0xyNaHhj6kMfcUQn5rAVSTLbAX+CDEBm25hSNBmNiHLu2lM7Usj2kJJ5j36D67bE8wR1hBNA8hjtvsQA=="],
|
||||
|
||||
"@solid-primitives/static-store": ["@solid-primitives/static-store@0.1.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-uxez7SXnr5GiRnzqO2IEDjOJRIXaG+0LZLBizmUA1FwSi+hrpuMzVBwyk70m4prcl8X6FDDXUl9O8hSq8wHbBQ=="],
|
||||
|
||||
"@solid-primitives/trigger": ["@solid-primitives/trigger@1.2.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-Za2JebEiDyfamjmDwRaESYqBBYOlgYGzB8kHYH0QrkXyLf2qNADlKdGN+z3vWSLCTDcKxChS43Kssjuc0OZhng=="],
|
||||
@@ -4583,8 +4579,6 @@
|
||||
|
||||
"@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="],
|
||||
|
||||
"@smithy/is-array-buffer/@smithy/core": ["@smithy/core@3.29.0", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-sEvpvkBVoMxjoek35XyJFn2ZD3EJ1RpiZrT47WaZodxzAIWS44zkdvbqGE/ZlugtjiQp62cffYZ9ldyRkjAGnA=="],
|
||||
|
||||
"@solid-primitives/resize-observer/@solid-primitives/rootless": ["@solid-primitives/rootless@1.5.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-N8cIDAHbWcLahNRLr0knAAQvXyEdEMoAZvIMZKmhNb1mlx9e2UOv9BRD5YNwQUJwbNoYVhhLwFOEOcVXFx0HqA=="],
|
||||
|
||||
"@storybook/addon-links/storybook": ["storybook@10.4.4", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^2.0.2", "@testing-library/jest-dom": "^6.9.1", "@testing-library/user-event": "^14.6.1", "@vitest/expect": "3.2.4", "@vitest/spy": "3.2.4", "@webcontainer/env": "^1.1.1", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0", "open": "^10.2.0", "oxc-parser": "^0.127.0", "oxc-resolver": "^11.19.1", "recast": "^0.23.5", "semver": "^7.7.3", "use-sync-external-store": "^1.5.0", "ws": "^8.18.0" }, "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "prettier": "^2 || ^3", "vite-plus": "^0.1.15" }, "optionalPeers": ["@types/react", "prettier", "vite-plus"], "bin": "./dist/bin/dispatcher.js" }, "sha512-Nn0qFRxU5fyABa6dGRftfL3lz0Y+HkKOaAkfytF8S4Q2K6Szwwq7TwPAEs3Wsj8hBQbYhsobrKADcPsyXQpJaA=="],
|
||||
@@ -4957,6 +4951,10 @@
|
||||
|
||||
"yargs-unparser/decamelize": ["decamelize@4.0.0", "", {}, "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ=="],
|
||||
|
||||
"@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
||||
|
||||
"@eslint/config-array/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
|
||||
@@ -5057,8 +5055,6 @@
|
||||
|
||||
"@opencode-ai/ui/@solid-primitives/resize-observer/@solid-primitives/rootless": ["@solid-primitives/rootless@1.5.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-N8cIDAHbWcLahNRLr0knAAQvXyEdEMoAZvIMZKmhNb1mlx9e2UOv9BRD5YNwQUJwbNoYVhhLwFOEOcVXFx0HqA=="],
|
||||
|
||||
"@smithy/is-array-buffer/@smithy/core/@smithy/types": ["@smithy/types@4.15.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-x3L0XSACF6UYzKpa9biqiRMgvH5+wnFFew9Tm/grFYqgaupPwx/+ojDPpPJM8dZON3S9tjz5U+PQYsCBd1Mw5Q=="],
|
||||
|
||||
"@storybook/addon-links/storybook/@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
|
||||
|
||||
"@storybook/addon-links/storybook/@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="],
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"nodeModules": {
|
||||
"x86_64-linux": "sha256-5/NgXEBhaNEEqIz9GVCXxQaLJwkqWXAAZOPoa6GyHTI=",
|
||||
"aarch64-linux": "sha256-qt7PKn0SAhDCcYtXRY9+1TBp9x3Far7kK24jhUzoMf8=",
|
||||
"aarch64-darwin": "sha256-3FN/i3chx01S52lAv0tjxVtRpUlPkIfInphpq+69uWA=",
|
||||
"x86_64-darwin": "sha256-+rOacJLx+qOCRGW4F+AjvFcc9XUE2biB0BRSy3dTWGI="
|
||||
"x86_64-linux": "sha256-5siIK4MUoCSQb24VpTjeNMpM1Y3HXju8F2ftO+afFoA=",
|
||||
"aarch64-linux": "sha256-AkbE9l9nx9Y+uDaO/3G/ayBa7ccGHSe4QZLYob060XE=",
|
||||
"aarch64-darwin": "sha256-DvK4m8jVh088uRQ4fPbGqvwRPwXn9pjJ+npsiwkCWBc=",
|
||||
"x86_64-darwin": "sha256-39bKoOcyRWilHIMMvFy5/hupLiQEcCe+yLhLq60AkEI="
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -7,6 +7,7 @@
|
||||
"packageManager": "bun@1.3.14",
|
||||
"scripts": {
|
||||
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts",
|
||||
"dev:local": "bun run packages/opencode/script/dev-local.ts",
|
||||
"dev:storybook": "bun --cwd packages/storybook storybook",
|
||||
"lint": "oxlint",
|
||||
"typecheck": "bun turbo typecheck",
|
||||
@@ -140,8 +141,7 @@
|
||||
"@opentui/core": "catalog:",
|
||||
"@opentui/solid": "catalog:",
|
||||
"solid-js": "catalog:",
|
||||
"@opentui/keymap": "catalog:",
|
||||
"@smithy/util-buffer-from": "4.2.2"
|
||||
"@opentui/keymap": "catalog:"
|
||||
},
|
||||
"patchedDependencies": {
|
||||
"@npmcli/agent@4.0.0": "patches/@npmcli%2Fagent@4.0.0.patch",
|
||||
@@ -150,6 +150,6 @@
|
||||
"solid-js@1.9.10": "patches/solid-js@1.9.10.patch",
|
||||
"mammoth@1.12.0": "patches/mammoth@1.12.0.patch"
|
||||
},
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"peerDependencies": {}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"name": "@opencode-ai/core",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"name": "@opencode-ai/effect-drizzle-sqlite",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
id = "kilo"
|
||||
name = "Kilo"
|
||||
description = "The open source coding agent."
|
||||
version = "7.4.1"
|
||||
version = "7.4.5"
|
||||
schema_version = 1
|
||||
authors = ["Anomaly"]
|
||||
repository = "https://github.com/Kilo-Org/kilocode"
|
||||
@@ -11,26 +11,26 @@ name = "Kilo"
|
||||
icon = "./icons/opencode.svg"
|
||||
|
||||
[agent_servers.opencode.targets.darwin-aarch64]
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.1/opencode-darwin-arm64.zip"
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.5/opencode-darwin-arm64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.darwin-x86_64]
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.1/opencode-darwin-x64.zip"
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.5/opencode-darwin-x64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.linux-aarch64]
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.1/opencode-linux-arm64.tar.gz"
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.5/opencode-linux-arm64.tar.gz"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.linux-x86_64]
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.1/opencode-linux-x64.tar.gz"
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.5/opencode-linux-x64.tar.gz"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.windows-x86_64]
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.1/opencode-windows-x64.zip"
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.5/opencode-windows-x64.zip"
|
||||
cmd = "./opencode.exe"
|
||||
args = ["acp"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"name": "@opencode-ai/http-recorder",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kilocode/kilo-console",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -74,6 +74,10 @@ Use the Markdoc codicon tag format:
|
||||
|
||||
## Documentation Guidelines
|
||||
|
||||
### Style Guide
|
||||
|
||||
Before writing documentation, review `packages/kilo-docs/STYLE_GUIDE.md` for voice, tone, and formatting conventions.
|
||||
|
||||
### Adding New Pages
|
||||
|
||||
1. Create your page in the appropriate directory under `pages/`
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
---
|
||||
title: "Documentation Style Guide"
|
||||
description: "Guidelines for writing Kilo Code documentation"
|
||||
---
|
||||
|
||||
# Documentation Style Guide
|
||||
|
||||
This guide covers writing, formatting, and structuring documentation for the Kilo Code docs site.
|
||||
|
||||
## Voice and Tone
|
||||
|
||||
Kilo Code documentation should be:
|
||||
|
||||
- **Clear and direct** - Cut unnecessary words. Prefer active voice.
|
||||
- **Helpful, not salesy** - Focus on what users can do, not just what's possible.
|
||||
- **Consistent** - Use the same terminology and phrasing across pages.
|
||||
- **Friendly but professional** - Write as a knowledgeable teammate explaining concepts.
|
||||
|
||||
### Do
|
||||
|
||||
- Write in the second person ("you")
|
||||
- Use present tense
|
||||
- Be specific: "Run `kilo run` to execute a task" not "You can run kilo run"
|
||||
|
||||
### Don't
|
||||
|
||||
- Use marketing fluff or hype language
|
||||
- Write in passive voice when active is clearer
|
||||
- Assume prior knowledge not explicitly stated
|
||||
|
||||
## Headings
|
||||
|
||||
- Use sentence case for heading text
|
||||
- Start with the most important word
|
||||
- One heading per section
|
||||
- Use heading levels logically (don't skip from H2 to H4)
|
||||
|
||||
```markdown
|
||||
## Installing Kilo Code
|
||||
|
||||
### VS Code Extension
|
||||
|
||||
### CLI
|
||||
```
|
||||
|
||||
## Procedures
|
||||
|
||||
Use numbered lists for step-by-step instructions. Each step should be a complete action.
|
||||
|
||||
```markdown
|
||||
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**
|
||||
```
|
||||
|
||||
### Procedural tips
|
||||
|
||||
- Include keyboard shortcuts in parentheses
|
||||
- Use present tense
|
||||
- Start each step with a verb
|
||||
- Don't number sub-steps; use nested lists instead
|
||||
|
||||
## Callouts
|
||||
|
||||
Use callouts to highlight important information. Choose the right type:
|
||||
|
||||
| Type | Use for |
|
||||
|---|---|
|
||||
| `note` | General information users should know |
|
||||
| `tip` | Helpful shortcuts or best practices |
|
||||
| `info` | Context or background information |
|
||||
| `warning` | Potential problems or important cautions |
|
||||
| `danger` | Critical warnings that could cause data loss |
|
||||
| `generic` | Content without a specific visual treatment |
|
||||
|
||||
```markdown
|
||||
{% callout type="tip" %}
|
||||
**The easiest way to configure Kilo is to ask the agent.** Just tell the agent what you want.
|
||||
{% /callout %}
|
||||
```
|
||||
|
||||
## Cross-References
|
||||
|
||||
- Use absolute paths starting from `/docs/` for internal links
|
||||
- Don't include `.md` extensions
|
||||
- Use descriptive link text, not "click here"
|
||||
|
||||
```markdown
|
||||
Good: [Quickstart Guide](/docs/getting-started/quickstart)
|
||||
|
||||
Bad: [Click here](/docs/getting-started/quickstart)
|
||||
```
|
||||
|
||||
## Code Examples
|
||||
|
||||
- Use fenced code blocks with language specified
|
||||
- Include comments in code where helpful
|
||||
- Show realistic, working examples
|
||||
- Use `kilo run` for CLI examples, not hypothetical commands
|
||||
|
||||
````markdown
|
||||
```bash
|
||||
kilo run "create a utils.py file with a function that adds two numbers"
|
||||
```
|
||||
````
|
||||
|
||||
### Code in prose
|
||||
|
||||
Use backticks for inline code, file references, and commands:
|
||||
|
||||
- `kilo.jsonc` for configuration files
|
||||
- `Ctrl+Shift+X` for keyboard shortcuts
|
||||
- `src/utils.ts` for file paths
|
||||
|
||||
## Markdoc Conventions
|
||||
|
||||
### Images
|
||||
|
||||
Use the Markdoc image tag format:
|
||||
|
||||
```markdown
|
||||
{% image src="/docs/img/kilo-provider/connected-accounts.png" alt="Connect account screen" width="800" caption="Connect account screen" /%}
|
||||
```
|
||||
|
||||
**Image path rules:**
|
||||
- Always include `/docs` prefix
|
||||
- Use generated screenshots from `packages/kilo-docs/public/img/screenshot-tests/` when available
|
||||
- Write descriptive alt text for accessibility
|
||||
|
||||
### Tables
|
||||
|
||||
Use compact markdown tables without padding:
|
||||
|
||||
```markdown
|
||||
| Command | What it runs |
|
||||
|---|---|
|
||||
| `kilo serve` | The prod CLI on `$PATH`. |
|
||||
```
|
||||
|
||||
### Tabs
|
||||
|
||||
Use tabs for platform-specific content:
|
||||
|
||||
```markdown
|
||||
{% tabs %}
|
||||
{% tab label="VS Code" %}
|
||||
|
||||
Content for VS Code
|
||||
|
||||
{% /tab %}
|
||||
{% tab label="CLI" %}
|
||||
|
||||
Content for CLI
|
||||
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
```
|
||||
|
||||
### Mermaid Diagrams
|
||||
|
||||
Use fenced `mermaid` blocks for architecture diagrams:
|
||||
|
||||
````markdown
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A --> B
|
||||
```
|
||||
````
|
||||
|
||||
## LLM-Generated Docs
|
||||
|
||||
This documentation site is maintained with AI assistance. When reviewing or editing:
|
||||
|
||||
- Verify technical accuracy manually
|
||||
- Ensure examples actually work
|
||||
- Check that terminology is consistent
|
||||
- Don't accept generated content without review
|
||||
|
||||
## Terminology
|
||||
|
||||
Use consistent terms throughout:
|
||||
|
||||
| Term | Use for |
|
||||
|---|---|
|
||||
| Kilo Code | The product name |
|
||||
| kilo CLI | The command-line interface |
|
||||
| VS Code extension | The VS Code extension |
|
||||
| JetBrains plugin | The JetBrains IDE plugin |
|
||||
| `kilo serve` | The local HTTP server |
|
||||
| `kilo run` | The headless execution command |
|
||||
| agent | The AI assistant |
|
||||
|
||||
## Navigation
|
||||
|
||||
- Add new pages to the appropriate nav file in `lib/nav/`
|
||||
- Update `lib/nav/index.ts` to export the new nav section
|
||||
- Navigation files are organized by section (e.g., `getting-started.ts`, `code-with-ai.ts`)
|
||||
|
||||
## Documentation Lifecycle
|
||||
|
||||
- Follow the branch naming convention: `docs/description-of-change`
|
||||
- For documentation-only changes, create branches with the `docs/` prefix
|
||||
- Update navigation when adding or removing pages
|
||||
- Add redirects in `previous-docs-redirects.js` when moving or removing pages
|
||||
@@ -10,7 +10,6 @@ export const AutomateNav: NavSection[] = [
|
||||
href: "/automate/code-reviews/overview",
|
||||
children: "Code Reviews",
|
||||
subLinks: [
|
||||
{ href: "/automate/code-reviews/overview", children: "Overview" },
|
||||
{ href: "/automate/code-reviews/github", children: "GitHub" },
|
||||
{ href: "/automate/code-reviews/gitlab", children: "GitLab" },
|
||||
],
|
||||
@@ -19,7 +18,6 @@ export const AutomateNav: NavSection[] = [
|
||||
href: "/automate/agent-manager",
|
||||
children: "Agent Manager",
|
||||
subLinks: [
|
||||
{ href: "/automate/agent-manager", children: "Reference" },
|
||||
{ href: "/automate/agent-manager-workflows", children: "Workflows" },
|
||||
],
|
||||
},
|
||||
@@ -42,7 +40,6 @@ export const AutomateNav: NavSection[] = [
|
||||
href: "/automate/mcp/overview",
|
||||
children: "MCP",
|
||||
subLinks: [
|
||||
{ href: "/automate/mcp/overview", children: "MCP Overview" },
|
||||
{
|
||||
href: "/automate/mcp/using-in-kilo-code",
|
||||
children: "Using MCP in Kilo Code",
|
||||
|
||||
@@ -30,6 +30,11 @@ export const CodeWithAiNav: NavSection[] = [
|
||||
},
|
||||
{ href: "/code-with-ai/platforms/cloud-agent", children: "Cloud Agent" },
|
||||
{ href: "/code-with-ai/platforms/mobile", children: "Mobile Apps" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Features",
|
||||
links: [
|
||||
{ href: "/code-with-ai/app-builder", children: "App Builder" },
|
||||
{
|
||||
href: "/code-with-ai/gastown",
|
||||
@@ -80,7 +85,6 @@ export const CodeWithAiNav: NavSection[] = [
|
||||
href: "/code-with-ai/agents/using-agents",
|
||||
children: "Agents",
|
||||
subLinks: [
|
||||
{ href: "/code-with-ai/agents/using-agents", children: "Using Agents" },
|
||||
{
|
||||
href: "/code-with-ai/agents/orchestrator-mode",
|
||||
children: "Orchestrator Mode",
|
||||
@@ -89,7 +93,6 @@ export const CodeWithAiNav: NavSection[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
title: "Productivity Tools",
|
||||
links: [
|
||||
@@ -113,11 +116,7 @@ export const CodeWithAiNav: NavSection[] = [
|
||||
href: "/code-with-ai/features/browser-use",
|
||||
children: "Agent Behavior",
|
||||
subLinks: [
|
||||
{ href: "/code-with-ai/features/browser-use", children: "Browser Use" },
|
||||
{
|
||||
href: "/code-with-ai/features/task-todo-list",
|
||||
children: "Task Todo List",
|
||||
},
|
||||
{ href: "/code-with-ai/features/task-todo-list", children: "Task Todo List" },
|
||||
{ href: "/code-with-ai/features/checkpoints", children: "Checkpoints" },
|
||||
{ href: "/code-with-ai/features/file-encoding", children: "File Encoding" },
|
||||
],
|
||||
|
||||
@@ -27,27 +27,26 @@ export const CollaborateNav: NavSection[] = [
|
||||
},
|
||||
{ href: "/collaborate/teams/billing", children: "Billing" },
|
||||
{ href: "/collaborate/teams/analytics", children: "Analytics" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "AI Adoption Dashboard",
|
||||
links: [
|
||||
{
|
||||
href: "/collaborate/adoption-dashboard/overview",
|
||||
children: "AI Adoption Dashboard",
|
||||
subLinks: [
|
||||
{
|
||||
href: "/collaborate/adoption-dashboard/overview",
|
||||
children: "Overview",
|
||||
},
|
||||
{
|
||||
href: "/collaborate/adoption-dashboard/understanding-your-score",
|
||||
children: "Understanding Your Score",
|
||||
},
|
||||
{
|
||||
href: "/collaborate/adoption-dashboard/improving-your-score",
|
||||
children: "Improving Your Score",
|
||||
},
|
||||
{
|
||||
href: "/collaborate/adoption-dashboard/for-team-leads",
|
||||
children: "For Team Leads",
|
||||
},
|
||||
],
|
||||
children: "Overview",
|
||||
},
|
||||
{
|
||||
href: "/collaborate/adoption-dashboard/understanding-your-score",
|
||||
children: "Understanding Your Score",
|
||||
},
|
||||
{
|
||||
href: "/collaborate/adoption-dashboard/improving-your-score",
|
||||
children: "Improving Your Score",
|
||||
},
|
||||
{
|
||||
href: "/collaborate/adoption-dashboard/for-team-leads",
|
||||
children: "For Team Leads",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -2,28 +2,22 @@ import { NavSection } from "../types"
|
||||
|
||||
export const GettingStartedNav: NavSection[] = [
|
||||
{
|
||||
title: "Introduction",
|
||||
title: "Get Started",
|
||||
links: [
|
||||
{ href: "/getting-started", children: "Overview" },
|
||||
{ href: "/getting-started/installing", children: "Installation" },
|
||||
{ href: "/getting-started/quickstart", children: "Quickstart" },
|
||||
{ href: "/getting-started/setup-authentication", children: "Authentication" },
|
||||
{ href: "/getting-started/quickstart", children: "Your First Task" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Configuration",
|
||||
links: [
|
||||
{
|
||||
href: "/getting-started/setup-authentication",
|
||||
children: "Setup & Authentication",
|
||||
},
|
||||
{
|
||||
href: "/getting-started/using-kilo-for-free",
|
||||
children: "Using Kilo for Free",
|
||||
},
|
||||
{
|
||||
href: "/getting-started/byok",
|
||||
children: "Bring Your Own Key (BYOK)",
|
||||
},
|
||||
{ href: "/getting-started/byok", children: "Bring Your Own Key (BYOK)" },
|
||||
{ href: "/ai-providers", children: "AI Providers" },
|
||||
{
|
||||
href: "/getting-started/settings",
|
||||
@@ -34,7 +28,10 @@ export const GettingStartedNav: NavSection[] = [
|
||||
],
|
||||
},
|
||||
{ href: "/getting-started/adding-credits", children: "Adding Credits" },
|
||||
{ href: "/getting-started/rate-limits-and-costs", children: "Cost Efficiency & Model Selection" },
|
||||
{
|
||||
href: "/getting-started/rate-limits-and-costs",
|
||||
children: "Cost Efficiency & Model Selection",
|
||||
},
|
||||
{ href: "/getting-started/cost-controls-and-usage-safeguards", children: "Cost Controls and Usage Safeguards" },
|
||||
],
|
||||
},
|
||||
|
||||
@@ -12,7 +12,6 @@ export const KiloClawNav: NavSection[] = [
|
||||
href: "/kiloclaw/control-ui/overview",
|
||||
children: "Control UI",
|
||||
subLinks: [
|
||||
{ href: "/kiloclaw/control-ui/overview", children: "Overview" },
|
||||
{ href: "/kiloclaw/control-ui/changing-models", children: "Changing Models" },
|
||||
{ href: "/kiloclaw/control-ui/exec-approvals", children: "Exec Approvals" },
|
||||
{ href: "/kiloclaw/control-ui/version-pinning", children: "Version Pinning" },
|
||||
@@ -22,7 +21,6 @@ export const KiloClawNav: NavSection[] = [
|
||||
href: "/kiloclaw/chat-platforms",
|
||||
children: "Chat Platforms",
|
||||
subLinks: [
|
||||
{ href: "/kiloclaw/chat-platforms", children: "Overview" },
|
||||
{ href: "/kiloclaw/chat-platforms/telegram", children: "Telegram" },
|
||||
{ href: "/kiloclaw/chat-platforms/discord", children: "Discord" },
|
||||
{ href: "/kiloclaw/chat-platforms/slack", children: "Slack" },
|
||||
@@ -32,7 +30,6 @@ export const KiloClawNav: NavSection[] = [
|
||||
href: "/kiloclaw/development-tools",
|
||||
children: "Integrations",
|
||||
subLinks: [
|
||||
{ href: "/kiloclaw/development-tools", children: "Overview" },
|
||||
{ href: "/kiloclaw/development-tools/github", children: "GitHub" },
|
||||
{ href: "/kiloclaw/development-tools/google", children: "Google Workspace" },
|
||||
{ href: "/kiloclaw/development-tools/linear", children: "Linear" },
|
||||
@@ -47,7 +44,6 @@ export const KiloClawNav: NavSection[] = [
|
||||
href: "/kiloclaw/triggers",
|
||||
children: "Triggers",
|
||||
subLinks: [
|
||||
{ href: "/kiloclaw/triggers", children: "Overview" },
|
||||
{ href: "/kiloclaw/triggers/webhooks", children: "Webhooks" },
|
||||
{ href: "/kiloclaw/triggers/scheduled", children: "Scheduled" },
|
||||
],
|
||||
|
||||
@@ -33,6 +33,8 @@ exclude = [
|
||||
'^https?://api\.voyageai\.com/v1/embeddings/?$',
|
||||
'^https?://inference\.do-ai\.run/v1/?$',
|
||||
'^https?://generativelanguage\.googleapis\.com/v1beta/openai/?$',
|
||||
# OpenRouter chat-completions is a POST-only endpoint; GET probes return 404
|
||||
'^https?://openrouter\.ai/api/v1/chat/completions/?$',
|
||||
'^https?://search\.parallel\.ai/mcp/?$',
|
||||
# xAI API and OAuth endpoints require request parameters or reject plain link checks.
|
||||
'^https?://api\.x\.ai/v1/?$',
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
Kilo Code's current JetBrains plugin uses a native interface and supports JetBrains remote development without requiring Node.js.
|
||||
Kilo Code v7 for JetBrains is officially available. It uses a native JetBrains interface, works well in [remote development split mode](https://www.jetbrains.com/remote-development/), and does not require Node.js.
|
||||
|
||||
### Try the v7 Early Access Program plugin {% #jetbrains-early-access %}
|
||||
The JetBrains plugin provides the best native JetBrains UX for working with an AI coding agent, and it improves with every release. Enable automatic plugin updates to get the latest fixes and improvements as soon as they are available.
|
||||
|
||||
The v7 EAP plugin is available for users who want to try the newest JetBrains experience before it reaches the default Marketplace channel. Follow the [v7 roadmap and release milestone](https://github.com/Kilo-Org/kilocode/milestone/1) for planned work and release progress.
|
||||
### Install the JetBrains plugin
|
||||
|
||||
1. Open IntelliJ IDEA or another [JetBrains IDE](https://www.jetbrains.com/ides/)
|
||||
2. Go to **Settings → Plugins**
|
||||
3. Search for **Kilo Code** in the **Marketplace** tab
|
||||
4. Click **Install** or **Update** and restart your IDE if prompted
|
||||
5. Open **Settings → Appearance & Behavior → System Settings → Updates**, then enable **Update plugins automatically** (recommended)
|
||||
|
||||
{% image src="/docs/img/jetbrains/plugin-marketplace.png" alt="JetBrains Plugins Marketplace showing the Kilo Code plugin search result" width="900" caption="Search for Kilo Code in the JetBrains Plugins Marketplace." /%}
|
||||
|
||||
{% image src="/docs/img/jetbrains/plugin-auto-updates.png" alt="JetBrains Updates settings with Update plugins automatically enabled" width="900" caption="Enable automatic plugin updates to receive Kilo Code fixes and improvements." /%}
|
||||
|
||||
### If you used the v7 EAP {% #jetbrains-early-access %}
|
||||
|
||||
{% callout type="info" %}
|
||||
The v7 EAP plugin is compatible with JetBrains IDE builds 261 and later. EAP builds update frequently, so we recommend enabling automatic plugin updates in your JetBrains IDE from **Settings/Preferences → System Settings → Updates → Update plugins automatically**. Share feedback in the JetBrains channel on the [Kilo Discord](https://kilo.ai/discord).
|
||||
Remove the EAP repository URL from **Settings → Plugins → Manage Plugin Repositories**. The official v7 plugin is now available from the default JetBrains Marketplace channel, and leaving the custom repository configured can keep your IDE on EAP updates.
|
||||
{% /callout %}
|
||||
|
||||
To install the EAP build and receive updates:
|
||||
|
||||
1. Open IntelliJ IDEA or another JetBrains IDE
|
||||
2. Go to **Settings/Preferences → Plugins**
|
||||
3. Click the gear icon and choose **Manage Plugin Repositories**
|
||||
4. Add this repository URL:
|
||||
|
||||
{% copyLine text="https://plugins.jetbrains.com/plugins/list?channel=eap&pluginId=28350" /%}
|
||||
|
||||
5. Return to the **Marketplace** tab
|
||||
6. Search for **Kilo Code**
|
||||
7. Click **Install** or **Update** and restart your IDE if prompted
|
||||
|
||||
After the custom repository is added, JetBrains will offer EAP updates through the normal plugin update flow.
|
||||
|
||||
### Supported IDEs
|
||||
|
||||
- IntelliJ IDEA
|
||||
@@ -34,7 +31,3 @@ After the custom repository is added, JetBrains will offer EAP updates through t
|
||||
- CLion
|
||||
- RubyMine
|
||||
- DataGrip
|
||||
|
||||
{% callout type="info" %}
|
||||
Both Community and Ultimate editions are supported. Some AI features may vary based on your JetBrains license.
|
||||
{% /callout %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kilocode/kilo-docs",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --webpack --port 3002",
|
||||
|
||||
@@ -39,7 +39,7 @@ The panel opens as an editor tab and stays active across focus changes.
|
||||
|
||||
Agent Manager uses the same sign-in, provider settings, models, BYOK keys, custom providers, MCP servers, and permission rules as the extension sidebar. Configure them from extension Settings and they apply to Agent Manager as well.
|
||||
|
||||
See [Setup & Authentication](/docs/getting-started/setup-authentication), [AI Providers](/docs/ai-providers), and [Bring Your Own Key](/docs/getting-started/byok) for setup details.
|
||||
See [Authentication](/docs/getting-started/setup-authentication), [AI Providers](/docs/ai-providers), and [Bring Your Own Key](/docs/getting-started/byok) for setup details.
|
||||
|
||||
## Working with Worktrees
|
||||
|
||||
@@ -153,7 +153,7 @@ The tool supports two modes:
|
||||
| `worktree` | Creates one Agent Manager git worktree and session per task |
|
||||
| `local` | Creates Agent Manager sessions in the current workspace without git worktree isolation |
|
||||
|
||||
Each request can include 1-20 tasks. Each task must include at least one of `prompt`, `name`, or `branchName`. A task with an initial prompt can also specify a `model` (by name, e.g. `Claude Opus 4.1`) and one of that model's reasoning `variant` values. Agent Manager resolves the provider for the chosen model, preferring the provider used by the current default model and falling back to the Kilo Gateway; a qualified `provider/model` ID is also accepted to force a specific provider. Tasks without those fields use the normal model defaults. Use `versions: true` only when the tasks are alternate versions of the same work to compare; otherwise, multiple tasks start as independent sessions.
|
||||
Each request can include 1-20 tasks. Each task must include at least one of `prompt`, `name`, or `branchName`. Prompted tasks inherit the model and reasoning variant used by the chat turn that starts them. A task can override that selection with a `model` (by name, e.g. `Claude Opus 4.1`) when you explicitly request a different model, or with one of the current model's reasoning `variant` values when you request a different variant. Agent Manager resolves the provider for a model override, preferring the provider used by the current turn and falling back to the Kilo Gateway; a qualified `provider/model` ID is also accepted to force a specific provider. Prepared sessions without an initial prompt use the normal model defaults. Use `versions: true` only when the tasks are alternate versions of the same work to compare; otherwise, multiple tasks start as independent sessions.
|
||||
|
||||
The companion `agent_manager_models` tool searches models and their supported reasoning variants on demand. Results are grouped by model name (with the offering providers listed for reference) and limited to 20 per call, so the full catalog is never added to the conversation context.
|
||||
|
||||
|
||||
@@ -339,6 +339,10 @@ The Kilo CLI is a fork of [OpenCode](https://opencode.ai) and supports the same
|
||||
|
||||
Project-level configuration takes precedence over global settings.
|
||||
|
||||
{% callout type="warning" %}
|
||||
**Migrating from opencode?** Kilo no longer falls back to opencode configuration stored in `.opencode` directories (such as `~/.config/opencode` or a project `./.opencode/`). To keep using it, move your global config into `~/.config/kilo/` and any project config into `./.kilo/`.
|
||||
{% /callout %}
|
||||
|
||||
### Key Configuration Options
|
||||
|
||||
```json
|
||||
|
||||
@@ -28,7 +28,7 @@ Your sessions sync across all of these, so you can start a task on your phone an
|
||||
## Quick Start
|
||||
|
||||
1. [Install Kilo Code](/docs/getting-started/installing) in your preferred environment
|
||||
2. [Connect an AI provider](/docs/ai-providers) or use Kilo's built-in provider & credits
|
||||
2. [Set up authentication](/docs/getting-started/setup-authentication) or use Kilo's built-in provider
|
||||
3. [Run your first task](/docs/getting-started/quickstart)
|
||||
|
||||
{% callout type="tip" %}
|
||||
|
||||
@@ -124,11 +124,10 @@ If you plan to remain on that version for a while, you may also want to temporar
|
||||
|
||||
## Next Steps
|
||||
|
||||
After installation, check out these resources to get started:
|
||||
After installation:
|
||||
|
||||
- [Quickstart Guide](/docs/getting-started/quickstart) - Get up and running in minutes
|
||||
- [Setting Up Authentication](/docs/getting-started/setup-authentication) - Configure your AI provider
|
||||
- [Your First Task](/docs/code-with-ai/agents/chat-interface) - Learn the basics of working with Kilo Code
|
||||
1. **[Set up authentication](/docs/getting-started/setup-authentication)** to configure your AI provider
|
||||
2. **[Run your first task](/docs/getting-started/quickstart)** — Learn how to chat with Kilo to complete tasks
|
||||
|
||||
## Getting Support
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
---
|
||||
title: "Quickstart"
|
||||
title: "Your First Task"
|
||||
description: "Get up and running with Kilo Code in minutes"
|
||||
---
|
||||
|
||||
# Quickstart
|
||||
# Your First Task
|
||||
|
||||
After you [set up Kilo Code](/docs/getting-started/setup-authentication), follow the guide for your platform below.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="VSCode" %}
|
||||
{% tab label="VS Code" %}
|
||||
|
||||
## Step by Step Guide
|
||||
|
||||
@@ -36,16 +36,9 @@ Kilo Code analyzes your request and proposes actions. By default, most tools are
|
||||
|
||||
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
|
||||
### Step 5: Iterate and Review
|
||||
|
||||
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
|
||||
Kilo Code works iteratively. Continue giving feedback or follow-up instructions until your task is complete. The assistant will propose file edits, run commands, and complete your request step by step.
|
||||
|
||||
{% /tab %}
|
||||
{% tab label="CLI" %}
|
||||
@@ -68,7 +61,7 @@ Run the `kilo` command to start the interactive TUI (terminal user interface):
|
||||
kilo
|
||||
```
|
||||
|
||||
If this is your first time, run `kilo auth login` first to authenticate (see [Setup & Authentication](/docs/getting-started/setup-authentication)).
|
||||
If this is your first time, run `kilo auth login` first to authenticate (see [Authentication](/docs/getting-started/setup-authentication)).
|
||||
|
||||
### Step 3: Type Your Task
|
||||
|
||||
@@ -86,9 +79,9 @@ Kilo analyzes your request and proposes actions. By default, most tools are auto
|
||||
|
||||
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
|
||||
### Step 5: Iterate and Review
|
||||
|
||||
Kilo works iteratively. Continue giving feedback or follow-up instructions until your task is complete.
|
||||
Kilo works iteratively. Continue giving feedback or follow-up instructions until your task is complete. The assistant will propose file edits, run commands, and complete your request step by step.
|
||||
|
||||
### One-Shot Mode
|
||||
|
||||
@@ -107,19 +100,13 @@ kilo run --auto "fix the failing tests in test/auth.test.ts"
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
## Conclusion
|
||||
## What You Can Do Next
|
||||
|
||||
You've completed your first task. Along the way you learned:
|
||||
Now that you've completed your first task, try these capabilities:
|
||||
|
||||
- How to interact with Kilo Code using natural language
|
||||
- Why approval keeps you in control
|
||||
- How iteration lets the AI refine its work
|
||||
|
||||
Ready for more? Here are some next steps:
|
||||
|
||||
- **[Autocomplete](/docs/code-with-ai/features/autocomplete)** — Get inline code suggestions as you type
|
||||
- **[Agents](/docs/code-with-ai/agents/using-agents)** — Explore different agents for different tasks
|
||||
- **[Git commit generation](/docs/code-with-ai/features/git-commit-generation)** — Automatically generate commit messages
|
||||
- **[Autocomplete](/docs/code-with-ai/features/autocomplete)** — Get inline code suggestions as you type in your editor
|
||||
- **[Agents](/docs/code-with-ai/agents/using-agents)** — Switch between specialized agents for coding, architecture, debugging, and more
|
||||
- **[Git](/docs/code-with-ai/features/git-commit-generation)** — Auto-generate commit messages from your changes
|
||||
|
||||
{% callout type="tip" %}
|
||||
**Accelerate development:** Check out multiple copies of your repository and run Kilo Code on all of them in parallel (using git to resolve any conflicts, same as with human devs). This can dramatically speed up development on large projects.
|
||||
|
||||
@@ -27,6 +27,12 @@ This is especially useful for complex configuration like custom model definition
|
||||
|
||||
## Managing Settings
|
||||
|
||||
Kilo reads JSONC config from a **global** location (`~/.config/kilo/kilo.jsonc`) and from your **project** (`kilo.jsonc`, or `.kilo/kilo.jsonc`). All clients — CLI, VS Code, and JetBrains — read the same files.
|
||||
|
||||
{% callout type="warning" %}
|
||||
**Migrating from opencode?** Kilo no longer falls back to opencode configuration stored in `.opencode` directories (such as `~/.config/opencode` or a project `./.opencode/`). To keep using it, move your global config into `~/.config/kilo/` and any project config into `./.kilo/`.
|
||||
{% /callout %}
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="VSCode" %}
|
||||
|
||||
@@ -155,6 +161,12 @@ For **session** export and import, use the CLI commands:
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
## Sandbox
|
||||
|
||||
On macOS and Linux, the VS Code extension includes a dedicated **Sandboxing** settings tab. The sandbox is disabled by default. When enabled, it limits agent filesystem writes and can block outbound network access from model-originated tools. Windows users do not see these settings because Windows sandboxing is not supported.
|
||||
|
||||
See [Sandboxing](/docs/getting-started/settings/sandboxing) for setup instructions, the exact filesystem and network boundaries, and platform limitations.
|
||||
|
||||
## Experimental Features
|
||||
|
||||
{% tabs %}
|
||||
@@ -169,7 +181,6 @@ Available experimental settings include:
|
||||
- **Paste summary** - summarize large clipboard pastes before including them
|
||||
- **Batch tool** - allow the agent to batch multiple tool calls in one step
|
||||
- **OpenTelemetry** - enable Kilo telemetry and optional OTLP export when configured
|
||||
- **Sandbox** - confine agent shell commands and file writes to the project and Kilo state directories, with optional outbound network blocking. See [Sandboxing](/docs/getting-started/settings/sandboxing).
|
||||
|
||||
Advanced options not exposed in the UI can be configured via the `experimental` key in `kilo.jsonc`:
|
||||
|
||||
|
||||
@@ -1,76 +1,163 @@
|
||||
---
|
||||
title: "Sandboxing"
|
||||
description: "Confine agent shell commands and file writes with the experimental OS-level sandbox"
|
||||
description: "Understand and configure filesystem write and network restrictions for agent tools"
|
||||
---
|
||||
|
||||
# Sandboxing
|
||||
|
||||
The experimental sandbox runs agent shell commands and file-tool writes inside an OS-level sandbox that restricts filesystem writes to your project and Kilo state directories, and can block outbound network access from model-originated commands. It is an extra guardrail on top of the permission system: even if the agent is allowed to run a command, the operating system will deny writes outside the allowed roots.
|
||||
The sandbox adds an operating-system boundary around agent tools. It limits where tools can write and, by default, blocks outbound network access from model-originated commands. This boundary applies even when a tool passes Kilo's permission checks.
|
||||
|
||||
The sandbox is **disabled by default**. It does not restrict filesystem reads. An agent can still read any file that your user account can read, but it can write only to explicitly allowed locations.
|
||||
|
||||
{% callout type="warning" %}
|
||||
Sandboxing is experimental. Behavior may change between releases, and it is not available on Windows.
|
||||
Sandboxing is not available on Windows. If the macOS or Linux sandbox backend is unavailable, Kilo reports the reason and runs tools without sandbox confinement. The sandbox does not fail closed.
|
||||
{% /callout %}
|
||||
|
||||
## How it works
|
||||
|
||||
When enabled, the agent's shell commands and file-write tools run confined to a small set of writable directories:
|
||||
|
||||
- Your **project directory** (and its worktree, when running in a linked git worktree)
|
||||
- Kilo **state directories**: data, cache, config, state, tmp, bin, log, and repos
|
||||
|
||||
Everything else is denied at the OS level. File **reads are not confined** — the agent can still read anywhere it has permission to. The `.git` directory is always denied for writes, regardless of location.
|
||||
|
||||
When network restriction is on (the default), outbound network access is blocked for:
|
||||
|
||||
- Shell commands originated by the model
|
||||
- First-party HTTP tools (for example web fetch and browser tools)
|
||||
|
||||
The following are **not** affected by the network restriction:
|
||||
|
||||
- **Provider and model inference traffic** — your LLM API calls keep working
|
||||
- **Local MCP servers and plugin hooks** — these run outside the restriction
|
||||
|
||||
## Enable the sandbox
|
||||
|
||||
The sandbox is off by default. Enable it under the `experimental` key in `kilo.jsonc`:
|
||||
In the VS Code extension:
|
||||
|
||||
1. Open Kilo Code Settings using the gear icon ({% codicon name="gear" /%}).
|
||||
2. Select **Sandboxing**.
|
||||
3. Turn on **Sandbox**.
|
||||
4. Keep **Restrict Network Access** on unless the agent's commands need outbound network access.
|
||||
5. Save the settings.
|
||||
|
||||
The **Sandboxing** tab is visible to all macOS and Linux users, including when the sandbox is off. Windows users do not see the tab because no Windows backend is available.
|
||||
|
||||
You can also configure the default in the global `kilo.jsonc` file:
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": {
|
||||
"sandbox": true,
|
||||
"sandbox_restrict_network": true
|
||||
"sandbox": {
|
||||
"enabled": true,
|
||||
"network": "deny",
|
||||
"writable_paths": ["~/shared-output"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Key | Default | Effect |
|
||||
|---|---|---|
|
||||
| `experimental.sandbox` | `false` | Turn the sandbox on. When `false`, no confinement applies. |
|
||||
| `experimental.sandbox_restrict_network` | `true` | Block outbound network from model-originated commands and HTTP tools. Set to `false` to allow network (filesystem confinement still applies). |
|
||||
| `sandbox.enabled` | `false` | Use sandbox confinement by default for new sessions. |
|
||||
| `sandbox.network` | `"deny"` | Control outbound network access while filesystem confinement is active. Set this to `"allow"` to permit network access without removing filesystem write restrictions. |
|
||||
| `sandbox.writable_paths` | `[]` | Add writable files or directories outside the built-in writable locations. Only global config may set these paths. |
|
||||
|
||||
You can also enable it from the VS Code Settings webview: gear icon ({% codicon name="gear" /%}) → **Experimental** → **Sandbox**. Once the sandbox is on, a dedicated **Sandboxing** tab appears with the **Restrict Network Access** switch for `sandbox_restrict_network`.
|
||||
Project config may tighten sandbox policy by setting `enabled` to `true` or `network` to `"deny"`. It cannot disable a globally enabled sandbox, allow network denied by global config, or add writable paths. This prevents repository-controlled configuration from weakening the user's security boundary.
|
||||
|
||||
## Toggle per session
|
||||
## When to use sandboxing
|
||||
|
||||
Enabling `experimental.sandbox` sets the default for new sessions, but the setting is ephemeral per session and can be flipped without editing config:
|
||||
Use the sandbox when the agent may run unfamiliar commands, install dependencies, execute code from an untrusted repository, or process content that could contain prompt injection. It provides a second boundary if the model makes a mistake or follows malicious instructions embedded in source files, issue text, web pages, or tool output.
|
||||
|
||||
- **VS Code**: a sandbox toggle appears in the prompt input when `experimental.sandbox` is on (not available for cloud sessions). The tooltip shows whether filesystem writes and network are restricted.
|
||||
- **CLI / TUI**: run the `/sandbox` slash command or the **Toggle sandbox** palette command. A `◆ Sandbox on` indicator appears next to the prompt when active.
|
||||
The sandbox can reduce the impact of an unsafe tool call by:
|
||||
|
||||
Toggling is in-memory and scoped to the current session, so it does not persist across restarts. If the OS sandbox backend is unavailable on your platform, the toggle reports the reason and confinement stays off.
|
||||
- Preventing writes outside the workspace and other explicitly writable locations
|
||||
- Keeping sandboxed commands from changing `.git` metadata
|
||||
- Blocking direct outbound connections from sandboxed commands and policy-aware tools when network restriction is on
|
||||
- Applying the same restrictions to child processes, such as package installation and build scripts launched by a shell command
|
||||
|
||||
This can reduce the risk of auto-approving selected routine commands, such as builds and tests, by placing operating-system limits around many of their effects. It does **not** make **Allow Everything** safe. An allowed command can still modify or delete workspace files, alter other writable Kilo directories, consume data it can read, or write unsafe code that runs later outside the sandbox.
|
||||
|
||||
The sandbox does not protect against every result of prompt injection. In particular, it does not prevent the agent from reading accessible files or including their contents in model context. It also cannot confine local MCP servers, plugin hooks, or any integration that runs outside the sandbox boundary.
|
||||
|
||||
{% callout type="warning" %}
|
||||
The network sandbox is not a provider privacy control. Provider and model inference traffic remains available. If Kilo reads a secret and includes it in a prompt, tool result, or conversation context, that content may be sent to the configured model provider even while network restriction is on. Choose providers with data-handling policies appropriate for your work, consider a local model for sensitive projects, and use read permissions to block or prompt for sensitive files. See [Prompt-Training Model Visibility](/docs/getting-started/settings#prompt-training-model-visibility).
|
||||
{% /callout %}
|
||||
|
||||
## Sandboxing and permissions
|
||||
|
||||
Permissions and sandboxing solve different parts of the security problem and work best together.
|
||||
|
||||
| Control | What it decides | Best used for |
|
||||
|---|---|---|
|
||||
| Permissions | Whether Kilo allows, asks about, or denies a matching tool invocation | Prompting for sensitive file reads, blocking specific commands or tools, reviewing consequential actions, and limiting MCP tool or subagent invocation |
|
||||
| Sandbox | What an allowed tool call can change or connect to while it runs | Limiting the impact of model mistakes, prompt injection, malicious dependencies, and unexpected child-process behavior |
|
||||
|
||||
Permissions can ask or deny Kilo tool invocations that read or change data. For example, set `read` or `external_directory` rules to `ask` or `deny` for credentials, personal files, or directories the agent does not need. Kilo's `read` tool also prompts for `.env` and `.env.*` unless you explicitly create a matching sensitive-file rule. See [Agent Permissions](/docs/customize/agent-permissions) for path and command rules.
|
||||
|
||||
Permission rules are tool-specific and do not create a complete file-confidentiality boundary. A `read` denial controls Kilo's file-reading tool, but an allowed `grep` call, shell command, build script, or other process may read the same file through a different path. A child process can also print sensitive content into tool output, which may then become model context. Configure `grep`, `bash`, and other data-accessing tools separately, and avoid running untrusted code when sensitive files remain readable by your operating-system account.
|
||||
|
||||
For a given tool invocation, approving a shell command does not grant writes outside the sandbox, and a path being writable inside the sandbox does not bypass a matching permission rule. Some integration code runs outside this boundary: plugin hooks can run before a tool's internal permission check, and a local MCP server starts as a separate trusted process. MCP permissions control exposed tool invocations, not everything the server process can do during startup or in the background. Enable only local MCP servers and plugins you trust.
|
||||
|
||||
A practical setup for work on unfamiliar or partially trusted code is:
|
||||
|
||||
- Keep `read`, `grep`, and unnecessary external-directory access set to `ask` or `deny` when they may expose sensitive content.
|
||||
- Allow only routine tools and command patterns that you want to run without interruption.
|
||||
- Keep shell approval prompts for commands with important in-workspace effects or commands that can read sensitive data, because the sandbox still allows workspace writes and filesystem reads.
|
||||
- Enable the sandbox and keep network restriction on to reduce write and direct network-exfiltration impact if an approved action behaves unexpectedly.
|
||||
- Add extra writable paths only when a known workflow requires them.
|
||||
|
||||
For a stronger confidentiality boundary, remove sensitive files from the environment or run Kilo under a separate operating-system account, container, or virtual machine that cannot read them. If file contents must not leave your machine, use local inference and disable other integrations that can send data over the network. If remote processing is acceptable, choose a provider with data-handling terms suitable for the data involved.
|
||||
|
||||
Configure these rules in **Settings > Auto Approve** or `kilo.jsonc`. See [Auto-Approving Actions](/docs/getting-started/settings/auto-approving-actions) for the settings UI and default permission behavior.
|
||||
|
||||
## Filesystem restrictions
|
||||
|
||||
When the sandbox is active, agent tools can read files normally. The sandbox restricts writes, including creating, changing, renaming, and deleting files.
|
||||
|
||||
Writes are allowed in:
|
||||
|
||||
- The active workspace or worktree
|
||||
- Kilo's runtime directories listed below
|
||||
- Paths listed in `sandbox.writable_paths`
|
||||
|
||||
| Writable Kilo path | Purpose |
|
||||
|---|---|
|
||||
| `$XDG_DATA_HOME/kilo` (normally `~/.local/share/kilo`) | Session data, logs, and Kilo's managed repository cache under `repos/` |
|
||||
| `$XDG_CACHE_HOME/kilo` (normally `~/.cache/kilo`) | Cached data and downloaded binaries |
|
||||
| `$XDG_CONFIG_HOME/kilo` (normally `~/.config/kilo`) | Configuration and installed plugins |
|
||||
| `$XDG_STATE_HOME/kilo` (normally `~/.local/state/kilo`) | Runtime state |
|
||||
| `$TMPDIR/kilo` | Temporary files; on macOS this is commonly under `/var/folders/.../T/kilo` |
|
||||
|
||||
Writes are denied everywhere else. The following rules still apply inside writable locations:
|
||||
|
||||
- `.git` directories are always read-only to sandboxed tools.
|
||||
- Kilo's stored sandbox policy and preference files are read-only.
|
||||
- A permission approval for a path outside the sandbox does not make that path writable. Add the path to **Additional Writable Paths** if the tool must modify it.
|
||||
- Linked worktree sessions can write to their active worktree, not the primary checkout or sibling worktrees.
|
||||
|
||||
Shell commands and their child processes inherit the same restrictions. Kilo's file tools perform mutations through a sandboxed worker. Writable file handles are unavailable, so a tool that requires an open read-write handle may fail even for an allowed path.
|
||||
|
||||
Because Kilo's config directory is writable, a shell command can change configuration, permissions, plugins, or additional writable paths that affect future tool calls. Direct filesystem access inside trusted integrations is confined only when the integration uses Kilo's sandbox-aware filesystem service. Starting or restarting a process with the background-process tool is unavailable while sandboxing is active.
|
||||
|
||||
{% callout type="info" %}
|
||||
The sandbox is a write boundary, not a privacy boundary. It does not prevent an agent from reading files outside your workspace if your operating-system account can read them.
|
||||
{% /callout %}
|
||||
|
||||
## Network restrictions
|
||||
|
||||
**Restrict Network Access** controls outbound network access independently of filesystem writes. Turning it off leaves the filesystem write restrictions active.
|
||||
|
||||
When network restriction is on, Kilo blocks:
|
||||
|
||||
- Outbound network access from model-originated shell commands and their child processes
|
||||
- Requests from built-in HTTP tools such as web fetch and web search
|
||||
- Remote MCP tool calls and custom or plugin tools that Kilo cannot prove will remain offline
|
||||
- Built-in tools such as codebase search, semantic search, and LSP that may use opaque or indirect network access
|
||||
|
||||
Network restriction does not block:
|
||||
|
||||
- Provider and model inference traffic, so conversations with the selected model continue to work
|
||||
- Local MCP server processes
|
||||
- Plugin hooks that run outside the sandboxed tool execution
|
||||
- Filesystem reads
|
||||
|
||||
This is not a system-wide firewall. It applies to the sandboxed tool execution boundary, not every Kilo, extension, or local process. Proxy environment variables are removed from sandboxed commands while network access is restricted.
|
||||
|
||||
## Session behavior
|
||||
|
||||
The config setting supplies the initial default for new sessions that do not have a saved preference. Use the lock button in the VS Code prompt or `/sandbox` in the CLI to change the current session. Your latest choice is saved as the default for future sessions in that project, takes precedence over the config default, and persists across restarts.
|
||||
|
||||
Each initialized session keeps its sandbox enabled state and network mode. Changing those settings affects new sessions; use the prompt control or `/sandbox` to change an existing session's enabled state. Changes to **Additional Writable Paths** are read when tools run and therefore also apply to existing sandboxed sessions.
|
||||
|
||||
Forked sessions retain the source session's confinement. Subagents inherit the stricter combination of the parent and child settings: sandboxing remains enabled if either requires it, and network remains blocked if either requires blocking.
|
||||
|
||||
Cloud sessions do not expose the local sandbox control because their tools do not run in your local sandbox.
|
||||
|
||||
## Platform support
|
||||
|
||||
| Platform | Backend | Notes |
|
||||
|---|---|---|
|
||||
| macOS | `sandbox-exec` (seatbelt) | Uses the system `/usr/bin/sandbox-exec`. |
|
||||
| Linux | Bubblewrap (`bwrap`) | Uses system `/usr/bin/bwrap`, or a bundled, SHA-256-verified binary. Override the path with the `KILO_BWRAP_PATH` environment variable. The executable is probed at startup to confirm it can create the sandbox. |
|
||||
| Windows | none | The sandbox backend is unavailable on Windows. Enabling the config has no effect. |
|
||||
|
||||
## Limitations
|
||||
|
||||
- **Windows is not supported.**
|
||||
- Local MCP servers and plugin hooks are **not** covered by the network restriction.
|
||||
- File **reads** are not confined — only writes and shell command effects are.
|
||||
- Writable file handles are unavailable while the sandbox is active; writes are performed through a sandboxed worker, so some tools that open files for writing may behave differently.
|
||||
- The sandbox is additive to the permission system, not a replacement. Permission rules still apply first.
|
||||
| macOS | `sandbox-exec` (Seatbelt) | Uses a Seatbelt profile through `/usr/bin/sandbox-exec`. |
|
||||
| Linux | Bubblewrap (`bwrap`) | Uses system `/usr/bin/bwrap` or a bundled, SHA-256-verified binary. `KILO_BWRAP_PATH` can select another binary. Kilo probes filesystem and network namespace support before enabling confinement. Additional writable paths must already exist before Bubblewrap starts. |
|
||||
| Windows | None | Unsupported. The VS Code settings and prompt controls are hidden, and enabling the config has no effect. |
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
---
|
||||
title: "Setup & Authentication"
|
||||
title: "Authentication"
|
||||
description: "Configure Kilo Code and connect to your AI providers"
|
||||
---
|
||||
|
||||
# Setup & Authentication
|
||||
# Authentication
|
||||
|
||||
When you install Kilo Code, you'll be prompted to sign in or create a free account. This automatically configures everything you need to get started.
|
||||
|
||||
## Quick Start with Kilo Account
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="VSCode" %}
|
||||
{% tab label="VS Code" %}
|
||||
|
||||
The extension prompts you to sign in when you first open Kilo Code in VS Code. Click **Sign In** and complete the browser-based flow. Sign-in applies across extension surfaces, including the sidebar and Agent Manager.
|
||||
|
||||
@@ -93,7 +93,7 @@ Already have a ChatGPT subscription? You can use it with Kilo Code through the [
|
||||
### Configuring Your Provider
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="VSCode" %}
|
||||
{% tab label="VS Code" %}
|
||||
|
||||
1. Open Kilo Code in VS Code
|
||||
2. Click the gear icon ({% codicon name="gear" /%}) in the extension UI to open **Settings**
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 291 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 549 KiB |
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:234454319a6d8ce9e513411c7eb94865053bd24b8ac6624b08151af6658ac7ac
|
||||
size 14909
|
||||
oid sha256:12f523463f86c86dffc350a32c0f76e39391f602c32f0b778d410c87cc83fb1a
|
||||
size 15708
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0a80f1cfd15e41bff690dda11e083b45dd0dba6936833bbb1292fd20e4e8e3a4
|
||||
size 15091
|
||||
oid sha256:58b145cc30b2d7580ea859dcd27b88535d33983d4125004586ba2568e3024252
|
||||
size 15889
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6f7e685eee7798085c2f68e3909b97c5cdef4610a5172ac29ec990e02d164e43
|
||||
size 17881
|
||||
oid sha256:d5a5fdd318bd14100e0c71f7f9055d830db1e59b6af57007608881f433a177ca
|
||||
size 18703
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6f05d9512bbe3309c6d073fd8aca8e0800c7e2827bdefe6115e636e8a6e94070
|
||||
size 16239
|
||||
oid sha256:d544d3964f4a442b12d1eb47aa992c756ac537c2c810adb9abb072f99a815135
|
||||
size 17177
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:836d6b819a7108510a2abd5db6c9307945a7489c5a2b240035bfc1acb3405385
|
||||
size 13009
|
||||
oid sha256:10956634c051d1d1eff54229083434ddb1882adc49161d524a14ab3fc3859554
|
||||
size 13822
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:19395088343e6546ae2f8d3232b8e1e17e5db482841dcf516a80c40fcbc8604a
|
||||
size 14912
|
||||
oid sha256:0249acab24874167ad0f6e88d12897be50dc12861e763a89a4d90545309de3b3
|
||||
size 15709
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:45f622206510533051173fbab26f30c1359d25b9baff7d515c05b664b16d7aa4
|
||||
size 14734
|
||||
oid sha256:dc61e88dc65c15583e0c972f2d370e1c75c7a87949c557492ffbc146b2f75ac5
|
||||
size 15535
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cba6f84ec6138fc59be088cdf84d2ebe57a55f8514df58eed693a84969ff7a90
|
||||
size 4794
|
||||
oid sha256:eecccfc0bbd53bd52261ff8cfc02c444c6d97f6438e6693d8cd998c36909708a
|
||||
size 5178
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c94c54757e88700b5c48a10a60d8626d8d5ed76a29879f06059e5f6457382a5f
|
||||
size 614004
|
||||
oid sha256:42c43e9ba12bc73da98c915dafca274beee1d0c893c168d8af4e3e3f41edd367
|
||||
size 630896
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user