Merge remote-tracking branch 'origin/main' into fix-a11y-history-10672

This commit is contained in:
marius-kilocode
2026-05-29 13:05:04 +02:00
231 changed files with 4983 additions and 1330 deletions
@@ -1,5 +0,0 @@
---
"kilo-code": minor
---
Add a "Not set (use server default)" option to the autocomplete model picker so users can follow the recommended default automatically. Users who previously had the default model pinned only because it was the only thing visible in the dropdown are migrated to "Not set" once.
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": patch
---
Center local session history delete buttons within their rows.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/cli": patch
---
Fix packaged CLI startup crashes caused by duplicate OpenTUI/Solid renderer instances.
@@ -0,0 +1,5 @@
---
"@kilocode/cli": patch
---
Fix LanceDB metadata corruption that caused a full re-index on every VS Code restart
+5
View File
@@ -0,0 +1,5 @@
---
"kilo-code": patch
---
Preserve prior context in forked sessions while recognizing the selected direction and current worktree context.
+5
View File
@@ -0,0 +1,5 @@
---
"kilo-code": minor
---
Link to Kilo Gateway BYOK usage information from provider API key connection dialogs.
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": patch
---
Improve the size and readability of the local History session context menu.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/cli": patch
---
Keep the extension responsive while semantic indexing processes large workspaces.
+8
View File
@@ -0,0 +1,8 @@
---
"@opencode-ai/app": patch
"@opencode-ai/ui": patch
"@kilocode/kilo-ui": patch
"@kilocode/kilo-i18n": patch
---
Support Italian as a display language.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/kilo-jetbrains": patch
---
Show question, permission, plan, and login-required badges for active JetBrains sessions in recent and history lists.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/kilo-jetbrains": minor
---
Support toggling auto-approve for permission prompts from the JetBrains chat input.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/kilo-jetbrains": patch
---
Refresh JetBrains history and recent-session rows when active session titles change, and keep pending inactive sessions alive when switching views.
@@ -1,5 +0,0 @@
---
"@kilocode/kilo-jetbrains": patch
---
Show a question indicator on the JetBrains session scroll overlay when user input is needed.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/kilo-jetbrains": patch
---
Resize the JetBrains prompt editor as prompt lines are added or removed.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/kilo-jetbrains": patch
---
Refine JetBrains session transcript styling with subtler tool rows, prompt-styled user messages, and underlined read file links that open files in the IDE.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/kilo-jetbrains": patch
---
Support opening links in JetBrains session markdown transcripts.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/kilo-jetbrains": patch
---
Keep JetBrains chat scrolled to the latest prompt and question updates when following the bottom.
@@ -0,0 +1,5 @@
---
"@kilocode/kilo-jetbrains": patch
---
Smooth the JetBrains session scroll button edges while preserving theme-aware SVG colors.
+5
View File
@@ -0,0 +1,5 @@
---
"@kilocode/kilo-jetbrains": patch
---
Use static light and dark SVG icon assets in the JetBrains plugin instead of runtime SVG recoloring.
@@ -1,8 +0,0 @@
---
"kilo-code": patch
"@kilocode/cli": patch
"@kilocode/kilo-indexing": patch
"@kilocode/sdk": patch
---
Use supported hosted model presets for Kilo indexing and clear obsolete model and dimension overrides.
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": minor
---
Add Mercury Next Edit as an opt-in autocomplete mode. Predicts multi-line edits beyond the cursor (including off-cursor and pure-insertion edits) and surfaces them with a Tab-to-jump / Tab-to-apply affordance. Select "Mercury Next Edit" under the autocomplete model setting to enable it (requires an Inception API key). Thanks [@tfiras](https://github.com/tfiras)!
-6
View File
@@ -1,6 +0,0 @@
---
"@kilocode/kilo-gateway": minor
"kilo-code": minor
---
Support Mercury Next Edit through the Kilo Gateway. The new "Mercury Next Edit via Kilo Gateway" autocomplete model routes Next Edit predictions through your Kilo account (no separate Inception API key required).
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": minor
---
Make the Agent Manager tool available by default in VS Code.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/cli": patch
---
Keep the extension usable on fresh startup when semantic indexing is enabled globally.
+5
View File
@@ -0,0 +1,5 @@
---
"@kilocode/cli": patch
---
Guide Agent Manager orchestration to recall completed session context only when needed.
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": minor
---
Allow renaming sessions with a consistent inline editor in the active chat header and History, using safe bounded titles.
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": patch
---
Restore readable diff highlighting and collapsed unchanged sections in VS Code themes.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/cli": patch
---
Prevent saved global indexing provider changes from temporarily reverting in active workspaces.
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": patch
---
Keep the VS Code chat position stable when reading earlier output during a streaming response.
+6
View File
@@ -0,0 +1,6 @@
---
"@kilocode/cli": patch
"kilo-code": patch
---
Access semantic indexing without an experimental feature toggle while keeping indexing disabled until enabled globally or for a project.
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": patch
---
Warn when a chat turn stops unexpectedly or ends while tracked to-dos remain unfinished.
+5
View File
@@ -0,0 +1,5 @@
---
"kilo-code": patch
---
Support Italian as a display language in the VS Code extension.
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/kilo-jetbrains": patch
---
Show running badges on active sessions in JetBrains recent and history lists.
@@ -0,0 +1,64 @@
# kilocode_change - new file
name: prepare-jetbrains-release
on:
workflow_dispatch:
inputs:
kind:
description: "Release kind"
required: true
type: choice
options:
- rc
- stable
version:
description: "Version, e.g. 7.3.13-rc.1 or 7.3.13"
required: true
type: string
from_tag:
description: "Optional previous tag for changelog range"
required: false
type: string
permissions:
contents: write
pull-requests: write
concurrency:
group: prepare-jetbrains-release-${{ inputs.version }}
cancel-in-progress: false
jobs:
prepare:
if: github.repository == 'Kilo-Org/kilocode'
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
persist-credentials: false
fetch-depth: 0
- name: Setup Bun
uses: ./.github/actions/setup-bun
- name: Setup Git Committer
id: committer
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: Create release tag and PR
run: |
args=(--kind "$KIND" --version "$VERSION")
if [[ -n "$FROM_TAG" ]]; then
args+=(--from-tag "$FROM_TAG")
fi
bun script/jetbrains-release-pr.ts "${args[@]}"
env:
GH_TOKEN: ${{ steps.committer.outputs.token }}
GH_REPO: ${{ github.repository }}
KIND: ${{ inputs.kind }}
VERSION: ${{ inputs.version }}
FROM_TAG: ${{ inputs.from_tag }}
+72 -52
View File
@@ -2,27 +2,61 @@
name: publish-jetbrains
on:
push:
tags:
- "jetbrains/*"
pull_request:
types:
- closed
branches:
- main
concurrency:
group: publish-jetbrains-${{ github.ref }}
group: publish-jetbrains-pr-${{ github.event.pull_request.number }}
cancel-in-progress: false
permissions:
contents: write
pull-requests: read
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
publish:
if: github.repository == 'Kilo-Org/kilocode'
if: >-
github.repository == 'Kilo-Org/kilocode' &&
github.event.pull_request.merged == true &&
startsWith(github.event.pull_request.head.ref, 'jetbrains/release/') &&
contains(github.event.pull_request.labels.*.name, 'jetbrains-release') &&
github.event.pull_request.head.repo.full_name == github.repository
runs-on: blacksmith-8vcpu-ubuntu-2404
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Checkout merged release PR
uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.merge_commit_sha }}
- name: Setup Bun for validation
uses: ./.github/actions/setup-bun
- name: Validate release PR and tag
id: release
run: bun script/jetbrains-release-validate.ts --pr "$PR_NUMBER"
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
- name: Save reviewed changelog
run: cp packages/kilo-jetbrains/CHANGELOG.md "$RUNNER_TEMP/jetbrains-CHANGELOG.md"
- name: Checkout release tag
uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ steps.release.outputs.tag }}
- name: Restore reviewed changelog
run: cp "$RUNNER_TEMP/jetbrains-CHANGELOG.md" packages/kilo-jetbrains/CHANGELOG.md
- name: Setup Node
uses: actions/setup-node@v4
@@ -46,40 +80,6 @@ jobs:
sudo apt-get update
sudo apt-get install -y patchelf zip
- name: Validate version tag
id: version
run: |
tag="$GITHUB_REF_NAME"
if [[ "$tag" != jetbrains/v* ]]; then
echo "Unsupported tag '$tag'. Expected jetbrains/v<version>." >&2
exit 1
fi
version="${tag#jetbrains/v}"
if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$ ]]; then
{
echo "version=$version"
echo "kind=rc"
echo "marketplace_channel=eap"
echo "cli_channel=rc"
} >> "$GITHUB_OUTPUT"
exit 0
fi
if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
{
echo "version=$version"
echo "kind=stable"
echo "marketplace_channel=default"
echo "cli_channel=latest"
} >> "$GITHUB_OUTPUT"
echo "Stable JetBrains Marketplace publishing is implemented but intentionally disabled; use an rc tag such as jetbrains/v7.0.1-rc.1." >&2
exit 1
fi
echo "Unsupported JetBrains plugin version '$version'. Expected jetbrains/vx.y.z-rc.n or jetbrains/vx.y.z." >&2
exit 1
- name: Validate publishing secrets
run: |
missing=0
@@ -100,22 +100,35 @@ jobs:
working-directory: packages/kilo-jetbrains
run: bun script/build.ts --production --prepare-cli
env:
KILO_VERSION: ${{ steps.version.outputs.version }}
KILO_CHANNEL: ${{ steps.version.outputs.cli_channel }}
KILO_VERSION: ${{ steps.release.outputs.version }}
KILO_CHANNEL: ${{ steps.release.outputs.cli_channel }}
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
- name: Verify plugin
working-directory: packages/kilo-jetbrains
run: ./gradlew verifyPlugin -Pproduction=true -Pkilo.channel="$CHANNEL"
run: ./gradlew verifyPlugin -Pproduction=true -Pkilo.version="$VERSION" -Pkilo.channel="$CHANNEL"
env:
CHANNEL: ${{ steps.version.outputs.marketplace_channel }}
VERSION: ${{ steps.release.outputs.version }}
CHANNEL: ${{ steps.release.outputs.marketplace_channel }}
- name: Render release notes
working-directory: packages/kilo-jetbrains
run: |
if ! grep -Fq "## [$VERSION]" CHANGELOG.md; then
echo "Missing packages/kilo-jetbrains/CHANGELOG.md entry for $VERSION. Review and merge a release PR before publishing." >&2
exit 1
fi
./gradlew getChangelog --project-version "$VERSION" --no-header --no-empty-sections --output-file=build/release-notes.md
env:
VERSION: ${{ steps.release.outputs.version }}
- name: Publish to JetBrains Marketplace
working-directory: packages/kilo-jetbrains
run: ./gradlew publishPlugin -Pproduction=true -Pkilo.channel="$CHANNEL"
run: ./gradlew publishPlugin -Pproduction=true -Pkilo.version="$VERSION" -Pkilo.channel="$CHANNEL"
env:
CHANNEL: ${{ steps.version.outputs.marketplace_channel }}
VERSION: ${{ steps.release.outputs.version }}
CHANNEL: ${{ steps.release.outputs.marketplace_channel }}
JETBRAINS_MARKETPLACE_TOKEN: ${{ secrets.JETBRAINS_MARKETPLACE_TOKEN }}
JETBRAINS_CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }}
JETBRAINS_PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }}
@@ -145,23 +158,30 @@ jobs:
- name: Upload to GitHub Release
run: |
tag="$GITHUB_REF_NAME"
tag="$TAG"
title="JetBrains $VERSION"
notes="JetBrains plugin $VERSION."
flags=(--title "$title" --notes-file "$NOTES")
if [[ "$KIND" == "rc" ]]; then
flags+=(--prerelease)
fi
if gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
gh release upload "$tag" "$ARCHIVE" --clobber --repo "$GITHUB_REPOSITORY"
gh release edit "$tag" "${flags[@]}" --repo "$GITHUB_REPOSITORY"
exit 0
fi
gh release create "$tag" "$ARCHIVE" --title "$title" --notes "$notes" --prerelease --repo "$GITHUB_REPOSITORY"
gh release create "$tag" "$ARCHIVE" "${flags[@]}" --repo "$GITHUB_REPOSITORY"
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.version }}
TAG: ${{ steps.release.outputs.tag }}
VERSION: ${{ steps.release.outputs.version }}
KIND: ${{ steps.release.outputs.kind }}
ARCHIVE: ${{ steps.archive.outputs.path }}
NOTES: packages/kilo-jetbrains/build/release-notes.md
- name: Upload workflow artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: kilo-jetbrains-${{ steps.version.outputs.version }}
name: kilo-jetbrains-${{ steps.release.outputs.version }}
path: packages/kilo-jetbrains/build/distributions/*.zip
if-no-files-found: ignore
+1 -1
View File
@@ -125,7 +125,7 @@ jobs:
./scripts/run_eval.sh \
-m kilo/anthropic/claude-sonnet-4.6 \
-d terminal-bench-sample \
-t "log-summary-date-ranges" \
--include-task-name "log-summary-date-ranges" \
--job-name smoke-test-log-summary \
--timeout-multiplier 2
+37
View File
@@ -0,0 +1,37 @@
# Sample Plan With Todos
## Goal
Create a clear sample plan that breaks work into actionable todos.
## Todos
1. Define the objective
- Clarify the desired outcome.
- Identify the target audience.
- List success criteria.
2. Gather requirements
- Collect relevant inputs.
- Note constraints and assumptions.
- Identify dependencies.
3. Break down the work
- Split the goal into smaller tasks.
- Prioritize tasks by importance.
- Estimate effort for each task.
4. Execute the tasks
- Complete the highest-priority items first.
- Track progress as todos are finished.
- Adjust the plan if new information appears.
5. Review and validate
- Check that all todos are complete.
- Verify the result matches the goal.
- Document any follow-up work.
## Acceptance Criteria
- The plan has a clear goal.
- The plan includes a list of actionable todos.
- The todos are ordered logically.
- The plan includes a way to confirm completion.
+38
View File
@@ -0,0 +1,38 @@
# Sample Plan With Todos
## Goal
Create a simple sample plan that demonstrates how to organize work into clear, actionable todos.
## Implementation Steps
1. Define the objective
- State the desired outcome in one sentence.
- Identify who the plan is for.
- List the criteria that indicate success.
2. Gather requirements
- Capture relevant inputs and context.
- Note constraints, assumptions, and dependencies.
- Identify any missing information that may affect execution.
3. Break down the work
- Split the objective into smaller tasks.
- Order tasks by dependency and priority.
- Keep each todo specific enough to complete independently.
4. Execute the todos
- Work through the highest-priority tasks first.
- Mark todos complete as progress is made.
- Update the plan if new information changes the scope.
5. Review the result
- Confirm every todo has been addressed.
- Verify the result matches the original objective.
- Record any follow-up work separately.
## Acceptance Criteria
- The plan has a clear goal.
- The plan includes actionable todos.
- The todos are ordered logically.
- The plan includes a review step to confirm completion.
@@ -0,0 +1,37 @@
# Sample Plan: Add Todo-Based Workflow
## Goal
Create a small, traceable workflow for implementing a feature with clear todos, validation steps, and completion criteria.
## Scope
- Identify the affected package or feature area.
- Make the smallest correct code change.
- Add or update tests only where they verify behavior.
- Run the smallest relevant checks before completion.
## Todos
- [ ] Inspect the relevant files and existing patterns.
- [ ] Confirm whether the change belongs in Kilo-owned code or shared upstream code.
- [ ] Implement the minimal code change.
- [ ] Add or update targeted tests if behavior changes.
- [ ] Run formatting or linting if the touched package requires it.
- [ ] Run the smallest relevant typecheck or test command.
- [ ] Fix any failures introduced by the change.
- [ ] Summarize changed files and verification results.
## Implementation Notes
- Prefer Kilo-owned directories for Kilo-specific behavior.
- If shared upstream files must be edited, keep the change narrow and add `kilocode_change` markers where required.
- Avoid broad refactors unless they are necessary for the requested behavior.
- Preserve existing style, naming, and package conventions.
## Verification
- Run the targeted test for the changed behavior when available.
- Run the package typecheck if TypeScript code changes.
- Run any repo-specific guard required by touched files, such as annotation or source-link checks.
## Completion Criteria
- The requested behavior is implemented.
- Tests or checks relevant to the change pass, or any inability to run them is documented.
- No unrelated files are modified.
- The final response includes a concise summary and verification status.
+35
View File
@@ -0,0 +1,35 @@
# Sample Plan
## Goal
Create a small example feature or change using a clear implementation workflow and tracked todo list.
## Scope
- Add or update a minimal code path.
- Add focused tests for the changed behavior.
- Run the smallest relevant verification command.
- Summarize the result and any follow-up work.
## Todo
- [ ] Inspect the relevant files and existing patterns.
- [ ] Identify the smallest safe implementation approach.
- [ ] Make the code change.
- [ ] Add or update tests for the behavior.
- [ ] Run targeted tests or typecheck.
- [ ] Fix any failures introduced by the change.
- [ ] Provide a concise final summary with verification results.
## Implementation Notes
- Prefer the smallest correct change over broad refactors.
- Preserve existing style and naming conventions.
- Avoid touching unrelated files.
- If shared upstream-owned files are involved, use the repository’s `kilocode_change` marker guidance.
## Verification
Run the most specific applicable check for the touched area, such as:
- CLI: `bun test ./path/to/test.ts` from `packages/opencode/`
- VS Code extension: `bun run test:unit` from `packages/kilo-vscode/`
- Cross-package changes: `bun run typecheck` from the repo root
## Risks
- The sample scope may need adjustment once the real target files are known.
- Verification commands depend on which package is touched.
+69
View File
@@ -0,0 +1,69 @@
# Plan: Replace Internal SVGLoader Usage
## Context
The JetBrains plugin currently imports `com.intellij.util.SVGLoader` in `packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/ui/SvgIconColorizer.kt` and calls `SVGLoader.load(ByteArrayInputStream(patch()), scale.toFloat())` from `SvgIcon.image(Graphics)`.
Inspection reports this as an internal API usage because `SVGLoader` and its `load(InputStream, float)` method are marked `@ApiStatus.Internal`.
I checked the local IntelliJ source reference via `$INTELLIJ_REPO=/Users/kirillk/products/intellij-community`:
- `platform/util/ui/src/com/intellij/util/SVGLoader.kt`
- `platform/util/ui/src/com/intellij/ui/svg/svg.kt`
- `platform/util/ui/src/com/intellij/ui/svg/jsvg.kt`
- `libraries/jsvg/intellij.libraries.jsvg.iml`
Important findings:
- IntelliJ `SVGLoader.load(stream, scale)` delegates to internal `loadSvg(...)` in `com.intellij.ui.svg`.
- The actual renderer uses `com.github.weisj:jsvg:2.1.0` and renders into a `BufferedImage` with antialiasing, bicubic interpolation, and pure stroke control.
- Copying `SVGLoader.kt` directly would keep references to other internal IntelliJ APIs (`IconLoader`, `ScaleContext`, `ImageUtil`, `SvgAttributePatcher`, `createJSvgDocument`, `renderSvgWithSize`, cache classes, etc.) and would be broader than needed.
## Implementation Plan
1. Add Kilo-owned SVG rendering code under the frontend UI package, for example:
- `packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/ui/SvgLoader.kt`
- Package: `ai.kilocode.client.ui`
- Suggested internal object name: `SvgLoader`
2. Keep the copied implementation minimal and purpose-specific:
- Accept `InputStream` and `scale: Float`.
- Parse the SVG with `com.github.weisj.jsvg.parser.SVGLoader().load(stream)` or the equivalent public jsvg API available in version `2.1.0`.
- Determine image dimensions from the root SVG `width` and `height` already parsed by existing `SvgIconColorizer.size(...)`, or by passing dimensions into the loader if the public jsvg API does not expose reliable intrinsic size.
- Render into `BufferedImage(width * scale, height * scale, BufferedImage.TYPE_INT_ARGB)` using `Graphics2D` rendering hints matching IntelliJ’s `jsvg.kt`:
- `KEY_ANTIALIASING = VALUE_ANTIALIAS_ON`
- `KEY_INTERPOLATION = VALUE_INTERPOLATION_BICUBIC`
- `KEY_STROKE_CONTROL = VALUE_STROKE_PURE`
- Return `Image`/`BufferedImage`.
3. If jsvg does not expose intrinsic size cleanly from public API, adjust the API to avoid duplicating SVG parsing:
- Add `width` and `height` parameters to the Kilo loader.
- In `SvgIcon.image(Graphics)`, call the loader with the already-computed `size.first` and `size.second`.
- This is the likely smallest stable solution because current icons already require explicit `width` and `height` for `SvgIconColorizer.size(...)`.
4. Add the jsvg dependency explicitly to the plugin frontend module instead of relying on the IntelliJ-bundled library:
- In `packages/kilo-jetbrains/gradle/libs.versions.toml`, add `jsvg = "2.1.0"` and `jsvg = { module = "com.github.weisj:jsvg", version.ref = "jsvg" }`.
- In `packages/kilo-jetbrains/frontend/build.gradle.kts`, add `implementation(libs.jsvg)`.
- This follows the package instruction to bundle third-party libraries with the plugin rather than relying on IDE-bundled versions.
5. Update `SvgIconColorizer.kt`:
- Remove `import com.intellij.util.SVGLoader`.
- Replace `SVGLoader.load(ByteArrayInputStream(patch()), scale.toFloat())` with the Kilo-owned loader call.
- Keep the existing color patching, cache key, scale calculation, and size parsing intact.
6. Add a focused frontend unit test:
- New test file: `frontend/src/test/kotlin/ai/kilocode/client/ui/SvgIconColorizerTest.kt` or `SvgLoaderTest.kt`.
- Exercise the actual loader/colorizer with a small SVG resource or inline SVG bytes.
- Assert that rendering returns a non-empty image at scale `1f` and `2f`, and that scaled dimensions are correct.
- If testing the colorizer, paint the icon into a `BufferedImage` and verify at least one expected patched pixel color appears.
7. Run verification from `packages/kilo-jetbrains/`:
- `./gradlew typecheck`
- A targeted frontend test if Gradle supports one cleanly, otherwise `./gradlew test`.
- The requested DevKit internal API inspection is IDE-based; note in final response that the code no longer references `com.intellij.util.SVGLoader`, and typecheck/tests were run.
## Notes And Risks
- The user said “copy SaveLoaer”; I interpret this as “copy `SVGLoader`”. The implementation should copy the relevant rendering behavior, not IntelliJ’s full internal `SVGLoader` object, because the full source depends on multiple other internal APIs and cache infrastructure.
- This change is in `packages/kilo-jetbrains/`, a Kilo-owned package, so `kilocode_change` markers are not needed.
- jsvg package names and constructors should be confirmed during implementation against the downloaded dependency/API available to Gradle. If the API differs from IntelliJ source usage, inspect the source jar or compile error and adapt the minimal wrapper accordingly.
+60
View File
@@ -0,0 +1,60 @@
# Remove JetBrains SVG Runtime Colorization
## Goal
Stop runtime SVG recoloring in the JetBrains plugin and rely on IntelliJ's standard light/dark icon asset resolution. Ensure every SVG asset used by the plugin has a light/dark pair.
## Findings
- Runtime colorization exists only in `frontend/src/main/kotlin/ai/kilocode/client/ui/SvgIconColorizer.kt`.
- The only production caller is `frontend/src/main/kotlin/ai/kilocode/client/session/scroll/ScrollButtonIcon.kt`.
- `ScrollButtonIcon` colorizes two icons at runtime:
- `/icons/scroll-bottom.svg`
- `/icons/scroll-question.svg`
- Both already have dark variants:
- `scroll-bottom_dark.svg`
- `scroll-question_dark.svg`
- Other used frontend icons already have light/dark pairs:
- `send.svg` / `send_dark.svg`
- `stop.svg` / `stop_dark.svg`
- `shield.svg` / `shield_dark.svg`
- `shield-filled.svg` / `shield-filled_dark.svg`
- `compress.svg` / `compress_dark.svg`
- `chevron-down.svg` / `chevron-down_dark.svg`
- `arrow-up.svg` / `arrow-up_dark.svg`
- `arrow-down-to-line.svg` / `arrow-down-to-line_dark.svg`
- `kilo.svg` / `kilo_dark.svg`
- `kilo-content.svg` / `kilo-content_dark.svg`
- `plus.svg` / `plus_dark.svg` exists, though no current direct source reference was found.
- `kilo@20x20.svg` / `kilo@20x20_dark.svg` exists, though no current direct source reference was found.
- `src/main/resources/META-INF/pluginIcon.svg` is present and has no `pluginIcon_dark.svg`. It is not referenced in source/XML, but JetBrains treats this filename conventionally as plugin metadata/marketplace icon, so it should be paired for completeness.
- The SVG assets use literal colors and no `currentColor`, `<style>`, CSS classes, or CSS variables were found in `frontend/src/main/resources/icons/*.svg`.
## Implementation Plan
1. Replace `ScrollButtonIcon` runtime colorization with standard `IconLoader.getIcon(...)` loading.
- Remove imports for `colorizedSvgIcon`, `SessionUiStyle`, `UiStyle`, `JBUI`, and `Color` from `ScrollButtonIcon.kt`.
- Add `IconLoader` import.
- Load `bottom` with `IconLoader.getIcon("/icons/scroll-bottom.svg", ScrollButtonIcon::class.java)`.
- Load `prompt` with `IconLoader.getIcon("/icons/scroll-question.svg", ScrollButtonIcon::class.java)`.
- Keep `create(question: Boolean = false)` unchanged so callers continue to receive the appropriate icon.
- IntelliJ should automatically resolve `_dark.svg` variants when the look and feel is dark.
2. Delete `frontend/src/main/kotlin/ai/kilocode/client/ui/SvgIconColorizer.kt` after confirming no callers remain.
3. Remove now-unused scroll icon source palette constants from `SessionUiStyle.ScrollIcon`.
- Delete the `ScrollIcon` object if no references remain.
- This also removes stale comments about runtime colorization.
4. Add `src/main/resources/META-INF/pluginIcon_dark.svg` as the dark-mode pair for `pluginIcon.svg`.
- Use the same artwork/colors as `pluginIcon.svg` unless there is a desired brand-specific dark variant; the current icon already has a black background and yellow mark, so an identical dark pair is acceptable and satisfies IntelliJ's expected pair convention.
5. Re-scan the JetBrains package after edits.
- Confirm there are no `colorizedSvgIcon` or `SvgIconColorizer` references.
- Confirm every used SVG path has a sibling `_dark.svg` where IntelliJ expects one.
- Confirm no frontend SVG uses `currentColor`, `<style>`, CSS classes, or CSS variables.
6. Run the smallest relevant verification from `packages/kilo-jetbrains/`:
- `bun run typecheck` or `./gradlew typecheck`.
## Files Expected To Change
- `packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/scroll/ScrollButtonIcon.kt`
- `packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/ui/style/SessionUiStyle.kt`
- Delete `packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/ui/SvgIconColorizer.kt`
- Add `packages/kilo-jetbrains/src/main/resources/META-INF/pluginIcon_dark.svg`
## Risks
- The scroll icons will no longer follow arbitrary runtime theme colors; they will use the static light/dark SVG asset colors. This matches the requested behavior.
- If a non-default theme expects palette overrides, static literal SVG colors still follow normal IntelliJ SVG handling better than custom byte-patching, but the exact custom-color behavior may differ from the old colorizer.
+49
View File
@@ -0,0 +1,49 @@
# Fix JetBrains Session Question Scroll
## Goal
When a question-like active view first appears in the JetBrains session UI, do not auto-scroll the transcript if the user is already away from the tail and the scroll-to-bottom button is visible. This applies to permission prompts and question-based views. Existing behavior should remain: if the transcript is already at the bottom, new questions/permissions keep the view at the bottom; explicit question navigation can still jump to the active card.
## Current Findings
- `SessionUi` wires `QuestionView` with:
- `follow = { scroll.following() }`
- `scroll = { scroll.followBottom(it) }`
- `QuestionView.show()` runs on first display and calls:
- `val tail = follow()` before rendering the card
- `scroll(tail)` after rendering
- `SessionScroll.following()` currently returns `component.viewport.view === messages && tail`.
- This can use stale internal follow state instead of the live scrollbar state. The user-visible condition is better represented by `SessionScroll.atBottom()`, which is also what `SessionController.beforeUpdate` uses for normal transcript updates.
- Existing `SessionScrollTest` already covers question and login-required middle-scroll preservation, but it does not cover permission first appearance and likely does not cover a stale-tail/live-not-at-bottom edge.
## Implementation Plan
1. Update question first-show follow sampling to use live bottom state.
- In `SessionUi.buildUi()`, change the `QuestionView` `follow` lambda from `scroll.following()` to `scroll.atBottom()`.
- Alternatively, if a single semantic API is preferred, change `SessionScroll.following()` to return `component.viewport.view === messages && atBottom()` and keep the `SessionUi` call site unchanged. Prefer the smaller, clearer call-site change unless tests show other `following()` behavior should change too.
2. Add permission scroll regression tests in `SessionScrollTest`.
- Add `test permission appearing at bottom keeps scroll at bottom`.
- Add `test permission appearing while user is in middle preserves scroll position`.
- Emit `ChatEventDto.PermissionAsked("ses_test", PermissionRequestDto(...))` using the same DTO style as the existing recovered permission test.
- Assert the scrollbar value is preserved and `jumpButton().isVisible` stays true when initially away from bottom.
3. Strengthen question regression coverage if needed.
- Keep the existing `test question appearing while user is in middle preserves scroll position`.
- If the bug reproduces only when the jump button is visible but `tail` can be stale, add a targeted regression that creates the visible jump state before `QuestionAsked` and asserts first display does not jump.
- Avoid adding production-only test hooks; use existing `setValue`, `setValuePassive`, `drainScroll`, and event helpers.
4. Preserve intentional explicit navigation behavior.
- Do not change `QuestionView.goForward()`, `goBack()`, or `goReview()`, which intentionally call `scroll(true)` and are covered by existing tests that expect navigation to jump to the active question card.
- Do not change prompt growth or normal streaming follow behavior unless a failing test shows the same stale-state issue applies there.
5. Verification.
- Run the targeted JetBrains frontend session scroll tests from `packages/kilo-jetbrains/` using Gradle test filtering for `SessionScrollTest` if supported.
- Run `./gradlew typecheck` from `packages/kilo-jetbrains/` if the targeted tests pass or if Gradle filtering is unavailable.
- If Java 21 is unavailable, first check/report that blocker as instructed by the repo docs.
## Expected Files To Touch
- `packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/SessionUi.kt`
- `packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/session/SessionScrollTest.kt`
## Non-Goals
- No backend or RPC protocol changes.
- No redesign of the session scroll algorithm.
- No changes to explicit question navigation auto-scroll behavior.
+81
View File
@@ -0,0 +1,81 @@
# Plan: JetBrains Question-Style Scroll Button
## Goal
Fix JetBrains session scrolling so that when any inline prompt card appears while the scroll/jump button is already visible, the transcript scroll position is preserved and only the scroll button state changes. This applies to all current `BaseQuestionView`-backed session cards: questions, permissions, and login-required prompts. Preserve existing behavior that question navigation, review/back/next, and bottom-following content changes auto-scroll when they are supposed to.
## Findings
- The relevant files are `packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/SessionUi.kt`, `.../scroll/SessionScroll.kt`, `.../views/question/QuestionView.kt`, `.../views/permission/PermissionView.kt`, `.../views/LoginRequiredView.kt`, `.../views/base/BaseQuestionView.kt`, and `frontend/src/test/kotlin/ai/kilocode/client/session/SessionScrollTest.kt`.
- `QuestionView`, `PermissionView`, and `LoginRequiredView` do not inherit from `BaseQuestionView`; they compose it as the shared card shell. Scroll behavior should stay outside `BaseQuestionView` because it is a pure visual component with no session scroll context.
- The current uncommitted `SessionUi.kt` attempt changes `QuestionView` from `follow = { scroll.following() }` to `follow = { scroll.atBottom() }`.
- That fixes initial question appearance when the user is visibly away from bottom, but it is too broad because `QuestionView.follow()` is also used after custom editor growth, selection refresh, reply/reject, and other internal updates.
- `QuestionView` already intentionally calls `scroll(true)` in `goBack`, `goForward`, and `goReview`; those forced calls are the behavior that preserves auto-scroll when switching question pages.
- `PermissionView.show()` and `LoginRequiredView.show()` do not call scroll directly. They rely on `SessionController.beforeUpdate` / `afterUpdate`, which samples `scroll.atBottom()` before the state change and calls `scroll.followBottom(follow)` afterward. With the stale-tail fix, this path can preserve scroll for all non-question inline prompt cards.
- The uncommitted `SessionScroll.followBottom(false)` change that clears stale `tail` when the transcript is visible and not actually at bottom is directionally correct. It prevents later `following()` calls from resurrecting auto-follow after a non-follow decision.
- The current scroll button pending state is named `question` / `setQuestionPending` and is only enabled for non-plan `AwaitingQuestion`. To cover all `BaseQuestionView`-backed prompts, this should become a generic pending-input/attention state and include `AwaitingPermission` and `LoginRequired`.
- Existing behavior intentionally keeps plan follow-up questions using the normal scroll icon (`test plan followup question keeps scroll icon`), so preserve that exception unless product intent changes separately.
- The uncommitted `build.gradle.kts` and `script/build-sign-check.sh` changes are unrelated to this bug and should not be touched as part of this fix.
## Implementation Plan
1. In `QuestionView.kt`, split the scroll-follow decision into two callbacks.
- Keep the existing `follow` callback for question-internal updates.
- Add a second callback for initial question appearance, with a default that delegates to `follow` so existing tests/call sites remain compatible.
- In `show(q)`, sample the new initial callback before making the question visible or rebuilding the card, then call `scroll(tail)` after `syncPage()` as today.
- Leave `scroll(true)` in `goBack`, `goForward`, and `goReview` unchanged.
- Leave existing `scroll(follow())` calls in custom editor changes, option selection, reply, and reject paths unchanged.
2. In `SessionUi.kt`, wire the callbacks with distinct meanings.
- Use `follow = { scroll.following() }` for question-internal updates.
- Use the new initial callback as `{ scroll.atBottom() }` for initial question appearance.
- Keep `scroll = { scroll.followBottom(it) }`.
3. Generalize the scroll button pending state for all inline prompt cards.
- Rename `SessionScroll.setQuestionPending` and the backing `question` boolean to a generic name such as `setInputPending` / `pending` or `setAttentionPending` / `pending`.
- Rename `questionPending(state)` in `SessionUi.kt` to match the broader meaning.
- Return `true` for non-plan `SessionState.AwaitingQuestion`, `SessionState.AwaitingPermission`, and `SessionState.LoginRequired`.
- Keep returning `false` for plan follow-up questions so the existing plan-specific icon behavior is preserved.
- Reuse the existing question-style icon and tooltip for now, unless a separate product decision asks for a different permission/login-specific icon or string.
4. In `SessionScroll.kt`, keep the stale-tail reconciliation in `followBottom(false)`.
- When `follow` is false, increment `seq`, and if the active view is the transcript and `!atBottom()`, set `tail = false` before `updateJump()`.
- Do not change `following()` to use `atBottom()`, because `tail` is needed to preserve bottom-follow behavior across deferred layout/height growth.
5. Do not add scroll callbacks to `PermissionView`, `LoginRequiredView`, or `BaseQuestionView` unless tests prove the controller-level path is insufficient.
- `PermissionView` and `LoginRequiredView` should remain retained visual views that show/hide themselves and refresh their parent.
- `BaseQuestionView` should stay a scroll-unaware card shell.
- The shared behavior for those cards should come from the controller-level state-change follow decision plus the generalized pending-button state.
6. In `SessionScrollTest.kt`, update tests around question-style prompt appearance and preserved behavior.
- Keep or add an assertion that the jump button is visible before emitting a question in the middle-scroll test.
- Keep a regression for stale `tail` plus visible jump button if no public-only scenario can reproduce the failed state; keep the reflective helper local to this test file and avoid adding production test hooks.
- Keep existing behavior tests for question navigation from the middle, forced navigation resuming follow, custom question answer growth at bottom, custom question answer growth in the middle, and option selection not resuming follow.
- Add or keep permission bottom/middle tests to prove `AwaitingPermission` preserves scroll when away from bottom and follows when at bottom.
- Add or keep login-required bottom/middle tests to prove `LoginRequired` preserves scroll when away from bottom and follows when at bottom.
- Add explicit button-state assertions for permission and login-required while away from bottom: the button remains visible, switches to the pending-input icon/tooltip, and clicking it still scrolls to bottom.
- Keep the plan follow-up test proving plan prompts do not switch to the pending-input icon.
7. Add a patch changeset for the JetBrains plugin unless an existing branch changeset is intentionally covering this exact fix.
- Suggested release note: `Preserve JetBrains chat scroll position when inline prompts appear while the scroll button is visible.`
## Verification
- From `packages/kilo-jetbrains/`, run `./gradlew test --tests "ai.kilocode.client.session.SessionScrollTest"`.
- From `packages/kilo-jetbrains/`, run `./gradlew typecheck`.
- Do not run root `bun test`.
## Expected Outcome
- If the transcript is away from bottom and the jump button is visible, a newly appearing question, permission prompt, or login-required prompt changes the button state without moving `bar.value`.
- If the transcript is at bottom, a newly appearing question, permission prompt, or login-required prompt follows to the new bottom.
- Clicking the visible pending-input scroll button still jumps to the bottom for every inline prompt card.
- Question carousel next/back/review still jumps to the bottom even if the transcript was previously in the middle.
- Custom question editor growth still follows when the transcript was following and preserves position when it was not.
+2
View File
@@ -51,6 +51,8 @@ All products are clients of the **CLI** (`packages/opencode/`), which contains t
**Agent Manager** refers to a feature inside `packages/kilo-vscode/` (extension code in `src/agent-manager/`, webview in `webview-ui/agent-manager/`). It is not a standalone product. See the extension's `AGENTS.md` for details.
In each VS Code extension host, one `KiloConnectionService` is created for the sidebar, every Kilo editor tab, and Agent Manager; it lazily starts and reuses one current `kilo serve` backend at a time. Agent Manager worktree sessions pass a directory context to this shared backend rather than starting one per worktree. State captured by the active service layer, such as Snapshot `trackState`, is shared across those requests; only directory-keyed `InstanceState` data is isolated.
Extension-specific settings should live in the Kilo extension settings, not default VS Code settings, unless they are intentionally VS Code-wide.
## Package Instructions
+15 -15
View File
@@ -33,7 +33,7 @@
},
"packages/core": {
"name": "@opencode-ai/core",
"version": "7.3.12",
"version": "7.3.16",
"bin": {
"opencode": "./bin/opencode",
},
@@ -68,7 +68,7 @@
},
"packages/kilo-docs": {
"name": "@kilocode/kilo-docs",
"version": "7.3.12",
"version": "7.3.16",
"dependencies": {
"@docsearch/css": "^4",
"@docsearch/js": "^4",
@@ -98,7 +98,7 @@
},
"packages/kilo-gateway": {
"name": "@kilocode/kilo-gateway",
"version": "7.3.12",
"version": "7.3.16",
"dependencies": {
"@ai-sdk/alibaba": "1.0.17",
"@ai-sdk/anthropic": "3.0.71",
@@ -134,7 +134,7 @@
},
"packages/kilo-i18n": {
"name": "@kilocode/kilo-i18n",
"version": "7.3.12",
"version": "7.3.16",
"devDependencies": {
"@tsconfig/node22": "catalog:",
"@types/bun": "catalog:",
@@ -144,7 +144,7 @@
},
"packages/kilo-indexing": {
"name": "@kilocode/kilo-indexing",
"version": "7.3.12",
"version": "7.3.16",
"dependencies": {
"@aws-sdk/client-bedrock-runtime": "3.1005.0",
"@aws-sdk/credential-provider-ini": "3.972.31",
@@ -176,11 +176,11 @@
},
"packages/kilo-jetbrains": {
"name": "@kilocode/kilo-jetbrains",
"version": "7.3.12",
"version": "7.3.16",
},
"packages/kilo-telemetry": {
"name": "@kilocode/kilo-telemetry",
"version": "7.3.12",
"version": "7.3.16",
"dependencies": {
"@kilocode/kilo-gateway": "workspace:*",
"posthog-node": "4.4.0",
@@ -194,7 +194,7 @@
},
"packages/kilo-ui": {
"name": "@kilocode/kilo-ui",
"version": "7.3.12",
"version": "7.3.16",
"dependencies": {
"@kilocode/sdk": "workspace:*",
"@kobalte/core": "0.13.11",
@@ -231,7 +231,7 @@
},
"packages/kilo-vscode": {
"name": "kilo-code",
"version": "7.3.12",
"version": "7.3.16",
"dependencies": {
"@anthropic-ai/sdk": "^0.39.0",
"@kilocode/kilo-gateway": "workspace:*",
@@ -294,7 +294,7 @@
},
"packages/opencode": {
"name": "@kilocode/cli",
"version": "7.3.12",
"version": "7.3.16",
"bin": {
"kilo": "./bin/kilo",
"kilocode": "./bin/kilo",
@@ -452,7 +452,7 @@
},
"packages/plugin": {
"name": "@kilocode/plugin",
"version": "7.3.12",
"version": "7.3.16",
"dependencies": {
"@kilocode/sdk": "workspace:*",
"effect": "catalog:",
@@ -477,7 +477,7 @@
},
"packages/script": {
"name": "@opencode-ai/script",
"version": "7.3.12",
"version": "7.3.16",
"dependencies": {
"semver": "^7.6.3",
},
@@ -488,7 +488,7 @@
},
"packages/sdk/js": {
"name": "@kilocode/sdk",
"version": "7.3.12",
"version": "7.3.16",
"dependencies": {
"cross-spawn": "catalog:",
},
@@ -503,7 +503,7 @@
},
"packages/storybook": {
"name": "@opencode-ai/storybook",
"version": "7.3.12",
"version": "7.3.16",
"devDependencies": {
"@opencode-ai/ui": "workspace:*",
"@solidjs/meta": "catalog:",
@@ -526,7 +526,7 @@
},
"packages/ui": {
"name": "@opencode-ai/ui",
"version": "7.3.12",
"version": "7.3.16",
"dependencies": {
"@kilocode/sdk": "workspace:*",
"@kobalte/core": "catalog:",
+1 -1
View File
@@ -149,6 +149,6 @@
"@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"
},
"version": "7.3.12",
"version": "7.3.16",
"peerDependencies": {}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "7.3.12",
"version": "7.3.16",
"name": "@opencode-ai/core",
"type": "module",
"license": "MIT",
+6 -6
View File
@@ -1,7 +1,7 @@
id = "kilo"
name = "Kilo"
description = "The open source coding agent."
version = "7.3.12"
version = "7.3.16"
schema_version = 1
authors = ["Anomaly"]
repository = "https://github.com/Kilo-Org/kilocode"
@@ -11,26 +11,26 @@ name = "Kilo"
icon = "./icons/opencode.svg"
[agent_servers.opencode.targets.darwin-aarch64]
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.12/opencode-darwin-arm64.zip"
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.16/opencode-darwin-arm64.zip"
cmd = "./opencode"
args = ["acp"]
[agent_servers.opencode.targets.darwin-x86_64]
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.12/opencode-darwin-x64.zip"
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.16/opencode-darwin-x64.zip"
cmd = "./opencode"
args = ["acp"]
[agent_servers.opencode.targets.linux-aarch64]
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.12/opencode-linux-arm64.tar.gz"
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.16/opencode-linux-arm64.tar.gz"
cmd = "./opencode"
args = ["acp"]
[agent_servers.opencode.targets.linux-x86_64]
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.12/opencode-linux-x64.tar.gz"
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.16/opencode-linux-x64.tar.gz"
cmd = "./opencode"
args = ["acp"]
[agent_servers.opencode.targets.windows-x86_64]
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.12/opencode-windows-x64.zip"
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.16/opencode-windows-x64.zip"
cmd = "./opencode.exe"
args = ["acp"]
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@kilocode/kilo-docs",
"version": "7.3.12",
"version": "7.3.16",
"private": true,
"scripts": {
"dev": "next dev --webpack --port 3002",
@@ -41,6 +41,29 @@ Key features include:
Settings apply across extension surfaces, including the sidebar and Agent Manager. The standalone CLI uses the same `~/.config/kilo/kilo.jsonc` (global) and `./kilo.jsonc` (project) files when used directly.
## Proxy and Certificate Troubleshooting
Kilo Code for VS Code starts its embedded runtime from the extension and applies the relevant VS Code network settings to that runtime. On managed networks, configure proxy and certificate trust in VS Code settings rather than in a separate CLI install.
Use these settings when your organization requires a proxy or inspects HTTPS traffic:
- Set `http.proxy` to your organization proxy URL.
- Use `http.noProxy` for hosts that should bypass the proxy.
- Leave `http.proxySupport` enabled unless you intentionally want VS Code and Kilo Code to ignore proxy settings.
- Install your organization's root certificate authority in the operating system trust store when HTTPS inspection is in use.
- If the operating system trust store is not enough, set `kilo-code.new.extraCaCerts` to the absolute path of a PEM file that contains the additional certificate authority certificates.
- Keep `http.proxyStrictSSL` enabled whenever possible. Disable it only as a temporary troubleshooting step or when your administrator explicitly requires it, because it disables TLS certificate verification for this path.
Example user or workspace settings:
```json
{
"http.proxy": "http://proxy.example.com:8080",
"http.noProxy": ["localhost", "127.0.0.1", ".example.internal"],
"kilo-code.new.extraCaCerts": "/absolute/path/to/corporate-ca.pem"
}
```
{% /tab %}
{% tab label="VSCode (Legacy)" %}
@@ -57,21 +57,25 @@ my-project/
The filename must be uppercase (`AGENTS.md`), not lowercase (`agents.md`). This ensures consistency across different operating systems and tools.
{% /callout %}
### Subdirectory AGENTS.md Files
### Per-Directory AGENTS.md Files
You can also place AGENTS.md files in subdirectories to provide context-specific instructions:
You can place AGENTS.md files in subdirectories to provide context-specific instructions when the agent accesses files in those locations:
```
my-project/
├── AGENTS.md # Root-level instructions
├── src/
│ └── backend/
│ └── AGENTS.md # Backend-specific instructions
│ └── AGENTS.md # Backend-specific instructions (loaded when reading backend files)
└── docs/
└── AGENTS.md # Documentation-specific instructions
└── AGENTS.md # Documentation-specific instructions (loaded when reading docs files)
```
When working in a subdirectory, Kilo Code will load both the root AGENTS.md and any subdirectory AGENTS.md files, with subdirectory files taking precedence for conflicting instructions.
{% callout type="info" %}
Per-directory AGENTS.md files are **dynamically loaded** when the agent reads files in that directory - they are not pre-loaded at session start. When the agent reads a file in `src/backend/`, the corresponding `AGENTS.md` is discovered and its contents are injected into the conversation as `<system-reminder>` tags.
This is useful for providing context-specific guidance for different parts of a monorepo or project.
{% /callout %}
## File Protection
@@ -7,8 +7,8 @@ description: "Index your codebase for improved AI understanding"
Codebase Indexing enables semantic code search across your entire project using AI embeddings. Instead of searching for exact text matches, it understands the _meaning_ of your queries, helping Kilo Code find relevant code even when you don't know specific function names or file locations.
{% callout type="warning" title="Experimental" %}
Codebase Indexing is currently **experimental** in the CLI and the new VS Code extension. You must explicitly opt in before the feature becomes available — see the **Setup** section below. Behavior, configuration, and defaults may change in future releases.
{% callout type="info" title="Opt-in indexing" %}
Codebase Indexing is disabled by default. It starts only after you enable indexing globally or for an individual project. Configuring an embedding provider without enabling one of those toggles does not start indexing.
{% /callout %}
## What It Does
@@ -34,28 +34,10 @@ This enables natural language queries like "user authentication logic" or "datab
{% tabs %}
{% tab label="VSCode" %}
### 1. Enable the experimental flag
Codebase Indexing is gated behind an experimental flag. Until the flag is on, the Indexing UI is hidden and `semantic_search` is unavailable.
1. Open Kilo Code **Settings** → **Experimental**.
2. Toggle **Semantic Indexing** on.
3. The **Indexing** tab will appear in Settings and the indexing status indicator will appear at the bottom of the prompt input panel.
Alternatively, set `experimental.semantic_indexing` to `true` in your `kilo.jsonc`:
```json
{
"experimental": {
"semantic_indexing": true
}
}
```
### 2. Configure indexing
### Configure indexing
1. Open Kilo Code **Settings** → **Indexing**, or click the indexing indicator at the bottom of the prompt input panel.
2. Toggle **Enable Indexing** on.
2. Turn on **Global Enable** to index every workspace, or turn on **Enable for This Project** to index only the current workspace. Both toggles are off until explicitly enabled.
3. Pick an **Embedding Provider** and fill in its required fields.
4. Pick a **Vector Store** (`Qdrant` or `LanceDB`) and configure it.
5. Optionally adjust **Tuning Parameters** (search score, batch size, retries, max results).
@@ -106,23 +88,9 @@ The prompt input panel shows a compact indexing status indicator that reflects t
{% /tab %}
{% tab label="CLI" %}
### 1. Enable the experimental flag
### Configure indexing
Codebase Indexing is gated behind an experimental flag. Until the flag is on, the `/indexing` command is hidden and `semantic_search` is unavailable.
Set the flag in your `kilo.jsonc`:
```json
{
"experimental": {
"semantic_indexing": true
}
}
```
Restart the CLI for the change to take effect. The `/indexing` command (and aliases `/index`, `/embedding`) will appear in the command palette once the flag is active.
### 2. Configure indexing
The `/indexing` command (and aliases `/index`, `/embedding`) is available when the indexing plugin is installed. Indexing remains disabled until it is enabled globally or for the current project.
Open a Kilo TUI session and run:
@@ -198,7 +166,7 @@ When indexing is enabled, the CLI shows an indexing status badge at the bottom o
{% /tab %}
{% tab label="VSCode (Legacy)" %}
The legacy extension does not require an experimental flag.
The legacy extension uses its own Codebase Indexing settings panel.
### Open Codebase Indexing Settings
@@ -50,7 +50,7 @@ Project-level instructions are loaded before global instructions and apply to ev
You can place `AGENTS.md` files in any subdirectory of your project. These are loaded dynamically — when the agent's Read tool accesses a file in that directory, the corresponding `AGENTS.md` is discovered and its contents are injected into the conversation as `<system-reminder>` tags.
This is useful for providing context-specific guidance for different parts of a monorepo or project.
This is useful for providing context-specific guidance for different parts of a monorepo or project. The subdirectory file does not need to duplicate root-level instructions; it supplements them for tasks within that directory.
## Additional Instruction Sources
@@ -127,7 +127,7 @@ Project-level instructions are loaded before global instructions and apply to ev
You can place `AGENTS.md` files in any subdirectory of your project. These are loaded dynamically — when the agent's Read tool accesses a file in that directory, the corresponding `AGENTS.md` is discovered and its contents are injected into the conversation as `<system-reminder>` tags.
This is useful for providing context-specific guidance for different parts of a monorepo or project.
This is useful for providing context-specific guidance for different parts of a monorepo or project. The subdirectory file does not need to duplicate root-level instructions; it supplements them for tasks within that directory.
## Additional Instruction Sources
@@ -1,13 +1,21 @@
---
title: "Chat Platforms"
description: "Connect your KiloClaw agent to Telegram, Discord, and Slack"
description: "Use Kilo Chat or connect your KiloClaw agent to Telegram, Discord, and Slack"
---
# Chat Platforms
KiloClaw supports connecting your AI agent to messaging platforms so it can receive instructions and send responses directly in your chat apps. You can configure channels from the **Settings** tab on your [KiloClaw dashboard](/docs/kiloclaw/dashboard#channels), or from the OpenClaw Control UI after accessing your instance.
KiloClaw includes Kilo Chat as its first-party channel and also supports connecting your AI agent to messaging platforms so it can receive instructions and send responses directly in your chat apps. You can configure third-party channels from the **Settings** tab on your [KiloClaw dashboard](/docs/kiloclaw/dashboard#channels), or from the OpenClaw Control UI after accessing your instance.
The general steps to connect any chat platform are:
## Kilo Chat
Kilo Chat is the zero-setup, first-party channel for KiloClaw. It is enabled by default, does not require a per-sandbox channel token, and is available from the Kilo web and mobile apps as well as supported Kilo Code editor and TUI surfaces.
Use Kilo Chat when you want to talk to your Claw without configuring a separate bot or app in another messaging platform. For external team chat tools, use one of the third-party channels below.
## Third-Party Platforms
The general steps to connect a third-party chat platform are:
1. Configure the channel token in Settings
2. Redeploy the KiloClaw instance
@@ -16,6 +24,7 @@ The general steps to connect any chat platform are:
## Supported Platforms
- [**Kilo Chat**](https://app.kilo.ai) — Use the built-in first-party channel with no token setup.
- [**Telegram**](/docs/kiloclaw/chat-platforms/telegram) — Connect via a BotFather bot token.
- [**Discord**](/docs/kiloclaw/chat-platforms/discord) — Connect via a Discord Developer Portal bot token.
- [**Slack**](/docs/kiloclaw/chat-platforms/slack) — Connect via a Slack app manifest with app-level and bot tokens.
@@ -9,6 +9,10 @@ This page covers everything you can do from the KiloClaw dashboard. For getting
{% image src="/docs/img/kiloclaw/dashboard.png" alt="Connect account screen" width="800" caption="The KiloClaw Dashboard" /%}
## Personal and Organization Instances
The dashboard controls are the same for personal and organization-scoped KiloClaw instances. Organization instances are selected from the organization context and are listed separately from your **Personal** instance. Availability depends on your organization membership and KiloClaw entitlement.
## Instance Status
Your instance is always in one of these states as indicated by the status label at the top of your dashboard:
@@ -88,7 +92,7 @@ For access to the full catalog of 335+ models, use the `/model` and `/models` co
### Channels
You can connect Telegram, Discord, and Slack by entering bot tokens in the Settings tab. See [Connecting Chat Platforms](/docs/kiloclaw/chat-platforms) for setup instructions.
Kilo Chat is always available as KiloClaw's first-party channel and does not need a token. You can also connect Telegram, Discord, and Slack by entering bot tokens in the Settings tab. See [Connecting Chat Platforms](/docs/kiloclaw/chat-platforms) for setup instructions.
{% callout type="info" %}
After saving channel tokens, you need to **Redeploy** or **Restart OpenClaw** for the changes to take effect.
@@ -154,7 +158,7 @@ Do not use the **Update** feature in the OpenClaw Control UI to update KiloClaw.
When your instance is running, the dashboard shows any pending pairing requests. These appear when:
- Someone messages your bot on Telegram, Discord, or Slack for the first time
- Someone messages your bot on a third-party chat channel for the first time
- A new browser or device connects to the Control UI
You need to **approve** each request before the user or device can interact with your agent. See [Pairing Requests](/docs/kiloclaw/chat-platforms#pairing-requests) for details.
@@ -21,7 +21,7 @@ We recommend creating **separate accounts** for your KiloClaw rather than connec
### Chat platform options
- **[Kilo Chat](https://app.kilo.ai)** — available in the web app and coming soon to iOS and Android; requires zero configuration
- **[Kilo Chat](https://app.kilo.ai)** — available in the Kilo web and mobile apps, plus supported Kilo Code editor and TUI surfaces; requires zero configuration
- **[Telegram](/docs/kiloclaw/chat-platforms/telegram)** — easy to set up, private by default
- **[Discord](/docs/kiloclaw/chat-platforms/discord)** — moderate setup
- **[Slack](/docs/kiloclaw/chat-platforms/slack)** — most involved setup
@@ -66,7 +66,7 @@ A Workspace-managed account benefits from your organization's admin policies, ma
## Set up a messaging platform
Your Claw needs a way to communicate with you. **[Kilo Chat](https://app.kilo.ai)** requires no setup — just open the web app. For other platforms, follow the relevant guide:
Your Claw needs a way to communicate with you. **[Kilo Chat](https://app.kilo.ai)** requires no setup — open the Kilo web or mobile app, or use a supported Kilo Code editor or TUI surface. For other platforms, follow the relevant guide:
- [Telegram](/docs/kiloclaw/chat-platforms/telegram) — about 2 minutes
- [Discord](/docs/kiloclaw/chat-platforms/discord) — about 10 minutes
@@ -160,4 +160,4 @@ Or ask your Claw to build a custom skill from scratch — it has a built-in skil
**Model picker:** Balanced is a good starting point. Frontier is more capable but significantly more expensive.
You can also use your KiloPass credits — find this under **Profile** in the dashboard.
You can also use your [Kilo Pass](https://kilo.ai/pricing/kilo-pass) credits — find this under **Profile** in the dashboard.
+17 -7
View File
@@ -1,19 +1,20 @@
---
title: "KiloClaw"
description: "One-click deployment of your personal AI agent with OpenClaw"
description: "One-click deployment of your Kilo-hosted AI agent with OpenClaw"
---
# KiloClaw 🦀
KiloClaw is Kilo's hosted [OpenClaw](https://openclaw.ai) service — a one-click deployment that gives you a personal AI agent without the complexity of self-hosting. OpenClaw is a 24/7, open source AI agent that connects to chat platforms like Telegram, Discord, and Slack so it can take real actions automatically, not just chat.
KiloClaw is Kilo's hosted [OpenClaw](https://openclaw.ai) service — a one-click deployment that gives you a personal or organization-scoped AI agent without the complexity of self-hosting. OpenClaw is a 24/7, open source AI agent that connects to Kilo Chat and optional chat platforms like Telegram, Discord, and Slack so it can take real actions automatically, not just chat.
KiloClaw is powered by KiloCode. The API key is platform-managed, so you never need to bring your own.
KiloClaw is powered by Kilo Code. The API key is platform-managed, so you never need to bring your own.
## Why KiloClaw?
- **No infrastructure setup** — Skip Docker, servers, and configuration files
- **Instant provisioning** — Your agent is ready in seconds
- **Powered by KiloCode** — API key is automatically generated and refreshed
- **Kilo Chat included** — Use the first-party Kilo Chat channel without token setup
- **Powered by Kilo Code** — API key is automatically generated and refreshed
- **Uses existing credits** — Runs on your Kilo Gateway balance
- **Multiple free models** — Choose from several models at no additional cost
- **Web UI included** — Access your agent's web interface directly from the dashboard
@@ -23,9 +24,10 @@ KiloClaw is powered by KiloCode. The API key is platform-managed, so you never n
- **Kilo account** — Sign up at [kilo.ai](https://kilo.ai) if you haven't already
- **Model access** — KiloClaw uses **Kilo Gateway by default**, which provides access to **500+ AI models** through a single integration.
You can also run KiloClaw using:
Depending on your setup, you can also use:
- **Your own provider API keys (BYOK)** such as Anthropic, OpenAI, Google, or other supported providers.
- **Organization access** if your organization has KiloClaw enabled and you want the instance scoped to that organization.
## Creating an Instance
@@ -39,11 +41,19 @@ You can also run KiloClaw using:
{% image src="/docs/img/kiloclaw/create-instance.png" alt="Create instance modal with model selection" width="600" caption="Model selection during instance creation" /%}
5. Optionally configure chat channels (Telegram, Discord, Slack) — you can also do this later from [Settings](/docs/kiloclaw/dashboard#settings)
5. Optionally configure third-party chat channels (Telegram, Discord, Slack) — Kilo Chat is already available, and you can add other channels later from [Settings](/docs/kiloclaw/dashboard#settings)
6. Click **Create & Provision**
Your instance will be provisioned in seconds. Each instance runs on a dedicated machine with 2 shared vCPUs, 3 GB RAM, and a 10 GB persistent SSD. Once created in a region, your instance always runs there.
## Organization KiloClaw
If your organization has KiloClaw enabled, you can use an organization-scoped instance for work that belongs to that organization. The core KiloClaw experience is the same as a personal instance, with these differences:
- Organization instances are separated from your **Personal** instance in KiloClaw lists.
- Provisioning depends on your organization membership and the organization's KiloClaw entitlement.
- Instance ownership and routing are scoped to the organization, so use organization-approved accounts and credentials for connected services.
## Managing Your Instance
The KiloClaw dashboard gives you full control over your instance.
@@ -75,7 +85,7 @@ When you initialize a new channel for the first time, or a new device connects t
## Using your OpenClaw Agent
OpenClaw lets you customize your own AI assistant that can actually take action — check your email, manage your calendar, control smart devices, browse the web, and message you on Telegram or Discord when something needs attention. It's like having a personal assistant that runs 24/7, with the skills and access you choose to give it.
OpenClaw lets you customize your own AI assistant that can actually take action — check your email, manage your calendar, control smart devices, browse the web, and message you through Kilo Chat or connected third-party channels when something needs attention. It's like having a personal assistant that runs 24/7, with the skills and access you choose to give it.
### Browser Tool
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e3050c782d797be7dad951b76199df2c87195415e699d3e8481bbf40ad0dfccf
size 10073
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e6d0ccfb86ad9a6eaab64e1afe455a96cd4c1443f12fbd47698a4730724712b6
size 931
oid sha256:5b8208c98b0ab3551094af455bf2c7a947c2973f0adb6fe6fa99f16da970454a
size 1184
+2
View File
@@ -35,6 +35,8 @@
<!-- packages/opencode/src/plugin/xai.ts -->
- <https://auth.x.ai/oauth2/token>
<!-- packages/opencode/src/plugin/xai.ts -->
- <https://blog.kilo.ai/p/kilo-gateway-now-supports-byok-20-providers>
<!-- packages/kilo-vscode/webview-ui/src/components/settings/ProviderConnectDialog.tsx -->
- <https://blog.kilo.ai/p/new-kilo-for-vs-code-is-live>
<!-- packages/kilo-vscode/webview-ui/src/components/migration/MigrationWizard.tsx -->
- <https://chatgpt.com/explore/plus>
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@kilocode/kilo-gateway",
"version": "7.3.12",
"version": "7.3.16",
"type": "module",
"license": "MIT",
"description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@kilocode/kilo-i18n",
"version": "7.3.12",
"version": "7.3.16",
"type": "module",
"license": "MIT",
"description": "Kilo-specific i18n translations and overrides",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "قم بزيارة ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " للحصول على مفتاح API الخاص بك.",
"provider.connect.kiloGateway.byok.prefix": "للحصول على المزيد من إحصائيات الاستخدام، استخدم ",
"provider.connect.kiloGateway.byok.link": "BYOK عبر Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "موصى به",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Visite ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " para obter sua chave de API.",
"provider.connect.kiloGateway.byok.prefix": "Para mais estatísticas de uso, utilize ",
"provider.connect.kiloGateway.byok.link": "BYOK via Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Recomendados",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Posjetite ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " da preuzmete svoj API ključ.",
"provider.connect.kiloGateway.byok.prefix": "Za više statistika korištenja, koristite ",
"provider.connect.kiloGateway.byok.link": "BYOK putem Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Preporučeno",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Besøg ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " for at hente din API-nøgle.",
"provider.connect.kiloGateway.byok.prefix": "For flere brugsstatistikker, brug ",
"provider.connect.kiloGateway.byok.link": "BYOK via Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Anbefalede",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Besuchen Sie ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": ", um Ihren API-Schlüssel zu erhalten.",
"provider.connect.kiloGateway.byok.prefix": "Für weitere Nutzungsstatistiken ",
"provider.connect.kiloGateway.byok.link": "BYOK via Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": " nutzen.",
// Provider dialog translations
"dialog.provider.group.recommended": "Empfohlen",
+3
View File
@@ -9,6 +9,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Visit ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " to collect your API key.",
"provider.connect.kiloGateway.byok.prefix": "For more usage stats, ",
"provider.connect.kiloGateway.byok.link": "BYOK via Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Recommended",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Visita ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " para obtener tu clave API.",
"provider.connect.kiloGateway.byok.prefix": "Para más estadísticas de uso, utiliza ",
"provider.connect.kiloGateway.byok.link": "BYOK a través de Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Recomendados",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Visitez ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " pour obtenir votre clé API.",
"provider.connect.kiloGateway.byok.prefix": "Pour plus de statistiques d'utilisation, utilisez ",
"provider.connect.kiloGateway.byok.link": "BYOK via Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Recommandés",
+107
View File
@@ -0,0 +1,107 @@
// Kilo-specific translations and overrides
// Keys here will override any matching keys from upstream translations
export const dict = {
// Kilo Gateway provider translations
"provider.connect.kiloGateway.line1":
"Kilo Gateway ti offre una selezione curata di modelli affidabili e ottimizzati per agenti di coding.",
"provider.connect.kiloGateway.line2":
"Con una sola API key puoi accedere a modelli come Claude, GPT, Gemini, GLM e altri.",
"provider.connect.kiloGateway.visit.prefix": "Visita ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " per ottenere la tua API key.",
"provider.connect.kiloGateway.byok.prefix": "Per ulteriori statistiche sull'utilizzo, utilizza ",
"provider.connect.kiloGateway.byok.link": "BYOK tramite Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Consigliati",
"dialog.provider.kilo.note": "Accesso a oltre 500 modelli AI",
// Reasoning block label
"ui.permission.run": "Esegui",
"ui.reasoning.label": "Ragionamento",
// Marketplace
"marketplace.tab.skills": "Skill",
"marketplace.tab.mcpServers": "Server MCP",
"marketplace.tab.agents": "Agenti",
"marketplace.category.all": "Tutti",
"marketplace.placeholder": "Da implementare",
"marketplace.card.installed": "Installato",
"marketplace.card.install": "Installa",
"marketplace.card.remove": "Rimuovi",
"marketplace.card.removeScope": "Rimuovi ({{scope}})",
"marketplace.card.showMore": "Mostra altro",
"marketplace.card.showLess": "Mostra meno",
"marketplace.install.title": "Installa {{name}}",
"marketplace.install.scope": "Ambito",
"marketplace.install.scope.project": "Progetto",
"marketplace.install.scope.global": "Globale",
"marketplace.install.prerequisites": "Prerequisiti",
"marketplace.install.installing": "Installazione...",
"marketplace.install.cancel": "Annulla",
"marketplace.install.success": "Installato correttamente!",
"marketplace.install.failed": "Installazione non riuscita",
"marketplace.install.done": "Fatto",
"marketplace.install.close": "Chiudi",
"marketplace.remove.title": "Rimuovere {{name}}?",
"marketplace.remove.confirm": "Vuoi davvero rimuovere questo {{type}}? Verrà rimosso dalla configurazione {{scope}}.",
"marketplace.remove.cancel": "Annulla",
"marketplace.remove.confirm.button": "Rimuovi",
"marketplace.tab.mcp": "MCP",
"marketplace.search": "Cerca...",
"marketplace.filter.all": "Tutti gli elementi",
"marketplace.filter.notInstalled": "Non installati",
"marketplace.empty": "Nessun elemento trovato",
"marketplace.badge.mcpServer": "Server MCP",
"marketplace.badge.mode": "Modalità",
"marketplace.card.by": "di {{author}}",
"marketplace.install.method": "Metodo di installazione",
"marketplace.install.parameters": "Parametri",
"marketplace.install.optional": "(opzionale)",
"marketplace.install.required": "{{name}} è obbligatorio",
"marketplace.scope.project": "progetto",
"marketplace.scope.global": "globale",
"marketplace.remove.type.mcp": "server MCP",
"marketplace.remove.type.skill": "skill",
"marketplace.remove.type.agent": "agente",
"marketplace.remove.failed": "Rimozione di {{name}} non riuscita",
"marketplace.install": "Installa",
"marketplace.filter.installed": "Installati",
"marketplace.error.dismiss": "Ignora",
"marketplace.warning.busyOne": "Una sessione è attiva e verrà interrotta",
"marketplace.warning.busyMany": "Più sessioni sono attive e verranno interrotte",
"marketplace.warning.installAnyway": "Installa comunque",
"marketplace.warning.cancel": "Annulla",
"marketplace.contribute.prompt": "Manca una skill, una modalità o un server MCP?",
"marketplace.contribute.cta": "Contribuisci su GitHub",
"marketplace.migration.notice":
"Le Modalità sono state sostituite dagli agenti. Se in precedenza hai installato Modalità dal marketplace, rimuovile e reinstallale come agenti per migrare al nuovo formato.",
// Plan follow-up question shown after plan_exit
"plan.followup.header": "Implementa",
"plan.followup.question": "Pronto per implementare?",
"plan.followup.answer.newSession": "Avvia una nuova sessione",
"plan.followup.answer.newSession.description": "Implementa in una nuova sessione con contesto vuoto",
"plan.followup.answer.continue": "Continua qui",
"plan.followup.answer.continue.description": "Implementa il piano in questa sessione",
"snapshot.slowRepo.header": "Snapshot lento",
"snapshot.slowRepo.question":
"L'inizializzazione del sistema snapshot sta richiedendo molto tempo, probabilmente a causa delle dimensioni del repository.\n\nVuoi disabilitare gli snapshot per questo repository?",
"snapshot.slowRepo.answer.continue": "Continua con gli snapshot",
"snapshot.slowRepo.answer.continue.description":
"Continua ad attendere il completamento dello snapshot. Le iterazioni successive saranno rapide dopo la creazione dello snapshot iniziale.",
"snapshot.slowRepo.answer.disable": "Disabilita per questo progetto",
"snapshot.slowRepo.answer.disable.description":
"Disattiva gli snapshot di Kilo per questo progetto. Perderai annulla/ripeti sulle modifiche ai file fatte da Kilo, ma git continuerà a tracciare tutto.",
"ui.messagePart.openInDiffViewer": "Apri nel visualizzatore diff",
"ui.messagePart.shell.command": "Comando",
"ui.messagePart.shell.output": "Output",
"ui.messagePart.openInEditor": "Apri nell'editor",
"ui.message.feedback.helpful": "È stato utile",
"ui.message.feedback.notHelpful": "Non è stato utile",
"ui.message.feedback.clearRating": "Cancella valutazione",
}
+3
View File
@@ -6,6 +6,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " にアクセスしてAPIキーを取得してください。",
"provider.connect.kiloGateway.byok.prefix": "詳細な使用統計については、",
"provider.connect.kiloGateway.byok.link": "Kilo's Gateway経由でBYOK",
"provider.connect.kiloGateway.byok.suffix": "をご利用ください。",
// Provider dialog translations
"dialog.provider.group.recommended": "おすすめ",
+3
View File
@@ -6,6 +6,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": "를 방문하여 API 키를 받으세요.",
"provider.connect.kiloGateway.byok.prefix": "더 많은 사용 통계를 보려면 ",
"provider.connect.kiloGateway.byok.link": "Kilo's Gateway를 통해 BYOK",
"provider.connect.kiloGateway.byok.suffix": "를 사용하세요.",
// Provider dialog translations
"dialog.provider.group.recommended": "추천",
+3
View File
@@ -9,6 +9,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Bezoek ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " om je API key op te halen.",
"provider.connect.kiloGateway.byok.prefix": "Voor meer gebruiksstatistieken, gebruik ",
"provider.connect.kiloGateway.byok.link": "BYOK via Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Aanbevolen",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Besøk ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " for å hente API-nøkkelen din.",
"provider.connect.kiloGateway.byok.prefix": "For mer bruksstatistikk, bruk ",
"provider.connect.kiloGateway.byok.link": "BYOK via Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Anbefalt",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Odwiedź ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": ", aby otrzymać swój klucz API.",
"provider.connect.kiloGateway.byok.prefix": "Aby uzyskać więcej statystyk użycia, użyj ",
"provider.connect.kiloGateway.byok.link": "BYOK przez Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Polecane",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Посетите ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": ", чтобы получить ваш API-ключ.",
"provider.connect.kiloGateway.byok.prefix": "Для получения дополнительной статистики использования используйте ",
"provider.connect.kiloGateway.byok.link": "BYOK через Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Рекомендуемые",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "เยี่ยมชม ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " เพื่อรับ API key ของคุณ",
"provider.connect.kiloGateway.byok.prefix": "สำหรับสถิติการใช้งานเพิ่มเติม โปรดใช้ ",
"provider.connect.kiloGateway.byok.link": "BYOK ผ่าน Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": "",
// Provider dialog translations
"dialog.provider.group.recommended": "แนะนำ",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "API anahtarınızı almak için ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " adresini ziyaret edin.",
"provider.connect.kiloGateway.byok.prefix": "Daha fazla kullanım istatistiği için ",
"provider.connect.kiloGateway.byok.link": "Kilo's Gateway üzerinden BYOK",
"provider.connect.kiloGateway.byok.suffix": " kullanın.",
// Provider dialog translations
"dialog.provider.group.recommended": "Önerilen",
+3
View File
@@ -7,6 +7,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "Відвідайте ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " щоб отримати свій API-ключ.",
"provider.connect.kiloGateway.byok.prefix": "Для отримання додаткової статистики використання використовуйте ",
"provider.connect.kiloGateway.byok.link": "BYOK через Kilo's Gateway",
"provider.connect.kiloGateway.byok.suffix": ".",
// Provider dialog translations
"dialog.provider.group.recommended": "Рекомендовані",
+3
View File
@@ -5,6 +5,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "访问 ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " 获取您的 API 密钥。",
"provider.connect.kiloGateway.byok.prefix": "如需更多使用统计信息,请",
"provider.connect.kiloGateway.byok.link": "通过 Kilo's Gateway 进行 BYOK",
"provider.connect.kiloGateway.byok.suffix": "。",
// Provider dialog translations
"dialog.provider.group.recommended": "推荐",
+3
View File
@@ -5,6 +5,9 @@ export const dict = {
"provider.connect.kiloGateway.visit.prefix": "訪問 ",
"provider.connect.kiloGateway.visit.link": "kilo.ai",
"provider.connect.kiloGateway.visit.suffix": " 獲取您的 API 金鑰。",
"provider.connect.kiloGateway.byok.prefix": "如需更多使用統計資訊,請",
"provider.connect.kiloGateway.byok.link": "透過 Kilo's Gateway 進行 BYOK",
"provider.connect.kiloGateway.byok.suffix": "。",
// Provider dialog translations
"dialog.provider.group.recommended": "推薦",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@kilocode/kilo-indexing",
"version": "7.3.12",
"version": "7.3.16",
"type": "module",
"license": "MIT",
"description": "Standalone indexing engine and host helpers for Kilo Code",
@@ -136,7 +136,7 @@ export class LanceDBVectorStore implements IVectorStore {
return [
{
key: KEY.size,
value: this.vectorSize,
value: String(this.vectorSize),
},
{
key: KEY.provider,
@@ -148,11 +148,11 @@ export class LanceDBVectorStore implements IVectorStore {
},
{
key: KEY.dimension,
value: this.profile.dimension,
value: String(this.profile.dimension),
},
{
key: KEY.complete,
value: false,
value: "false",
},
]
}
@@ -572,7 +572,7 @@ export class LanceDBVectorStore implements IVectorStore {
}
const metadataTable = await db.openTable(this.metadataTableName)
const metadataResults = await metadataTable.query().where(`key = '${KEY.complete}'`).toArray()
const indexed = metadataResults.length > 0 ? metadataResults[0].value : false
const indexed = metadataResults.length > 0 ? String(metadataResults[0].value) === "true" : false
log.info("LanceDB indexing metadata evaluated", {
workspacePath: this.workspacePath,
pointCount,
@@ -590,7 +590,9 @@ export class LanceDBVectorStore implements IVectorStore {
throw new Error(`Invalid metadata key: ${key}`)
}
await metadataTable.delete(`key = '${key}'`)
await metadataTable.add([{ key, value }])
// All values must be strings to prevent LanceDB from inferring the value column
// type as number from the first row, which corrupts subsequent string/boolean values.
await metadataTable.add([{ key, value: String(value) }])
}
private async _persistEmbeddingProfile(metadataTable: Table): Promise<void> {
@@ -609,7 +611,7 @@ export class LanceDBVectorStore implements IVectorStore {
const db = await this.getDb()
const metadataTable = await db.openTable(this.metadataTableName)
await this._persistEmbeddingProfile(metadataTable)
await this._upsertMetadata(metadataTable, KEY.complete, true)
await this._upsertMetadata(metadataTable, KEY.complete, "true")
log.info("Marked indexing as complete")
} catch (error) {
log.error("Failed to mark indexing as complete", { error })
@@ -626,7 +628,7 @@ export class LanceDBVectorStore implements IVectorStore {
const db = await this.getDb()
const metadataTable = await db.openTable(this.metadataTableName)
await this._persistEmbeddingProfile(metadataTable)
await this._upsertMetadata(metadataTable, KEY.complete, false)
await this._upsertMetadata(metadataTable, KEY.complete, "false")
log.info("Marked indexing as incomplete (in progress)")
} catch (error) {
log.error("Failed to mark indexing as incomplete", { error })
+2
View File
@@ -168,6 +168,8 @@ For blocking I/O in coroutines, move the dispatcher switch inside the callee usi
## Build and Verification
- **Marketplace version build**: Use `script/build-version.sh <version>` from `packages/kilo-jetbrains/` to clean, prepare production CLI binaries, build, sign, and verify the JetBrains Marketplace plugin ZIP. Pass `--skip-verification` only when explicitly needed.
- **Test version build**: If the user asks for a JetBrains test build, still require a version and use `script/build-version.sh <version> --skip-signing --skip-verification` from `packages/kilo-jetbrains/` so no signing secrets are needed. Add `--skip-clean` only when the user wants a faster incremental test build.
- **Typecheck**: `bun run typecheck` or `./gradlew typecheck` from `packages/kilo-jetbrains/` — compiles all Kotlin sources including the generated API client. Does NOT require CLI binaries.
- **Full build**: `bun run build` from `packages/kilo-jetbrains/` (prepares CLI binaries + runs Gradle `buildPlugin`).
- **Gradle only**: `./gradlew buildPlugin` from `packages/kilo-jetbrains/` (requires CLI binaries already present in `backend/build/generated/cli/`; run `bun run build --prepare-cli` first).
+8
View File
@@ -0,0 +1,8 @@
# Changelog
## [Unreleased]
## [0.0.0-dev]
### Added
- Initial JetBrains plugin development builds.
+15 -7
View File
@@ -13,7 +13,8 @@
- Create a JetBrains Marketplace permanent token from Marketplace `My Tokens`.
- Add `JETBRAINS_MARKETPLACE_TOKEN` to GitHub Actions secrets or the protected environment.
- Confirm `GITHUB_TOKEN` has `contents: write` permission for creating and updating GitHub Releases from `jetbrains/v*` tags.
- Confirm `GITHUB_TOKEN` has `contents: write` permission for creating and updating GitHub Releases for `jetbrains/v*` tags.
- Confirm `KILO_MAINTAINER_APP_ID` and `KILO_MAINTAINER_APP_SECRET` are available to create release PRs and immediate release tags.
- Optionally create a protected `jetbrains-marketplace` GitHub Environment with required reviewers.
- If using an environment, move the Marketplace and signing secrets there and set the workflow job environment.
@@ -29,16 +30,23 @@
## Per-RC Release
- Choose an RC version in the form `x.y.z-rc.n`.
- Push tag `jetbrains/vx.y.z-rc.n`, for example `jetbrains/v7.0.1-rc.1`.
- Run the `prepare-jetbrains-release` workflow with `kind=rc` and version `x.y.z-rc.n`.
- Confirm the workflow created `jetbrains/vx.y.z-rc.n` immediately at the intended source commit.
- Review and edit `packages/kilo-jetbrains/CHANGELOG.md` in the generated release PR.
- Merge the release PR to trigger publish from `jetbrains/vx.y.z-rc.n`, for example `jetbrains/v7.0.1-rc.1`.
- Watch the `publish-jetbrains` workflow.
- Download and retain the workflow artifact if needed.
- Confirm the update appears on the JetBrains Marketplace `eap` channel.
- Confirm the GitHub Release for the `jetbrains/vx.y.z-rc.n` tag exists and contains the JetBrains plugin ZIP asset.
- Share `https://plugins.jetbrains.com/plugins/eap/list` with testers.
## Stable Release Guard
## Per-Stable Release
- Stable tags like `jetbrains/vx.y.z` are intentionally rejected for now.
- Before enabling stable releases, remove the workflow stable guard.
- Verify `kilo.channel=default` publishes to the default Marketplace channel.
- Update this checklist before stable releases are enabled.
- Choose a stable version in the form `x.y.z`.
- Run the `prepare-jetbrains-release` workflow with `kind=stable` and version `x.y.z`.
- Confirm the workflow created `jetbrains/vx.y.z` immediately at the intended source commit.
- Review and edit `packages/kilo-jetbrains/CHANGELOG.md` in the generated release PR.
- Merge the release PR to trigger publish from `jetbrains/vx.y.z`.
- Watch the `publish-jetbrains` workflow.
- Confirm the update appears on the default JetBrains Marketplace channel.
- Confirm the GitHub Release for the `jetbrains/vx.y.z` tag exists and contains the JetBrains plugin ZIP asset.
+101 -31
View File
@@ -1,62 +1,132 @@
# Releasing the JetBrains Plugin
## RC releases (currently the only supported flow)
JetBrains releases are locked by an immediate `jetbrains/v<version>` tag, then gated by a reviewed release PR. The tag fixes the exact source code that will be published; the PR is where maintainers review and edit the version and changelog before publishing starts.
Stable release tags (`jetbrains/vx.y.z`) are recognized by the workflow but intentionally rejected. Only RC tags are accepted right now.
The published code comes from `jetbrains/v<version>`. Marketplace and GitHub release notes come from the reviewed changelog merged in the release PR.
### 1. Create and push a tag
## Create Release Tag And PR
Tag format: `jetbrains/v<major>.<minor>.<patch>-rc.<n>`
1. Open the GitHub Actions workflow:
```
git tag jetbrains/v7.0.1-rc.1
git push origin jetbrains/v7.0.1-rc.1
[https://github.com/Kilo-Org/kilocode/actions/workflows/prepare-jetbrains-release.yml](https://github.com/Kilo-Org/kilocode/actions/workflows/prepare-jetbrains-release.yml)
2. Click **Run workflow**. This immediately creates `jetbrains/v<version>` at the current `origin/main` commit, then creates or updates the release PR.
3. Fill the inputs:
| Input | Value |
|---|---|
| `kind` | `rc` for an EAP release, `stable` for a default Marketplace release. |
| `version` | `x.y.z-rc.n` for RCs, `x.y.z` for stable releases. |
| `from_tag` | Optional previous tag for the changelog range. Leave empty unless the default range is wrong. |
Examples:
```text
kind=rc
version=7.3.13-rc.1
```
### 2. Watch the workflow
```text
kind=stable
version=7.3.13
```
The `publish-jetbrains` workflow starts automatically on tag push. Follow progress at:
## Changelog Range Defaults
The workflow chooses a changelog base automatically and generates notes against the locked release commit:
| Release | Default `from_tag` |
|---|---|
| First RC for a version, e.g. `7.3.13-rc.1` | Latest stable JetBrains tag. |
| Later RC, e.g. `7.3.13-rc.2` | Previous RC for the same base version. |
| Stable, e.g. `7.3.13` | Latest stable JetBrains tag, ignoring RCs. |
Use `from_tag` only to override this comparison range. It does not change the release target commit.
For the first stable JetBrains release, there may be no previous stable tag yet. In that case, pass the last RC or another reviewed JetBrains tag as `from_tag`.
## Review the PR
The workflow creates or updates a branch like:
```text
jetbrains/release/v7.3.13-rc.1
```
The PR updates:
| File | Purpose |
|---|---|
| `packages/kilo-jetbrains/package.json` | JetBrains plugin package version. |
| `packages/kilo-jetbrains/CHANGELOG.md` | Release notes packaged into the plugin. |
Review and edit `packages/kilo-jetbrains/CHANGELOG.md` before merging. This changelog entry is rendered into JetBrains `<change-notes>`, so it appears on the Marketplace and inside IntelliJ plugin UI.
The PR can change release metadata such as `packages/kilo-jetbrains/package.json` and `packages/kilo-jetbrains/CHANGELOG.md`, but it does not change the tagged source code that will be built.
## Merge and Publish
When the release PR is merged, the `publish-jetbrains` workflow validates the existing tag and release PR markers:
```text
jetbrains/v<version>
```
Then it publishes from that tag:
[https://github.com/Kilo-Org/kilocode/actions/workflows/publish-jetbrains.yml](https://github.com/Kilo-Org/kilocode/actions/workflows/publish-jetbrains.yml)
The workflow:
1. Validates the tag format and required secrets.
2. Downloads CLI binaries for all 6 platforms from the matching GitHub Release.
3. Verifies and signs the plugin with `./gradlew verifyPlugin publishPlugin -Pproduction=true`.
4. Publishes the signed ZIP to the JetBrains Marketplace `eap` channel.
5. Uploads the signed ZIP to a GitHub prerelease for the tag.
Publishing behavior:
### 3. Verify on the Marketplace
| Version | Marketplace channel | GitHub release |
|---|---|---|
| `x.y.z-rc.n` | `eap` | Prerelease |
| `x.y.z` | default | Stable release |
Once the workflow succeeds, the new version should appear in the plugin's version list:
The workflow checks out `jetbrains/v<version>` for verification, signing, and Marketplace publishing. It overlays the reviewed `packages/kilo-jetbrains/CHANGELOG.md` from the merged PR before rendering release notes and before `publishPlugin`, so Marketplace metadata and the GitHub Release use the reviewed changelog.
[https://plugins.jetbrains.com/plugin/28350-kilo-code/edit/versions](https://plugins.jetbrains.com/plugin/28350-kilo-code/edit/versions)
## Installing RC Builds
---
## Installing RC builds via the custom plugin repository
RC builds are published to the `eap` channel, not the default channel. To get them in IntelliJ IDEA:
RC builds are published to the `eap` channel. To get them in IntelliJ IDEA:
1. Open **Settings > Plugins**.
2. Click the gear icon and choose **Manage Plugin Repositories**.
3. Add the following URL:
```
```text
https://plugins.jetbrains.com/plugins/list?channel=eap&pluginId=28350
```
4. Search for **Kilo Code** in the Marketplace tab — the latest RC version will appear and update automatically.
4. Search for **Kilo Code** in the Marketplace tab.
---
## Manual Recovery
## Required GitHub Actions secrets
If the prepare workflow created the tag but failed before creating or updating the PR, rerun the workflow for the same version. It reuses the tag if it still points to the same locked commit.
If publish validation says the tag points to the wrong SHA, stop and inspect manually. Do not move, delete, or recreate release tags casually.
If publish failed after merge, rerun the failed `publish-jetbrains` workflow if the failure happened before Marketplace accepted the version. Marketplace may reject a duplicate version after a successful publish.
If Marketplace publishing succeeded but GitHub Release upload failed, manually create or edit the GitHub Release for the existing tag. Use the reviewed release notes from `packages/kilo-jetbrains/CHANGELOG.md` in the merged release PR.
If the immediate tag must be created manually because the prepare workflow could not push it, create it at the intended locked `origin/main` commit before merging the release PR:
```bash
git fetch origin main
git tag jetbrains/v7.3.13 <locked-main-sha>
git push origin jetbrains/v7.3.13
```
## Required GitHub Actions Secrets
| Secret | Purpose |
|---|---|
| `JETBRAINS_MARKETPLACE_TOKEN` | Marketplace API token for publishing |
| `JETBRAINS_CERTIFICATE_CHAIN` | PEM certificate chain for plugin signing |
| `JETBRAINS_PRIVATE_KEY` | PEM private key for plugin signing |
| `JETBRAINS_PRIVATE_KEY_PASSWORD` | Password for the private key |
| `KILO_MAINTAINER_APP_ID` | GitHub App ID used to create/update release PRs and immediate release tags. |
| `KILO_MAINTAINER_APP_SECRET` | GitHub App private key used to create/update release PRs and immediate release tags. |
| `JETBRAINS_MARKETPLACE_TOKEN` | Marketplace API token for publishing. |
| `JETBRAINS_CERTIFICATE_CHAIN` | PEM certificate chain for plugin signing. |
| `JETBRAINS_PRIVATE_KEY` | PEM private key for plugin signing. |
| `JETBRAINS_PRIVATE_KEY_PASSWORD` | Password for the private key. |
Before the first publish, complete `RELEASE_TODO.md` to set up these secrets and the Marketplace plugin entry.
+26 -2
View File
@@ -1,7 +1,9 @@
import org.jetbrains.changelog.Changelog
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
import org.jetbrains.intellij.platform.gradle.tasks.RunIdeTask
import org.jetbrains.intellij.platform.gradle.tasks.aware.SplitModeAware.SplitModeTarget
import java.time.LocalDate
group = "ai.kilocode.jetbrains"
@@ -39,12 +41,12 @@ fun gitTag(): String? {
}
val release = providers.gradleProperty("production").map { it.toBoolean() }.orElse(false).get()
val ver = if (release) checked(
val override = providers.gradleProperty("kilo.version").orNull?.trim()?.takeIf { it.isNotEmpty() }
val ver = override?.let(::checked) ?: if (release) checked(
gitTag()?.removePrefix("jetbrains/v")
?: error("Missing JetBrains plugin version. Publish builds must run from a jetbrains/v<version> tag."),
) else checked(gitTag()?.removePrefix("jetbrains/v") ?: "0.0.0-dev")
val notes = providers.gradleProperty("kilo.changeNotes").orElse("Release candidate build.")
val channel = providers.gradleProperty("kilo.channel").map { it.trim() }.orElse("default")
val splitPort = providers.gradleProperty("kilo.splitModeServerPort").orNull?.let(::port) ?: fallback()
val isolated = providers.gradleProperty("kilo.dev.storage.isolated").map { it.toBoolean() }.orElse(false)
@@ -59,12 +61,34 @@ plugins {
id("java")
alias(libs.plugins.intellij.platform)
alias(libs.plugins.detekt)
alias(libs.plugins.changelog)
alias(libs.plugins.kotlin) apply false
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.compose.compiler) apply false
}
changelog {
version = ver
path = file("CHANGELOG.md").canonicalPath
header = provider { "[${version.get()}] - ${LocalDate.now()}" }
unreleasedTerm = "[Unreleased]"
keepUnreleasedSection = true
repositoryUrl = "https://github.com/Kilo-Org/kilocode"
groups = listOf("Added", "Changed", "Fixed", "Removed", "Security")
combinePreReleases = false
}
val notes = providers.gradleProperty("kilo.changeNotes").orElse(
provider {
val item = if (changelog.has(ver)) changelog.get(ver) else changelog.getUnreleased()
changelog.renderItem(
item.withHeader(false).withEmptySections(false),
Changelog.OutputType.HTML,
)
},
)
subprojects {
apply(plugin = "org.jetbrains.intellij.platform.module")
apply(plugin = "io.gitlab.arturbosch.detekt")
@@ -4,7 +4,6 @@ import ai.kilocode.client.app.KiloWorkspaceService
import ai.kilocode.client.app.Workspace
import ai.kilocode.client.session.SessionSidePanelManager
import ai.kilocode.log.KiloLog
import com.intellij.openapi.actionSystem.ActionGroup
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbAware
@@ -64,11 +63,13 @@ class KiloToolWindowFactory : ToolWindowFactory, DumbAware {
toolWindow.contentManager.setSelectedContent(content)
manager.newSession()
val toolbar = ActionManager.getInstance().getAction("Kilo.ToolWindowToolbar")
if (toolbar is ActionGroup) {
val actions = toolbar.getChildren(null).toList()
toolWindow.setTitleActions(actions)
}
val actions = listOfNotNull(
ActionManager.getInstance().getAction("Kilo.NewSession"),
ActionManager.getInstance().getAction("Kilo.History"),
ActionManager.getInstance().getAction("Kilo.ShowProfile"),
ActionManager.getInstance().getAction("Kilo.Settings"),
)
toolWindow.setTitleActions(actions)
} catch (e: Exception) {
LOG.error("Failed to set up Kilo tool window content", e)
}
@@ -5,7 +5,6 @@ import ai.kilocode.client.settings.profile.UserProfileConfigurable
import com.intellij.icons.AllIcons
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification
import com.intellij.openapi.options.Configurable
import com.intellij.openapi.options.ConfigurableWithId
import com.intellij.openapi.options.ShowSettingsUtil
@@ -22,7 +21,7 @@ class ShowProfileAction : DumbAwareAction(
KiloBundle.message("action.Kilo.ShowProfile.text"),
KiloBundle.message("action.Kilo.ShowProfile.description"),
AllIcons.General.User,
), ActionRemoteBehaviorSpecification.Frontend {
) {
override fun actionPerformed(e: AnActionEvent) {
ShowSettingsUtil.getInstance().showSettingsDialog(
@@ -56,8 +56,10 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.awt.BorderLayout
import java.awt.event.HierarchyEvent
import javax.swing.JComponent
import javax.swing.JPanel
import javax.swing.UIManager
/**
* Top-level session UI composition root.
@@ -134,6 +136,8 @@ class SessionUi(
private var empty: EmptySessionPanel? = null
private var modalFocus: (() -> JComponent)? = null
private var style = SessionEditorStyle.current()
private var editorTheme = style.editorScheme
private var colorTheme = UIManager.getLookAndFeel()
init {
buildUi()
@@ -274,7 +278,7 @@ class SessionUi(
prompt.model.onSelect = { item -> controller.selectModel(item.provider, item.id) }
prompt.reasoning.onSelect = { item -> controller.selectVariant(item.id) }
prompt.onReset = { controller.clearModelOverride() }
prompt.onChange = { scroll.followTail() }
prompt.onChange = { scroll.refresh() }
prompt.onAutoApproveToggle = { value ->
controller.setAutoApprove(value)
prompt.setAutoApprove(controller.autoApprove)
@@ -405,6 +409,12 @@ class SessionUi(
}
private fun bindStyle() {
addHierarchyListener { event ->
if ((event.changeFlags and HierarchyEvent.SHOWING_CHANGED.toLong()) == 0L) return@addHierarchyListener
if (!isShowing) return@addHierarchyListener
applyStyleIfThemeChanged()
}
val bus = ApplicationManager.getApplication().messageBus.connect(this)
bus.subscribe(EditorColorsManager.TOPIC, EditorColorsListener {
ApplicationManager.getApplication().invokeLater {
@@ -496,6 +506,12 @@ class SessionUi(
override fun applyStyle(style: SessionEditorStyle) {
this.style = style
editorTheme = style.editorScheme
colorTheme = UIManager.getLookAndFeel()
background = style.editorBackground
root.content.background = style.editorBackground
sessionContent.background = style.editorBackground
blankBody.background = style.editorBackground
load.applyStyle(style)
header.applyStyle(style)
prompt.applyStyle(style)
@@ -503,6 +519,13 @@ class SessionUi(
refresh()
}
private fun applyStyleIfThemeChanged() {
val next = SessionEditorStyle.current()
val laf = UIManager.getLookAndFeel()
if (editorTheme === next.editorScheme && colorTheme == laf) return
applyStyle(next)
}
private fun openProfileSettings() {
ShowSettingsUtil.getInstance().showSettingsDialog(
project,
@@ -1,31 +1,14 @@
package ai.kilocode.client.session.scroll
import ai.kilocode.client.ui.colorizeIfPossible
import ai.kilocode.client.ui.UiStyle
import com.intellij.openapi.util.IconLoader
import com.intellij.util.ui.JBUI
import java.awt.Color
import javax.swing.Icon
internal object ScrollButtonIcon {
private val bottom = IconLoader.getIcon("/icons/scroll-bottom.svg", ScrollButtonIcon::class.java)
private val prompt = IconLoader.getIcon("/icons/scroll-question.svg", ScrollButtonIcon::class.java)
private val bottom: Icon = IconLoader.getIcon("/icons/scroll-bottom.svg", ScrollButtonIcon::class.java)
private val prompt: Icon = IconLoader.getIcon("/icons/scroll-question.svg", ScrollButtonIcon::class.java)
fun create(question: Boolean = false): Icon {
if (question) {
return prompt.colorizeIfPossible(
fillColor = UiStyle.Colors.warningLabelForeground(),
borderColor = Color.WHITE,
fillId = "ScrollQuestion.Background",
strokeId = "ScrollQuestion.Foreground",
)
}
return bottom.colorizeIfPossible(
fillColor = JBUI.CurrentTheme.Button.defaultButtonColorStart(),
borderColor = JBUI.CurrentTheme.Button.defaultButtonForeground(),
fillId = "ScrollButton.Background",
strokeId = "ScrollButton.Foreground",
)
if (question) return prompt
return bottom
}
}
@@ -53,6 +53,7 @@ internal class SessionScroll(
private var user = false
private var value = 0
private var question = false
private var restoring = false
init {
jump = JBLabel(ScrollButtonIcon.create()).apply {
@@ -71,6 +72,7 @@ internal class SessionScroll(
user = true
}
})
component.viewport.addChangeListener { onViewport() }
component.verticalScrollBar.addAdjustmentListener { onScroll() }
root.addOverlay(jump) { _, child ->
val size = child.preferredSize
@@ -166,6 +168,8 @@ internal class SessionScroll(
@RequiresEdt
fun applyStyle(style: SessionEditorStyle) {
this.style = style
component.background = style.editorBackground
component.viewport.background = style.editorBackground
syncIcon()
messages.applyStyle(style)
val view = component.viewport.view
@@ -266,6 +270,21 @@ internal class SessionScroll(
bar.value = bottom()
}
@RequiresEdt
private fun onViewport() {
if (restoring || auto || opening || user || tail || component.viewport.view !== messages) return
val y = value.coerceIn(0, bottom())
if (component.viewport.viewPosition.y == y && bar.value == y) return
restoring = true
try {
component.viewport.viewPosition = Point(0, y)
bar.value = y
} finally {
restoring = false
}
updateJump()
}
@RequiresEdt
private fun bottom(): Int {
val bar = component.verticalScrollBar
@@ -363,7 +363,8 @@ class PromptPanel(
@RequiresEdt
private fun syncEditorHeight() {
val lines = (editor.document.lineCount + SessionUiStyle.View.Prompt.EDITOR_SPARE_LINES).coerceIn(
val count = ApplicationManager.getApplication().runReadAction<Int> { editor.document.lineCount }
val lines = (count + SessionUiStyle.View.Prompt.EDITOR_SPARE_LINES).coerceIn(
SessionUiStyle.View.Prompt.EDITOR_LINES,
SessionUiStyle.View.Prompt.EDITOR_MAX_LINES,
)
@@ -35,10 +35,9 @@ class PlanExitView(tool: Tool, openFile: (String) -> Unit) : PartView() {
}
override fun applyStyle(style: SessionEditorStyle) {
val changed = md.font != style.transcriptFont || md.codeFont != style.editorFamily
if (md.font != style.transcriptFont) md.font = style.transcriptFont
if (md.codeFont != style.editorFamily) md.codeFont = style.editorFamily
if (!changed) return
md.font = style.transcriptFont
md.codeFont = style.editorFamily
md.foreground = style.editorForeground
refresh()
}
@@ -50,10 +50,9 @@ class TextView(
internal fun contentOpaque() = md.opaque
override fun applyStyle(style: SessionEditorStyle) {
val changed = md.font != style.transcriptFont || md.codeFont != style.editorFamily
if (md.font != style.transcriptFont) md.font = style.transcriptFont
if (md.codeFont != style.editorFamily) md.codeFont = style.editorFamily
if (!changed) return
md.font = style.transcriptFont
md.codeFont = style.editorFamily
md.foreground = style.editorForeground
refresh()
}
@@ -15,6 +15,7 @@ import java.awt.BorderLayout
import java.awt.Color
import java.awt.Component
import java.awt.Dimension
import java.awt.Rectangle
import javax.swing.JButton
import javax.swing.Icon
import javax.swing.JComponent
@@ -315,6 +316,8 @@ class BaseQuestionView : RoundedContentPanel(
return Dimension(Int.MAX_VALUE, size.height)
}
override fun scrollRectToVisible(aRect: Rectangle) {}
private fun withWidth(fallback: Int): Dimension {
val w = availableWidth()
if (w <= 0) return Dimension(super.getPreferredSize().width, fallback)
@@ -18,6 +18,7 @@ import java.awt.Component
import java.awt.Cursor
import java.awt.Dimension
import java.awt.Font
import java.awt.Rectangle
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import javax.swing.BoxLayout
@@ -213,6 +214,8 @@ class QuestionResultView(tool: Tool) : PartView() {
return Dimension(Int.MAX_VALUE, size.height)
}
override fun scrollRectToVisible(aRect: Rectangle) {}
private fun withWidth(fallback: Int): Dimension {
val width = space()
if (width <= 0) return Dimension(super.getPreferredSize().width, fallback)

Some files were not shown because too many files have changed in this diff Show More