mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
Merge branch 'main' into utopian-starflower
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"@kilocode/kilo-i18n": "workspace:*",
|
||||
"@kilocode/kilo-ui": "workspace:*",
|
||||
@@ -79,7 +79,7 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode-ai/desktop",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"@opencode-ai/app": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
@@ -112,7 +112,7 @@
|
||||
},
|
||||
"packages/desktop-electron": {
|
||||
"name": "@opencode-ai/desktop-electron",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"@opencode-ai/app": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
@@ -142,7 +142,7 @@
|
||||
},
|
||||
"packages/kilo-docs": {
|
||||
"name": "@kilocode/kilo-docs",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"@docsearch/css": "^4",
|
||||
"@docsearch/js": "^4",
|
||||
@@ -171,7 +171,7 @@
|
||||
},
|
||||
"packages/kilo-gateway": {
|
||||
"name": "@kilocode/kilo-gateway",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "2.0.65",
|
||||
"@ai-sdk/openai": "2.0.101",
|
||||
@@ -206,7 +206,7 @@
|
||||
},
|
||||
"packages/kilo-i18n": {
|
||||
"name": "@kilocode/kilo-i18n",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"devDependencies": {
|
||||
"@tsconfig/node22": "catalog:",
|
||||
"@types/bun": "catalog:",
|
||||
@@ -219,7 +219,7 @@
|
||||
},
|
||||
"packages/kilo-telemetry": {
|
||||
"name": "@kilocode/kilo-telemetry",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"@kilocode/kilo-gateway": "workspace:*",
|
||||
"@opentelemetry/api": "1.9.0",
|
||||
@@ -239,7 +239,7 @@
|
||||
},
|
||||
"packages/kilo-ui": {
|
||||
"name": "@kilocode/kilo-ui",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "0.13.11",
|
||||
"@opencode-ai/util": "workspace:*",
|
||||
@@ -274,7 +274,7 @@
|
||||
},
|
||||
"packages/kilo-vscode": {
|
||||
"name": "kilo-code",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.39.0",
|
||||
"@kilocode/kilo-i18n": "workspace:*",
|
||||
@@ -327,7 +327,7 @@
|
||||
},
|
||||
"packages/opencode": {
|
||||
"name": "@kilocode/cli",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"bin": {
|
||||
"kilo": "./bin/kilo",
|
||||
"kilocode": "./bin/kilo",
|
||||
@@ -451,7 +451,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@kilocode/plugin",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"@kilocode/sdk": "workspace:*",
|
||||
"zod": "catalog:",
|
||||
@@ -465,14 +465,14 @@
|
||||
},
|
||||
"packages/script": {
|
||||
"name": "@opencode-ai/script",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"devDependencies": {
|
||||
"@types/bun": "catalog:",
|
||||
},
|
||||
},
|
||||
"packages/sdk/js": {
|
||||
"name": "@kilocode/sdk",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "0.90.10",
|
||||
"@tsconfig/node22": "catalog:",
|
||||
@@ -483,7 +483,7 @@
|
||||
},
|
||||
"packages/storybook": {
|
||||
"name": "@opencode-ai/storybook",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"devDependencies": {
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
"@solidjs/meta": "catalog:",
|
||||
@@ -506,7 +506,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"@kilocode/sdk": "workspace:*",
|
||||
"@kobalte/core": "catalog:",
|
||||
@@ -553,7 +553,7 @@
|
||||
},
|
||||
"packages/util": {
|
||||
"name": "@opencode-ai/util",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {
|
||||
"zod": "catalog:",
|
||||
},
|
||||
|
||||
+1
-1
@@ -112,6 +112,6 @@
|
||||
"@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch",
|
||||
"ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch"
|
||||
},
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"peerDependencies": {}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop-electron",
|
||||
"private": true,
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"homepage": "https://opencode.ai",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop",
|
||||
"private": true,
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
id = "kilo"
|
||||
name = "Kilo"
|
||||
description = "The open source coding agent."
|
||||
version = "7.1.21"
|
||||
version = "7.1.22"
|
||||
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.1.21/opencode-darwin-arm64.zip"
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.22/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.1.21/opencode-darwin-x64.zip"
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.22/opencode-darwin-x64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.linux-aarch64]
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.21/opencode-linux-arm64.tar.gz"
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.22/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.1.21/opencode-linux-x64.tar.gz"
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.22/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.1.21/opencode-windows-x64.zip"
|
||||
archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.1.22/opencode-windows-x64.zip"
|
||||
cmd = "./opencode.exe"
|
||||
args = ["acp"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kilocode/kilo-docs",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --webpack --port 3002",
|
||||
|
||||
@@ -91,6 +91,43 @@ All fields are optional. When a model ID matches one already in the built-in cat
|
||||
| `provider` | `object` | Override `{ npm?, api? }` — the AI SDK package or base API URL for this model |
|
||||
| `variants` | `object` | Named variant configurations (e.g., different reasoning efforts) |
|
||||
|
||||
### Token Limits (`limit`)
|
||||
|
||||
The `limit` object controls how Kilo manages the model's context window and output length. These values are specified in **tokens**.
|
||||
|
||||
| Sub-field | Type | Required | Description |
|
||||
| --------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `context` | `number` | No | The model's total context window size (e.g., `131072` for a 128K model). Used to determine when conversation history should be compacted to stay within the window. |
|
||||
| `output` | `number` | No | The maximum number of tokens the model can generate in a single response. Sent to the provider as `max_tokens` or equivalent. Capped at 32,000 by default. |
|
||||
| `input` | `number` | No | An optional stricter input limit. Some providers enforce an input token ceiling that is lower than the full context window. When set, compaction triggers against this value instead of `context`. |
|
||||
|
||||
```jsonc
|
||||
"limit": {
|
||||
"context": 131072,
|
||||
"output": 16384
|
||||
}
|
||||
```
|
||||
|
||||
#### How limits are resolved
|
||||
|
||||
Kilo resolves token limits in this order:
|
||||
|
||||
1. **Your config** — values you set under `provider.<id>.models.<model>.limit`
|
||||
2. **Built-in catalog** — Kilo ships a snapshot of [models.dev](https://models.dev) and refreshes it hourly. If your model ID matches a known model, catalog values are used as defaults.
|
||||
3. **Fallback** — if neither source provides a value, `context` and `output` default to `0`.
|
||||
|
||||
#### What happens when limits are `0`
|
||||
|
||||
If you use a custom or local model and don't specify limits — and the model isn't in the built-in catalog — both `context` and `output` resolve to `0`. This has meaningful side effects:
|
||||
|
||||
- **Compaction is disabled.** Kilo uses `context` to detect when the conversation exceeds the model's window and needs to be summarized. With `context: 0`, overflow detection is skipped and conversations will grow unbounded until the provider rejects the request.
|
||||
- **Output falls back to 32,000 tokens.** When `output` is `0`, Kilo uses its internal default of 32,000 tokens (configurable via the `KILO_EXPERIMENTAL_OUTPUT_TOKEN_MAX` environment variable).
|
||||
- **No context usage tracking.** Usage metrics that depend on knowing the context size are skipped.
|
||||
|
||||
{% callout type="warning" %}
|
||||
For custom and local models, always set `limit.context` and `limit.output` to match the model's actual capabilities. Without these values, automatic context management is disabled.
|
||||
{% /callout %}
|
||||
|
||||
## Examples
|
||||
|
||||
### Local model with LM Studio
|
||||
@@ -313,5 +350,6 @@ Control which models appear in the model picker for a provider using allowlists
|
||||
**Model errors or unexpected behavior:**
|
||||
|
||||
- Set `tool_call: true` if you need the model to use tools (file editing, terminal, etc.)
|
||||
- Set `limit.context` and `limit.output` to match the model's actual capabilities
|
||||
- Set `limit.context` and `limit.output` to match the model's actual capabilities — see [Token Limits](#token-limits-limit) above for details and defaults
|
||||
- If conversations seem to grow without being compacted, your `limit.context` is likely `0` (unset)
|
||||
- For local models, ensure your inference server is running and accessible at the configured URL
|
||||
|
||||
@@ -25,3 +25,45 @@ For security reasons, SSH access is currently disabled for all KiloClaw instance
|
||||
Do **not** click **Update Now** inside the OpenClaw Control UI — this is not supported for KiloClaw instances and may break your setup.
|
||||
|
||||
Updates are managed by the KiloClaw platform team to ensure stability. When a new version is available, it will be announced in the **Changelog** on your dashboard. To apply the update, click **Upgrade & Redeploy** from the [KiloClaw Dashboard](/docs/kiloclaw/dashboard#redeploy).
|
||||
|
||||
## How do I migrate my OpenClaw?
|
||||
|
||||
Whether you're migrating from another OpenClaw provider to KiloClaw, moving between KiloClaw instances (e.g., individual to org or vice versa), or leaving KiloClaw for another OpenClaw provider, you should plan to migrate your workspace, memory, and context so your new Claw retains the same knowledge as before.
|
||||
|
||||
You should plan to reconfigure integrations in the new instance as these are often tied to the instance and will break if you attempt migration.
|
||||
|
||||
### 1. Back up your workspace
|
||||
|
||||
Have your current instance export the workspace. We recommend creating a GitHub repo or `tar` archive file for easy loading.
|
||||
|
||||
If you are on KiloClaw, you can use
|
||||
|
||||
**GitHub export** — make sure [GitHub is configured](/docs/kiloclaw/development-tools/github) and ask your instance:
|
||||
|
||||
> Create a new GitHub repo and push your entire workspace there with the `gh` CLI. Tell me the URL of the repo you used.
|
||||
|
||||
**Google Drive** — make sure [Google Drive is configured](/docs/kiloclaw/development-tools/google) and ask your instance:
|
||||
|
||||
> Tar compress your workspace and push the file to Google Drive with the `gog` CLI. Then share the filename you used.
|
||||
|
||||
### 2. Stand up the new instance
|
||||
|
||||
### 3. Reconfigure integrations on the new instance
|
||||
|
||||
If you are using GitHub or Google Drive for the migration, prioritize that configuration.
|
||||
|
||||
### 4. Restore the workspace on the new instance
|
||||
|
||||
On your new Claw, restore the workspace from whichever backup method you used:
|
||||
|
||||
**From GitHub:**
|
||||
|
||||
> The GitHub repo `<repo>` has a backup of your workspace. Pull the workspace from the repo with the `gh` CLI and overwrite the existing workspace directory with the repo's contents.
|
||||
|
||||
**From Google Drive:**
|
||||
|
||||
> The Google Drive file `<filename>` has a backup of your workspace. Pull the tar file from Google Drive with the `gog` CLI and overwrite the existing workspace directory with its contents.
|
||||
|
||||
{% callout type="note" %}
|
||||
Replace `<repo>` or `<filename>` with the actual repository URL or filename from the backup step.
|
||||
{% /callout %}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@kilocode/kilo-gateway",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@kilocode/kilo-i18n",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Kilo-specific i18n translations and overrides",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@kilocode/kilo-telemetry",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"description": "Telemetry for Kilo CLI - PostHog analytics integration",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kilocode/kilo-ui",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
|
||||
@@ -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.1.21",
|
||||
"version": "7.1.22",
|
||||
"icon": "assets/icons/logo-outline-black.png",
|
||||
"galleryBanner": {
|
||||
"color": "#FFFFFF",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Reusable branch selector: search input + scrollable list with keyboard navigation
|
||||
|
||||
import { type Component, For, Show, onMount } from "solid-js"
|
||||
import { type Component, For, Show } from "solid-js"
|
||||
import type { BranchInfo } from "../src/types/messages"
|
||||
import { Icon } from "@kilocode/kilo-ui/icon"
|
||||
import { Spinner } from "@kilocode/kilo-ui/spinner"
|
||||
@@ -34,10 +34,6 @@ interface BranchSelectProps {
|
||||
}
|
||||
|
||||
export const BranchSelect: Component<BranchSelectProps> = (props) => {
|
||||
let ref: HTMLInputElement | undefined
|
||||
|
||||
onMount(() => requestAnimationFrame(() => ref?.focus()))
|
||||
|
||||
const isDefault = (branch: BranchInfo) => {
|
||||
if (props.defaultName) return branch.name === props.defaultName
|
||||
return branch.isDefault
|
||||
@@ -48,7 +44,7 @@ export const BranchSelect: Component<BranchSelectProps> = (props) => {
|
||||
<div class="am-dropdown-search">
|
||||
<Icon name="magnifying-glass" size="small" />
|
||||
<input
|
||||
ref={ref}
|
||||
data-autofocus
|
||||
class="am-dropdown-search-input"
|
||||
type="text"
|
||||
placeholder={props.searchPlaceholder}
|
||||
|
||||
@@ -380,8 +380,10 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
|
||||
setHighlightedIndex(0)
|
||||
}
|
||||
}}
|
||||
placement="bottom-start"
|
||||
placement="top-start"
|
||||
flip={false}
|
||||
sameWidth
|
||||
portal={false}
|
||||
class="am-dropdown"
|
||||
trigger={
|
||||
<button class="am-selector-trigger" type="button">
|
||||
@@ -625,8 +627,10 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
|
||||
<Popover
|
||||
open={branchOpen()}
|
||||
onOpenChange={setBranchOpen}
|
||||
placement="bottom-start"
|
||||
placement="top-start"
|
||||
flip={false}
|
||||
sameWidth
|
||||
portal={false}
|
||||
class="am-dropdown"
|
||||
trigger={
|
||||
<button class="am-selector-trigger" disabled={isPending()} type="button">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"name": "@kilocode/cli",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -31,6 +31,8 @@ export namespace FileIgnore {
|
||||
"mypy_cache",
|
||||
".history",
|
||||
".gradle",
|
||||
".kilocode", // kilocode_change — ignore legacy local storage (#8379)
|
||||
".opencode", // kilocode_change — ignore legacy local storage (#8379)
|
||||
])
|
||||
|
||||
const FILES = [
|
||||
|
||||
@@ -187,8 +187,31 @@ export namespace Snapshot {
|
||||
ref: "FileDiff",
|
||||
})
|
||||
export type FileDiff = z.infer<typeof FileDiff>
|
||||
|
||||
// kilocode_change start — cache diffFull results to prevent redundant git spawning (#8379)
|
||||
const diffCache = new Map<string, Promise<FileDiff[]>>()
|
||||
const DIFF_CACHE_MAX = 100
|
||||
|
||||
export async function diffFull(from: string, to: string): Promise<FileDiff[]> {
|
||||
if (from === to) return []
|
||||
const key = `${from}:${to}`
|
||||
const cached = diffCache.get(key)
|
||||
if (cached) return cached
|
||||
if (diffCache.size >= DIFF_CACHE_MAX) {
|
||||
const first = diffCache.keys().next().value
|
||||
if (first) diffCache.delete(first)
|
||||
}
|
||||
const pending = diffFullUncached(from, to).catch((err) => {
|
||||
diffCache.delete(key)
|
||||
throw err
|
||||
})
|
||||
diffCache.set(key, pending)
|
||||
return pending
|
||||
}
|
||||
|
||||
async function diffFullUncached(from: string, to: string): Promise<FileDiff[]> {
|
||||
const git = await KiloSnapshot.prepare() // kilocode_change
|
||||
// kilocode_change end
|
||||
const result: FileDiff[] = []
|
||||
const status = new Map<string, "added" | "deleted" | "modified">()
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import { test, expect } from "bun:test"
|
||||
import { $ } from "bun"
|
||||
import { Snapshot } from "../../src/snapshot"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { Filesystem } from "../../src/util/filesystem"
|
||||
import { tmpdir } from "../fixture/fixture"
|
||||
|
||||
async function bootstrap() {
|
||||
return tmpdir({
|
||||
git: true,
|
||||
init: async (dir) => {
|
||||
await Filesystem.write(`${dir}/a.txt`, "A")
|
||||
await Filesystem.write(`${dir}/b.txt`, "B")
|
||||
await $`git add .`.cwd(dir).quiet()
|
||||
await $`git commit --no-gpg-sign -m init`.cwd(dir).quiet()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
test("diffFull returns cached result for same hash pair", async () => {
|
||||
await using tmp = await bootstrap()
|
||||
await Instance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const before = await Snapshot.track()
|
||||
expect(before).toBeTruthy()
|
||||
|
||||
await Filesystem.write(`${tmp.path}/a.txt`, "MODIFIED")
|
||||
const after = await Snapshot.track()
|
||||
expect(after).toBeTruthy()
|
||||
expect(after).not.toBe(before)
|
||||
|
||||
const first = await Snapshot.diffFull(before!, after!)
|
||||
const second = await Snapshot.diffFull(before!, after!)
|
||||
|
||||
// Should be the exact same array reference (cached)
|
||||
expect(second).toBe(first)
|
||||
expect(first.length).toBeGreaterThan(0)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("diffFull returns empty array when from === to", async () => {
|
||||
await using tmp = await bootstrap()
|
||||
await Instance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const hash = await Snapshot.track()
|
||||
expect(hash).toBeTruthy()
|
||||
|
||||
const result = await Snapshot.diffFull(hash!, hash!)
|
||||
expect(result).toEqual([])
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("diffFull concurrent calls for same pair share one result", async () => {
|
||||
await using tmp = await bootstrap()
|
||||
await Instance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const before = await Snapshot.track()
|
||||
expect(before).toBeTruthy()
|
||||
|
||||
await Filesystem.write(`${tmp.path}/a.txt`, "CONCURRENT")
|
||||
const after = await Snapshot.track()
|
||||
expect(after).toBeTruthy()
|
||||
|
||||
// Fire multiple concurrent calls — they should all resolve to the same object
|
||||
const results = await Promise.all([
|
||||
Snapshot.diffFull(before!, after!),
|
||||
Snapshot.diffFull(before!, after!),
|
||||
Snapshot.diffFull(before!, after!),
|
||||
])
|
||||
|
||||
expect(results[0]).toBe(results[1])
|
||||
expect(results[1]).toBe(results[2])
|
||||
expect(results[0].length).toBeGreaterThan(0)
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@kilocode/plugin",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {},
|
||||
"peerDependencies": {}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@kilocode/sdk",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"typescript": "catalog:",
|
||||
"vite": "catalog:"
|
||||
},
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"dependencies": {},
|
||||
"peerDependencies": {}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
|
||||
@@ -59,6 +59,14 @@ export function Popover<T extends ValidComponent = "div">(props: PopoverProps<T>
|
||||
return uncontrolledOpen()
|
||||
}
|
||||
|
||||
const focus = (node?: ParentNode | null) => {
|
||||
const root = node ?? contentRef()
|
||||
if (!root) return
|
||||
const target = root.querySelector<HTMLElement>("[data-autofocus]")
|
||||
if (!target) return
|
||||
target.focus()
|
||||
}
|
||||
|
||||
const onOpenChange = (next: boolean) => {
|
||||
if (next) setDismiss(null)
|
||||
if (local.onOpenChange) local.onOpenChange(next)
|
||||
@@ -135,6 +143,14 @@ export function Popover<T extends ValidComponent = "div">(props: PopoverProps<T>
|
||||
})
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
if (!opened()) return
|
||||
const node = contentRef()
|
||||
if (!node) return
|
||||
const id = requestAnimationFrame(() => focus(node))
|
||||
onCleanup(() => cancelAnimationFrame(id))
|
||||
})
|
||||
|
||||
const content = () => (
|
||||
<Kobalte.Content
|
||||
ref={(el: HTMLElement | undefined) => setContentRef(el)}
|
||||
@@ -153,6 +169,12 @@ export function Popover<T extends ValidComponent = "div">(props: PopoverProps<T>
|
||||
onFocusOutside={(event: Event) => {
|
||||
event.preventDefault()
|
||||
}}
|
||||
onOpenAutoFocus={(event: Event) => {
|
||||
const node = event.currentTarget as ParentNode | null
|
||||
if (!node) return
|
||||
event.preventDefault()
|
||||
focus(node)
|
||||
}}
|
||||
onCloseAutoFocus={(event: Event) => {
|
||||
if (dismiss() === "outside") event.preventDefault()
|
||||
setDismiss(null)
|
||||
|
||||
@@ -30,6 +30,7 @@ function init() {
|
||||
const [active, setActive] = createSignal<Active | undefined>()
|
||||
const timer = { current: undefined as ReturnType<typeof setTimeout> | undefined }
|
||||
const lock = { value: false }
|
||||
const hasPopover = () => !!document.querySelector('[data-component="popover-content"]')
|
||||
|
||||
onCleanup(() => {
|
||||
if (timer.current === undefined) return
|
||||
@@ -63,6 +64,7 @@ function init() {
|
||||
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key !== "Escape") return
|
||||
if (hasPopover()) return
|
||||
close()
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/util",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kilocode/upstream-merge",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "Scripts for automating upstream opencode merges into Kilo",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "opencode",
|
||||
"displayName": "opencode",
|
||||
"description": "opencode for VS Code",
|
||||
"version": "7.1.21",
|
||||
"version": "7.1.22",
|
||||
"publisher": "sst-dev",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
Reference in New Issue
Block a user