Merge branch 'main' into conscious-jackrabbit

This commit is contained in:
Kirill Kalishev
2026-05-21 10:17:00 -04:00
committed by GitHub
50 changed files with 473 additions and 148 deletions
-5
View File
@@ -1,5 +0,0 @@
---
"@kilocode/kilo-ui": patch
---
Show the first leading reasoning title in each block header without repeating it in the expanded body, while keeping untitled blocks unchanged.
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": patch
---
Keep final streamed responses visible during session reconciliation.
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": minor
---
Render file mentions as styled chips with click-to-open in both the chat input and sent user messages, with atomic backspace removal, arrow key skipping, selection snapping, and mention formatting preserved after reverting a session.
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": patch
---
Persist Speech to Text experimental settings through Kilo config instead of VS Code settings.
-6
View File
@@ -1,6 +0,0 @@
---
"@kilocode/cli": patch
"kilo-code": patch
---
Resolve bundled tree-sitter WASM resources from the installed CLI layout so codebase indexing works in packaged CLI and VS Code builds.
@@ -0,0 +1,5 @@
---
"@kilocode/cli": patch
---
Vertically center TUI dialogs on screen
-5
View File
@@ -1,5 +0,0 @@
---
"kilo-code": patch
---
Fix stale indexing status updates in the VS Code extension on Windows so Settings and the chat indicator refresh while indexing progresses. Directory matching for indexing SSE events now handles Windows path casing, and indexing status pushes are no longer dropped if they arrive before the initial config payload.
+2 -1
View File
@@ -175,6 +175,7 @@ jobs:
cli_version: ${{ needs.version.outputs.version }}
secrets: inherit
# kilocode_change end
publish:
needs:
- version
@@ -208,6 +209,7 @@ jobs:
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
package-manager-cache: false # kilocode_change
- name: Install @vscode/vsce
run: bun install -g @vscode/vsce
@@ -265,7 +267,6 @@ jobs:
GH_REPO: ${{ github.repository }}
AUR_KEY: ${{ secrets.AUR_KEY }}
GITHUB_TOKEN: ${{ steps.committer.outputs.token }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true
VSCE_PAT: ${{ secrets.VSCE_TOKEN }}
OPENVSX_TOKEN: ${{ secrets.OVSX_TOKEN }}
+31 -31
View File
@@ -28,12 +28,12 @@
"prettier": "3.6.2",
"semver": "^7.6.0",
"sst": "3.18.10",
"turbo": "2.8.13",
"turbo": "2.9.14",
},
},
"packages/core": {
"name": "@opencode-ai/core",
"version": "7.3.2",
"version": "7.3.6",
"bin": {
"opencode": "./bin/opencode",
},
@@ -68,7 +68,7 @@
},
"packages/kilo-docs": {
"name": "@kilocode/kilo-docs",
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {
"@docsearch/css": "^4",
"@docsearch/js": "^4",
@@ -98,7 +98,7 @@
},
"packages/kilo-gateway": {
"name": "@kilocode/kilo-gateway",
"version": "7.3.2",
"version": "7.3.6",
"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.2",
"version": "7.3.6",
"devDependencies": {
"@tsconfig/node22": "catalog:",
"@types/bun": "catalog:",
@@ -144,7 +144,7 @@
},
"packages/kilo-indexing": {
"name": "@kilocode/kilo-indexing",
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {
"@aws-sdk/client-bedrock-runtime": "3.1005.0",
"@aws-sdk/credential-provider-ini": "3.972.31",
@@ -179,7 +179,7 @@
},
"packages/kilo-telemetry": {
"name": "@kilocode/kilo-telemetry",
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {
"@kilocode/kilo-gateway": "workspace:*",
"posthog-node": "4.4.0",
@@ -193,7 +193,7 @@
},
"packages/kilo-ui": {
"name": "@kilocode/kilo-ui",
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {
"@kilocode/sdk": "workspace:*",
"@kobalte/core": "0.13.11",
@@ -230,7 +230,7 @@
},
"packages/kilo-vscode": {
"name": "kilo-code",
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {
"@anthropic-ai/sdk": "^0.39.0",
"@kilocode/kilo-gateway": "workspace:*",
@@ -293,7 +293,7 @@
},
"packages/opencode": {
"name": "@kilocode/cli",
"version": "7.3.2",
"version": "7.3.6",
"bin": {
"kilo": "./bin/kilo",
"kilocode": "./bin/kilo",
@@ -451,7 +451,7 @@
},
"packages/plugin": {
"name": "@kilocode/plugin",
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {
"@kilocode/sdk": "workspace:*",
"effect": "catalog:",
@@ -476,7 +476,7 @@
},
"packages/script": {
"name": "@opencode-ai/script",
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {
"semver": "^7.6.3",
},
@@ -487,7 +487,7 @@
},
"packages/sdk/js": {
"name": "@kilocode/sdk",
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {
"cross-spawn": "catalog:",
},
@@ -502,7 +502,7 @@
},
"packages/storybook": {
"name": "@opencode-ai/storybook",
"version": "7.3.2",
"version": "7.3.6",
"devDependencies": {
"@opencode-ai/ui": "workspace:*",
"@solidjs/meta": "catalog:",
@@ -525,7 +525,7 @@
},
"packages/ui": {
"name": "@opencode-ai/ui",
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {
"@kilocode/sdk": "workspace:*",
"@kobalte/core": "catalog:",
@@ -614,7 +614,7 @@
"@openauthjs/openauth": "0.0.0-20250322224806",
"@opentui/core": "0.2.2",
"@opentui/solid": "0.2.2",
"@pierre/diffs": "1.1.0-beta.18",
"@pierre/diffs": "1.1.22",
"@playwright/test": "1.59.1",
"@solid-primitives/storage": "4.3.3",
"@solidjs/meta": "0.29.4",
@@ -1644,9 +1644,9 @@
"@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="],
"@pierre/diffs": ["@pierre/diffs@1.1.0-beta.18", "", { "dependencies": { "@pierre/theme": "0.0.22", "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-7ZF3YD9fxdbYsPnltz5cUqHacN7ztp8RX/fJLxwv8wIEORpP4+7dHz1h/qx3o4EW2xUrIhmbM8ImywLasB787Q=="],
"@pierre/diffs": ["@pierre/diffs@1.1.22", "", { "dependencies": { "@pierre/theme": "0.0.28", "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-1Iv7kdl6OABFCd1n2HQbGUiRHouXPaHoIjcb7Lwg8zeJKY5ph+cESFcGEyIiwW0NCbKGtYS2bTnXmI+Eze5dwg=="],
"@pierre/theme": ["@pierre/theme@0.0.22", "", {}, "sha512-ePUIdQRNGjrveELTU7fY89Xa7YGHHEy5Po5jQy/18lm32eRn96+tnYJEtFooGdffrx55KBUtOXfvVy/7LDFFhA=="],
"@pierre/theme": ["@pierre/theme@0.0.28", "", {}, "sha512-1j/H/fECBuc9dEvntdWI+l435HZapw+RCJTlqCA6BboQ5TjlnE005j/ROWutXIs8aq5OAc82JI2Kwk4A1WWBgw=="],
"@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="],
@@ -2028,6 +2028,18 @@
"@tufjs/models": ["@tufjs/models@4.1.0", "", { "dependencies": { "@tufjs/canonical-json": "2.0.0", "minimatch": "^10.1.1" } }, "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww=="],
"@turbo/darwin-64": ["@turbo/darwin-64@2.9.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-t7QiPflaEyBE4oayeZtSmu4mEfjgIrcNlNNl1z1dmIVPqEdtA7+CfTf8d7KXsOGPh6aNgWjKxyvQg9uGfDQF+A=="],
"@turbo/darwin-arm64": ["@turbo/darwin-arm64@2.9.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-d23147mC9BsCPA9mJ0h/ubcpbRgcJBXbcG3+Vq7YLhjz3IXuvQsJ1UXH8f4MD76ZjJ4m/E4aRdJV+MW88CDfbw=="],
"@turbo/linux-64": ["@turbo/linux-64@2.9.14", "", { "os": "linux", "cpu": "x64" }, "sha512-P3ZKB5tuUDdDQWuAsACGUR1qv9W7BNWxdxqVJ0kZNuNNPRaVYTPPikLcp79+GiEcW3npsR+KyP38lnQiBc5aSA=="],
"@turbo/linux-arm64": ["@turbo/linux-arm64@2.9.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZRTlzcUMrrPv9ZuDzRF9n60Ym13bKeG9jDB8WjxyLhWNzV+AJQN+zdpIk3NJYf2zQsGUm1mNar2P0elRzLw25g=="],
"@turbo/windows-64": ["@turbo/windows-64@2.9.14", "", { "os": "win32", "cpu": "x64" }, "sha512-exanwN6sIduZwykYeiTQj8kCmOhazP5WOz3bvXMcYtjhL6Z3iRWLewKrXCBq0bqwSP3iBMb/AerRCnHI4lx46A=="],
"@turbo/windows-arm64": ["@turbo/windows-arm64@2.9.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-fVdCsnmYoKICsycbWuuGp6Jvi51/3G/UluFWuAUCvR8PIW5IJkAk5BM9UF8PSm0Q2IphWHFZjYEgjHsh3B9y/g=="],
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
"@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="],
@@ -4296,19 +4308,7 @@
"tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
"turbo": ["turbo@2.8.13", "", { "optionalDependencies": { "turbo-darwin-64": "2.8.13", "turbo-darwin-arm64": "2.8.13", "turbo-linux-64": "2.8.13", "turbo-linux-arm64": "2.8.13", "turbo-windows-64": "2.8.13", "turbo-windows-arm64": "2.8.13" }, "bin": { "turbo": "bin/turbo" } }, "sha512-nyM99hwFB9/DHaFyKEqatdayGjsMNYsQ/XBNO6MITc7roncZetKb97MpHxWf3uiU+LB9c9HUlU3Jp2Ixei2k1A=="],
"turbo-darwin-64": ["turbo-darwin-64@2.8.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-PmOvodQNiOj77+Zwoqku70vwVjKzL34RTNxxoARjp5RU5FOj/CGiC6vcDQhNtFPUOWSAaogHF5qIka9TBhX4XA=="],
"turbo-darwin-arm64": ["turbo-darwin-arm64@2.8.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kI+anKcLIM4L8h+NsM7mtAUpElkCOxv5LgiQVQR8BASyDFfc8Efj5kCk3cqxuxOvIqx0sLfCX7atrHQ2kwuNJQ=="],
"turbo-linux-64": ["turbo-linux-64@2.8.13", "", { "os": "linux", "cpu": "x64" }, "sha512-j29KnQhHyzdzgCykBFeBqUPS4Wj7lWMnZ8CHqytlYDap4Jy70l4RNG46pOL9+lGu6DepK2s1rE86zQfo0IOdPw=="],
"turbo-linux-arm64": ["turbo-linux-arm64@2.8.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-OEl1YocXGZDRDh28doOUn49QwNe82kXljO1HXApjU0LapkDiGpfl3jkAlPKxEkGDSYWc8MH5Ll8S16Rf5tEBYg=="],
"turbo-windows-64": ["turbo-windows-64@2.8.13", "", { "os": "win32", "cpu": "x64" }, "sha512-717bVk1+Pn2Jody7OmWludhEirEe0okoj1NpRbSm5kVZz/yNN/jfjbxWC6ilimXMz7xoMT3IDfQFJsFR3PMANA=="],
"turbo-windows-arm64": ["turbo-windows-arm64@2.8.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-R819HShLIT0Wj6zWVnIsYvSNtRNj1q9VIyaUz0P24SMcLCbQZIm1sV09F4SDbg+KCCumqD2lcaR2UViQ8SnUJA=="],
"turbo": ["turbo@2.9.14", "", { "optionalDependencies": { "@turbo/darwin-64": "2.9.14", "@turbo/darwin-arm64": "2.9.14", "@turbo/linux-64": "2.9.14", "@turbo/linux-arm64": "2.9.14", "@turbo/windows-64": "2.9.14", "@turbo/windows-arm64": "2.9.14" }, "bin": { "turbo": "bin/turbo" } }, "sha512-BQqXRr4UoWI3UPFrtznCLykYHxwxWh53iCB57x092jPMjIlW1wnm3N895g5irpiXmnxUhREBB0n6+y8BHhs4nw=="],
"turndown": ["turndown@7.2.0", "", { "dependencies": { "@mixmark-io/domino": "^2.2.0" } }, "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A=="],
+4 -4
View File
@@ -1,8 +1,8 @@
{
"nodeModules": {
"x86_64-linux": "sha256-lENbjYvGZewVWQcr7zXJn+v1hrvipHEnjE1yS+kEwLs=",
"aarch64-linux": "sha256-yqTdPGtoLEOaFc7PhBFRiS/6gI3xUgHG/cQcULKytyM=",
"aarch64-darwin": "sha256-lyn6yjD8qv2KwIDwlA8LXBPkcHTCZCtXIsktK5acoXM=",
"x86_64-darwin": "sha256-diaLa3lmWzLcm4TeAwH1hFIqQYQQUcG4YD306vQWCqA="
"x86_64-linux": "sha256-1GI3/cmf3ne+dxfEHzp7EzvEO0GzjgXtlilFGzV73hc=",
"aarch64-linux": "sha256-lHO7dmc1inyzFjAgoU7hyNUHldcrWOFu6eeBL1NaB14=",
"aarch64-darwin": "sha256-9j9ZdIZ6TD9F1GioHSRynaPjNHENdrl2sgMI93P2QhA=",
"x86_64-darwin": "sha256-3qKN9xzg2TzhnxX/zhwtP5V0152d5bfnn3hlctv8IJI="
}
}
+3 -3
View File
@@ -42,7 +42,7 @@
"@tsconfig/bun": "1.0.9",
"@cloudflare/workers-types": "4.20251008.0",
"@openauthjs/openauth": "0.0.0-20250322224806",
"@pierre/diffs": "1.1.0-beta.18",
"@pierre/diffs": "1.1.22",
"opentui-spinner": "0.0.6",
"@solid-primitives/storage": "4.3.3",
"@tailwindcss/vite": "4.1.11",
@@ -91,7 +91,7 @@
"prettier": "3.6.2",
"semver": "^7.6.0",
"sst": "3.18.10",
"turbo": "2.8.13",
"turbo": "2.9.14",
"@types/bun": "catalog:",
"@changesets/changelog-github": "^0.5.1",
"@changesets/cli": "^2.27.10"
@@ -145,6 +145,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.2",
"version": "7.3.6",
"peerDependencies": {}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "7.3.2",
"version": "7.3.6",
"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.2"
version = "7.3.6"
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.2/opencode-darwin-arm64.zip"
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.6/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.2/opencode-darwin-x64.zip"
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.6/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.2/opencode-linux-arm64.tar.gz"
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.6/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.2/opencode-linux-x64.tar.gz"
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.6/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.2/opencode-windows-x64.zip"
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.6/opencode-windows-x64.zip"
cmd = "./opencode.exe"
args = ["acp"]
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@kilocode/kilo-docs",
"version": "7.3.2",
"version": "7.3.6",
"private": true,
"scripts": {
"dev": "next dev --webpack --port 3002",
@@ -68,7 +68,7 @@ To fill empty seats or remove members ahead of seat deletion, see the [team mana
## Automatic Top-Up
Ensure your team has uninterrupted access to Kilo Code by enabling Automatic Top-Up. This feature keeps your organization's balance funded so you never have to worry about manual recharges.
Ensure your team has uninterrupted access to Kilo Code by enabling [Automatic Top-Up](https://kilo.ai/features/auto-top-ups). This feature keeps your organization's balance funded so you never have to worry about manual recharges. Auto top-up is also available for individual accounts — see [Adding Credits](/docs/getting-started/adding-credits) for details.
### How It Works
@@ -9,9 +9,9 @@ Once you've used any initial free Kilo Credits, you can easily add more:
- Subscribe to the [Kilo Pass](https://kilo.ai/features/kilo-pass), the most cost effective way to add credits.
- Purchase additional credits as a one-time transaction.
- Enable automatic top-up, which purchases additional credits when your balance is below $5.
- Enable [automatic top-up](https://kilo.ai/features/auto-top-ups), which purchases additional credits when your balance runs low. Auto top-up is available for both individual and organization accounts.
These options are available to purchase from your [personal profile page](https://app.kilo.ai/profile).
These options are available to purchase from your [personal profile page](https://app.kilo.ai/profile). Organization owners can manage credits and auto top-up from the [Organization dashboard](https://app.kilo.ai).
You can also use subscriptions or credits you may have purchased directly with an AI provider by adding your keys on the [Bring your own Key (BYOK)](https://app.kilo.ai/byok) settings screen. For setup details and supported providers, see [AI Providers documentation](/docs/ai-providers). If your provider is not yet supported, you can also [directly connect your provider](/docs/getting-started/setup-authentication) in the extension and CLI.
@@ -871,4 +871,10 @@ module.exports = [
basePath: false,
permanent: true,
},
{
source: "/auto-top-ups",
destination: "https://kilo.ai/features/auto-top-ups",
basePath: false,
permanent: true,
},
]
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7aa0924c6679cbff6e816dd86371a2d483afb7f0840824503ef4ba325c25d6c5
size 26282
oid sha256:97728b91ed1c92556abfde08824b91536e87cc7afa4d121bb5b1b488946c1d05
size 26009
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f28a551185ec9d7607d02295803b155e0f7bac378fcefdf0996c6ca51c0afad6
size 21892
oid sha256:7b8e9f6e0b9a9a62efc9b1e807936049c7627674ba241239dfd777698f951acc
size 21820
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@kilocode/kilo-gateway",
"version": "7.3.2",
"version": "7.3.6",
"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.2",
"version": "7.3.6",
"type": "module",
"license": "MIT",
"description": "Kilo-specific i18n translations and overrides",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@kilocode/kilo-indexing",
"version": "7.3.2",
"version": "7.3.6",
"type": "module",
"license": "MIT",
"description": "Standalone indexing engine and host helpers for Kilo Code",
@@ -302,10 +302,9 @@ export class CodeIndexConfigManager {
}
public get currentModelDimension(): number | undefined {
if (this.modelDimension && this.modelDimension > 0) return this.modelDimension
const id = this.modelId ?? getDefaultModelId(this.embedderProvider)
const dim = getModelDimension(this.embedderProvider, id)
if (!dim && this.modelDimension && this.modelDimension > 0) return this.modelDimension
return dim
return getModelDimension(this.embedderProvider, id)
}
public get currentSearchMinScore(): number {
@@ -25,7 +25,8 @@ interface EmbeddingItem {
}
interface OpenRouterEmbeddingResponse {
data: EmbeddingItem[]
data?: EmbeddingItem[]
error?: string | { code?: string | number; message?: string }
usage?: {
prompt_tokens?: number
total_tokens?: number
@@ -193,10 +194,7 @@ export class OpenRouterEmbedder implements IEmbedder {
const requestParams: any = {
input: batchTexts,
model: model,
// OpenAI package (as of v4.78.1) has a parsing issue that truncates embedding dimensions to 256
// when processing numeric arrays, which breaks compatibility with models using larger dimensions.
// By requesting base64 encoding, we bypass the package's parser and handle decoding ourselves.
encoding_format: "base64",
encoding_format: "float",
}
if (this.dimensions !== undefined) {
@@ -213,8 +211,24 @@ export class OpenRouterEmbedder implements IEmbedder {
}
const response = (await this.embeddingsClient.embeddings.create(requestParams)) as OpenRouterEmbeddingResponse
const err = response.error
const msg = typeof err === "string" ? err : err?.message
const code = typeof err === "object" && err ? err.code : undefined
if (!response.data || response.data.length === 0) {
log.warn("OpenRouter embedder batch returned invalid response", {
location: "OpenRouterEmbedder:_embedBatchWithRetries",
model,
dimensions: this.dimensions,
provider: this.specificProvider,
code,
err: msg,
})
const invalid = new Error(msg ?? "Invalid response from OpenRouter embedding endpoint") as HttpError
invalid.status = typeof code === "number" ? code : 422
throw invalid
}
// Convert base64 embeddings to float32 arrays
// Normalize base64 embeddings if OpenRouter returns them despite the float request.
const processedEmbeddings = response.data.map((item: EmbeddingItem) => {
if (typeof item.embedding === "string") {
const buffer = Buffer.from(item.embedding, "base64")
@@ -292,7 +306,7 @@ export class OpenRouterEmbedder implements IEmbedder {
const requestParams: any = {
input: testTexts,
model: modelToUse,
encoding_format: "base64",
encoding_format: "float",
}
if (this.dimensions !== undefined) {
@@ -315,6 +329,18 @@ export class OpenRouterEmbedder implements IEmbedder {
// Check if we got a valid response
if (!response?.data || response.data.length === 0) {
const err = response?.error
const msg = typeof err === "string" ? err : err?.message
const code = typeof err === "object" && err ? err.code : undefined
log.warn("OpenRouter embedder validation returned invalid response", {
location: "OpenRouterEmbedder:validateConfiguration",
model: modelToUse,
dimensions: this.dimensions,
provider: this.specificProvider,
dataCount: response?.data?.length ?? 0,
code,
err: msg,
})
return {
valid: false,
error: "Invalid response from OpenRouter embedding endpoint",
@@ -20,7 +20,7 @@ export function resolveEmbeddingProfile(
modelDimension?: number,
): EmbeddingProfile | undefined {
const id = modelId ?? getDefaultModelId(provider)
const dim = getModelDimension(provider, id) ?? parseDimension(modelDimension)
const dim = parseDimension(modelDimension) ?? getModelDimension(provider, id)
if (!dim) return undefined
return {
provider,
@@ -48,6 +48,7 @@ const profiles: Record<string, Record<string, ModelProfile>> = {
openrouter: {
"openai/text-embedding-3-small": { dimension: 1536, scoreThreshold: 0.4 },
"openai/text-embedding-3-large": { dimension: 3072, scoreThreshold: 0.4 },
"google/gemini-embedding-2-preview": { dimension: 3072, scoreThreshold: 0.35 },
},
"openai-compatible": {},
"vercel-ai-gateway": {
@@ -83,6 +83,20 @@ describe("CodeIndexConfigManager", () => {
expect(cfg.currentModelDimension).toBe(2048)
})
test("uses configured dimension before static model metadata", () => {
const cfg = new CodeIndexConfigManager(
createInput({
embedderProvider: "openrouter",
openAiKey: undefined,
openRouterApiKey: "or-test",
modelId: "google/gemini-embedding-2-preview",
modelDimension: 1536,
}),
)
expect(cfg.currentModelDimension).toBe(1536)
})
describe("loadConfiguration restart checks", () => {
test("requires restart when model changes with same dimension", () => {
const cfg = new CodeIndexConfigManager(createInput({ modelId: "text-embedding-3-small" }))
@@ -68,14 +68,10 @@ describe("OpenRouterEmbedder", () => {
})
test("should create embeddings successfully", async () => {
// Create base64 encoded embedding with values that can be exactly represented in Float32
const testEmbedding = new Float32Array([0.25, 0.5, 0.75])
const base64String = Buffer.from(testEmbedding.buffer).toString("base64")
const mockResponse = {
data: [
{
embedding: base64String,
embedding: [0.25, 0.5, 0.75],
},
],
usage: {
@@ -91,7 +87,7 @@ describe("OpenRouterEmbedder", () => {
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
input: ["test text"],
model: defaultModel,
encoding_format: "base64",
encoding_format: "float",
})
expect(result.embeddings).toHaveLength(1)
expect(result.embeddings[0]).toEqual([0.25, 0.5, 0.75])
@@ -99,6 +95,20 @@ describe("OpenRouterEmbedder", () => {
expect(result.usage?.totalTokens).toBe(5)
})
test("should not retry invalid responses without embedding data", async () => {
mockEmbeddingsCreate.mockResolvedValue({
error: {
code: 404,
message: "No successful provider responses.",
},
})
await expect(embedder.createEmbeddings(["test"])).rejects.toThrow(
"Embedding request failed after 3 attempts with status 404: No successful provider responses.",
)
expect(mockEmbeddingsCreate).toHaveBeenCalledTimes(1)
})
test("should handle multiple texts", async () => {
const embedding1 = new Float32Array([0.25, 0.5])
const embedding2 = new Float32Array([0.75, 1.0])
@@ -156,7 +166,7 @@ describe("OpenRouterEmbedder", () => {
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
input: ["test"],
model: customModel,
encoding_format: "base64",
encoding_format: "float",
})
})
@@ -187,7 +197,7 @@ describe("OpenRouterEmbedder", () => {
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
input: ["test"],
model: defaultModel,
encoding_format: "base64",
encoding_format: "float",
provider: {
order: [specificProvider],
only: [specificProvider],
@@ -221,7 +231,7 @@ describe("OpenRouterEmbedder", () => {
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
input: ["test"],
model: defaultModel,
encoding_format: "base64",
encoding_format: "float",
dimensions: 1024,
})
})
@@ -257,7 +267,7 @@ describe("OpenRouterEmbedder", () => {
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
input: ["test"],
model: defaultModel,
encoding_format: "base64",
encoding_format: "float",
})
})
})
@@ -271,13 +281,10 @@ describe("OpenRouterEmbedder", () => {
})
test("should validate configuration successfully", async () => {
const testEmbedding = new Float32Array([0.25, 0.5])
const base64String = Buffer.from(testEmbedding.buffer).toString("base64")
const mockResponse = {
data: [
{
embedding: base64String,
embedding: [0.25, 0.5],
},
],
usage: {
@@ -296,7 +303,7 @@ describe("OpenRouterEmbedder", () => {
{
input: ["test"],
model: defaultModel,
encoding_format: "base64",
encoding_format: "float",
},
{
timeout: REMOTE_EMBEDDER_VALIDATION_TIMEOUT_MS,
@@ -305,6 +312,20 @@ describe("OpenRouterEmbedder", () => {
)
})
test("should reject responses without embedding data", async () => {
mockEmbeddingsCreate.mockResolvedValue({
error: {
code: 404,
message: "No successful provider responses.",
},
})
const result = await embedder.validateConfiguration()
expect(result.valid).toBe(false)
expect(result.error).toBe("Invalid response from OpenRouter embedding endpoint")
})
test("should handle validation failure", async () => {
const authError = new Error("Invalid API key")
;(authError as any).status = 401
@@ -346,7 +367,7 @@ describe("OpenRouterEmbedder", () => {
{
input: ["test"],
model: defaultModel,
encoding_format: "base64",
encoding_format: "float",
provider: {
order: [specificProvider],
only: [specificProvider],
@@ -388,7 +409,7 @@ describe("OpenRouterEmbedder", () => {
{
input: ["test"],
model: defaultModel,
encoding_format: "base64",
encoding_format: "float",
dimensions: 1024,
},
{
@@ -149,11 +149,42 @@ describe("CodeIndexServiceFactory", () => {
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
input: ["hello"],
model: "openai/text-embedding-3-small",
encoding_format: "base64",
encoding_format: "float",
dimensions: 1024,
})
})
test("creates vector store for OpenRouter Gemini embedding preview", () => {
const factory = createFactory({
embedderProvider: "openrouter",
openAiKey: undefined,
openRouterApiKey: "or-test",
modelId: "google/gemini-embedding-2-preview",
vectorStoreProvider: "lancedb",
})
const store = factory.createVectorStore() as unknown as { vectorSize: number }
expect(store).toBeDefined()
expect(store.vectorSize).toBe(3072)
})
test("uses configured dimension before static model metadata for vector stores", () => {
const factory = createFactory({
embedderProvider: "openrouter",
openAiKey: undefined,
openRouterApiKey: "or-test",
modelId: "openai/text-embedding-3-small",
modelDimension: 1024,
vectorStoreProvider: "lancedb",
})
const store = factory.createVectorStore() as unknown as { vectorSize: number }
expect(store).toBeDefined()
expect(store.vectorSize).toBe(1024)
})
test("creates Kilo embedder with Cloud-provided model", async () => {
const factory = createFactory({
embedderProvider: "kilo",
@@ -177,6 +208,7 @@ describe("CodeIndexServiceFactory", () => {
input: ["hello"],
model: "mistralai/mistral-embed-2312",
encoding_format: "base64",
dimensions: 1024,
})
})
})
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@kilocode/kilo-telemetry",
"version": "7.3.2",
"version": "7.3.6",
"type": "module",
"license": "MIT",
"description": "Telemetry for Kilo CLI - PostHog analytics integration",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@kilocode/kilo-ui",
"version": "7.3.2",
"version": "7.3.6",
"type": "module",
"license": "MIT",
"exports": {
@@ -280,8 +280,8 @@ html[data-theme="kilo-vscode"] {
--syntax-diff-unknown: var(--vscode-charts-red);
/* ===== Pierre diff engine (theme its CSS vars to VS Code editor colors) ===== */
--diffs-light-bg: var(--vscode-editor-background, #1e1e1e);
--diffs-dark-bg: var(--vscode-editor-background, #1e1e1e);
--diffs-light-bg: var(--background-stronger);
--diffs-dark-bg: var(--background-stronger);
--diffs-bg-addition-override: color-mix(
in lab,
+34
View File
@@ -1,5 +1,39 @@
# kilo-code
## 7.3.5
### Patch Changes
- [#10481](https://github.com/Kilo-Org/kilocode/pull/10481) [`15bdd0f`](https://github.com/Kilo-Org/kilocode/commit/15bdd0f96f3f6713b552436806f6e218528443ab) - Prevent VS Code local CLI reconnect flapping while the event stream is unavailable.
- [#10479](https://github.com/Kilo-Org/kilocode/pull/10479) [`048338a`](https://github.com/Kilo-Org/kilocode/commit/048338a31422fd057bcaefc8db6c397cf33adff1) - Clear Agent Manager file diff previews stuck on `Loading diff...` when the active diff source stops or changes.
- [#10480](https://github.com/Kilo-Org/kilocode/pull/10480) [`9067de0`](https://github.com/Kilo-Org/kilocode/commit/9067de039ed820eab757d1e798abe264315c6f02) - Improve VS Code diff rendering stability across review and chat surfaces.
- Updated dependencies [[`205e22e`](https://github.com/Kilo-Org/kilocode/commit/205e22ee4672305d3cb2e0c34b607a4950f8f4e8), [`9067de0`](https://github.com/Kilo-Org/kilocode/commit/9067de039ed820eab757d1e798abe264315c6f02)]:
- @kilocode/kilo-indexing@7.3.5
- @kilocode/kilo-ui@7.3.5
- @opencode-ai/ui@7.3.5
## 7.3.3
### Minor Changes
- [#10099](https://github.com/Kilo-Org/kilocode/pull/10099) [`47c8600`](https://github.com/Kilo-Org/kilocode/commit/47c8600b21dfc9ce5f9010a471e075af10867cf0) Thanks [@sylwester-liljegren](https://github.com/sylwester-liljegren)! - Render file mentions as styled chips with click-to-open in both the chat input and sent user messages, with atomic backspace removal, arrow key skipping, selection snapping, and mention formatting preserved after reverting a session.
### Patch Changes
- [#10450](https://github.com/Kilo-Org/kilocode/pull/10450) [`75f6819`](https://github.com/Kilo-Org/kilocode/commit/75f68190e45a4c10f72438d1cf6ab40730e865f8) - Keep final streamed responses visible during session reconciliation.
- [#10440](https://github.com/Kilo-Org/kilocode/pull/10440) [`e739c29`](https://github.com/Kilo-Org/kilocode/commit/e739c29bb57262d7567be1a25b62a03460f6c8d1) - Persist Speech to Text experimental settings through Kilo config instead of VS Code settings.
- [#10155](https://github.com/Kilo-Org/kilocode/pull/10155) [`371b7e8`](https://github.com/Kilo-Org/kilocode/commit/371b7e8ae6057f0fefae3982eee6923f2c0a61f0) - Resolve bundled tree-sitter WASM resources from the installed CLI layout so codebase indexing works in packaged CLI and VS Code builds.
- [#9806](https://github.com/Kilo-Org/kilocode/pull/9806) [`c5903fd`](https://github.com/Kilo-Org/kilocode/commit/c5903fdc09b1cf731e538cd632b47e4befd8367a) Thanks [@shssoichiro](https://github.com/shssoichiro)! - Fix stale indexing status updates in the VS Code extension on Windows so Settings and the chat indicator refresh while indexing progresses. Directory matching for indexing SSE events now handles Windows path casing, and indexing status pushes are no longer dropped if they arrive before the initial config payload.
- Updated dependencies [[`241efc6`](https://github.com/Kilo-Org/kilocode/commit/241efc6959ae1fe2fd2adc3533737ad0712983c5)]:
- @kilocode/kilo-ui@7.3.3
## 7.3.2
### Patch Changes
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "kilo-code",
"displayName": "Kilo Code: AI Coding Agent, Copilot, and Autocomplete",
"description": "Open Source AI coding agent that generates code from natural language, automates tasks, and runs terminal commands. Features inline autocomplete, browser automation, automated refactoring, and custom modes for planning, coding, and debugging. Supports 500+ AI models including Claude (Anthropic), Gemini, Grok, GPT, Codex and GLM.",
"version": "7.3.2",
"version": "7.3.6",
"icon": "assets/icons/logo-outline-black.png",
"galleryBanner": {
"color": "#FFFFFF",
+9 -2
View File
@@ -23,6 +23,7 @@ const kiloVscodeDir = join(import.meta.dir, "..")
const packagesDir = join(kiloVscodeDir, "..")
const opencodeDir = join(packagesDir, "opencode")
const coreDir = join(packagesDir, "core")
const indexingDir = join(packagesDir, "kilo-indexing")
const targetBinDir = join(kiloVscodeDir, "bin")
const binName = process.platform === "win32" ? "kilo.exe" : "kilo"
@@ -37,7 +38,8 @@ async function cliSourceHash(): Promise<string | null> {
try {
const opencodeResult = await $`git log -1 --format=%H -- .`.cwd(opencodeDir).quiet()
const coreResult = await $`git log -1 --format=%H -- .`.cwd(coreDir).quiet()
return `${opencodeResult.text().trim()}-${coreResult.text().trim()}` || null
const indexingResult = await $`git log -1 --format=%H -- .`.cwd(indexingDir).quiet()
return `${opencodeResult.text().trim()}-${coreResult.text().trim()}-${indexingResult.text().trim()}` || null
} catch {
return null
}
@@ -47,7 +49,12 @@ async function isDirty(): Promise<boolean> {
try {
const opencodeResult = await $`git status --porcelain -- .`.cwd(opencodeDir).quiet()
const coreResult = await $`git status --porcelain -- .`.cwd(coreDir).quiet()
return opencodeResult.text().trim().length > 0 || coreResult.text().trim().length > 0
const indexingResult = await $`git status --porcelain -- .`.cwd(indexingDir).quiet()
return (
opencodeResult.text().trim().length > 0 ||
coreResult.text().trim().length > 0 ||
indexingResult.text().trim().length > 0
)
} catch {
return false
}
@@ -181,8 +181,12 @@ export class SourceController {
return
}
const diff = await source.fetchFile(file).catch(() => null)
// Drop the response if the source has been disposed/swapped while we waited.
if (this.epoch !== epoch) return
// Discard stale content after disposal/swap, but still complete the request
// so consumers can clear per-file loading state.
if (this.epoch !== epoch) {
this.send(this.messages.diffFile(source, file, null))
return
}
this.send(this.messages.diffFile(source, file, diff))
}
@@ -584,7 +584,8 @@ export class KiloConnectionService {
this.sseClient = new SdkSSEAdapter(this.client)
// Wait until SSE actually reaches a terminal state before resolving connect().
// Wait until SSE yields its first server event before resolving connect().
// Initial stream failures are handled by the adapter reconnect loop.
let resolveConnected: (() => void) | null = null
let rejectConnected: ((error: Error) => void) | null = null
const connectedPromise = new Promise<void>((resolve, reject) => {
@@ -601,11 +602,8 @@ export class KiloConnectionService {
}
})
this.sseClient.onError((error) => {
this.sseClient.onError(() => {
this.setState("error")
rejectConnected?.(error)
resolveConnected = null
rejectConnected = null
})
// Wire SSE state → broadcast to all registered state listeners
@@ -15,9 +15,8 @@ export type SSEStateHandler = (state: "connecting" | "connected" | "disconnected
*
* In this VS Code extension context the connection is localhost (extension ↔
* child-process server), so zombie-connection scenarios are less likely than in
* a browser client (which goes through proxies/CDNs). We keep the heartbeat for
* consistency with the original strategy but use a generous 90 s timeout to
* avoid false-positive reconnections during idle periods.
* a browser client (which goes through proxies/CDNs). We still keep a heartbeat
* grace window so dead local streams recover without waiting indefinitely.
*
* NOTE on event coalescing:
* The app batches rapid events into 16 ms windows before flushing to the UI.
@@ -37,6 +36,7 @@ export class SdkSSEAdapter {
// Reduced from 90s: with 90s a dead connection could linger for ~1.5 minutes.
private static readonly HEARTBEAT_TIMEOUT_MS = 15_000
private static readonly RECONNECT_DELAY_MS = 250
private static readonly MAX_RECONNECT_DELAY_MS = 5_000
constructor(private readonly client: KiloClient) {}
@@ -126,8 +126,11 @@ export class SdkSSEAdapter {
* Main reconnection loop — mirrors the pattern in `global-sdk.tsx`.
*/
private async consumeLoop(signal: AbortSignal): Promise<void> {
let delay = SdkSSEAdapter.RECONNECT_DELAY_MS
while (!signal.aborted) {
const attempt = new AbortController()
let ready = false
// Forward the outer abort to the per-attempt controller so
// `disconnect()` cancels the current fetch immediately.
@@ -159,8 +162,7 @@ export class SdkSSEAdapter {
},
})
console.log("[Kilo New] SSE: ✅ Stream opened successfully")
this.notifyState("connected")
console.log("[Kilo New] SSE: ⏳ Waiting for first stream event")
this.resetHeartbeat(attempt)
for await (const event of events.stream) {
@@ -170,6 +172,13 @@ export class SdkSSEAdapter {
this.resetHeartbeat(attempt)
if (!ready) {
ready = true
delay = SdkSSEAdapter.RECONNECT_DELAY_MS
console.log("[Kilo New] SSE: ✅ Stream opened successfully")
this.notifyState("connected")
}
// The SDK yields GlobalEvent = { directory, payload: Event }.
const globalEvent = event as GlobalEvent
const type = (globalEvent.payload as { type: string }).type
@@ -179,7 +188,9 @@ export class SdkSSEAdapter {
this.notifyEvent(globalEvent.payload as Event, globalEvent.directory)
}
console.log("[Kilo New] SSE: 📭 Stream ended normally")
console.log(
ready ? "[Kilo New] SSE: 📭 Stream ended normally" : "[Kilo New] SSE: 📭 Stream ended before first event",
)
} catch (error) {
// Suppress AbortErrors — they are expected when the heartbeat timer
// or reconnect() aborts the per-attempt controller.
@@ -198,9 +209,11 @@ export class SdkSSEAdapter {
break
}
console.log(`[Kilo New] SSE: 🔄 Reconnecting in ${SdkSSEAdapter.RECONNECT_DELAY_MS}ms...`)
const wait = delay
delay = ready ? SdkSSEAdapter.RECONNECT_DELAY_MS : Math.min(delay * 2, SdkSSEAdapter.MAX_RECONNECT_DELAY_MS)
console.log(`[Kilo New] SSE: 🔄 Reconnecting in ${wait}ms...`)
this.notifyState("connecting")
await new Promise((resolve) => setTimeout(resolve, SdkSSEAdapter.RECONNECT_DELAY_MS))
await new Promise((resolve) => setTimeout(resolve, wait))
}
this.notifyState("disconnected")
+1 -1
View File
@@ -1,6 +1,6 @@
{
"type": "module",
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {},
"devDependencies": {},
"peerDependencies": {}
@@ -0,0 +1,148 @@
import { describe, expect, it } from "bun:test"
import type { KiloClient } from "@kilocode/sdk/v2/client"
import { KiloConnectionService } from "../../src/services/cli-backend/connection-service"
import { SdkSSEAdapter } from "../../src/services/cli-backend/sdk-sse-adapter"
type Opts = {
onSseError?: (error: unknown) => void
signal?: AbortSignal
}
type Stream = AsyncGenerator<unknown, void, unknown>
function client(open: (opts: Opts) => Stream): KiloClient {
return {
global: {
event: async (opts: Opts) => ({ stream: open(opts) }),
},
} as unknown as KiloClient
}
function event() {
return {
directory: "/repo",
payload: {
id: "evt_connected",
type: "server.connected",
properties: {},
},
}
}
function wait(ms: number) {
return new Promise<void>((resolve) => setTimeout(resolve, ms))
}
function aborted(signal?: AbortSignal) {
if (!signal || signal.aborted) return Promise.resolve()
return new Promise<void>((resolve) => signal.addEventListener("abort", () => resolve(), { once: true }))
}
describe("SdkSSEAdapter", () => {
it("reports connected only after the first SSE event arrives", async () => {
let release = () => {}
const gate = new Promise<void>((resolve) => {
release = resolve
})
const adapter = new SdkSSEAdapter(
client(async function* (opts) {
await gate
yield event()
await aborted(opts.signal)
}),
)
const states: string[] = []
const connected = new Promise<void>((resolve) => {
adapter.onStateChange((state) => {
states.push(state)
if (state === "connected") resolve()
})
})
adapter.connect()
await wait(10)
expect(states).toEqual(["connecting"])
release()
await connected
expect(states).toEqual(["connecting", "connected"])
adapter.disconnect()
})
it("backs off reconnects when an SSE fetch fails before opening", async () => {
const timer = globalThis.setTimeout
const delays: number[] = []
let count = 0
let finish = () => {}
const reached = new Promise<void>((resolve) => {
finish = resolve
})
globalThis.setTimeout = ((handler: TimerHandler, timeout?: number, ...args: unknown[]) => {
if (typeof timeout === "number" && timeout <= 5_000) {
delays.push(timeout)
return timer(handler, 0, ...args)
}
return timer(handler, timeout, ...args)
}) as typeof setTimeout
const failing = new SdkSSEAdapter(
client((opts) => {
count += 1
if (count === 3) finish()
return (async function* () {
opts.onSseError?.(new TypeError("fetch failed"))
})()
}),
)
try {
failing.connect()
await reached
failing.disconnect()
expect(delays.slice(0, 2)).toEqual([250, 500])
} finally {
failing.disconnect()
globalThis.setTimeout = timer
}
})
})
describe("KiloConnectionService SSE startup", () => {
it("waits through an initial SSE fetch failure until the stream opens", async () => {
const original = globalThis.fetch
const chunk = new TextEncoder().encode(
'data: {"payload":{"id":"evt_connected","type":"server.connected","properties":{}}}\n\n',
)
let calls = 0
globalThis.fetch = (async () => {
calls += 1
if (calls === 1) throw new TypeError("fetch failed")
return new Response(
new ReadableStream<Uint8Array>({
start(controller) {
controller.enqueue(chunk)
},
}),
{
status: 200,
headers: { "content-type": "text/event-stream" },
},
)
}) as typeof fetch
const service = new KiloConnectionService({} as any)
;(service as any).serverManager.getServer = async () => ({ port: 52512, password: "secret", process: {} })
try {
await expect(service.connect("/tmp/workspace")).resolves.toBeUndefined()
expect(calls).toBe(2)
expect(service.getConnectionState()).toBe("connected")
} finally {
service.dispose()
globalThis.fetch = original
}
})
})
@@ -345,6 +345,40 @@ describe("SourceController.requestFile", () => {
controller.stop()
})
it("posts null when a pending fetchFile result is invalidated by stop", async () => {
let release: () => void = () => {}
const workspace: DiffSource = {
descriptor: WORKSPACE_DESC,
async fetch() {
return { diffs: [] }
},
async fetchFile() {
await new Promise<void>((resolve) => (release = resolve))
return {
file: "foo.ts",
before: "a",
after: "b",
additions: 1,
deletions: 1,
}
},
}
const { controller, posted } = make({ workspace })
controller.setContext({ workspaceRoot: "/repo" })
await controller.activate("workspace")
posted.length = 0
const request = controller.requestFile("foo.ts")
controller.stop()
release()
await request
const files = byType(posted, "diffViewer.diffFile")
expect(files).toHaveLength(1)
expect(files[0]!.file).toBe("foo.ts")
expect(files[0]!.diff).toBeNull()
})
})
describe("SourceController.reactivate", () => {
+13
View File
@@ -1,5 +1,18 @@
# @kilocode/cli
## 7.3.5
### Patch Changes
- Updated dependencies [[`205e22e`](https://github.com/Kilo-Org/kilocode/commit/205e22ee4672305d3cb2e0c34b607a4950f8f4e8)]:
- @kilocode/kilo-indexing@7.3.5
## 7.3.3
### Patch Changes
- [#10155](https://github.com/Kilo-Org/kilocode/pull/10155) [`371b7e8`](https://github.com/Kilo-Org/kilocode/commit/371b7e8ae6057f0fefae3982eee6923f2c0a61f0) - Resolve bundled tree-sitter WASM resources from the installed CLI layout so codebase indexing works in packaged CLI and VS Code builds.
## 7.3.2
## 7.3.1
+1 -1
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "7.3.2",
"version": "7.3.6",
"name": "@kilocode/cli",
"type": "module",
"license": "MIT",
@@ -39,9 +39,9 @@ export function Dialog(
width={dimensions().width}
height={dimensions().height}
alignItems="center"
justifyContent="center" // kilocode_change
position="absolute"
zIndex={3000}
paddingTop={dimensions().height / 4}
left={0}
top={0}
backgroundColor={RGBA.fromInts(0, 0, 0, 150)}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@kilocode/plugin",
"version": "7.3.2",
"version": "7.3.6",
"type": "module",
"license": "MIT",
"scripts": {
+1 -1
View File
@@ -12,6 +12,6 @@
"exports": {
".": "./src/index.ts"
},
"version": "7.3.2",
"version": "7.3.6",
"peerDependencies": {}
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@kilocode/sdk",
"version": "7.3.2",
"version": "7.3.6",
"type": "module",
"license": "MIT",
"scripts": {
+1 -1
View File
@@ -26,7 +26,7 @@
"typescript": "catalog:",
"vite": "catalog:"
},
"version": "7.3.2",
"version": "7.3.6",
"dependencies": {},
"peerDependencies": {}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/ui",
"version": "7.3.2",
"version": "7.3.6",
"type": "module",
"license": "MIT",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@kilocode/upstream-merge",
"version": "7.3.2",
"version": "7.3.6",
"private": true,
"type": "module",
"description": "Scripts for automating upstream opencode merges into Kilo",