mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-21 14:07:20 +08:00
Merge branch 'main' into fix/grok-4.5-reasoning-variants
This commit is contained in:
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@kilocode/kilo-jetbrains": patch
|
||||
---
|
||||
|
||||
Use the standard transcript font for JetBrains prompt text and custom question responses.
|
||||
@@ -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.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Allow Shift+Arrow selections in the prompt input to shrink back across file mentions.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -35,3 +35,7 @@ packages/kilo-i18n/src/de.ts linguist-generated=false
|
||||
# Auto-generated CLI reference docs
|
||||
packages/kilo-docs/markdoc/partials/cli-commands-table.md linguist-generated=true
|
||||
packages/kilo-docs/pages/code-with-ai/platforms/cli-reference.md linguist-generated=true
|
||||
|
||||
# Upstream generated migration artifacts
|
||||
packages/core/migration/**/snapshot.json linguist-generated
|
||||
packages/core/src/database/migration.gen.ts linguist-generated
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -57,14 +57,24 @@ jobs:
|
||||
BUILD_LOG=$(mktemp)
|
||||
trap 'rm -f "$BUILD_LOG"' EXIT
|
||||
|
||||
# Build with fakeHash to trigger hash mismatch and reveal correct hash
|
||||
nix build ".#packages.${SYSTEM}.node_modules_updater" --no-link 2>&1 | tee "$BUILD_LOG" || true
|
||||
HASH=""
|
||||
MAX_ATTEMPTS=3
|
||||
for ((ATTEMPT = 1; ATTEMPT <= MAX_ATTEMPTS; ATTEMPT++)); do
|
||||
# Build with fakeHash to trigger hash mismatch and reveal correct hash
|
||||
nix build ".#packages.${SYSTEM}.node_modules_updater" --no-link 2>&1 | tee "$BUILD_LOG" || true
|
||||
|
||||
# Extract hash from build log with portability
|
||||
HASH="$(nix run --inputs-from . nixpkgs#gnugrep -- -oP 'got:\s*\Ksha256-[A-Za-z0-9+/=]+' "$BUILD_LOG" | tail -n1 || true)"
|
||||
HASH="$(nix run --inputs-from . nixpkgs#gnugrep -- -oP 'got:\s*\Ksha256-[A-Za-z0-9+/=]+' "$BUILD_LOG" | tail -n1 || true)"
|
||||
|
||||
[ -n "$HASH" ] && break
|
||||
|
||||
if [ "$ATTEMPT" -lt "$MAX_ATTEMPTS" ]; then
|
||||
echo "::warning::Attempt ${ATTEMPT}/${MAX_ATTEMPTS} produced no hash for ${SYSTEM}; retrying in $((ATTEMPT * 10))s"
|
||||
sleep $((ATTEMPT * 10))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$HASH" ]; then
|
||||
echo "::error::Failed to compute hash for ${SYSTEM}"
|
||||
echo "::error::Failed to compute hash for ${SYSTEM} after ${MAX_ATTEMPTS} attempts"
|
||||
cat "$BUILD_LOG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -42,8 +42,6 @@ jobs:
|
||||
needs: changes
|
||||
if: github.event_name == 'workflow_dispatch' || needs.changes.outputs.jetbrains == 'true'
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
container:
|
||||
image: ghcr.io/kilo-org/build/jetbrains:24.04
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
@@ -56,8 +54,21 @@ jobs:
|
||||
- name: Mark workspace as git-safe
|
||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||
with:
|
||||
bun-version-file: package.json
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "21"
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
- name: Run JetBrains unit tests
|
||||
run: bun script/test-ci.ts
|
||||
|
||||
+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: |
|
||||
|
||||
@@ -27,6 +27,8 @@ storybook-static
|
||||
.turbo
|
||||
**/.serena
|
||||
.serena/
|
||||
**/.omo
|
||||
.omo/
|
||||
/result
|
||||
refs
|
||||
Session.vim
|
||||
|
||||
@@ -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}`)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1 +1 @@
|
||||
v1.15.13
|
||||
v1.16.2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
description: translate English to other languages
|
||||
model: opencode/claude-opus-4-7
|
||||
model: opencode/claude-opus-4-8
|
||||
---
|
||||
|
||||
run git diff and translate changed english doc and UI copy files to other international languages. Translate all languages in parallel to save time.
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
"packages/opencode/migration/*": "deny",
|
||||
},
|
||||
},
|
||||
"reference": {
|
||||
"effect": "github.com/Effect-TS/effect-smol",
|
||||
},
|
||||
"mcp": {},
|
||||
"tools": {
|
||||
"github-triage": false,
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
# OpenCode Session Runtime
|
||||
|
||||
OpenCode sessions preserve durable conversational history while assembling the runtime context an agent needs to act correctly in its current environment.
|
||||
|
||||
## Language
|
||||
|
||||
**System Context**:
|
||||
The structured collection of contextual facts presented to the model as initial instructions and chronological updates.
|
||||
_Avoid_: System prompt
|
||||
|
||||
**Session History**:
|
||||
The projected chronological conversation selected for a provider turn after applying the active compaction and **Context Epoch** cutoffs.
|
||||
_Avoid_: Session Context
|
||||
|
||||
**Context Source**:
|
||||
One independently observed typed value within the **System Context**, represented by a stable key, JSON codec, infallible loader, pure baseline/update renderers, and an optional removal renderer for dynamic sources.
|
||||
_Avoid_: Prompt fragment
|
||||
|
||||
**System Context Registry**:
|
||||
The Location-scoped registry of ordered, scoped producers that contribute to the current **System Context**.
|
||||
|
||||
**Mid-Conversation System Message**:
|
||||
A durable chronological instruction that tells the model the newly effective state of a changed **Context Source**.
|
||||
_Avoid_: System update, system notification, raw text diff
|
||||
|
||||
**Context Epoch**:
|
||||
The span during which one effective agent's initially rendered **System Context** remains immutable, ending at compaction or another baseline-replacing transition.
|
||||
|
||||
**Baseline System Context**:
|
||||
The full **System Context** rendered at the start of a **Context Epoch**.
|
||||
_Avoid_: Live system prompt
|
||||
|
||||
**Context Snapshot**:
|
||||
The overwriteable model-hidden JSON state used to compare each **Context Source** with the value last admitted to a provider turn.
|
||||
|
||||
**Unavailable Context**:
|
||||
An expected temporary inability to observe a **Context Source** value; the runtime retains its prior effective state and emits no update, or omits it until first successfully loaded.
|
||||
|
||||
**Safe Provider-Turn Boundary**:
|
||||
The point immediately before a provider call, after durable input promotion and any required tool settlement, where context changes may be admitted chronologically.
|
||||
|
||||
## Relationships
|
||||
|
||||
- A **System Context** is an opaque carrier composed from zero or more **Context Sources**.
|
||||
- **Session History** contains projected conversational messages and admitted **Mid-Conversation System Messages**; the active **Baseline System Context** remains separate provider-request state.
|
||||
- The **System Context Registry** uses stable-keyed scoped contributions to assemble the current **System Context**; contributor removal naturally removes its sources at the next **Safe Provider-Turn Boundary**.
|
||||
- A changed **Context Source** may produce one **Mid-Conversation System Message** containing its newly effective state.
|
||||
- A **Mid-Conversation System Message** persists the exact combined rendered text sent to the model.
|
||||
- The current **Context Snapshot** advances atomically with the corresponding durable **Mid-Conversation System Message**.
|
||||
- A **Context Snapshot** stores one codec-encoded JSON value and, for removable dynamic sources, a pre-rendered removal message per stable **Context Source** key.
|
||||
- Changes from multiple **Context Sources** admitted at one safe boundary combine into one **Mid-Conversation System Message**.
|
||||
- Context changes are sampled and admitted lazily at a **Safe Provider-Turn Boundary**, never pushed asynchronously when their source changes.
|
||||
- At a **Safe Provider-Turn Boundary**, newly promoted user input or settled tool results precede any combined **Mid-Conversation System Message**.
|
||||
- The first provider turn renders the latest complete **Baseline System Context** and initializes its **Context Snapshot** without emitting a redundant **Mid-Conversation System Message**; unavailable initial context blocks the turn instead of persisting an incomplete baseline.
|
||||
- Initial **System Context** preparation precedes the first durable input promotion so an unavailable baseline leaves that input pending and retryable; ordinary reconciliation remains after promotion.
|
||||
- Compaction starts a new **Context Epoch** with a freshly rendered **Baseline System Context** and **Context Snapshot**; prior **Mid-Conversation System Messages** remain durable audit history but leave projected model history.
|
||||
- A newly registered core or plugin-defined **Context Source** absent from the current snapshot emits its baseline rendering once at the next **Safe Provider-Turn Boundary**.
|
||||
- **Context Source** keys are stable and namespaced; duplicate keys fail composition. `SystemContext.combine(...)` preserves caller order; the **System Context Registry** evaluates producers concurrently and combines them in stable contribution-key order so rendered context remains deterministic.
|
||||
- Each **Context Source** loader returns one coherent typed value. `SystemContext.make(...)` hides that value type so differently typed sources compose uniformly. Its codec compares and stores that value; its pure renderers produce model-visible baseline, update, and removal text only when needed.
|
||||
- `SystemContext.initialize(...)` observes a composed **System Context** once and produces a fresh **Baseline System Context** with its **Context Snapshot**.
|
||||
- `SystemContext.reconcile(...)` observes a composed **System Context** once and returns exactly one next action: unchanged, updated, replacement ready, or replacement blocked.
|
||||
- `SystemContext.replace(...)` represents an explicit baseline-replacing transition such as compaction or model/provider switch; it either produces a fresh generation or reports that replacement is blocked by unavailable admitted context.
|
||||
- Context Epoch preparation retries until stable after optimistic revision mismatches so concurrent replacement requests cannot terminate an otherwise valid safe-boundary run.
|
||||
- **Unavailable Context** uses stale-while-revalidate semantics and is distinct from a successfully loaded absence, which may emit removal text.
|
||||
- Ordinary **Context Source** loaders return values directly; loaders that intentionally use stale-while-revalidate may explicitly return **Unavailable Context**.
|
||||
- Nested project instruction discovery after successful reads remains a follow-up; when implemented, discovered instructions must be admitted durably at the next **Safe Provider-Turn Boundary**.
|
||||
- Location-scoped services naturally re-resolve effective context when a moved session next runs in its destination location.
|
||||
- Moving a Session clears its active **Context Epoch**, so the destination must initialize a complete baseline before another prompt can promote.
|
||||
- Context Epoch initialization is fenced against the authoritative Session Location, so an old-Location runner cannot recreate source context after a concurrent move.
|
||||
- Instruction discovery, source identity, persistence, and file loading belong to the instruction service; the **System Context** abstraction only composes effectful producers and renders loaded values.
|
||||
- The first instruction-service slice observes global and upward project `AGENTS.md` files as one ordered aggregate **Context Source** at each **Safe Provider-Turn Boundary**.
|
||||
- Built-in and instruction context producers register through the **System Context Registry** with stable contribution keys. Plugin-defined context registration and hot-reload lifecycle remain a follow-up built on the same scoped registry seam.
|
||||
- Selected-agent available-skill guidance is a **Context Source** composed with Location-wide registry sources immediately before Context Epoch admission. It lists only names and descriptions permitted for that agent; skill bodies and locations are exposed only through the permission-checked `skill` tool.
|
||||
- Switching the selected agent requests **Context Epoch** replacement. A switch admitted after the current **Safe Provider-Turn Boundary** applies to the next provider turn while leaving the already-prepared baseline durable. Epoch creation is fenced against the authoritative effective agent, and retries re-observe the current agent.
|
||||
- A cross-agent replacement must complete before another provider turn; unavailable admitted context blocks that replacement instead of exposing the previous agent's privileged baseline.
|
||||
- Local tool authorization and pending permission requests retain the effective agent of the provider turn that issued the call; a later agent switch cannot change that call's policy.
|
||||
- Context source changes never wake idle sessions; the next naturally scheduled **Safe Provider-Turn Boundary** loads and compares current values lazily.
|
||||
- Once admitted, a **Mid-Conversation System Message** remains durable even if the following provider attempt fails and is replayed unchanged on retry.
|
||||
- **Mid-Conversation System Messages** remain durable Session-message history; normal user-facing transcript surfaces may hide them.
|
||||
- The date **Context Source** initially preserves host-local calendar-date behavior; a configured user timezone may replace that default later.
|
||||
- A **Context Epoch** begins with one immutable **Baseline System Context**.
|
||||
- A **Context Epoch** durably records the effective agent that owns its **Baseline System Context**.
|
||||
- A **Baseline System Context** is stored durably and reused verbatim across process restarts within its **Context Epoch**.
|
||||
- A **Baseline System Context** durably preserves the exact joined text used for the active provider-cache prefix.
|
||||
- Compaction or a model/provider switch starts a new **Context Epoch** because the baseline can be replaced without preserving the prior provider cache.
|
||||
- A model/provider switch always starts a new **Context Epoch** while preserving chronological conversation history.
|
||||
- A **Mid-Conversation System Message** lowers to the provider's native chronological instruction role when supported and to a wrapped chronological fallback otherwise.
|
||||
- When the effective aggregate instruction set changes, its **Mid-Conversation System Message** includes the complete current ordered set and supersedes the prior aggregate value; when no ambient instructions remain, the message states that previously loaded instructions no longer apply.
|
||||
- Ambient project instruction discovery honors `KILO_DISABLE_PROJECT_CONFIG`; global instructions remain eligible.
|
||||
|
||||
## Example dialogue
|
||||
|
||||
> **Dev:** "The date changed while the session was active. Should the **Mid-Conversation System Message** say what the old date was?"
|
||||
> **Domain expert:** "No. Emit the newly effective date so the agent can act on the current **System Context**."
|
||||
|
||||
## Flagged ambiguities
|
||||
|
||||
- Legacy `experimental.chat.system.transform` can mutate the assembled baseline system prompt arbitrarily, but V2 plugins do not yet expose an equivalent hook. Decide separately whether to port it, replace dynamic uses with plugin-defined **Context Sources**, or narrow its semantics.
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
exact = true
|
||||
# Keep Kilo's longer supply-chain quarantine while allowing packages that must track coordinated releases.
|
||||
minimumReleaseAge = 410520 # seconds (~4.75 days / ~114 hours)
|
||||
minimumReleaseAgeExcludes = ["mermaid", "@mermaid-js/parser", "@opentui/core", "@opentui/core-darwin-arm64", "@opentui/core-darwin-x64", "@opentui/core-linux-arm64", "@opentui/core-linux-x64", "@opentui/core-win32-arm64", "@opentui/core-win32-x64", "@opentui/keymap", "@opentui/solid"]
|
||||
minimumReleaseAgeExcludes = ["mermaid", "@mermaid-js/parser", "@ai-sdk/amazon-bedrock", "@opentui/core", "@opentui/core-darwin-arm64", "@opentui/core-darwin-x64", "@opentui/core-linux-arm64", "@opentui/core-linux-arm64-musl", "@opentui/core-linux-x64", "@opentui/core-linux-x64-musl", "@opentui/core-win32-arm64", "@opentui/core-win32-x64", "@opentui/keymap", "@opentui/solid"]
|
||||
|
||||
[test]
|
||||
root = "./do-not-run-tests-from-root"
|
||||
|
||||
@@ -183,13 +183,17 @@ else
|
||||
fi
|
||||
|
||||
if [ -z "$requested_version" ]; then
|
||||
url="https://github.com/Kilo-Org/kilocode/releases/latest/download/$filename"
|
||||
specific_version=$(curl -s https://api.github.com/repos/Kilo-Org/kilocode/releases/latest | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
|
||||
|
||||
if [[ $? -ne 0 || -z "$specific_version" ]]; then
|
||||
# The npm latest tag tracks stable CLI releases independently of other GitHub release types.
|
||||
if ! specific_version=$(curl -fsSL "https://registry.npmjs.org/-/package/%40kilocode%2Fcli/dist-tags" |
|
||||
sed -n 's/.*"latest"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p'); then
|
||||
echo -e "${RED}Failed to fetch version information${NC}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "$specific_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo -e "${RED}Failed to fetch version information${NC}"
|
||||
exit 1
|
||||
fi
|
||||
url="https://github.com/Kilo-Org/kilocode/releases/download/v${specific_version}/$filename"
|
||||
else
|
||||
# Strip leading 'v' if present
|
||||
requested_version="${requested_version#v}"
|
||||
|
||||
+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-yNHrsBXfCWeuX13frVTjIL7U4k71wSimDtdTjoBndoY=",
|
||||
"aarch64-linux": "sha256-zbRBPcPduV1a2EH4BiZWPJ+LyZMLCEPkQ3s+U7tDxtk=",
|
||||
"aarch64-darwin": "sha256-NLLlE2t3vs1E5fDwyiFGoneJAdTb6uXrFuVa+LwBtlY=",
|
||||
"x86_64-darwin": "sha256-BH31+FPgkt1xXJixkj+DgXIveJ49fWk4AIc3Hx+4XzM="
|
||||
}
|
||||
}
|
||||
|
||||
+30
-16
@@ -7,14 +7,16 @@
|
||||
"packageManager": "bun@1.3.14",
|
||||
"scripts": {
|
||||
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts",
|
||||
"dev:stats": "bun sst shell --stage=production -- bun run --cwd packages/stats/app dev",
|
||||
"dev:local": "bun run packages/opencode/script/dev-local.ts",
|
||||
"dev:storybook": "bun --cwd packages/storybook storybook",
|
||||
"lint": "oxlint",
|
||||
"typecheck": "bun turbo typecheck",
|
||||
"upgrade-opentui": "bun run script/upgrade-opentui.ts",
|
||||
"postinstall": "bun run --cwd packages/opencode fix-node-pty && bun run script/setup-git.ts",
|
||||
"postinstall": "bun run --cwd packages/core fix-node-pty && bun run script/setup-git.ts",
|
||||
"prepare": "husky",
|
||||
"random": "echo 'Random script'",
|
||||
"hello": "echo 'Hello World!'",
|
||||
"sso": "aws sso login --sso-session=opencode --no-browser",
|
||||
"test": "echo 'do not run tests from root' && exit 1",
|
||||
"extension": "bun --cwd packages/kilo-vscode script/launch.ts",
|
||||
"dev-setup": "bun run --cwd packages/opencode --conditions=browser src/index.ts dev-setup"
|
||||
@@ -25,14 +27,15 @@
|
||||
"packages/sdk/js"
|
||||
],
|
||||
"catalog": {
|
||||
"@effect/opentelemetry": "4.0.0-beta.66",
|
||||
"@effect/platform-node": "4.0.0-beta.66",
|
||||
"@effect/opentelemetry": "4.0.0-beta.74",
|
||||
"@effect/platform-node": "4.0.0-beta.74",
|
||||
"@anthropic-ai/sandbox-runtime": "0.0.63",
|
||||
"@npmcli/arborist": "9.4.0",
|
||||
"@types/bun": "1.3.14",
|
||||
"@types/cross-spawn": "6.0.6",
|
||||
"@octokit/rest": "22.0.0",
|
||||
"@opentui/core": "0.2.15",
|
||||
"@opentui/solid": "0.2.15",
|
||||
"@opentui/core": "0.3.2",
|
||||
"@opentui/solid": "0.3.2",
|
||||
"ulid": "3.0.1",
|
||||
"@kobalte/core": "0.13.11",
|
||||
"@types/luxon": "3.7.1",
|
||||
@@ -50,11 +53,12 @@
|
||||
"dompurify": "3.4.2",
|
||||
"drizzle-kit": "1.0.0-rc.2",
|
||||
"drizzle-orm": "1.0.0-rc.2",
|
||||
"effect": "4.0.0-beta.66",
|
||||
"effect": "4.0.0-beta.74",
|
||||
"ai": "6.0.168",
|
||||
"cross-spawn": "7.0.6",
|
||||
"hono": "4.12.12",
|
||||
"hono-openapi": "1.1.2",
|
||||
"ipaddr.js": "2.4.0",
|
||||
"fuzzysort": "3.1.0",
|
||||
"luxon": "3.6.1",
|
||||
"marked": "17.0.1",
|
||||
@@ -69,7 +73,7 @@
|
||||
"shiki": "3.20.0",
|
||||
"solid-list": "0.3.0",
|
||||
"tailwindcss": "4.1.11",
|
||||
"virtua": "0.42.3",
|
||||
"virtua": "0.49.1",
|
||||
"vite": "7.3.5",
|
||||
"@solidjs/meta": "0.29.4",
|
||||
"@solidjs/router": "0.15.4",
|
||||
@@ -77,8 +81,11 @@
|
||||
"solid-js": "1.9.12",
|
||||
"vite-plugin-solid": "2.11.10",
|
||||
"@lydell/node-pty": "1.2.0-beta.12",
|
||||
"@opentui/keymap": "0.2.15",
|
||||
"@effect/sql-sqlite-bun": "4.0.0-beta.66"
|
||||
"@opentui/keymap": "0.3.2",
|
||||
"@effect/sql-sqlite-bun": "4.0.0-beta.74",
|
||||
"@hono/standard-validator": "0.2.0",
|
||||
"@hono/zod-validator": "0.4.2",
|
||||
"sst": "4.13.1"
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -94,13 +101,17 @@
|
||||
"turbo": "2.9.14",
|
||||
"@types/bun": "catalog:",
|
||||
"@changesets/changelog-github": "^0.5.1",
|
||||
"@changesets/cli": "^2.27.10"
|
||||
"@changesets/cli": "^2.27.10",
|
||||
"@actions/artifact": "5.0.1",
|
||||
"sst": "catalog:"
|
||||
},
|
||||
"dependencies": {
|
||||
"@kilocode/plugin": "workspace:*",
|
||||
"@opencode-ai/script": "workspace:*",
|
||||
"@kilocode/sdk": "workspace:*",
|
||||
"typescript": "catalog:"
|
||||
"typescript": "catalog:",
|
||||
"@aws-sdk/client-s3": "3.933.0",
|
||||
"heap-snapshot-toolkit": "1.1.3"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -125,7 +136,7 @@
|
||||
"@types/bun": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"effect": "catalog:",
|
||||
"@effect/platform-node-shared": "4.0.0-beta.46",
|
||||
"@effect/platform-node-shared": "4.0.0-beta.74",
|
||||
"path-to-regexp": ">=8.4.0",
|
||||
"picomatch": ">=2.3.2",
|
||||
"defu": "6.1.6",
|
||||
@@ -140,16 +151,19 @@
|
||||
"@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",
|
||||
"@silvia-odwyer/photon-node@0.3.4": "patches/@silvia-odwyer%2Fphoton-node@0.3.4.patch",
|
||||
"@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch",
|
||||
"solid-js@1.9.10": "patches/solid-js@1.9.10.patch",
|
||||
"virtua@0.49.1": "patches/virtua@0.49.1.patch",
|
||||
"@ai-sdk/xai@3.0.92": "patches/@ai-sdk%2Fxai@3.0.92.patch",
|
||||
"pacote@21.5.1": "patches/pacote@21.5.1.patch",
|
||||
"@ai-sdk/google@3.0.73": "patches/@ai-sdk%2Fgoogle@3.0.73.patch",
|
||||
"mammoth@1.12.0": "patches/mammoth@1.12.0.patch"
|
||||
},
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.8",
|
||||
"peerDependencies": {}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { defineConfig } from "drizzle-kit"
|
||||
|
||||
export default defineConfig({
|
||||
dialect: "sqlite",
|
||||
schema: "./src/**/*.sql.ts",
|
||||
schema: ["./src/**/*.sql.ts", "./src/**/sql.ts"],
|
||||
out: "./migration",
|
||||
dbCredentials: {
|
||||
url: "/home/thdxr/.local/share/kilo/kilo.db",
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `session` ADD `metadata` text;
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user