From 190b4a4dc6ed38a71978a82c4cc2d3e0824106e7 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Wed, 19 Aug 2026 16:15:49 +0200 Subject: [PATCH 01/18] feat(vscode): add Agent Manager document inspector --- .changeset/rendered-document-inspector.md | 5 + .../kilo-ui/src/components/message-part.css | 2 + .../kilo-ui/src/components/message-part.tsx | 21 +- packages/kilo-vscode/src/KiloProvider.ts | 10 + .../src/agent-manager/AgentManagerProvider.ts | 24 +- .../src/agent-manager/document-reader.ts | 49 +++ .../kilo-vscode/src/agent-manager/types.ts | 20 ++ .../agent-manager/worktree-diff-controller.ts | 36 ++ .../src/diff/DiffViewerProvider.ts | 20 +- packages/kilo-vscode/src/diff/types.ts | 4 + packages/kilo-vscode/src/extension.ts | 1 + .../src/kilo-provider/editor-actions.ts | 10 +- .../tests/unit/agent-manager-arch.test.ts | 2 + .../tests/unit/agent-manager-i18n.test.ts | 2 + .../tests/unit/document-reader.test.ts | 33 ++ .../agent-manager/AgentManagerApp.tsx | 40 ++- .../webview-ui/agent-manager/ClosableTab.tsx | 14 +- .../webview-ui/agent-manager/DiffPanel.tsx | 15 + .../webview-ui/agent-manager/TabBar.tsx | 15 + .../agent-manager/agent-manager.css | 127 +++++++ .../agent-manager/documents/DocumentPanel.tsx | 315 ++++++++++++++++++ .../documents/DocumentPanelHost.tsx | 28 ++ .../agent-manager/documents/state.ts | 172 ++++++++++ .../webview-ui/agent-manager/i18n/ar.ts | 8 + .../webview-ui/agent-manager/i18n/br.ts | 8 + .../webview-ui/agent-manager/i18n/bs.ts | 8 + .../webview-ui/agent-manager/i18n/da.ts | 8 + .../webview-ui/agent-manager/i18n/de.ts | 8 + .../webview-ui/agent-manager/i18n/en.ts | 8 + .../webview-ui/agent-manager/i18n/es.ts | 8 + .../webview-ui/agent-manager/i18n/fa.ts | 8 + .../webview-ui/agent-manager/i18n/fr.ts | 8 + .../webview-ui/agent-manager/i18n/it.ts | 8 + .../webview-ui/agent-manager/i18n/ja.ts | 8 + .../webview-ui/agent-manager/i18n/ko.ts | 8 + .../webview-ui/agent-manager/i18n/nl.ts | 8 + .../webview-ui/agent-manager/i18n/no.ts | 8 + .../webview-ui/agent-manager/i18n/pl.ts | 8 + .../webview-ui/agent-manager/i18n/ru.ts | 8 + .../webview-ui/agent-manager/i18n/th.ts | 8 + .../webview-ui/agent-manager/i18n/tr.ts | 8 + .../webview-ui/agent-manager/i18n/uk.ts | 8 + .../webview-ui/agent-manager/i18n/zh.ts | 8 + .../webview-ui/agent-manager/i18n/zht.ts | 8 + .../agent-manager/side-panel-layout.ts | 1 + .../webview-ui/diff-viewer/DiffViewerApp.tsx | 10 + .../diff-viewer/FullScreenDiffView.tsx | 5 +- .../diff-viewer/MarkdownAnnotationLayer.tsx | 8 +- .../diff-viewer/MarkdownDiffView.tsx | 4 +- packages/kilo-vscode/webview-ui/src/App.tsx | 5 + .../src/components/chat/AssistantMessage.tsx | 1 + .../webview-ui/src/styles/plan-exit.css | 27 ++ .../src/types/messages/extension-messages.ts | 25 ++ .../src/types/messages/webview-messages.ts | 7 + .../opencode/src/kilocode/session/prompt.ts | 1 + packages/ui/src/components/markdown.css | 19 ++ packages/ui/src/i18n/ar.ts | 1 + packages/ui/src/i18n/az.ts | 1 + packages/ui/src/i18n/br.ts | 1 + packages/ui/src/i18n/bs.ts | 1 + packages/ui/src/i18n/da.ts | 1 + packages/ui/src/i18n/de.ts | 1 + packages/ui/src/i18n/en.ts | 1 + packages/ui/src/i18n/es.ts | 1 + packages/ui/src/i18n/fi.ts | 1 + packages/ui/src/i18n/fr.ts | 1 + packages/ui/src/i18n/hi.ts | 1 + packages/ui/src/i18n/id.ts | 1 + packages/ui/src/i18n/it.ts | 1 + packages/ui/src/i18n/ja.ts | 1 + packages/ui/src/i18n/ko.ts | 1 + packages/ui/src/i18n/nl.ts | 1 + packages/ui/src/i18n/no.ts | 1 + packages/ui/src/i18n/pa.ts | 1 + packages/ui/src/i18n/pl.ts | 1 + packages/ui/src/i18n/ru.ts | 1 + packages/ui/src/i18n/sv.ts | 1 + packages/ui/src/i18n/th.ts | 1 + packages/ui/src/i18n/tr.ts | 1 + packages/ui/src/i18n/uk.ts | 1 + packages/ui/src/i18n/ur.ts | 1 + packages/ui/src/i18n/vi.ts | 1 + packages/ui/src/i18n/zh.ts | 1 + packages/ui/src/i18n/zht.ts | 1 + 84 files changed, 1229 insertions(+), 45 deletions(-) create mode 100644 .changeset/rendered-document-inspector.md create mode 100644 packages/kilo-vscode/src/agent-manager/document-reader.ts create mode 100644 packages/kilo-vscode/tests/unit/document-reader.test.ts create mode 100644 packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx create mode 100644 packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx create mode 100644 packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts diff --git a/.changeset/rendered-document-inspector.md b/.changeset/rendered-document-inspector.md new file mode 100644 index 0000000000..a625b494b3 --- /dev/null +++ b/.changeset/rendered-document-inspector.md @@ -0,0 +1,5 @@ +--- +"kilo-code": minor +--- + +Add an Agent Manager document inspector that previews Markdown and text files, with inline Markdown review comments that can be sent to the agent. diff --git a/packages/kilo-ui/src/components/message-part.css b/packages/kilo-ui/src/components/message-part.css index c7991e9392..9272fa8496 100644 --- a/packages/kilo-ui/src/components/message-part.css +++ b/packages/kilo-ui/src/components/message-part.css @@ -119,6 +119,7 @@ color: var(--text-base); } } + } [data-slot="message-part-title-filename"] { @@ -154,6 +155,7 @@ direction: rtl; text-align: left; } + } /* Task tool child-session tool list (v1.0.25 style) */ diff --git a/packages/kilo-ui/src/components/message-part.tsx b/packages/kilo-ui/src/components/message-part.tsx index 8300f6943f..0c561d3710 100644 --- a/packages/kilo-ui/src/components/message-part.tsx +++ b/packages/kilo-ui/src/components/message-part.tsx @@ -1427,10 +1427,13 @@ PART_MAPPING["text"] = function TextPartDisplay(props) { if (!exists) { el.classList.remove("file-link-candidate") el.classList.remove("file-link") + el.classList.remove("plan-document-link") el.removeAttribute("data-file-candidate") el.removeAttribute("data-file-path") + el.removeAttribute("data-file-kind") el.removeAttribute("data-file-line") el.removeAttribute("data-file-col") + el.removeAttribute("title") return } // Strip ./ prefix for the click handler — VS Code resolves relative @@ -1440,6 +1443,16 @@ PART_MAPPING["text"] = function TextPartDisplay(props) { el.classList.add("file-link") el.setAttribute("data-file-path", clean) el.removeAttribute("data-file-candidate") + // A plan document gets a document glyph and a localized kind hint instead of + // an inline badge, so the reference stays readable inside a sentence. + el.classList.remove("plan-document-link") + el.removeAttribute("data-file-kind") + el.removeAttribute("title") + if (/(?:^|\/)(?:plans|\.plans?)\/.*\.md$/i.test(clean)) { + el.classList.add("plan-document-link") + el.setAttribute("data-file-kind", "plan") + el.setAttribute("title", i18n.t("ui.patch.action.plan")) + } } const dispatch = (el: HTMLElement, p: string) => { @@ -2053,9 +2066,9 @@ ToolRegistry.register({ animate={props.reveal} onClick={data.openFile ? () => data.openFile!(filepath) : undefined} /> - )} + )} - 0}> + 0}>
{(file) => ( @@ -2941,7 +2954,9 @@ ToolRegistry.register({ { if (!data.openFile) return e.stopPropagation() diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index c288da5bf8..988679918a 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -465,6 +465,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper private createWorktreeHandler: ((baseBranch?: string, branchName?: string) => Promise) | null = null private diffVirtualProvider: import("./DiffVirtualProvider").DiffVirtualProvider | undefined + private diffViewerProvider: import("./diff/DiffViewerProvider").DiffViewerProvider | undefined private remoteService: RemoteStatusService | null = null private unsubscribeRemote: (() => void) | null = null private readonly requirements: AgentRequirementsController @@ -582,6 +583,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.diffVirtualProvider = provider } + public setDiffViewerProvider(provider: import("./diff/DiffViewerProvider").DiffViewerProvider): void { + this.diffViewerProvider = provider + } + getTelemetryProperties(): Record { return { appName: "kilo-code", @@ -1604,6 +1609,11 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper // the live currentSession — see editor-actions.ts's validateFiles case. dir: (sessionID) => this.getWorkspaceDirectory(sessionID ?? this.currentSession?.id), diff: this.diffVirtualProvider, + openMarkdown: (file, sessionID) => { + if (!this.diffViewerProvider) return false + this.diffViewerProvider.openFromCommand({ sessionId: sessionID, file }) + return true + }, storage: this.extensionContext?.globalStorageUri, post: (msg) => this.postMessage(msg), }) diff --git a/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts b/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts index 8cfab373fa..ed59d29acb 100644 --- a/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts +++ b/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts @@ -855,39 +855,21 @@ export class AgentManagerProvider implements Disposable { return null } if (m.type === "agentManager.requestDiffBranches") { - void this.sendDiffBranches(m.sessionId, m.scope) + void this.diffs.postBranches(composeDiffId(m.sessionId, normalizeScope(m.scope))) return null } if (m.type === "agentManager.setDiffBaseBranch") { void this.diffs .setBase(composeDiffId(m.sessionId, normalizeScope(m.scope)), m.branch) .catch((err) => this.log("Failed to set diff base:", err instanceof Error ? err.message : String(err))) - .then(() => void this.sendDiffBranches(m.sessionId, m.scope)) + .then(() => void this.diffs.postBranches(composeDiffId(m.sessionId, normalizeScope(m.scope)))) return null } if (m.type === "agentManager.openFile") { this.openWorktreeFile(m.sessionId, m.filePath, m.line, m.column) return null } - } - - private async sendDiffBranches(sessionId: string, scope?: string): Promise { - const id = composeDiffId(sessionId, normalizeScope(scope)) - const result = await this.diffs.branches(id).catch((err) => { - this.log("Failed to list diff branches:", err instanceof Error ? err.message : String(err)) - return undefined - }) - if (!result) return - this.postToWebview({ - type: "agentManager.diffBranches", - sessionId: id, - branches: result.branches, - defaultBranch: result.defaultBranch, - autoBase: result.autoBase, - currentBase: result.currentBase, - isAuto: result.isAuto, - currentBranch: result.currentBranch, - }) + if (m.type === "agentManager.requestDocument") return this.diffs.document(m.sessionId, m.file) } private onBridgeMessage(m: AgentManagerInMessage): Record | null | undefined { diff --git a/packages/kilo-vscode/src/agent-manager/document-reader.ts b/packages/kilo-vscode/src/agent-manager/document-reader.ts new file mode 100644 index 0000000000..7765394bfe --- /dev/null +++ b/packages/kilo-vscode/src/agent-manager/document-reader.ts @@ -0,0 +1,49 @@ +import * as fs from "fs" +import * as path from "path" + +const MAX_TEXT_BYTES = 2_000_000 +const MAX_IMAGE_BYTES = 5_000_000 + +export type DocumentResult = + | { file: string; kind: "text"; content: string } + | { file: string; kind: "image"; mime: string; data: string } + | { error: string } + +function mime(file: string): string | undefined { + const ext = path.extname(file).toLowerCase() + if (ext === ".png") return "image/png" + if (ext === ".jpg" || ext === ".jpeg") return "image/jpeg" + if (ext === ".gif") return "image/gif" + if (ext === ".webp") return "image/webp" + if (ext === ".svg") return "image/svg+xml" + return undefined +} + +export function readDocument(root: string, file: string): DocumentResult { + if (!file) return { error: "Invalid document path." } + + try { + const base = fs.realpathSync(root) + const target = path.isAbsolute(file) ? file : path.resolve(root, file) + const resolved = fs.realpathSync(target) + if (resolved !== base && !resolved.startsWith(base + path.sep)) + return { error: "Document is outside the worktree." } + + const stat = fs.statSync(resolved) + if (!stat.isFile()) return { error: "Document is not a file." } + + const type = mime(resolved) + const limit = type ? MAX_IMAGE_BYTES : MAX_TEXT_BYTES + if (stat.size > limit) return { error: "Document is too large to preview." } + + const relative = path.relative(base, resolved).split(path.sep).join("/") + if (type) return { file: relative, kind: "image", mime: type, data: fs.readFileSync(resolved).toString("base64") } + + const content = fs.readFileSync(resolved) + if (content.includes(0)) return { error: "Binary files cannot be previewed." } + return { file: relative, kind: "text", content: content.toString("utf8") } + } catch (error) { + console.error("[Kilo New] AgentManagerProvider: Cannot read document:", error) + return { error: "Document could not be read." } + } +} diff --git a/packages/kilo-vscode/src/agent-manager/types.ts b/packages/kilo-vscode/src/agent-manager/types.ts index edfa7666f6..42743183b9 100644 --- a/packages/kilo-vscode/src/agent-manager/types.ts +++ b/packages/kilo-vscode/src/agent-manager/types.ts @@ -362,6 +362,18 @@ interface WorktreeDiffFileMessage { diff: WorktreeDiffEntry | null } +interface DocumentMessage { + type: "agentManager.document" + sessionId: string + file: string + requestedFile?: string + content?: string + kind?: "text" | "image" + mime?: string + data?: string + error?: string +} + interface RevertWorktreeFileResultMessage { type: "agentManager.revertWorktreeFileResult" sessionId: string @@ -440,6 +452,7 @@ export type AgentManagerOutMessage = | WorktreeDiffNoticeMessage | WorktreeDiffMessage | WorktreeDiffFileMessage + | DocumentMessage | RevertWorktreeFileResultMessage | DiffBranchesMessage | PRStatusOutMessage @@ -787,6 +800,12 @@ interface OpenFileIn { column?: number } +interface RequestDocumentIn { + type: "agentManager.requestDocument" + sessionId: string + file: string +} + // Pass-through messages intercepted for side effects interface GenericOpenFileIn { type: "openFile" @@ -1065,6 +1084,7 @@ export type AgentManagerInMessage = | OpenSessionsIn | VisibleSessionIn | OpenFileIn + | RequestDocumentIn | GenericOpenFileIn | PreviewImageIn | SaveImageIn diff --git a/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts b/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts index b8a4b269e7..80caa2bbbf 100644 --- a/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts +++ b/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts @@ -8,6 +8,7 @@ import type { ApplyConflict, GitOps } from "./GitOps" import { shouldStopDiffPolling } from "./delete-worktree" import { remoteRef, type ManagedSession, type WorktreeStateManager } from "./WorktreeStateManager" import { parseDiffId, scopeToSourceId } from "./diff-scope" +import { readDocument } from "./document-reader" import type { AgentManagerOutMessage, WorktreeDiffEntry } from "./types" const LOCAL_DIFF_ID = "local" as const @@ -182,6 +183,41 @@ export class WorktreeDiffController { await this.controller.requestFile(file) } + /** Resolve the base-branch choices for a context and push them to the webview. */ + public async postBranches(id: string): Promise { + const result = await this.branches(id).catch((err) => { + this.ctx.log("Failed to list diff branches:", err instanceof Error ? err.message : String(err)) + return undefined + }) + if (!result) return + this.ctx.post({ + type: "agentManager.diffBranches", + sessionId: id, + branches: result.branches, + defaultBranch: result.defaultBranch, + autoBase: result.autoBase, + currentBase: result.currentBase, + isAuto: result.isAuto, + currentBranch: result.currentBranch, + }) + } + + /** + * Read one file from a worktree for the document inspector. Reuses this + * controller's state/root context because a document read is a worktree file + * read, resolved against the same directory the diff for that context uses. + */ + public document(sessionId: string, file: string): null { + const state = this.ctx.getState() + const worktree = state?.getWorktree(sessionId) + const session = worktree ? undefined : state?.getSession(sessionId) + const root = + worktree?.path ?? (session?.worktreeId ? state?.getWorktree(session.worktreeId)?.path : this.ctx.getRoot()) + if (!root) return null + this.ctx.post({ type: "agentManager.document", sessionId, file, requestedFile: file, ...readDocument(root, file) }) + return null + } + public start(id: string): void { if (this.controller.isPolling && this.controller.currentId === id) return this.ctx.log(`Starting diff polling for ${id}`) diff --git a/packages/kilo-vscode/src/diff/DiffViewerProvider.ts b/packages/kilo-vscode/src/diff/DiffViewerProvider.ts index c17b5a34f4..b517e469a9 100644 --- a/packages/kilo-vscode/src/diff/DiffViewerProvider.ts +++ b/packages/kilo-vscode/src/diff/DiffViewerProvider.ts @@ -55,6 +55,11 @@ export class DiffViewerProvider implements vscode.Disposable { if (this.panel && this.controller) { this.panel.reveal(this.panel.viewColumn ?? vscode.ViewColumn.One) + void this.panel.webview.postMessage({ type: "diffViewer.initialFile", file: this.ctx.initialFile }) + void this.panel.webview.postMessage({ + type: "diffViewer.initialMarkdown", + render: this.ctx.initialMarkdown === true, + }) this.controller.setContext(this.ctx) const nextId = this.catalog.defaultSourceId(this.ctx) if (nextId && nextId !== this.controller.currentId) { @@ -77,7 +82,13 @@ export class DiffViewerProvider implements vscode.Disposable { * the source picker hidden — the view becomes a static "diff of this turn" * rather than the switchable workspace/session viewer. */ - openFromCommand(arg?: { sessionId?: string; turnId?: string; initialSourceId?: string; directory?: string }): void { + openFromCommand(arg?: { + sessionId?: string + turnId?: string + initialSourceId?: string + directory?: string + file?: string + }): void { const sessionId = arg?.sessionId ?? this.sessionIdProvider() const explicit = !!arg && "directory" in arg const dir = explicit ? arg.directory : sessionId ? this.sessionDirectoryProvider(sessionId) : undefined @@ -87,6 +98,8 @@ export class DiffViewerProvider implements vscode.Disposable { sessionId, dir, initialSourceId: turnInitialSourceId ?? arg?.initialSourceId, + initialFile: arg?.file, + initialMarkdown: typeof arg?.file === "string" && /\.(md|mdx|markdown)$/i.test(arg.file), hidePicker: !!turnInitialSourceId, }) } @@ -229,6 +242,11 @@ export class DiffViewerProvider implements vscode.Disposable { workspaceDirectory: this.ctx?.dir ?? getWorkspaceRoot(), }) void this.panel.webview.postMessage({ type: "diffViewer.markdownRender", render: getDiffMarkdownRender() }) + void this.panel.webview.postMessage({ type: "diffViewer.initialFile", file: this.ctx?.initialFile }) + void this.panel.webview.postMessage({ + type: "diffViewer.initialMarkdown", + render: this.ctx?.initialMarkdown === true, + }) const initial = this.ctx ? this.catalog.defaultSourceId(this.ctx) : undefined if (initial) this.swap(initial) } diff --git a/packages/kilo-vscode/src/diff/types.ts b/packages/kilo-vscode/src/diff/types.ts index 3ff72904e1..b8b5c01574 100644 --- a/packages/kilo-vscode/src/diff/types.ts +++ b/packages/kilo-vscode/src/diff/types.ts @@ -3,6 +3,10 @@ export interface PanelContext { sessionId?: string /** Overrides the computed default source on open. */ initialSourceId?: string + /** Select a file when the source first loads. */ + initialFile?: string + /** Render Markdown when the viewer was opened from a Markdown file link. */ + initialMarkdown?: boolean /** * Hides the source picker header in the diff viewer. Used for panels that * open in a fixed view (e.g. a specific turn's diff) diff --git a/packages/kilo-vscode/src/extension.ts b/packages/kilo-vscode/src/extension.ts index 88e498254c..0d1d0b748f 100644 --- a/packages/kilo-vscode/src/extension.ts +++ b/packages/kilo-vscode/src/extension.ts @@ -278,6 +278,7 @@ export function activate(context: vscode.ExtensionContext) { diffViewerProvider.setCommentHandler((comments, autoSend) => { void provider.appendReviewComments(comments, autoSend) }) + provider.setDiffViewerProvider(diffViewerProvider) context.subscriptions.push(diffViewerProvider) // Create diff virtual provider (lightweight single-file diff for permission approval) diff --git a/packages/kilo-vscode/src/kilo-provider/editor-actions.ts b/packages/kilo-vscode/src/kilo-provider/editor-actions.ts index 982c587045..f639b46b7f 100644 --- a/packages/kilo-vscode/src/kilo-provider/editor-actions.ts +++ b/packages/kilo-vscode/src/kilo-provider/editor-actions.ts @@ -14,6 +14,10 @@ type EditorOpenMessage = { sessionID?: string } +function isMarkdownFile(file: string): boolean { + return /\.(md|mdx|markdown)$/i.test(file) +} + function openExternal(url: unknown): void { if (typeof url !== "string") return void vscode.env.openExternal(vscode.Uri.parse(url)) @@ -76,6 +80,7 @@ export function handleEditorAction( opts: { dir: (sessionID?: string) => string diff?: DiffVirtualProvider + openMarkdown?: (file: string, sessionID?: string) => boolean storage?: vscode.Uri post?: (msg: unknown) => void }, @@ -84,7 +89,10 @@ export function handleEditorAction( // Resolve the directory from the session the file reference was rendered // for (when the webview provides it), not whatever session happens to be // current — mirrors the validateFiles case below. - if (message.filePath) openFile(opts.dir(message.sessionID), message.filePath, message.line, message.column) + if (message.filePath) { + if (isMarkdownFile(message.filePath) && opts.openMarkdown?.(message.filePath, message.sessionID)) return true + openFile(opts.dir(message.sessionID), message.filePath, message.line, message.column) + } return true } if (message.type === "openContent") { diff --git a/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts index 84c63ad8d3..2eac3c5959 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts @@ -27,6 +27,8 @@ const TSX_FILES = [ path.join(ROOT, "webview-ui/agent-manager/ProjectSelect.tsx"), path.join(ROOT, "webview-ui/agent-manager/sortable-tab.tsx"), path.join(ROOT, "webview-ui/agent-manager/DiffPanel.tsx"), + path.join(ROOT, "webview-ui/agent-manager/documents/DocumentPanel.tsx"), + path.join(ROOT, "webview-ui/agent-manager/documents/DocumentPanelHost.tsx"), path.join(ROOT, "webview-ui/diff-viewer/FullScreenDiffView.tsx"), path.join(ROOT, "webview-ui/diff-viewer/ImageDiffView.tsx"), path.join(ROOT, "webview-ui/diff-viewer/MarkdownDiffView.tsx"), diff --git a/packages/kilo-vscode/tests/unit/agent-manager-i18n.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-i18n.test.ts index 8142d2c20c..bf9cbea424 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-i18n.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-i18n.test.ts @@ -28,6 +28,8 @@ const TSX_FILES = [ path.join(ROOT, "webview-ui/agent-manager/sortable-tab.tsx"), path.join(ROOT, "webview-ui/agent-manager/terminal/SideTerminalPanel.tsx"), path.join(ROOT, "webview-ui/agent-manager/terminal/TerminalDestinationButton.tsx"), + path.join(ROOT, "webview-ui/agent-manager/documents/DocumentPanel.tsx"), + path.join(ROOT, "webview-ui/agent-manager/documents/DocumentPanelHost.tsx"), ] /** diff --git a/packages/kilo-vscode/tests/unit/document-reader.test.ts b/packages/kilo-vscode/tests/unit/document-reader.test.ts new file mode 100644 index 0000000000..3de360d0ba --- /dev/null +++ b/packages/kilo-vscode/tests/unit/document-reader.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, it } from "bun:test" +import * as fs from "node:fs" +import * as os from "node:os" +import * as path from "node:path" +import { readDocument } from "../../src/agent-manager/document-reader" + +function workspace() { + return fs.mkdtempSync(path.join(os.tmpdir(), "kilo-document-")) +} + +describe("readDocument", () => { + it("reads text files inside the worktree", () => { + const root = workspace() + fs.writeFileSync(path.join(root, "plan.md"), "# Plan\n") + + expect(readDocument(root, "plan.md")).toEqual({ file: "plan.md", kind: "text", content: "# Plan\n" }) + }) + + it("rejects paths outside the worktree", () => { + const root = workspace() + const outside = path.join(root, "..", "outside.md") + fs.writeFileSync(outside, "secret") + + expect(readDocument(root, "../outside.md")).toEqual({ error: "Document is outside the worktree." }) + }) + + it("rejects binary files", () => { + const root = workspace() + fs.writeFileSync(path.join(root, "data.bin"), Buffer.from([1, 0, 2])) + + expect(readDocument(root, "data.bin")).toEqual({ error: "Binary files cannot be previewed." }) + }) +}) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx index 10e72057ad..841c629225 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx @@ -180,6 +180,8 @@ import { setTabWidths } from "./tab-widths" import { clampPanelWidth, createPanelResize, maxPanelWidth, minPanelWidth, SidePanel } from "./side-panel-layout" import { SubagentPanel } from "./SubagentPanel" import { createSubagentTabs } from "./subagent-tabs" +import { DocumentPanelHost } from "./documents/DocumentPanelHost" +import { createDocumentInspector } from "./documents/state" import { buildShortcutCategories } from "./shortcuts" import { tracker } from "./telemetry" import { createChatFocus, createPromptFocus, hasQuestionOption } from "./focus" @@ -296,6 +298,7 @@ const AgentManagerContent: Component = () => { const [sidePanel, setSidePanel] = createSignal(null) const diffOpen = () => sidePanel() === SidePanel.Diff const prOpen = () => sidePanel() === SidePanel.PR + const documentsOpen = () => sidePanel() === SidePanel.Documents const activePR = createMemo(() => { const selected = selection() if (!selected || selected === LOCAL) return undefined @@ -308,8 +311,7 @@ const AgentManagerContent: Component = () => { const diffLoading = diffs.diffLoading const setDiffLoading = diffs.setDiffLoading const diffNotices = diffs.diffNotices - // Diff, PR, terminal, and subagent views share one inspector width, restored - // from webview state so the user's divider position survives panel reloads. + // Diff, PR, terminal, and subagent views share one inspector width. const [panelWidth, setPanelWidth] = createSignal(clampPanelWidth(persisted?.sidePanelWidth, window.innerWidth)) const resizeSide = createPanelResize(setPanelWidth, () => window.innerWidth) const showSideTerminal = () => { @@ -323,6 +325,17 @@ const AgentManagerContent: Component = () => { const reviewComposer = createReviewComposer() const [reviewActive, setReviewActive] = createSignal(false) const [reviewDiffStyle, setReviewDiffStyle] = createSignal<"unified" | "split">("unified") + const documentInspector = createDocumentInspector( + vscode, + selection, + documentsOpen, + () => { + setHistory(false) + setReviewActive(false) + setSidePanel(SidePanel.Documents) + }, + () => setSidePanel(null), + ) const subagents = createSubagentTabs({ current: session.currentSessionID, sync: (id, parentID) => session.syncSession(id, parentID, "inspector"), @@ -335,17 +348,14 @@ const AgentManagerContent: Component = () => { hide: () => setSidePanel(null), }) const markdown = createMarkdownRender(vscode) - // Per-worktree git stats (diff additions/deletions, commits missing from origin) const worktreeStats = () => registry.active().worktreeStats() const prStatuses = () => registry.active().prStatuses() - const runStatuses = () => registry.active().runStatuses() const setRunStatuses: Setter> = (v) => registry.active().setRunStatuses(v) const runScriptConfigured = () => registry.active().runScriptConfigured() const setRunScriptConfigured = (v: Parameters>[0]) => registry.active().setRunScriptConfigured(v) - // Local repo git stats (branch name, diff additions/deletions, commits) const localStats = () => registry.active().localStats() const projectLive = createProjectLive({ @@ -495,15 +505,9 @@ const AgentManagerContent: Component = () => { ) onCleanup(() => clearTimeout(pendingDeleteTimer)) - // Per-context tab memory lives in the active project's store: maps sidebar - // selection ("local" or a worktree id) -> last active session/pending ID const tabMemory = () => registry.active().tabMemory.all() - const reviewOpen = createMemo(() => { - const sel = selection() - if (sel === null) return false - return reviewOpenByContext()[sel] === true - }) + const reviewOpen = createMemo(() => selection() !== null && reviewOpenByContext()[selection()!] === true) const setReviewOpenForContext = (context: string, open: boolean) => { setReviewOpenByContext((prev) => { @@ -2249,6 +2253,8 @@ const AgentManagerContent: Component = () => { setSidePanel((prev) => (prev === SidePanel.Diff ? null : SidePanel.Diff)) } + const toggleDocumentsPanel = documentInspector.toggle + const renderTabById = (id: string) => renderTab(id, { terms, @@ -2445,6 +2451,9 @@ const AgentManagerContent: Component = () => { prStatus={() => activePR()?.pr} prOpen={prOpen} onTogglePR={togglePRPanel} + documentsOpen={documentsOpen} + documentsAvailable={documentInspector.available} + onToggleDocuments={toggleDocumentsPanel} terminalDestination={sideCtl.destination} terminalDestinationActive={() => sidePanel() === SidePanel.Terminal} terminalKeybind={() => kb().showTerminal ?? ""} @@ -2662,6 +2671,7 @@ const AgentManagerContent: Component = () => { if (id) vscode.postMessage({ type: "agentManager.openFile", sessionId: id, filePath: file, line }) }} + onOpenDocument={documentInspector.open} onRevertFile={metrics.use("revert_file", "side_review", revertCtl.revert)} revertingFiles={revertCtl.reverting()} activeTerminalId={terms.activeId()} @@ -2696,6 +2706,12 @@ const AgentManagerContent: Component = () => { onClosePanel={() => setSidePanel(null)} /> + setSidePanel(null)} + activeTerminalId={terms.activeId()} + visible={documentsOpen} + /> tooltip: Value icon: Value + /** Renders instead of `icon`, for tabs that need a per-filetype glyph. */ + iconNode?: Value iconStatus?: Value<"success" | "failure" | undefined> class?: string focused?: boolean @@ -71,8 +73,15 @@ export const ClosableTabChrome: Component = (props) => { > - }> - + }> + + + } + > + {value(props.iconNode!)} {label()} @@ -133,6 +142,7 @@ export const SortableClosableTab: Component< label={props.label} tooltip={props.tooltip} icon={props.icon} + iconNode={props.iconNode} iconStatus={props.iconStatus} class={props.class} focused={props.focused} diff --git a/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx b/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx index eff3750a77..93ee1a45a7 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx @@ -91,6 +91,7 @@ interface DiffPanelProps { onExpand?: () => void onRequestDiff?: (file: string) => void onOpenFile?: (relativePath: string, line?: number) => void + onOpenDocument?: (relativePath: string) => void onRevertFile?: (file: string) => void revertingFiles?: Set activeTerminalId?: string @@ -660,6 +661,20 @@ export const DiffPanel: Component = (props) => { /> + + + { + e.stopPropagation() + props.onOpenDocument?.(diff.file) + }} + /> + + PRStatus | undefined prOpen: () => boolean onTogglePR: () => void + documentsOpen: () => boolean + documentsAvailable: () => boolean + onToggleDocuments: () => void terminalDestination: () => TerminalDestination terminalDestinationActive: () => boolean terminalKeybind: () => string @@ -232,6 +235,18 @@ export const TabBar: Component = (props) => ( )} + + + + + + active: Accessor + getData: (file: string) => DocumentData | undefined + comments: ReviewComment[] + onCommentsChange: (comments: ReviewComment[]) => void + onSelect: (id: string) => void + onClose: (id: string) => void + onCloseOthers: (id: string) => void + onReorder: (from: string, to: string) => void + onOpenFile: (file: string, line?: number) => void + onClosePanel: () => void + activeTerminalId?: string + visible: Accessor +} + +function pathName(file: string): string { + return file.slice(file.lastIndexOf("/") + 1) +} + +function virtualDiff(file: string, content: string): WorktreeFileDiff { + return { + file, + before: "", + after: content, + additions: lineCount(content), + deletions: 0, + status: "added", + } +} + +export const DocumentPanel: Component = (props) => { + const { t } = useLanguage() + const code = useCodeComponent() + const [source, setSource] = createSignal(false) + const [draft, setDraft] = createSignal(null) + const [editing, setEditing] = createSignal(null) + const composer: ReviewComposer = createReviewComposer() + let draftMeta: AnnotationMeta | null = null + let editMeta: AnnotationMeta | null = null + let nextId = 0 + + const selected = createMemo(() => { + const id = props.active() + return props.tabs().find((tab) => tab.id === id) + }) + const data = () => { + const tab = selected() + return tab ? props.getData(tab.file) : undefined + } + const file = () => selected()?.file ?? "" + const content = () => data()?.content ?? "" + const diff = () => virtualDiff(file(), content()) + const labels = (): AnnotationLabels => ({ + commentOnLine: (line) => t("agentManager.review.commentOnLine", { line }), + editCommentOnLine: (line) => t("agentManager.review.editCommentOnLine", { line }), + placeholder: t("agentManager.review.commentPlaceholder"), + cancel: t("common.cancel"), + comment: t("agentManager.review.commentAction"), + send: t("prompt.action.send"), + save: t("common.save"), + sendToChat: t("agentManager.review.sendToChat"), + edit: t("common.edit"), + delete: t("common.delete"), + }) + + const updateComments = (next: ReviewComment[]) => props.onCommentsChange(next) + const comments = () => props.comments.filter((item) => item.file === file()) + const addComment = (path: string, side: AnnotationSide, line: number, text: string, selectedText: string) => { + updateComments([ + ...props.comments, + { id: `doc-${++nextId}-${Date.now()}`, file: path, side, line, comment: text, selectedText }, + ]) + setDraft(null) + draftMeta = null + composer.draft = null + } + const sendComment = (path: string, side: AnnotationSide, line: number, text: string, selectedText: string) => { + sendReviewComments( + [{ id: `doc-${++nextId}-${Date.now()}`, file: path, side, line, comment: text, selectedText }], + props.activeTerminalId, + ) + setDraft(null) + draftMeta = null + composer.draft = null + } + const updateComment = (id: string, text: string) => { + updateComments(props.comments.map((item) => (item.id === id ? { ...item, comment: text } : item))) + setEditing(null) + editMeta = null + composer.edit = null + } + const deleteComment = (id: string) => { + updateComments(props.comments.filter((item) => item.id !== id)) + setEditing(null) + editMeta = null + composer.edit = null + } + const cancelDraft = () => { + setDraft(null) + draftMeta = null + composer.draft = null + } + const annotations = (): DiffLineAnnotation[] => { + const result = buildFileAnnotations(file(), comments(), editing(), draft(), draftMeta, editMeta) + draftMeta = result.draftMeta + editMeta = result.editMeta + composer.draft = draft() ? draftMeta : null + composer.edit = editing() ? editMeta : null + return result.annotations + } + const renderAnnotation = (annotation: DiffLineAnnotation) => + buildReviewAnnotation(annotation, { + diffs: [diff()], + editing: editing(), + setEditing: (id) => setEditing(id), + addComment, + sendComment, + updateComment, + deleteComment, + cancelDraft, + labels: labels(), + activeTerminalId: props.activeTerminalId, + }) + const gutter = (range: SelectedLineRange) => { + if (draft()) return + const side: AnnotationSide = "additions" + const next = { file: file(), side, line: range.start, endLine: range.end } + draftMeta = { type: "draft", comment: null, ...next } + composer.draft = draftMeta + setDraft(next) + } + const sendAll = () => { + if (comments().length === 0) return + sendReviewComments(comments(), props.activeTerminalId) + updateComments(props.comments.filter((item) => item.file !== file())) + } + + createEffect( + on( + () => [file(), content(), props.comments] as const, + ([path, text, current]) => { + if (!path) return + const max = lineCount(text) + const valid = current.filter((item) => item.file !== path || (item.line >= 1 && item.line <= max)) + if (valid.length !== current.length) updateComments(valid) + const currentDraft = draft() + if (currentDraft && currentDraft.file === path && currentDraft.line > max) cancelDraft() + }, + { defer: true }, + ), + ) + + const close = (id: string, focus: { restore: () => void }) => { + props.onClose(id) + if (props.tabs().length > 0) focus.restore() + } + + return ( +
+
+
+ + {t("agentManager.documents.title")} + {props.tabs().length} +
+
+ + + setSource((value) => !value)} + /> + + + props.onOpenFile(file())} + /> + + + +
+
+ props.tabs().map((tab) => tab.id)} + active={props.active} + label={t("agentManager.documents.tabs")} + overlay={(id) => props.tabs().find((tab) => tab.id === id)?.file ?? ""} + onSelect={props.onSelect} + onReorder={props.onReorder} + renderTab={(id, api) => { + const tab = props.tabs().find((item) => item.id === id)! + return ( + } + showKeybind={false} + active={props.active() === id} + role="tab" + selected={props.active() === id} + tabIndex={props.active() === id ? 0 : -1} + onKeyDown={(event) => api.focus.key(id, event)} + onSelect={() => props.onSelect(id)} + onMiddleClick={(event) => { + if (event.button !== 1) return + event.preventDefault() + close(id, api.focus) + }} + onClose={() => close(id, api.focus)} + onCloseOthers={() => props.onCloseOthers(id)} + /> + ) + }} + /> + {t("agentManager.documents.empty")}
}> + +
{t("agentManager.documents.loading")}
+
+ {(error) =>
{error()}
}
+ +
+ {file()} +
+
+ +
+ + } + > + props.onOpenFile(file(), event.lineNumber)} + /> + +
+
+
+ 0}> + + + + ) +} diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx new file mode 100644 index 0000000000..48df0518d0 --- /dev/null +++ b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx @@ -0,0 +1,28 @@ +import type { Accessor, Component } from "solid-js" +import { DocumentPanel } from "./DocumentPanel" +import { createDocumentInspector } from "./state" + +interface Props { + inspector: ReturnType + onClosePanel: () => void + activeTerminalId?: string + visible: Accessor +} + +export const DocumentPanelHost: Component = (props) => ( + +) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts b/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts new file mode 100644 index 0000000000..212ff82dba --- /dev/null +++ b/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts @@ -0,0 +1,172 @@ +import { createSignal, onCleanup, onMount, type Accessor } from "solid-js" +import type { useVSCode } from "../../src/context/vscode" +import type { ReviewComment } from "../../diff-viewer/review-comments" +import type { AgentManagerDocumentMessage } from "../../src/types/messages" + +export interface DocumentTab { + id: string + file: string +} + +export interface DocumentData { + file: string + content?: string + kind?: "text" | "image" + mime?: string + data?: string + error?: string + loading: boolean +} + +function key(context: string, file: string): string { + return `${context}:${file}` +} + +export function isMarkdownPath(file: string): boolean { + return /\.(md|mdx|markdown)$/i.test(file) +} + +export function createDocuments(vscode: ReturnType, context: Accessor) { + const [tabs, setTabs] = createSignal>({}) + const [active, setActive] = createSignal>({}) + const [data, setData] = createSignal>({}) + + const current = () => context() ?? "" + const list = () => tabs()[current()] ?? [] + const selected = () => active()[current()] + const document = (file: string) => data()[key(current(), file)] + + const request = (file: string) => { + const ctx = current() + if (!ctx) return + const id = key(ctx, file) + setData((prev) => ({ ...prev, [id]: { ...(prev[id] ?? { file }), file, loading: true, error: undefined } })) + vscode.postMessage({ type: "agentManager.requestDocument", sessionId: ctx, file }) + } + + const open = (file: string) => { + const ctx = current() + if (!ctx || !file) return + setTabs((prev) => { + const list = prev[ctx] ?? [] + if (list.some((tab) => tab.file === file)) return prev + return { ...prev, [ctx]: [...list, { id: key(ctx, file), file }] } + }) + setActive((prev) => ({ ...prev, [ctx]: key(ctx, file) })) + request(file) + } + + const select = (id: string) => { + const ctx = current() + if (!ctx) return + const tab = (tabs()[ctx] ?? []).find((item) => item.id === id) + if (!tab) return + setActive((prev) => ({ ...prev, [ctx]: id })) + if (!document(tab.file)) request(tab.file) + } + + const close = (id: string) => { + const ctx = current() + const list = tabs()[ctx] ?? [] + const index = list.findIndex((tab) => tab.id === id) + if (index < 0) return + const next = list.filter((tab) => tab.id !== id) + setTabs((prev) => ({ ...prev, [ctx]: next })) + if (active()[ctx] !== id) return + const target = next[Math.min(index, next.length - 1)] + setActive((prev) => ({ ...prev, [ctx]: target?.id })) + } + + const closeOthers = (id: string) => { + const ctx = current() + const tab = (tabs()[ctx] ?? []).find((item) => item.id === id) + if (!tab) return + setTabs((prev) => ({ ...prev, [ctx]: [tab] })) + setActive((prev) => ({ ...prev, [ctx]: id })) + } + + const reorder = (from: string, to: string) => { + const ctx = current() + const list = tabs()[ctx] ?? [] + const fromIndex = list.findIndex((tab) => tab.id === from) + const toIndex = list.findIndex((tab) => tab.id === to) + if (fromIndex < 0 || toIndex < 0 || fromIndex === toIndex) return + const next = [...list] + const [item] = next.splice(fromIndex, 1) + next.splice(toIndex, 0, item!) + setTabs((prev) => ({ ...prev, [ctx]: next })) + } + + const onMessage = (message: AgentManagerDocumentMessage) => { + const id = key(message.sessionId, message.requestedFile ?? message.file) + setData((prev) => ({ + ...prev, + [id]: { + file: message.file, + content: message.content, + kind: message.kind, + mime: message.mime, + data: message.data, + error: message.error, + loading: false, + }, + })) + } + + return { tabs: list, active: selected, document, open, select, close, closeOthers, reorder, onMessage, request } +} + +export function createDocumentComments(context: Accessor) { + const [byContext, setByContext] = createSignal>({}) + const comments = () => { + const ctx = context() + return ctx ? (byContext()[ctx] ?? []) : [] + } + const setComments = (value: ReviewComment[]) => { + const ctx = context() + if (!ctx) return + setByContext((prev) => ({ ...prev, [ctx]: value })) + } + return { comments, setComments } +} + +export function createDocumentInspector( + vscode: ReturnType, + context: Accessor, + isOpen: Accessor, + openPanel: () => void, + closePanel: () => void, +) { + const documents = createDocuments(vscode, context) + const comments = createDocumentComments(context) + const open = (file?: string) => (openPanel(), file ? documents.open(file) : undefined) + onMount(() => { + const handler = (event: Event) => handleDocumentOpen(event, open) + const message = vscode.onMessage((item) => { + if (item.type === "agentManager.document") documents.onMessage(item) + }) + window.addEventListener("kilo:open-file", handler) + onCleanup(() => { + window.removeEventListener("kilo:open-file", handler) + message() + }) + }) + // The toolbar button is a way back to already-open documents, not a way to + // open an empty panel: documents arrive from a file reference or a diff row. + // Tabs are keyed per worktree, so this hides itself on a worktree with none, + // and stays visible while the panel is open so it can still be toggled shut. + const available = () => documents.tabs().length > 0 || isOpen() + const openFile = (file: string, line?: number) => { + const sessionId = context() + if (sessionId) vscode.postMessage({ type: "agentManager.openFile", sessionId, filePath: file, line }) + } + const toggle = () => (isOpen() ? closePanel() : open()) + return { documents, comments, open, openFile, toggle, available } +} + +export function handleDocumentOpen(event: Event, open: (file: string) => void): void { + const file = (event as CustomEvent<{ filePath?: unknown }>).detail?.filePath + if (typeof file !== "string" || !file) return + event.preventDefault() + open(file) +} diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts index a4d8180b12..94940d15e0 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ar.ts @@ -198,6 +198,14 @@ export const dict = { "agentManager.review.imageUnavailable": "معاينة الصورة غير متاحة في لقطة الجلسة هذه.", "agentManager.review.endOfLongDiff": "لقد وصلت إلى النهاية!", + "agentManager.documents.title": "المستندات", + "agentManager.documents.toggle": "إظهار/إخفاء لوحة المستندات", + "agentManager.documents.tabs": "المستندات المفتوحة", + "agentManager.documents.empty": "افتح ملفًا من الدردشة أو diff لمعاينته هنا.", + "agentManager.documents.loading": "جارٍ تحميل المستند...", + "agentManager.documents.preview": "معاينة المستند", + "agentManager.documents.source": "عرض التعليمات البرمجية المصدر", + "agentManager.documents.comments": "{{count}} تعليقًا", "agentManager.import.pullRequest": "طلب سحب", "agentManager.import.pastePrUrl": "الصق رابط PR...", "agentManager.import.open": "فتح", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts index a3c8066462..730b56eee9 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/br.ts @@ -202,6 +202,14 @@ export const dict = { "A visualização da imagem não está disponível para este instantâneo da sessão.", "agentManager.review.endOfLongDiff": "Você chegou ao fim!", + "agentManager.documents.title": "Documentos", + "agentManager.documents.toggle": "Mostrar/ocultar painel de documentos", + "agentManager.documents.tabs": "Documentos abertos", + "agentManager.documents.empty": "Abra um arquivo pelo chat ou pelo diff para pré-visualizá-lo aqui.", + "agentManager.documents.loading": "Carregando documento...", + "agentManager.documents.preview": "Visualizar documento", + "agentManager.documents.source": "Mostrar código-fonte", + "agentManager.documents.comments": "{{count}} comentários", "agentManager.import.pullRequest": "Solicitação de extração", "agentManager.import.pastePrUrl": "Cole a URL do PR...", "agentManager.import.open": "Abrir", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts index e42a222d5c..362e2823eb 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/bs.ts @@ -201,6 +201,14 @@ export const dict = { "agentManager.review.imageUnavailable": "Pregled slike nije dostupan za ovaj snimak sesije.", "agentManager.review.endOfLongDiff": "Došli ste do kraja!", + "agentManager.documents.title": "Dokumenti", + "agentManager.documents.toggle": "Prikaži/sakrij panel dokumenata", + "agentManager.documents.tabs": "Otvoreni dokumenti", + "agentManager.documents.empty": "Otvorite datoteku iz chata ili diff da biste je ovdje pregledali.", + "agentManager.documents.loading": "Učitavanje dokumenta...", + "agentManager.documents.preview": "Pregled dokumenta", + "agentManager.documents.source": "Prikaži izvorni kod", + "agentManager.documents.comments": "{{count}} komentara", "agentManager.import.pullRequest": "Zahtjev za povlačenje", "agentManager.import.pastePrUrl": "Zalijepite PR URL...", "agentManager.import.open": "Otvori", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts index 22f6811774..848c913da8 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/da.ts @@ -203,6 +203,14 @@ export const dict = { "Forhåndsvisning af billedet er ikke tilgængelig for dette snapshot af sessionen.", "agentManager.review.endOfLongDiff": "Du nåede slutningen!", + "agentManager.documents.title": "Dokumenter", + "agentManager.documents.toggle": "Slå dokumentpanelet til/fra", + "agentManager.documents.tabs": "Åbnede dokumenter", + "agentManager.documents.empty": "Åbn en fil fra chatten eller diff for at få vist en forhåndsvisning her.", + "agentManager.documents.loading": "Indlæser dokument...", + "agentManager.documents.preview": "Forhåndsvis dokument", + "agentManager.documents.source": "Vis kildekode", + "agentManager.documents.comments": "{{count}} kommentarer", "agentManager.import.pullRequest": "Pull request", "agentManager.import.pastePrUrl": "Indsæt PR URL...", "agentManager.import.open": "Åbn", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts index 7f70f0feac..33eaaf1b23 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/de.ts @@ -203,6 +203,14 @@ export const dict = { "agentManager.review.imageUnavailable": "Für diesen Sitzungssnapshot ist keine Bildvorschau verfügbar.", "agentManager.review.endOfLongDiff": "Du hast das Ende erreicht!", + "agentManager.documents.title": "Dokumente", + "agentManager.documents.toggle": "Dokumentenbereich ein-/ausblenden", + "agentManager.documents.tabs": "Geöffnete Dokumente", + "agentManager.documents.empty": "Öffnen Sie eine Datei im Chat oder im Diff, um sie hier in der Vorschau anzuzeigen.", + "agentManager.documents.loading": "Dokument wird geladen...", + "agentManager.documents.preview": "Dokument in der Vorschau anzeigen", + "agentManager.documents.source": "Quelltext anzeigen", + "agentManager.documents.comments": "{{count}} Kommentare", "agentManager.import.pullRequest": "Pull Request", "agentManager.import.pastePrUrl": "PR-URL einfügen...", "agentManager.import.open": "Öffnen", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts index cd455fab94..f3d8d5e9d5 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/en.ts @@ -203,6 +203,14 @@ export const dict = { "agentManager.review.imageUnreadable": "This image could not be rendered.", "agentManager.review.imageUnavailable": "Image preview is unavailable for this session snapshot.", "agentManager.review.endOfLongDiff": "You made it to the end!", + "agentManager.documents.title": "Documents", + "agentManager.documents.toggle": "Toggle document panel", + "agentManager.documents.tabs": "Open documents", + "agentManager.documents.empty": "Open a file from chat or the diff to preview it here.", + "agentManager.documents.loading": "Loading document...", + "agentManager.documents.preview": "Preview document", + "agentManager.documents.source": "Show source", + "agentManager.documents.comments": "{{count}} comments", "agentManager.import.pullRequest": "Pull Request", "agentManager.import.pastePrUrl": "Paste PR URL...", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts index b0ab933273..6aa1a52ff8 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/es.ts @@ -203,6 +203,14 @@ export const dict = { "La vista previa de la imagen no está disponible para esta instantánea de la sesión.", "agentManager.review.endOfLongDiff": "¡Llegaste al final!", + "agentManager.documents.title": "Documentos", + "agentManager.documents.toggle": "Mostrar u ocultar el panel de documentos", + "agentManager.documents.tabs": "Documentos abiertos", + "agentManager.documents.empty": "Abre un archivo desde el chat o el diff para previsualizarlo aquí.", + "agentManager.documents.loading": "Cargando documento...", + "agentManager.documents.preview": "Previsualizar documento", + "agentManager.documents.source": "Mostrar código fuente", + "agentManager.documents.comments": "{{count}} comentarios", "agentManager.import.pullRequest": "Pull Request", "agentManager.import.pastePrUrl": "Pegar URL del PR...", "agentManager.import.open": "Abrir", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts index b2c47eaea6..402cc25a76 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fa.ts @@ -205,6 +205,14 @@ export const dict = { "agentManager.review.imageUnavailable": "پیش‌نمایش تصویر برای این نمونه جلسه در دسترس نیست.", "agentManager.review.endOfLongDiff": "به انتها رسیدید!", + "agentManager.documents.title": "اسناد", + "agentManager.documents.toggle": "نمایش/پنهان کردن پنل اسناد", + "agentManager.documents.tabs": "اسناد باز", + "agentManager.documents.empty": "برای پیش‌نمایش فایل در اینجا، آن را از چت یا diff باز کنید.", + "agentManager.documents.loading": "در حال بارگذاری سند...", + "agentManager.documents.preview": "پیش‌نمایش سند", + "agentManager.documents.source": "نمایش کد منبع", + "agentManager.documents.comments": "{{count}} نظر", "agentManager.import.pullRequest": "درخواست ادغام", "agentManager.import.pastePrUrl": "URL درخواست PR را وارد کنید...", "agentManager.import.open": "باز کردن", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts index 57794271f5..cd71a6c0e5 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/fr.ts @@ -203,6 +203,14 @@ export const dict = { "agentManager.review.imageUnavailable": "L’aperçu de l’image n’est pas disponible pour cet instantané de session.", "agentManager.review.endOfLongDiff": "Vous êtes arrivé à la fin !", + "agentManager.documents.title": "Documents", + "agentManager.documents.toggle": "Afficher/masquer le panneau des documents", + "agentManager.documents.tabs": "Documents ouverts", + "agentManager.documents.empty": "Ouvrez un fichier depuis le chat ou le diff pour en afficher un aperçu ici.", + "agentManager.documents.loading": "Chargement du document...", + "agentManager.documents.preview": "Prévisualiser le document", + "agentManager.documents.source": "Afficher le code source", + "agentManager.documents.comments": "{{count}} commentaires", "agentManager.import.pullRequest": "Pull Request", "agentManager.import.pastePrUrl": "Coller l'URL du PR...", "agentManager.import.open": "Ouvrir", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts index 12543b3b2d..0073b3cfe9 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/it.ts @@ -209,6 +209,14 @@ export const dict = { "L'anteprima dell'immagine non è disponibile per questa istantanea della sessione.", "agentManager.review.endOfLongDiff": "Sei arrivato alla fine!", + "agentManager.documents.title": "Documenti", + "agentManager.documents.toggle": "Mostra/nascondi il pannello dei documenti", + "agentManager.documents.tabs": "Documenti aperti", + "agentManager.documents.empty": "Apri un file dalla chat o dal diff per visualizzarne qui l'anteprima.", + "agentManager.documents.loading": "Caricamento del documento...", + "agentManager.documents.preview": "Visualizza anteprima del documento", + "agentManager.documents.source": "Mostra il codice sorgente", + "agentManager.documents.comments": "{{count}} commenti", "agentManager.import.pullRequest": "Pull Request", "agentManager.import.pastePrUrl": "Incolla URL PR...", "agentManager.import.open": "Apri", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts index 91b66c4aa7..73c418b258 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ja.ts @@ -202,6 +202,14 @@ export const dict = { "agentManager.review.imageUnavailable": "このセッションスナップショットでは画像プレビューを利用できません。", "agentManager.review.endOfLongDiff": "最後まで到達しました!", + "agentManager.documents.title": "ドキュメント", + "agentManager.documents.toggle": "ドキュメントパネルを切り替え", + "agentManager.documents.tabs": "開いているドキュメント", + "agentManager.documents.empty": "チャットまたは diff からファイルを開くと、ここでプレビューできます。", + "agentManager.documents.loading": "ドキュメントを読み込み中...", + "agentManager.documents.preview": "ドキュメントをプレビュー", + "agentManager.documents.source": "ソースを表示", + "agentManager.documents.comments": "{{count}}件のコメント", "agentManager.import.pullRequest": "プルリクエスト", "agentManager.import.pastePrUrl": "PR URLを貼り付け...", "agentManager.import.open": "開く", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts index be6304117a..965c0f919c 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ko.ts @@ -200,6 +200,14 @@ export const dict = { "agentManager.review.imageUnavailable": "이 세션 스냅샷에서는 이미지 미리보기를 사용할 수 없습니다.", "agentManager.review.endOfLongDiff": "끝까지 도달했습니다!", + "agentManager.documents.title": "문서", + "agentManager.documents.toggle": "문서 패널 전환", + "agentManager.documents.tabs": "열린 문서", + "agentManager.documents.empty": "채팅이나 diff에서 파일을 열어 여기에서 미리 보세요.", + "agentManager.documents.loading": "문서 로드 중...", + "agentManager.documents.preview": "문서 미리 보기", + "agentManager.documents.source": "소스 보기", + "agentManager.documents.comments": "댓글 {{count}}개", "agentManager.import.pullRequest": "풀 리퀘스트", "agentManager.import.pastePrUrl": "PR URL 붙여넣기...", "agentManager.import.open": "열기", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts index c2ef4e5d14..1545c1261a 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/nl.ts @@ -207,6 +207,14 @@ export const dict = { "agentManager.review.imageUnavailable": "Afbeeldingsvoorbeeld is niet beschikbaar voor deze sessiesnapshot.", "agentManager.review.endOfLongDiff": "Je hebt het einde bereikt!", + "agentManager.documents.title": "Documenten", + "agentManager.documents.toggle": "Documentenpaneel tonen/verbergen", + "agentManager.documents.tabs": "Geopende documenten", + "agentManager.documents.empty": "Open een bestand vanuit de chat of diff om het hier te bekijken.", + "agentManager.documents.loading": "Document wordt geladen...", + "agentManager.documents.preview": "Voorbeeld van document bekijken", + "agentManager.documents.source": "Broncode weergeven", + "agentManager.documents.comments": "{{count}} opmerkingen", "agentManager.import.pullRequest": "Pull request", "agentManager.import.pastePrUrl": "Plak PR URL...", "agentManager.import.open": "Openen", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts index d26092e3ae..b67bcd4cf4 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/no.ts @@ -200,6 +200,14 @@ export const dict = { "Forhåndsvisning av bildet er ikke tilgjengelig for dette øyeblikksbildet av økten.", "agentManager.review.endOfLongDiff": "Du nådde slutten!", + "agentManager.documents.title": "Dokumenter", + "agentManager.documents.toggle": "Vis/skjul dokumentpanelet", + "agentManager.documents.tabs": "Åpne dokumenter", + "agentManager.documents.empty": "Åpne en fil fra chatten eller diff for å forhåndsvise den her.", + "agentManager.documents.loading": "Laster inn dokument...", + "agentManager.documents.preview": "Forhåndsvis dokument", + "agentManager.documents.source": "Vis kildekode", + "agentManager.documents.comments": "{{count}} kommentarer", "agentManager.import.pullRequest": "Pull request", "agentManager.import.pastePrUrl": "Lim inn PR URL...", "agentManager.import.open": "Åpne", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts index b4f8324807..0ef67c6873 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/pl.ts @@ -201,6 +201,14 @@ export const dict = { "agentManager.review.imageUnavailable": "Podgląd obrazu jest niedostępny dla tej migawki sesji.", "agentManager.review.endOfLongDiff": "Dotarłeś do końca!", + "agentManager.documents.title": "Dokumenty", + "agentManager.documents.toggle": "Pokaż/ukryj panel dokumentów", + "agentManager.documents.tabs": "Otwarte dokumenty", + "agentManager.documents.empty": "Otwórz plik z czatu lub diff, aby wyświetlić jego podgląd tutaj.", + "agentManager.documents.loading": "Ładowanie dokumentu...", + "agentManager.documents.preview": "Podgląd dokumentu", + "agentManager.documents.source": "Pokaż kod źródłowy", + "agentManager.documents.comments": "{{count}} komentarzy", "agentManager.import.pullRequest": "Prośba o scalenie", "agentManager.import.pastePrUrl": "Wklej URL PR...", "agentManager.import.open": "Otwórz", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts index 809b074b9a..01bc640025 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/ru.ts @@ -202,6 +202,14 @@ export const dict = { "agentManager.review.imageUnavailable": "Предварительный просмотр изображения недоступен для этого снимка сеанса.", "agentManager.review.endOfLongDiff": "Вы дошли до конца!", + "agentManager.documents.title": "Документы", + "agentManager.documents.toggle": "Показать или скрыть панель документов", + "agentManager.documents.tabs": "Открытые документы", + "agentManager.documents.empty": "Откройте файл из чата или diff, чтобы просмотреть его здесь.", + "agentManager.documents.loading": "Загрузка документа...", + "agentManager.documents.preview": "Предпросмотр документа", + "agentManager.documents.source": "Показать исходный код", + "agentManager.documents.comments": "{{count}} комментариев", "agentManager.import.pullRequest": "Запрос на слияние", "agentManager.import.pastePrUrl": "Вставьте URL PR...", "agentManager.import.open": "Открыть", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts index e74d7dbef9..b1f4ee85e4 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/th.ts @@ -196,6 +196,14 @@ export const dict = { "agentManager.review.imageUnavailable": "ไม่สามารถแสดงตัวอย่างรูปภาพสำหรับสแนปช็อตของเซสชันนี้ได้", "agentManager.review.endOfLongDiff": "คุณมาถึงท้ายสุดแล้ว!", + "agentManager.documents.title": "เอกสาร", + "agentManager.documents.toggle": "สลับแผงเอกสาร", + "agentManager.documents.tabs": "เอกสารที่เปิดอยู่", + "agentManager.documents.empty": "เปิดไฟล์จากแชทหรือ diff เพื่อดูตัวอย่างที่นี่", + "agentManager.documents.loading": "กำลังโหลดเอกสาร...", + "agentManager.documents.preview": "ดูตัวอย่างเอกสาร", + "agentManager.documents.source": "แสดงซอร์สโค้ด", + "agentManager.documents.comments": "{{count}} ความคิดเห็น", "agentManager.import.pullRequest": "คำขอรวมโค้ด", "agentManager.import.pastePrUrl": "วาง URL ของ PR...", "agentManager.import.open": "เปิด", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts index d6d5c3012a..53d9bdff3e 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/tr.ts @@ -209,6 +209,14 @@ export const dict = { "agentManager.review.imageUnavailable": "Bu oturum anlık görüntüsü için görsel önizlemesi kullanılamıyor.", "agentManager.review.endOfLongDiff": "Sonuna geldiniz!", + "agentManager.documents.title": "Belgeler", + "agentManager.documents.toggle": "Belge panelini aç/kapat", + "agentManager.documents.tabs": "Açık belgeler", + "agentManager.documents.empty": "Burada önizlemek için sohbetten veya diff üzerinden bir dosya açın.", + "agentManager.documents.loading": "Belge yükleniyor...", + "agentManager.documents.preview": "Belgeyi önizle", + "agentManager.documents.source": "Kaynak kodu göster", + "agentManager.documents.comments": "{{count}} yorum", "agentManager.import.pullRequest": "Çekme İsteği", "agentManager.import.pastePrUrl": "PR URL'sini yapıştırın...", "agentManager.import.open": "Aç", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts index 9959ad6a40..ff7b02dea1 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/uk.ts @@ -210,6 +210,14 @@ export const dict = { "agentManager.review.imageUnavailable": "Попередній перегляд зображення недоступний для цього знімка сеансу.", "agentManager.review.endOfLongDiff": "Ви дійшли до кінця!", + "agentManager.documents.title": "Документи", + "agentManager.documents.toggle": "Показати або приховати панель документів", + "agentManager.documents.tabs": "Відкриті документи", + "agentManager.documents.empty": "Відкрийте файл із чату або diff, щоб переглянути його тут.", + "agentManager.documents.loading": "Завантаження документа...", + "agentManager.documents.preview": "Попередній перегляд документа", + "agentManager.documents.source": "Показати вихідний код", + "agentManager.documents.comments": "{{count}} коментарів", "agentManager.import.pullRequest": "Пул-реквест", "agentManager.import.pastePrUrl": "Вставте URL PR...", "agentManager.import.open": "Відкрити", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts index c8456673d0..190c1d268f 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zh.ts @@ -194,6 +194,14 @@ export const dict = { "agentManager.review.imageUnavailable": "此会话快照无法提供图片预览。", "agentManager.review.endOfLongDiff": "你已经到末尾了!", + "agentManager.documents.title": "文档", + "agentManager.documents.toggle": "切换文档面板", + "agentManager.documents.tabs": "打开的文档", + "agentManager.documents.empty": "从聊天或 diff 中打开文件,即可在此处预览。", + "agentManager.documents.loading": "正在加载文档...", + "agentManager.documents.preview": "预览文档", + "agentManager.documents.source": "显示源代码", + "agentManager.documents.comments": "{{count}} 条评论", "agentManager.import.pullRequest": "拉取请求", "agentManager.import.pastePrUrl": "粘贴 PR URL...", "agentManager.import.open": "打开", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts index dd009844c7..dfc107163a 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/i18n/zht.ts @@ -194,6 +194,14 @@ export const dict = { "agentManager.review.imageUnavailable": "此工作階段快照無法預覽圖片。", "agentManager.review.endOfLongDiff": "你已經到最後了!", + "agentManager.documents.title": "文件", + "agentManager.documents.toggle": "切換文件面板", + "agentManager.documents.tabs": "已開啟的文件", + "agentManager.documents.empty": "從聊天或 diff 中開啟檔案,即可在此處預覽。", + "agentManager.documents.loading": "正在載入文件...", + "agentManager.documents.preview": "預覽文件", + "agentManager.documents.source": "顯示原始碼", + "agentManager.documents.comments": "{{count}} 則留言", "agentManager.import.pullRequest": "提取請求", "agentManager.import.pastePrUrl": "貼上 PR URL...", "agentManager.import.open": "開啟", diff --git a/packages/kilo-vscode/webview-ui/agent-manager/side-panel-layout.ts b/packages/kilo-vscode/webview-ui/agent-manager/side-panel-layout.ts index d89341e31f..f1d87f7e33 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/side-panel-layout.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/side-panel-layout.ts @@ -10,6 +10,7 @@ export enum SidePanel { PR = "pr", Terminal = "terminal", Subagents = "subagents", + Documents = "documents", } function viewportWidth(viewport: number): number { diff --git a/packages/kilo-vscode/webview-ui/diff-viewer/DiffViewerApp.tsx b/packages/kilo-vscode/webview-ui/diff-viewer/DiffViewerApp.tsx index 0811537142..fdc7573008 100644 --- a/packages/kilo-vscode/webview-ui/diff-viewer/DiffViewerApp.tsx +++ b/packages/kilo-vscode/webview-ui/diff-viewer/DiffViewerApp.tsx @@ -46,6 +46,7 @@ const DiffViewerContent: Component = () => { const [loadingFiles, setLoadingFiles] = createSignal>(new Set()) const [availableSources, setAvailableSources] = createSignal([]) const [currentSourceId, setCurrentSourceId] = createSignal(undefined) + const [initialFile, setInitialFile] = createSignal(undefined) const [capabilities, setCapabilities] = createSignal(undefined) const [notice, setNotice] = createSignal(undefined) const [branches, setBranches] = createSignal([]) @@ -136,6 +137,14 @@ const DiffViewerContent: Component = () => { setMarkdown(msg.render) return } + if ((msg as { type: string; file?: string }).type === "diffViewer.initialFile") { + setInitialFile((msg as { file?: string }).file) + return + } + if ((msg as { type: string; render?: boolean }).type === "diffViewer.initialMarkdown") { + setMarkdown((msg as { render?: boolean }).render === true) + return + } if (msg.type === "setAvailableSources") { setAvailableSources(msg.descriptors) setCurrentSourceId(msg.currentId) @@ -266,6 +275,7 @@ const DiffViewerContent: Component = () => { onOpenFile={(relativePath) => { post({ type: "openFile", filePath: relativePath }) }} + initialFile={initialFile()} onRevertFile={(file) => { markReverting(file, true) post({ type: "diffViewer.revertFile", file }) diff --git a/packages/kilo-vscode/webview-ui/diff-viewer/FullScreenDiffView.tsx b/packages/kilo-vscode/webview-ui/diff-viewer/FullScreenDiffView.tsx index db2373c3e1..1e538cca0a 100644 --- a/packages/kilo-vscode/webview-ui/diff-viewer/FullScreenDiffView.tsx +++ b/packages/kilo-vscode/webview-ui/diff-viewer/FullScreenDiffView.tsx @@ -90,6 +90,7 @@ interface FullScreenDiffViewProps { onMarkdownRenderChange?: (render: boolean) => void onRequestDiff?: (file: string) => void onOpenFile?: (relativePath: string, line?: number) => void + initialFile?: string onRevertFile?: (file: string) => void revertingFiles?: Set activeTerminalId?: string @@ -234,7 +235,9 @@ export const FullScreenDiffView: Component = (props) => // Keep active file in sync — pick first if current is stale const current = activeFile() if (!current || !diffs.some((d) => d.file === current)) { - setActiveFile(diffs[0]!.file) + const initial = + props.initialFile && diffs.some((d) => d.file === props.initialFile) ? props.initialFile : undefined + setActiveFile(initial ?? diffs[0]!.file) } // New context: initialize open state from the diff policy. diff --git a/packages/kilo-vscode/webview-ui/diff-viewer/MarkdownAnnotationLayer.tsx b/packages/kilo-vscode/webview-ui/diff-viewer/MarkdownAnnotationLayer.tsx index f0a5c0288e..70324d1ca0 100644 --- a/packages/kilo-vscode/webview-ui/diff-viewer/MarkdownAnnotationLayer.tsx +++ b/packages/kilo-vscode/webview-ui/diff-viewer/MarkdownAnnotationLayer.tsx @@ -145,12 +145,16 @@ export const MarkdownAnnotationLayer: Component = } const paneBox = pane.getBoundingClientRect() + let bottom = 0 for (const anchor of list) { const box = anchor.element.getBoundingClientRect() const row = document.createElement("div") row.className = "am-markdown-target" - row.style.top = `${box.top - paneBox.top}px` - row.style.height = `${Math.max(20, box.height)}px` + const height = Math.max(20, box.height) + const top = Math.max(box.top - paneBox.top, bottom) + row.style.top = `${top}px` + row.style.height = `${height}px` + bottom = top + height if (props.enableGutterUtility) { const button = document.createElement("button") diff --git a/packages/kilo-vscode/webview-ui/diff-viewer/MarkdownDiffView.tsx b/packages/kilo-vscode/webview-ui/diff-viewer/MarkdownDiffView.tsx index 3627809ccd..78533670ec 100644 --- a/packages/kilo-vscode/webview-ui/diff-viewer/MarkdownDiffView.tsx +++ b/packages/kilo-vscode/webview-ui/diff-viewer/MarkdownDiffView.tsx @@ -24,7 +24,7 @@ export function isMarkdownFile(file: string): boolean { return /\.(md|mdx|markdown)$/i.test(file) } -interface PaneProps { +export interface MarkdownPaneProps { title?: string text: string side: AnnotationSide @@ -36,7 +36,7 @@ interface PaneProps { onLineNumberClick: ((event: { annotationSide: AnnotationSide; lineNumber: number }) => void) | undefined } -const MarkdownPane: Component = (props) => { +export const MarkdownPane: Component = (props) => { let pane: HTMLElement | undefined let body: HTMLDivElement | undefined const interactive = () => diff --git a/packages/kilo-vscode/webview-ui/src/App.tsx b/packages/kilo-vscode/webview-ui/src/App.tsx index a0162ce04e..53cac0212b 100644 --- a/packages/kilo-vscode/webview-ui/src/App.tsx +++ b/packages/kilo-vscode/webview-ui/src/App.tsx @@ -121,6 +121,11 @@ export const DataBridge: Component<{ children: any }> = (props) => { } const open = (filePath: string, line?: number, column?: number, sessionID?: string) => { + const event = new CustomEvent("kilo:open-file", { + cancelable: true, + detail: { filePath, line, column, sessionID }, + }) + if (!window.dispatchEvent(event)) return vscode.postMessage({ type: "openFile", filePath, line, column, sessionID }) } diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/AssistantMessage.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/AssistantMessage.tsx index 3b42083c99..ce9b9f25e7 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/AssistantMessage.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/AssistantMessage.tsx @@ -76,6 +76,7 @@ function PlanExitCard(props: { part: ToolPart }) {
{label()}{" "} + {language.t("ui.patch.action.plan")} {display()} diff --git a/packages/kilo-vscode/webview-ui/src/styles/plan-exit.css b/packages/kilo-vscode/webview-ui/src/styles/plan-exit.css index 0aed607ecd..3c92434f70 100644 --- a/packages/kilo-vscode/webview-ui/src/styles/plan-exit.css +++ b/packages/kilo-vscode/webview-ui/src/styles/plan-exit.css @@ -23,7 +23,27 @@ font-weight: var(--font-weight-medium); } + [data-slot="plan-exit-badge"] { + display: inline-flex; + align-items: center; + padding: 1px 5px; + border: 1px solid var(--border-interactive-base); + border-radius: 999px; + color: var(--text-interactive-base); + font-size: var(--kilo-font-size-11); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-small); + text-transform: uppercase; + letter-spacing: 0.04em; + } + [data-slot="plan-exit-link"] { + display: inline-flex; + align-items: center; + gap: 5px; + padding: 2px 6px; + border: 1px solid transparent; + border-radius: 4px; cursor: pointer; color: var(--text-interactive-base); text-decoration: none; @@ -33,7 +53,14 @@ word-break: break-all; &:hover { + border-color: var(--border-interactive-base); + background: var(--surface-interactive-weak); text-decoration: underline; } + + &:focus-visible { + outline: 1px solid var(--focus-base); + outline-offset: 1px; + } } } diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts index fda0c747d5..c63638d8e5 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts @@ -977,6 +977,18 @@ export interface AgentManagerWorktreeDiffFileMessage { diff: WorktreeFileDiff | null } +export interface AgentManagerDocumentMessage { + type: "agentManager.document" + sessionId: string + file: string + requestedFile?: string + content?: string + kind?: "text" | "image" + mime?: string + data?: string + error?: string +} + // Agent Manager: Diff loading state (extension → webview) export interface AgentManagerWorktreeDiffLoadingMessage { type: "agentManager.worktreeDiffLoading" @@ -1132,6 +1144,16 @@ export interface DiffViewerMarkdownRenderMessage { render: boolean } +export interface DiffViewerInitialFileMessage { + type: "diffViewer.initialFile" + file?: string +} + +export interface DiffViewerInitialMarkdownMessage { + type: "diffViewer.initialMarkdown" + render: boolean +} + export interface SetAvailableSourcesMessage { type: "setAvailableSources" descriptors: DiffSourceDescriptor[] @@ -1408,6 +1430,7 @@ export type ExtensionMessage = | WorkspaceDirectoryChangedMessage | AgentManagerWorktreeDiffMessage | AgentManagerWorktreeDiffFileMessage + | AgentManagerDocumentMessage | AgentManagerWorktreeDiffLoadingMessage | AgentManagerWorktreeDiffNoticeMessage | AgentManagerApplyWorktreeDiffResultMessage @@ -1439,6 +1462,8 @@ export type ExtensionMessage = | DiffViewerRevertFileResultMessage | DiffViewerDiffFileMessage | DiffViewerMarkdownRenderMessage + | DiffViewerInitialFileMessage + | DiffViewerInitialMarkdownMessage | SetAvailableSourcesMessage | DiffViewerCapabilitiesMessage | DiffViewerNoticeMessage diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts index c271ceaca2..d058873d29 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts @@ -869,6 +869,12 @@ export interface AgentManagerOpenFileRequest { column?: number } +export interface AgentManagerRequestDocumentMessage { + type: "agentManager.requestDocument" + sessionId: string + file: string +} + // Create multiple worktree sessions for the same prompt (multi-version mode) export interface CreateMultiVersionRequest { type: "agentManager.createMultiVersion" @@ -1527,6 +1533,7 @@ export type WebviewMessage = | CopyToClipboardRequest | ShowExistingLocalTerminalRequest | AgentManagerOpenFileRequest + | AgentManagerRequestDocumentMessage | CreateMultiVersionRequest | SetTabOrderRequest | SetWorktreeOrderRequest diff --git a/packages/opencode/src/kilocode/session/prompt.ts b/packages/opencode/src/kilocode/session/prompt.ts index bd9b2b5c71..4b997d2a5f 100644 --- a/packages/opencode/src/kilocode/session/prompt.ts +++ b/packages/opencode/src/kilocode/session/prompt.ts @@ -451,6 +451,7 @@ export namespace KiloSessionPrompt { info, "Use the chosen plan path as the main plan file. Do not write or edit other files unless the user explicitly asks and your permissions allow it.", "Project/user instructions about plan location (for example plans/ or .plans/) are authorized when permissions allow them; they do not conflict with this reminder. When finalizing, call plan_exit with the path of the plan file you wrote.", + "In the visible final response, cite the saved plan path as an inline code span so the client can open it as a document. Cite other user-facing files you create the same way instead of pasting the full file into chat.", supportsPlanFollowup() ? "When the plan is implementation-ready, write the main plan file and call plan_exit. Do not ask the user to choose between finalizing and refining in chat; the client follow-up after plan_exit asks whether to implement the saved plan or keep refining." : 'Before creating or updating the plan file, or calling plan_exit, ask the user to choose exactly one of: "Finalize and save the plan" or "Continue refining". If the user chooses to finalize, write the main plan file, then call plan_exit.', diff --git a/packages/ui/src/components/markdown.css b/packages/ui/src/components/markdown.css index 4d8955bd2a..0a2b844187 100644 --- a/packages/ui/src/components/markdown.css +++ b/packages/ui/src/components/markdown.css @@ -263,6 +263,25 @@ text-decoration-style: solid; } } + + /* A plan reference reads as a document, not a boxed chip: a small glyph in + front of the path, keeping the same dotted-underline affordance every + other validated file link already uses. No border, no badge, no fill. */ + &.plan-document-link::before { + content: ""; + display: inline-block; + width: 0.95em; + height: 0.95em; + margin-inline-end: 0.3em; + vertical-align: -0.15em; + background-color: currentColor; + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z'/%3E%3Cpath d='M14 2v5h6'/%3E%3Cpath d='M9 13h6'/%3E%3Cpath d='M9 17h4'/%3E%3C/svg%3E"); + mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z'/%3E%3Cpath d='M14 2v5h6'/%3E%3Cpath d='M9 13h6'/%3E%3Cpath d='M9 17h4'/%3E%3C/svg%3E"); + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: contain; + } /* kilocode_change end */ } diff --git a/packages/ui/src/i18n/ar.ts b/packages/ui/src/i18n/ar.ts index a91cb5bad2..e4f82a4ed8 100644 --- a/packages/ui/src/i18n/ar.ts +++ b/packages/ui/src/i18n/ar.ts @@ -211,6 +211,7 @@ export const dict = { "ui.patch.action.created": "تم الإنشاء", "ui.patch.action.moved": "منقول", "ui.patch.action.patched": "تم تطبيق رقعة", + "ui.patch.action.plan": "خطة", // kilocode_change "ui.question.subtitle.answered": "تمت الإجابة عن {{count}}", "ui.question.answer.none": "(لا توجد إجابة)", diff --git a/packages/ui/src/i18n/az.ts b/packages/ui/src/i18n/az.ts index 65bf6016b0..0a635b9201 100644 --- a/packages/ui/src/i18n/az.ts +++ b/packages/ui/src/i18n/az.ts @@ -188,6 +188,7 @@ export const dict: Record = { "ui.patch.action.created": "Yaradıldı", "ui.patch.action.moved": "Köçürüldü", "ui.patch.action.patched": "Yamaq tətbiq edildi", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "{{count}} cavablandı", "ui.question.answer.none": "(cavab yoxdur)", "ui.question.review.notAnswered": "(cavablanmayıb)", diff --git a/packages/ui/src/i18n/br.ts b/packages/ui/src/i18n/br.ts index 332ff798a2..d007beff11 100644 --- a/packages/ui/src/i18n/br.ts +++ b/packages/ui/src/i18n/br.ts @@ -215,6 +215,7 @@ export const dict = { "ui.patch.action.created": "Criado", "ui.patch.action.moved": "Movido", "ui.patch.action.patched": "Patch aplicado", + "ui.patch.action.plan": "Plano", // kilocode_change "ui.question.subtitle.answered": "{{count}} respondidas", "ui.question.subtitle.dismissed": "{{count}} dismissed", // kilocode_change diff --git a/packages/ui/src/i18n/bs.ts b/packages/ui/src/i18n/bs.ts index 83173fb671..5ab12ecec4 100644 --- a/packages/ui/src/i18n/bs.ts +++ b/packages/ui/src/i18n/bs.ts @@ -203,6 +203,7 @@ export const dict = { "ui.patch.action.created": "Kreirano", "ui.patch.action.moved": "Premješteno", "ui.patch.action.patched": "Primijenjeno", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "Odgovoreno: {{count}}", "ui.question.answer.none": "(nema odgovora)", diff --git a/packages/ui/src/i18n/da.ts b/packages/ui/src/i18n/da.ts index 8b3c3aa09d..cbdb268416 100644 --- a/packages/ui/src/i18n/da.ts +++ b/packages/ui/src/i18n/da.ts @@ -191,6 +191,7 @@ export const dict = { "ui.patch.action.created": "Oprettet", "ui.patch.action.moved": "Flyttet", "ui.patch.action.patched": "Patchet", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "{{count}} besvaret", "ui.question.subtitle.dismissed": "{{count}} dismissed", // kilocode_change diff --git a/packages/ui/src/i18n/de.ts b/packages/ui/src/i18n/de.ts index c5e8708281..b1cffac666 100644 --- a/packages/ui/src/i18n/de.ts +++ b/packages/ui/src/i18n/de.ts @@ -181,6 +181,7 @@ export const dict = { "ui.patch.action.created": "Erstellt", "ui.patch.action.moved": "Verschoben", "ui.patch.action.patched": "Gepatched", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "{{count}} beantwortet", "ui.question.answer.none": "(keine Antwort)", diff --git a/packages/ui/src/i18n/en.ts b/packages/ui/src/i18n/en.ts index ba503f61f1..fe48472b9a 100644 --- a/packages/ui/src/i18n/en.ts +++ b/packages/ui/src/i18n/en.ts @@ -227,6 +227,7 @@ export const dict: Record = { "ui.patch.action.created": "Created", "ui.patch.action.moved": "Moved", "ui.patch.action.patched": "Patched", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "{{count}} answered", "ui.question.subtitle.dismissed": "{{count}} dismissed", // kilocode_change diff --git a/packages/ui/src/i18n/es.ts b/packages/ui/src/i18n/es.ts index 58d87ea16a..a66be5cf76 100644 --- a/packages/ui/src/i18n/es.ts +++ b/packages/ui/src/i18n/es.ts @@ -199,6 +199,7 @@ export const dict = { "ui.patch.action.created": "Creado", "ui.patch.action.moved": "Movido", "ui.patch.action.patched": "Parcheado", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "{{count}} respondidas", "ui.question.answer.none": "(sin respuesta)", diff --git a/packages/ui/src/i18n/fi.ts b/packages/ui/src/i18n/fi.ts index 35bf61fdef..e938d8c1bf 100644 --- a/packages/ui/src/i18n/fi.ts +++ b/packages/ui/src/i18n/fi.ts @@ -170,6 +170,7 @@ export const dict: Record = { "ui.patch.action.created": "Luotu", "ui.patch.action.moved": "Siirretty", "ui.patch.action.patched": "Paikattu", + "ui.patch.action.plan": "Suunnitelma", // kilocode_change "ui.question.subtitle.answered": "Vastatut kysymykset: {{count}}", "ui.question.answer.none": "(ei vastausta)", "ui.question.review.notAnswered": "(ei vastattu)", diff --git a/packages/ui/src/i18n/fr.ts b/packages/ui/src/i18n/fr.ts index bc4fbad5b0..3a766418fa 100644 --- a/packages/ui/src/i18n/fr.ts +++ b/packages/ui/src/i18n/fr.ts @@ -201,6 +201,7 @@ export const dict = { "ui.patch.action.created": "Créé", "ui.patch.action.moved": "Déplacé", "ui.patch.action.patched": "Correctif appliqué", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "Réponses : {{count}}", "ui.question.answer.none": "(pas de réponse)", diff --git a/packages/ui/src/i18n/hi.ts b/packages/ui/src/i18n/hi.ts index 94edecffbf..e63a252ea5 100644 --- a/packages/ui/src/i18n/hi.ts +++ b/packages/ui/src/i18n/hi.ts @@ -190,6 +190,7 @@ export const dict: Record = { "ui.patch.action.created": "बनाया गया", "ui.patch.action.moved": "ले जाया गया", "ui.patch.action.patched": "पैच किया गया", + "ui.patch.action.plan": "योजना", // kilocode_change "ui.question.subtitle.answered": "{{count}} के उत्तर दिए गए", "ui.question.answer.none": "(कोई जवाब नहीं)", "ui.question.review.notAnswered": "(उत्तर नहीं दिया गया)", diff --git a/packages/ui/src/i18n/id.ts b/packages/ui/src/i18n/id.ts index 7ea583106b..8dd26dfb17 100644 --- a/packages/ui/src/i18n/id.ts +++ b/packages/ui/src/i18n/id.ts @@ -209,6 +209,7 @@ export const dict: Record = { "ui.patch.action.created": "Dibuat", "ui.patch.action.moved": "Dipindahkan", "ui.patch.action.patched": "Ditambal", + "ui.patch.action.plan": "Rencana", // kilocode_change "ui.question.subtitle.answered": "{{count}} dijawab", "ui.question.answer.none": "(tidak ada jawaban)", diff --git a/packages/ui/src/i18n/it.ts b/packages/ui/src/i18n/it.ts index f0603e340d..2d0e7c5824 100644 --- a/packages/ui/src/i18n/it.ts +++ b/packages/ui/src/i18n/it.ts @@ -193,6 +193,7 @@ export const dict: Record = { "ui.patch.action.created": "Creato", "ui.patch.action.moved": "Spostato", "ui.patch.action.patched": "Modificato", + "ui.patch.action.plan": "Piano", // kilocode_change "ui.question.subtitle.answered": "{{count}} risposte", "ui.question.answer.none": "(nessuna risposta)", "ui.question.review.notAnswered": "(senza risposta)", diff --git a/packages/ui/src/i18n/ja.ts b/packages/ui/src/i18n/ja.ts index 78d5dce0d0..60c194110d 100644 --- a/packages/ui/src/i18n/ja.ts +++ b/packages/ui/src/i18n/ja.ts @@ -194,6 +194,7 @@ export const dict = { "ui.patch.action.created": "作成済み", "ui.patch.action.moved": "移動済み", "ui.patch.action.patched": "パッチ適用済み", + "ui.patch.action.plan": "計画", // kilocode_change "ui.question.subtitle.answered": "{{count}}件回答済み", "ui.question.answer.none": "(回答なし)", diff --git a/packages/ui/src/i18n/ko.ts b/packages/ui/src/i18n/ko.ts index 8cf4e0fe04..080b33c710 100644 --- a/packages/ui/src/i18n/ko.ts +++ b/packages/ui/src/i18n/ko.ts @@ -171,6 +171,7 @@ export const dict = { "ui.patch.action.created": "생성됨", "ui.patch.action.moved": "이동됨", "ui.patch.action.patched": "패치됨", + "ui.patch.action.plan": "계획", // kilocode_change "ui.question.subtitle.answered": "{{count}}개 답변됨", "ui.question.answer.none": "(답변 없음)", diff --git a/packages/ui/src/i18n/nl.ts b/packages/ui/src/i18n/nl.ts index 1f2d324437..fca188d67a 100644 --- a/packages/ui/src/i18n/nl.ts +++ b/packages/ui/src/i18n/nl.ts @@ -188,6 +188,7 @@ export const dict: Record = { "ui.patch.action.created": "Gemaakt", "ui.patch.action.moved": "Verplaatst", "ui.patch.action.patched": "Bijgewerkt", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "{{count}} beantwoord", "ui.question.answer.none": "(geen antwoord)", "ui.question.review.notAnswered": "(niet beantwoord)", diff --git a/packages/ui/src/i18n/no.ts b/packages/ui/src/i18n/no.ts index a94a2b25b6..d8362c62ba 100644 --- a/packages/ui/src/i18n/no.ts +++ b/packages/ui/src/i18n/no.ts @@ -174,6 +174,7 @@ export const dict: Record = { "ui.patch.action.created": "Opprettet", "ui.patch.action.moved": "Flyttet", "ui.patch.action.patched": "Oppdatert", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "{{count}} besvart", "ui.question.answer.none": "(ingen svar)", diff --git a/packages/ui/src/i18n/pa.ts b/packages/ui/src/i18n/pa.ts index 874abacb04..770a8fbf13 100644 --- a/packages/ui/src/i18n/pa.ts +++ b/packages/ui/src/i18n/pa.ts @@ -189,6 +189,7 @@ export const dict: Record = { "ui.patch.action.created": "بنایا گیا", "ui.patch.action.moved": "منتقل ہو گیا", "ui.patch.action.patched": "پیچ کیتا گیا", + "ui.patch.action.plan": "ਯੋਜਨਾ", // kilocode_change "ui.question.subtitle.answered": "{{count}} جواب دتا گیا", "ui.question.answer.none": "(کوئی جواب نئیں)", "ui.question.review.notAnswered": "(جواب نئیں دتا گیا)", diff --git a/packages/ui/src/i18n/pl.ts b/packages/ui/src/i18n/pl.ts index dfd773969a..2a22c018fb 100644 --- a/packages/ui/src/i18n/pl.ts +++ b/packages/ui/src/i18n/pl.ts @@ -203,6 +203,7 @@ export const dict = { "ui.patch.action.created": "Utworzono", "ui.patch.action.moved": "Przeniesiono", "ui.patch.action.patched": "Załatano", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "Liczba odpowiedzi: {{count}}", "ui.question.answer.none": "(brak odpowiedzi)", diff --git a/packages/ui/src/i18n/ru.ts b/packages/ui/src/i18n/ru.ts index d67ec21163..a8c702ba0b 100644 --- a/packages/ui/src/i18n/ru.ts +++ b/packages/ui/src/i18n/ru.ts @@ -202,6 +202,7 @@ export const dict = { "ui.patch.action.created": "Создано", "ui.patch.action.moved": "Перемещено", "ui.patch.action.patched": "Изменено", + "ui.patch.action.plan": "План", // kilocode_change "ui.question.subtitle.answered": "Получено ответов: {{count}}", "ui.question.answer.none": "(нет ответа)", diff --git a/packages/ui/src/i18n/sv.ts b/packages/ui/src/i18n/sv.ts index bbff73961c..16d32736c1 100644 --- a/packages/ui/src/i18n/sv.ts +++ b/packages/ui/src/i18n/sv.ts @@ -188,6 +188,7 @@ export const dict: Record = { "ui.patch.action.created": "Skapad", "ui.patch.action.moved": "Flyttad", "ui.patch.action.patched": "Patchad", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "{{count}} besvarade", "ui.question.answer.none": "(inget svar)", "ui.question.review.notAnswered": "(ej besvarad)", diff --git a/packages/ui/src/i18n/th.ts b/packages/ui/src/i18n/th.ts index 961ebf6b18..f27d63037e 100644 --- a/packages/ui/src/i18n/th.ts +++ b/packages/ui/src/i18n/th.ts @@ -195,6 +195,7 @@ export const dict = { "ui.patch.action.created": "สร้าง", "ui.patch.action.moved": "ย้าย", "ui.patch.action.patched": "แพตช์", + "ui.patch.action.plan": "แผน", // kilocode_change "ui.question.subtitle.answered": "ตอบแล้ว {{count}} ข้อ", "ui.question.answer.none": "(ไม่มีคำตอบ)", diff --git a/packages/ui/src/i18n/tr.ts b/packages/ui/src/i18n/tr.ts index b8578e67bd..ba516a4e04 100644 --- a/packages/ui/src/i18n/tr.ts +++ b/packages/ui/src/i18n/tr.ts @@ -201,6 +201,7 @@ export const dict = { "ui.patch.action.created": "Oluşturuldu", "ui.patch.action.moved": "Taşındı", "ui.patch.action.patched": "Yamalandı", + "ui.patch.action.plan": "Plan", // kilocode_change "ui.question.subtitle.answered": "{{count}} yanıtlandı", "ui.question.answer.none": "(yanıt yok)", diff --git a/packages/ui/src/i18n/uk.ts b/packages/ui/src/i18n/uk.ts index a49abafbac..38333e9ed2 100644 --- a/packages/ui/src/i18n/uk.ts +++ b/packages/ui/src/i18n/uk.ts @@ -218,6 +218,7 @@ export const dict: Record = { "ui.patch.action.created": "Створено", "ui.patch.action.moved": "Переміщено", "ui.patch.action.patched": "Застосовано патч", + "ui.patch.action.plan": "План", // kilocode_change "ui.question.subtitle.answered": "{{count}} відповідей", "ui.question.answer.none": "(немає відповіді)", diff --git a/packages/ui/src/i18n/ur.ts b/packages/ui/src/i18n/ur.ts index 0019290f89..38a83c7bdb 100644 --- a/packages/ui/src/i18n/ur.ts +++ b/packages/ui/src/i18n/ur.ts @@ -189,6 +189,7 @@ export const dict: Record = { "ui.patch.action.created": "بنا دیا گیا", "ui.patch.action.moved": "منتقل کر دیا گیا", "ui.patch.action.patched": "پیچ کیا گیا", + "ui.patch.action.plan": "منصوبہ", // kilocode_change "ui.question.subtitle.answered": "{{count}} کے جواب دیے گئے", "ui.question.answer.none": "(کوئی جواب نہیں)", "ui.question.review.notAnswered": "(جواب نہیں دیا گیا)", diff --git a/packages/ui/src/i18n/vi.ts b/packages/ui/src/i18n/vi.ts index 7019868f60..7c43a8475b 100644 --- a/packages/ui/src/i18n/vi.ts +++ b/packages/ui/src/i18n/vi.ts @@ -188,6 +188,7 @@ export const dict: Record = { "ui.patch.action.created": "Đã tạo", "ui.patch.action.moved": "Đã di chuyển", "ui.patch.action.patched": "Đã vá", + "ui.patch.action.plan": "Kế hoạch", // kilocode_change "ui.question.subtitle.answered": "{{count}} đã trả lời", "ui.question.answer.none": "(không có câu trả lời)", "ui.question.review.notAnswered": "(chưa trả lời)", diff --git a/packages/ui/src/i18n/zh.ts b/packages/ui/src/i18n/zh.ts index eaca27f0b0..e3a84304be 100644 --- a/packages/ui/src/i18n/zh.ts +++ b/packages/ui/src/i18n/zh.ts @@ -197,6 +197,7 @@ export const dict = { "ui.patch.action.created": "已创建", "ui.patch.action.moved": "已移动", "ui.patch.action.patched": "已应用补丁", + "ui.patch.action.plan": "计划", // kilocode_change "ui.question.subtitle.answered": "已回答 {{count}} 个", "ui.question.answer.none": "(无答案)", diff --git a/packages/ui/src/i18n/zht.ts b/packages/ui/src/i18n/zht.ts index 27b7f8b9ac..43eddffe14 100644 --- a/packages/ui/src/i18n/zht.ts +++ b/packages/ui/src/i18n/zht.ts @@ -197,6 +197,7 @@ export const dict = { "ui.patch.action.created": "已建立", "ui.patch.action.moved": "已移動", "ui.patch.action.patched": "已套用修補", + "ui.patch.action.plan": "計畫", // kilocode_change "ui.question.subtitle.answered": "已回答 {{count}} 題", "ui.question.answer.none": "(無答案)", From 65a025b8dc43f82d31b04de16d51b1f4f0575bb6 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Wed, 19 Aug 2026 16:28:56 +0200 Subject: [PATCH 02/18] fix(vscode): keep document inspector lint compliant --- .../webview-ui/agent-manager/AgentManagerApp.tsx | 13 +++++-------- .../webview-ui/agent-manager/documents/state.ts | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx index 841c629225..745b3c7d83 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx @@ -298,7 +298,6 @@ const AgentManagerContent: Component = () => { const [sidePanel, setSidePanel] = createSignal(null) const diffOpen = () => sidePanel() === SidePanel.Diff const prOpen = () => sidePanel() === SidePanel.PR - const documentsOpen = () => sidePanel() === SidePanel.Documents const activePR = createMemo(() => { const selected = selection() if (!selected || selected === LOCAL) return undefined @@ -311,7 +310,7 @@ const AgentManagerContent: Component = () => { const diffLoading = diffs.diffLoading const setDiffLoading = diffs.setDiffLoading const diffNotices = diffs.diffNotices - // Diff, PR, terminal, and subagent views share one inspector width. + // Diff, PR, terminal, and subagent views share one inspector width. const [panelWidth, setPanelWidth] = createSignal(clampPanelWidth(persisted?.sidePanelWidth, window.innerWidth)) const resizeSide = createPanelResize(setPanelWidth, () => window.innerWidth) const showSideTerminal = () => { @@ -328,7 +327,7 @@ const AgentManagerContent: Component = () => { const documentInspector = createDocumentInspector( vscode, selection, - documentsOpen, + () => sidePanel() === SidePanel.Documents, () => { setHistory(false) setReviewActive(false) @@ -2253,8 +2252,6 @@ const AgentManagerContent: Component = () => { setSidePanel((prev) => (prev === SidePanel.Diff ? null : SidePanel.Diff)) } - const toggleDocumentsPanel = documentInspector.toggle - const renderTabById = (id: string) => renderTab(id, { terms, @@ -2451,9 +2448,9 @@ const AgentManagerContent: Component = () => { prStatus={() => activePR()?.pr} prOpen={prOpen} onTogglePR={togglePRPanel} - documentsOpen={documentsOpen} + documentsOpen={documentInspector.isOpen} documentsAvailable={documentInspector.available} - onToggleDocuments={toggleDocumentsPanel} + onToggleDocuments={documentInspector.toggle} terminalDestination={sideCtl.destination} terminalDestinationActive={() => sidePanel() === SidePanel.Terminal} terminalKeybind={() => kb().showTerminal ?? ""} @@ -2710,7 +2707,7 @@ const AgentManagerContent: Component = () => { inspector={documentInspector} onClosePanel={() => setSidePanel(null)} activeTerminalId={terms.activeId()} - visible={documentsOpen} + visible={documentInspector.isOpen} /> (isOpen() ? closePanel() : open()) - return { documents, comments, open, openFile, toggle, available } + return { documents, comments, open, openFile, toggle, available, isOpen } } export function handleDocumentOpen(event: Event, open: (file: string) => void): void { From 5aa2cb8a117cd80829edce2d1aa3c54a57cc92bc Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Wed, 19 Aug 2026 16:34:05 +0200 Subject: [PATCH 03/18] fix(vscode): reduce Agent Manager app lint size --- .../agent-manager/AgentManagerApp.tsx | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx index 745b3c7d83..86640e35e9 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx @@ -374,9 +374,6 @@ const AgentManagerContent: Component = () => { /** Namespace key so worktree/local ids from different projects never collide. */ const nsKey = (sel: string) => `${currentProjectId() ?? "single"}:${sel}` - // Per-sidebar-context terminal state. `terms.activeId` holds the id of the focused - // terminal tab, if any — takes precedence over session/pending/review when deriving - // the visible tab. Contexts are project-keyed: every project reuses LOCAL and ids like "0". const terms = createTerminalState(() => { const sel = selection() return sel === null ? null : nsKey(sel) @@ -949,9 +946,6 @@ const AgentManagerContent: Component = () => { if (el instanceof HTMLElement) scrollIntoView(el) } - // Sidebar previous/next + numeric-shortcut nav. Multi-project mode traverses - // every expanded project and atomically activates via activateSelection; - // single-project mode keeps the legacy in-process path. const projectNav = createProjectNav( { multiProject, @@ -1254,8 +1248,6 @@ const AgentManagerContent: Component = () => { if (["t", "w", "n", "d", "e", "f"].includes(e.key.toLowerCase()) && !e.shiftKey) { e.preventDefault() } - // Prevent browser defaults for shift variants (new terminal, close worktree, - // advanced/new/open worktree, open PR, terminal cycling) if (["t", "m", "w", "n", "o", "r", "[", "]"].includes(e.key.toLowerCase()) && e.shiftKey) { e.preventDefault() } @@ -1270,10 +1262,6 @@ const AgentManagerContent: Component = () => { } window.addEventListener("keydown", preventDefaults, true) - // Cmd/Ctrl+/ toggles the terminal even when VS Code's webview keybinding - // forwarding drops the key before it reaches the workbench (reported with - // the prompt input focused). When forwarding does work, the extension - // echoes the shortcut back as an action message and sideCtl dedupes it. const shortcut = (e: KeyboardEvent) => sideCtl.press(e) window.addEventListener("keydown", shortcut, true) @@ -1639,8 +1627,6 @@ const AgentManagerContent: Component = () => { } }) - // Diff context = sidebar selection (worktree id or LOCAL), stable across - // session tab switches inside the context so the git scopes don't refetch. const diffCtx = createMemo(() => selection() ?? undefined) // Active session within the diff context. The Session scope follows it, so @@ -1690,8 +1676,6 @@ const AgentManagerContent: Component = () => { /> ) - // Start/stop diff watch when the panel opens/closes, the review tab opens, - // or the composite id (context, scope, active session) changes. createEffect(() => { const panel = diffOpen() const active = reviewActive() @@ -2085,7 +2069,6 @@ const AgentManagerContent: Component = () => { closeReviewTab() } - // Drag-and-drop handlers for tab reordering const tabLookup = createMemo(() => new Map(activeTabs().map((s) => [s.id, s]))) const tabIds = createMemo(() => { const ids = activeTabs().map((s) => s.id) From d220415356bad2e5274bd0bbb2c3fedd19254442 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Wed, 19 Aug 2026 18:04:44 +0200 Subject: [PATCH 04/18] fix(vscode): address document inspector review findings --- .../src/agent-manager/AgentManagerProvider.ts | 2 +- .../kilo-vscode/src/agent-manager/types.ts | 2 + .../agent-manager/worktree-diff-controller.ts | 25 +++++--- .../src/diff/DiffViewerProvider.ts | 14 ++-- .../agent-manager/AgentManagerApp.tsx | 1 + .../agent-manager/documents/DocumentPanel.tsx | 21 +++++- .../agent-manager/documents/state.ts | 64 +++++++++++++------ .../diff-viewer/FullScreenDiffView.tsx | 15 +++-- .../src/types/messages/extension-messages.ts | 1 + .../src/types/messages/webview-messages.ts | 1 + 10 files changed, 101 insertions(+), 45 deletions(-) diff --git a/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts b/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts index ed59d29acb..283671df1a 100644 --- a/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts +++ b/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts @@ -869,7 +869,7 @@ export class AgentManagerProvider implements Disposable { this.openWorktreeFile(m.sessionId, m.filePath, m.line, m.column) return null } - if (m.type === "agentManager.requestDocument") return this.diffs.document(m.sessionId, m.file) + if (m.type === "agentManager.requestDocument") return this.diffs.document(m.sessionId, m.file, m.contextKey) } private onBridgeMessage(m: AgentManagerInMessage): Record | null | undefined { diff --git a/packages/kilo-vscode/src/agent-manager/types.ts b/packages/kilo-vscode/src/agent-manager/types.ts index 42743183b9..7baa490ce8 100644 --- a/packages/kilo-vscode/src/agent-manager/types.ts +++ b/packages/kilo-vscode/src/agent-manager/types.ts @@ -365,6 +365,7 @@ interface WorktreeDiffFileMessage { interface DocumentMessage { type: "agentManager.document" sessionId: string + contextKey?: string file: string requestedFile?: string content?: string @@ -804,6 +805,7 @@ interface RequestDocumentIn { type: "agentManager.requestDocument" sessionId: string file: string + contextKey?: string } // Pass-through messages intercepted for side effects diff --git a/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts b/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts index 80caa2bbbf..ba3278a61b 100644 --- a/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts +++ b/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts @@ -207,14 +207,23 @@ export class WorktreeDiffController { * controller's state/root context because a document read is a worktree file * read, resolved against the same directory the diff for that context uses. */ - public document(sessionId: string, file: string): null { - const state = this.ctx.getState() - const worktree = state?.getWorktree(sessionId) - const session = worktree ? undefined : state?.getSession(sessionId) - const root = - worktree?.path ?? (session?.worktreeId ? state?.getWorktree(session.worktreeId)?.path : this.ctx.getRoot()) - if (!root) return null - this.ctx.post({ type: "agentManager.document", sessionId, file, requestedFile: file, ...readDocument(root, file) }) + public document(sessionId: string, file: string, contextKey?: string): null { + void this.ready("stateReady rejected, continuing document resolve:").then(() => { + const state = this.ctx.getState() + const worktree = sessionId === LOCAL_DIFF_ID ? undefined : state?.getWorktree(sessionId) + const session = worktree || sessionId === LOCAL_DIFF_ID ? undefined : state?.getSession(sessionId) + const root = + sessionId === LOCAL_DIFF_ID + ? this.ctx.getRoot() + : (worktree?.path ?? + (session?.worktreeId + ? state?.getWorktree(session.worktreeId)?.path + : session + ? this.ctx.getRoot() + : undefined)) + const result = root ? readDocument(root, file) : { error: "The document context is no longer available." } + this.ctx.post({ type: "agentManager.document", sessionId, file, requestedFile: file, contextKey, ...result }) + }) return null } diff --git a/packages/kilo-vscode/src/diff/DiffViewerProvider.ts b/packages/kilo-vscode/src/diff/DiffViewerProvider.ts index b517e469a9..854b405dd9 100644 --- a/packages/kilo-vscode/src/diff/DiffViewerProvider.ts +++ b/packages/kilo-vscode/src/diff/DiffViewerProvider.ts @@ -56,10 +56,8 @@ export class DiffViewerProvider implements vscode.Disposable { if (this.panel && this.controller) { this.panel.reveal(this.panel.viewColumn ?? vscode.ViewColumn.One) void this.panel.webview.postMessage({ type: "diffViewer.initialFile", file: this.ctx.initialFile }) - void this.panel.webview.postMessage({ - type: "diffViewer.initialMarkdown", - render: this.ctx.initialMarkdown === true, - }) + if (this.ctx.initialMarkdown !== undefined) + void this.panel.webview.postMessage({ type: "diffViewer.initialMarkdown", render: this.ctx.initialMarkdown }) this.controller.setContext(this.ctx) const nextId = this.catalog.defaultSourceId(this.ctx) if (nextId && nextId !== this.controller.currentId) { @@ -99,7 +97,7 @@ export class DiffViewerProvider implements vscode.Disposable { dir, initialSourceId: turnInitialSourceId ?? arg?.initialSourceId, initialFile: arg?.file, - initialMarkdown: typeof arg?.file === "string" && /\.(md|mdx|markdown)$/i.test(arg.file), + ...(typeof arg?.file === "string" && /\.(md|mdx|markdown)$/i.test(arg.file) ? { initialMarkdown: true } : {}), hidePicker: !!turnInitialSourceId, }) } @@ -243,10 +241,8 @@ export class DiffViewerProvider implements vscode.Disposable { }) void this.panel.webview.postMessage({ type: "diffViewer.markdownRender", render: getDiffMarkdownRender() }) void this.panel.webview.postMessage({ type: "diffViewer.initialFile", file: this.ctx?.initialFile }) - void this.panel.webview.postMessage({ - type: "diffViewer.initialMarkdown", - render: this.ctx?.initialMarkdown === true, - }) + if (this.ctx?.initialMarkdown !== undefined) + void this.panel.webview.postMessage({ type: "diffViewer.initialMarkdown", render: this.ctx.initialMarkdown }) const initial = this.ctx ? this.catalog.defaultSourceId(this.ctx) : undefined if (initial) this.swap(initial) } diff --git a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx index 86640e35e9..a6f3c9441c 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx @@ -327,6 +327,7 @@ const AgentManagerContent: Component = () => { const documentInspector = createDocumentInspector( vscode, selection, + currentProjectId, () => sidePanel() === SidePanel.Documents, () => { setHistory(false) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx index 6a5e1d5dbd..76b59b462a 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx @@ -36,7 +36,7 @@ export interface DocumentPanelProps { onClose: (id: string) => void onCloseOthers: (id: string) => void onReorder: (from: string, to: string) => void - onOpenFile: (file: string, line?: number) => void + onOpenFile: (file: string, line?: number, column?: number) => void onClosePanel: () => void activeTerminalId?: string visible: Accessor @@ -166,9 +166,10 @@ export const DocumentPanel: Component = (props) => { createEffect( on( - () => [file(), content(), props.comments] as const, + () => [file(), content(), props.comments, data()?.loading, data()?.error] as const, ([path, text, current]) => { if (!path) return + if (data()?.loading || data()?.error || data()?.content === undefined) return const max = lineCount(text) const valid = current.filter((item) => item.file !== path || (item.line >= 1 && item.line <= max)) if (valid.length !== current.length) updateComments(valid) @@ -178,6 +179,20 @@ export const DocumentPanel: Component = (props) => { { defer: true }, ), ) + createEffect( + on( + () => [file(), props.tabs()] as const, + () => { + setDraft(null) + setEditing(null) + draftMeta = null + editMeta = null + composer.draft = null + composer.edit = null + }, + { defer: true }, + ), + ) const close = (id: string, focus: { restore: () => void }) => { props.onClose(id) @@ -218,7 +233,7 @@ export const DocumentPanel: Component = (props) => { size="small" variant="ghost" label={t("agentManager.diff.openFile")} - onClick={() => props.onOpenFile(file())} + onClick={() => props.onOpenFile(file(), selected()?.line, selected()?.column)} /> diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts b/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts index 6ee0490015..cc0aee6c1a 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts @@ -6,6 +6,8 @@ import type { AgentManagerDocumentMessage } from "../../src/types/messages" export interface DocumentTab { id: string file: string + line?: number + column?: number } export interface DocumentData { @@ -26,7 +28,11 @@ export function isMarkdownPath(file: string): boolean { return /\.(md|mdx|markdown)$/i.test(file) } -export function createDocuments(vscode: ReturnType, context: Accessor) { +export function createDocuments( + vscode: ReturnType, + context: Accessor, + session: Accessor = context, +) { const [tabs, setTabs] = createSignal>({}) const [active, setActive] = createSignal>({}) const [data, setData] = createSignal>({}) @@ -36,24 +42,28 @@ export function createDocuments(vscode: ReturnType, context: A const selected = () => active()[current()] const document = (file: string) => data()[key(current(), file)] - const request = (file: string) => { + const request = (file: string, sessionId = session() ?? "") => { const ctx = current() if (!ctx) return const id = key(ctx, file) setData((prev) => ({ ...prev, [id]: { ...(prev[id] ?? { file }), file, loading: true, error: undefined } })) - vscode.postMessage({ type: "agentManager.requestDocument", sessionId: ctx, file }) + vscode.postMessage({ type: "agentManager.requestDocument", sessionId, file, contextKey: ctx }) } - const open = (file: string) => { + const open = (file: string, sessionId = current(), line?: number, column?: number) => { const ctx = current() if (!ctx || !file) return setTabs((prev) => { const list = prev[ctx] ?? [] - if (list.some((tab) => tab.file === file)) return prev - return { ...prev, [ctx]: [...list, { id: key(ctx, file), file }] } + const id = key(ctx, file) + if (list.some((tab) => tab.id === id)) { + return { ...prev, [ctx]: list.map((tab) => (tab.id === id ? { ...tab, line, column } : tab)) } + } + return { ...prev, [ctx]: [...list, { id, file, line, column }] } }) setActive((prev) => ({ ...prev, [ctx]: key(ctx, file) })) - request(file) + request(file, sessionId) + return true } const select = (id: string) => { @@ -98,7 +108,7 @@ export function createDocuments(vscode: ReturnType, context: A } const onMessage = (message: AgentManagerDocumentMessage) => { - const id = key(message.sessionId, message.requestedFile ?? message.file) + const id = key(message.contextKey ?? message.sessionId, message.requestedFile ?? message.file) setData((prev) => ({ ...prev, [id]: { @@ -133,13 +143,24 @@ export function createDocumentComments(context: Accessor) { export function createDocumentInspector( vscode: ReturnType, context: Accessor, + project: Accessor, isOpen: Accessor, openPanel: () => void, closePanel: () => void, ) { - const documents = createDocuments(vscode, context) - const comments = createDocumentComments(context) - const open = (file?: string) => (openPanel(), file ? documents.open(file) : undefined) + const scope = () => `${project() ?? "single"}:${context() ?? ""}` + const documents = createDocuments(vscode, scope, context) + const comments = createDocumentComments(scope) + const open = (file?: string, sessionId?: string, line?: number, column?: number) => { + if (!file) { + openPanel() + return true + } + const sid = sessionId ?? context() + if (!sid || !documents.open(file, sid, line, column)) return false + openPanel() + return true + } onMount(() => { const handler = (event: Event) => handleDocumentOpen(event, open) const message = vscode.onMessage((item) => { @@ -156,17 +177,24 @@ export function createDocumentInspector( // Tabs are keyed per worktree, so this hides itself on a worktree with none, // and stays visible while the panel is open so it can still be toggled shut. const available = () => documents.tabs().length > 0 || isOpen() - const openFile = (file: string, line?: number) => { + const openFile = (file: string, line?: number, column?: number) => { const sessionId = context() - if (sessionId) vscode.postMessage({ type: "agentManager.openFile", sessionId, filePath: file, line }) + if (sessionId) vscode.postMessage({ type: "agentManager.openFile", sessionId, filePath: file, line, column }) } const toggle = () => (isOpen() ? closePanel() : open()) - return { documents, comments, open, openFile, toggle, available, isOpen } + return { documents, comments, open, openFile, toggle, available, isOpen, scope } } -export function handleDocumentOpen(event: Event, open: (file: string) => void): void { - const file = (event as CustomEvent<{ filePath?: unknown }>).detail?.filePath +export function handleDocumentOpen( + event: Event, + open: (file: string, sessionId?: string, line?: number, column?: number) => boolean, +): void { + const detail = (event as CustomEvent<{ filePath?: unknown; sessionID?: unknown; line?: unknown; column?: unknown }>) + .detail + const file = detail?.filePath if (typeof file !== "string" || !file) return - event.preventDefault() - open(file) + const sessionId = typeof detail.sessionID === "string" ? detail.sessionID : undefined + const line = typeof detail.line === "number" ? detail.line : undefined + const column = typeof detail.column === "number" ? detail.column : undefined + if (open(file, sessionId, line, column)) event.preventDefault() } diff --git a/packages/kilo-vscode/webview-ui/diff-viewer/FullScreenDiffView.tsx b/packages/kilo-vscode/webview-ui/diff-viewer/FullScreenDiffView.tsx index 1e538cca0a..3d2e11faf7 100644 --- a/packages/kilo-vscode/webview-ui/diff-viewer/FullScreenDiffView.tsx +++ b/packages/kilo-vscode/webview-ui/diff-viewer/FullScreenDiffView.tsx @@ -161,6 +161,7 @@ export const FullScreenDiffView: Component = (props) => // Initialize each worktree with every file expanded, then preserve manual // collapse state while adding and removing files from live summaries. let initializedKey: string | undefined + let initialFileKey: string | undefined let known = new Set() let rootRef: HTMLDivElement | undefined const [scroller, setScroller] = createSignal() @@ -221,7 +222,7 @@ export const FullScreenDiffView: Component = (props) => // vs when we just prune stale entries from the open list. createEffect( on( - () => [props.sessionKey, props.diffs] as const, + () => [props.sessionKey, props.diffs, props.initialFile] as const, ([key, diffs]) => { if (diffs.length === 0) { // No diffs yet — clear active file only for a new key; keep current @@ -234,11 +235,13 @@ export const FullScreenDiffView: Component = (props) => // Keep active file in sync — pick first if current is stale const current = activeFile() - if (!current || !diffs.some((d) => d.file === current)) { - const initial = - props.initialFile && diffs.some((d) => d.file === props.initialFile) ? props.initialFile : undefined - setActiveFile(initial ?? diffs[0]!.file) - } + const initial = + props.initialFile && diffs.some((d) => d.file === props.initialFile) ? props.initialFile : undefined + const initialKey = initial ? `${key}:${initial}` : undefined + if (initial && initial !== current && initialFileKey !== initialKey) { + initialFileKey = initialKey + setActiveFile(initial) + } else if (!current || !diffs.some((d) => d.file === current)) setActiveFile(diffs[0]!.file) // New context: initialize open state from the diff policy. if (key !== initializedKey) { diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts index c63638d8e5..2a93c8a60e 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts @@ -980,6 +980,7 @@ export interface AgentManagerWorktreeDiffFileMessage { export interface AgentManagerDocumentMessage { type: "agentManager.document" sessionId: string + contextKey?: string file: string requestedFile?: string content?: string diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts index d058873d29..8d80003571 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts @@ -873,6 +873,7 @@ export interface AgentManagerRequestDocumentMessage { type: "agentManager.requestDocument" sessionId: string file: string + contextKey?: string } // Create multiple worktree sessions for the same prompt (multi-version mode) From 056db466132115ae632d27f1863115fc078562cc Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Wed, 19 Aug 2026 19:28:16 +0200 Subject: [PATCH 05/18] test(vscode): cover document worktree isolation --- .../unit/agent-manager-documents.test.ts | 72 +++++++++++++++++++ .../agent-manager/documents/state.ts | 2 +- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 packages/kilo-vscode/tests/unit/agent-manager-documents.test.ts diff --git a/packages/kilo-vscode/tests/unit/agent-manager-documents.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-documents.test.ts new file mode 100644 index 0000000000..78e422ffe9 --- /dev/null +++ b/packages/kilo-vscode/tests/unit/agent-manager-documents.test.ts @@ -0,0 +1,72 @@ +import { describe, expect, it } from "bun:test" +import { createRoot, createSignal } from "solid-js" +import { createDocumentComments, createDocuments } from "../../webview-ui/agent-manager/documents/state" +import type { AgentManagerDocumentMessage } from "../../webview-ui/src/types/messages" + +describe("Agent Manager document state", () => { + it("keeps tabs, content, and comments scoped when switching worktrees and projects", () => { + createRoot((dispose) => { + const sent: unknown[] = [] + const vscode = { postMessage: (message: unknown) => sent.push(message) } as Parameters[0] + const [scope, setScope] = createSignal("project-a:wt-a") + const [session, setSession] = createSignal("ses-a") + const docs = createDocuments(vscode, scope, session) + const comments = createDocumentComments(scope) + + docs.open("plans/plan.md") + expect(sent[0]).toMatchObject({ sessionId: "ses-a", contextKey: "project-a:wt-a" }) + docs.onMessage({ + type: "agentManager.document", + sessionId: "ses-a", + contextKey: "project-a:wt-a", + requestedFile: "plans/plan.md", + file: "plans/plan.md", + kind: "text", + content: "# Worktree A", + } satisfies AgentManagerDocumentMessage) + comments.setComments([{ id: "a", file: "plans/plan.md", side: "additions", line: 1, comment: "A" }]) + + setScope("project-a:wt-b") + setSession("ses-b") + expect(docs.tabs()).toEqual([]) + expect(docs.document("plans/plan.md")).toBeUndefined() + expect(comments.comments()).toEqual([]) + + docs.onMessage({ + type: "agentManager.document", + sessionId: "ses-a", + contextKey: "project-a:wt-a", + requestedFile: "plans/late.md", + file: "plans/late.md", + kind: "text", + content: "# Late A", + } satisfies AgentManagerDocumentMessage) + expect(docs.tabs()).toEqual([]) + expect(docs.document("plans/late.md")).toBeUndefined() + + docs.open("plans/plan.md") + expect(sent[1]).toMatchObject({ sessionId: "ses-b", contextKey: "project-a:wt-b" }) + docs.onMessage({ + type: "agentManager.document", + sessionId: "ses-b", + contextKey: "project-a:wt-b", + requestedFile: "plans/plan.md", + file: "plans/plan.md", + kind: "text", + content: "# Worktree B", + } satisfies AgentManagerDocumentMessage) + comments.setComments([{ id: "b", file: "plans/plan.md", side: "additions", line: 1, comment: "B" }]) + + setScope("project-a:wt-a") + setSession("ses-a") + expect(docs.tabs()).toHaveLength(1) + expect(docs.document("plans/plan.md")?.content).toBe("# Worktree A") + expect(comments.comments().map((item) => item.comment)).toEqual(["A"]) + + setScope("project-b:wt-a") + expect(docs.tabs()).toEqual([]) + expect(comments.comments()).toEqual([]) + dispose() + }) + }) +}) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts b/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts index cc0aee6c1a..10c46fec80 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts @@ -50,7 +50,7 @@ export function createDocuments( vscode.postMessage({ type: "agentManager.requestDocument", sessionId, file, contextKey: ctx }) } - const open = (file: string, sessionId = current(), line?: number, column?: number) => { + const open = (file: string, sessionId = session() ?? "", line?: number, column?: number) => { const ctx = current() if (!ctx || !file) return setTabs((prev) => { From 9fbb7a1aacc818afad90ff10857927bdb48a53ab Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 20 Aug 2026 10:21:47 +0200 Subject: [PATCH 06/18] fix(vscode): open review comment files directly --- .../src/components/chat/ReviewComments.tsx | 62 +++---------------- 1 file changed, 7 insertions(+), 55 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/ReviewComments.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/ReviewComments.tsx index ccc0960498..8a2d3afce8 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/ReviewComments.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/ReviewComments.tsx @@ -1,13 +1,8 @@ import { For, Show, type Component } from "solid-js" import { Button } from "@kilocode/kilo-ui/button" -import { Dialog } from "@kilocode/kilo-ui/dialog" import { Icon } from "@kilocode/kilo-ui/icon" -import { IconButton } from "@kilocode/kilo-ui/icon-button" -import { Tooltip } from "@kilocode/kilo-ui/tooltip" -import { useDialog } from "@kilocode/kilo-ui/context/dialog" import { useLanguage } from "../../context/language" import { useVSCode } from "../../context/vscode" -import { useWorktreeMode } from "../../context/worktree-mode" import type { ReviewComment } from "../../types/messages" import { fileName } from "./prompt-input-utils" @@ -22,58 +17,15 @@ interface ReviewCommentsProps { export const ReviewComments: Component = (props) => { const language = useLanguage() const vscode = useVSCode() - const worktree = useWorktreeMode() - const dialog = useDialog() const side = (item: ReviewComment) => (item.side === "deletions" ? "-" : "+") - const title = (item: ReviewComment) => `${fileName(item.file)} ${side(item)}${item.line}` const open = (item: ReviewComment) => { - if (worktree && props.sessionID) { - vscode.postMessage({ - type: "agentManager.openFile", - sessionId: props.sessionID, - filePath: item.file, - line: item.line, - }) - dialog.close() - return - } - vscode.postMessage({ type: "openFile", filePath: item.file, line: item.line, column: 1 }) - dialog.close() - } - - const show = (item: ReviewComment) => { - dialog.show(() => ( - -
-
- {title(item)} - - open(item)} - /> - -
- -
- {language.t("agentManager.review.metaFile")} - {item.file} - {language.t("agentManager.review.metaLine")} - L{item.line} - {language.t("agentManager.review.metaComment")} - {item.comment} -
- - -
{item.selectedText}
-
-
-
- )) + const event = new CustomEvent("kilo:open-file", { + cancelable: true, + detail: { filePath: item.file, line: item.line, column: 1, sessionID: props.sessionID }, + }) + if (window.dispatchEvent(event)) + vscode.postMessage({ type: "openFile", filePath: item.file, line: item.line, column: 1 }) } return ( @@ -96,7 +48,7 @@ export const ReviewComments: Component = (props) => { {(item) => (
- From 9026260650cf5609e6a02de9b89ae691434a3ae4 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 20 Aug 2026 10:57:54 +0200 Subject: [PATCH 08/18] fix(vscode): preserve document review keyboard flow --- .../agent-manager/documents/DocumentPanel.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx index f0642096d2..8dc8f26280 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx @@ -112,6 +112,11 @@ export const DocumentPanel: Component = (props) => { const updateComments = (next: ReviewComment[]) => props.onCommentsChange(next) const comments = () => props.comments.filter((item) => item.file === file()) + const focusRoot = () => { + requestAnimationFrame(() => { + requestAnimationFrame(() => rootRef?.focus()) + }) + } const addComment = (path: string, side: AnnotationSide, line: number, text: string, selectedText: string) => { updateComments([ ...props.comments, @@ -120,6 +125,7 @@ export const DocumentPanel: Component = (props) => { setDraft(null) draftMeta = null composer.draft = null + focusRoot() } const sendComment = (path: string, side: AnnotationSide, line: number, text: string, selectedText: string) => { sendReviewComments( @@ -129,23 +135,27 @@ export const DocumentPanel: Component = (props) => { setDraft(null) draftMeta = null composer.draft = null + focusRoot() } const updateComment = (id: string, text: string) => { updateComments(props.comments.map((item) => (item.id === id ? { ...item, comment: text } : item))) setEditing(null) editMeta = null composer.edit = null + focusRoot() } const deleteComment = (id: string) => { updateComments(props.comments.filter((item) => item.id !== id)) setEditing(null) editMeta = null composer.edit = null + focusRoot() } const cancelDraft = () => { setDraft(null) draftMeta = null composer.draft = null + focusRoot() } const annotations = (): DiffLineAnnotation[] => { const result = buildFileAnnotations(file(), comments(), editing(), draft(), draftMeta, editMeta) @@ -183,10 +193,6 @@ export const DocumentPanel: Component = (props) => { focusRoot() } - const focusRoot = () => { - requestAnimationFrame(() => rootRef?.focus()) - } - createEffect( on( () => [file(), content(), props.comments, data()?.loading, data()?.error] as const, From 55333d4a12a1af8045f07c0dc0d66b79201bf3a7 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 20 Aug 2026 11:07:09 +0200 Subject: [PATCH 09/18] fix(vscode): restore prompt focus after document review --- .../kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx | 1 + .../kilo-vscode/webview-ui/agent-manager/agent-manager.css | 1 + .../webview-ui/agent-manager/documents/DocumentPanel.tsx | 4 +++- .../webview-ui/agent-manager/documents/DocumentPanelHost.tsx | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx index 79a78a08ba..d6a7eabc16 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx @@ -2707,6 +2707,7 @@ const AgentManagerContent: Component = () => { setSidePanel(null)} + onSendAll={focusCtl.focus} activeTerminalId={terms.activeId()} visible={documentInspector.isOpen} /> diff --git a/packages/kilo-vscode/webview-ui/agent-manager/agent-manager.css b/packages/kilo-vscode/webview-ui/agent-manager/agent-manager.css index d9269755c8..2fcfc501db 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/agent-manager.css +++ b/packages/kilo-vscode/webview-ui/agent-manager/agent-manager.css @@ -1952,6 +1952,7 @@ body.am-wt-dragging-active * { } .am-diff-panel:focus, +.am-document-panel:focus, .am-review-layout:focus { outline: none; } diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx index 8dc8f26280..f4fd7c90da 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx @@ -38,6 +38,7 @@ export interface DocumentPanelProps { onReorder: (from: string, to: string) => void onOpenFile: (file: string, line?: number, column?: number) => void onClosePanel: () => void + onSendAll?: () => void activeTerminalId?: string visible: Accessor } @@ -190,7 +191,8 @@ export const DocumentPanel: Component = (props) => { if (props.comments.length === 0) return sendReviewComments(props.comments, props.activeTerminalId) updateComments([]) - focusRoot() + if (props.onSendAll) props.onSendAll() + else focusRoot() } createEffect( diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx index 48df0518d0..2717e1434e 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx @@ -5,6 +5,7 @@ import { createDocumentInspector } from "./state" interface Props { inspector: ReturnType onClosePanel: () => void + onSendAll?: () => void activeTerminalId?: string visible: Accessor } @@ -22,6 +23,7 @@ export const DocumentPanelHost: Component = (props) => ( onReorder={props.inspector.documents.reorder} onOpenFile={props.inspector.openFile} onClosePanel={props.onClosePanel} + onSendAll={props.onSendAll} activeTerminalId={props.activeTerminalId} visible={props.visible} /> From 8e26de0f182ee50954fb02ed19a94c52e5d1ca68 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 20 Aug 2026 12:12:19 +0200 Subject: [PATCH 10/18] fix(vscode): preserve review comment session fallback --- .../webview-ui/src/components/chat/ReviewComments.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/ReviewComments.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/ReviewComments.tsx index e73b88ddd8..56412887c4 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/ReviewComments.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/ReviewComments.tsx @@ -42,7 +42,13 @@ export const ReviewComments: Component = (props) => { detail: { filePath: item.file, line: item.line, column: 1, sessionID: props.sessionID }, }) if (window.dispatchEvent(event)) - vscode.postMessage({ type: "openFile", filePath: item.file, line: item.line, column: 1 }) + vscode.postMessage({ + type: "openFile", + filePath: item.file, + line: item.line, + column: 1, + sessionID: props.sessionID, + }) dialog.close() } From 3be279fec53da257a6027ed5fd86970bd4e7f6af Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 20 Aug 2026 13:10:03 +0200 Subject: [PATCH 11/18] feat(vscode): reuse document viewer for sidebar files --- packages/kilo-vscode/esbuild.js | 1 + .../kilo-vscode/src/DocumentViewerProvider.ts | 151 ++++++++++++++++++ packages/kilo-vscode/src/KiloProvider.ts | 13 +- .../agent-manager/worktree-diff-controller.ts | 2 +- .../document-reader.ts | 0 packages/kilo-vscode/src/extension.ts | 16 ++ .../tests/unit/agent-manager-arch.test.ts | 3 +- .../unit/agent-manager-documents.test.ts | 2 +- .../tests/unit/agent-manager-i18n.test.ts | 3 +- .../tests/unit/document-reader.test.ts | 2 +- .../agent-manager/AgentManagerApp.tsx | 2 +- .../documents/DocumentPanelHost.tsx | 4 +- .../documents/DocumentPanel.tsx | 16 +- .../webview-ui/documents/index.tsx | 87 ++++++++++ .../{agent-manager => }/documents/state.ts | 34 ++-- .../src/types/messages/extension-messages.ts | 24 +++ .../src/types/messages/webview-messages.ts | 28 ++++ 17 files changed, 358 insertions(+), 30 deletions(-) create mode 100644 packages/kilo-vscode/src/DocumentViewerProvider.ts rename packages/kilo-vscode/src/{agent-manager => documents}/document-reader.ts (100%) rename packages/kilo-vscode/webview-ui/{agent-manager => }/documents/DocumentPanel.tsx (96%) create mode 100644 packages/kilo-vscode/webview-ui/documents/index.tsx rename packages/kilo-vscode/webview-ui/{agent-manager => }/documents/state.ts (86%) diff --git a/packages/kilo-vscode/esbuild.js b/packages/kilo-vscode/esbuild.js index 2fa1876afd..ec5b59f98b 100644 --- a/packages/kilo-vscode/esbuild.js +++ b/packages/kilo-vscode/esbuild.js @@ -275,6 +275,7 @@ function getWebviewsConfig() { kiloclaw: "webview-ui/kiloclaw/index.tsx", marketplace: "webview-ui/marketplace/index.tsx", "diff-viewer": "webview-ui/diff-viewer/index.tsx", + documents: "webview-ui/documents/index.tsx", "diff-virtual": "webview-ui/diff-virtual/index.tsx", webview: "webview-ui/src/index.tsx", }, diff --git a/packages/kilo-vscode/src/DocumentViewerProvider.ts b/packages/kilo-vscode/src/DocumentViewerProvider.ts new file mode 100644 index 0000000000..8390ded5ff --- /dev/null +++ b/packages/kilo-vscode/src/DocumentViewerProvider.ts @@ -0,0 +1,151 @@ +import * as vscode from "vscode" +import type { ReviewCommentEntry } from "./shared/review-comments" +import { readDocument } from "./documents/document-reader" +import { buildWebviewHtml } from "./utils" +import type { KiloConnectionService } from "./services/cli-backend" + +interface Context { + sessionId?: string + directory?: string +} + +type Comment = ReviewCommentEntry + +export interface DocumentViewerOptions { + onComments: (comments: Comment[], autoSend: boolean) => void +} + +export class DocumentViewerProvider implements vscode.Disposable { + public static readonly viewType = "kilo-code.new.DocumentsPanel" + private panel: vscode.WebviewPanel | undefined + private pending: { file: string; sessionId?: string; directory?: string; line?: number; column?: number } | undefined + private readonly contexts = new Map() + private currentKey = "" + private readonly disposables: vscode.Disposable[] = [] + + constructor( + private readonly extensionUri: vscode.Uri, + private readonly connection: KiloConnectionService, + private readonly options: DocumentViewerOptions, + ) {} + + openFromCommand(input: { + file: string + sessionId?: string + directory?: string + line?: number + column?: number + }): void { + const contextKey = this.contextKey(input.sessionId, input.directory) + this.contexts.set(contextKey, { sessionId: input.sessionId, directory: input.directory }) + this.currentKey = contextKey + const next = { ...input, contextKey } + if (this.panel) { + this.panel.reveal(this.panel.viewColumn ?? vscode.ViewColumn.One) + void this.panel.webview.postMessage({ type: "document.open", ...next }) + return + } + this.pending = input + this.createPanel() + } + + dispose(): void { + this.panel?.dispose() + for (const item of this.disposables) item.dispose() + this.disposables.length = 0 + this.contexts.clear() + } + + private contextKey(sessionId?: string, directory?: string): string { + return `${sessionId ?? "local"}:${directory ?? ""}` + } + + private createPanel(): void { + const panel = vscode.window.createWebviewPanel( + DocumentViewerProvider.viewType, + "Documents", + vscode.ViewColumn.One, + { + enableScripts: true, + retainContextWhenHidden: true, + localResourceRoots: [this.extensionUri], + }, + ) + panel.iconPath = { + light: vscode.Uri.joinPath(this.extensionUri, "assets", "icons", "kilo-light.svg"), + dark: vscode.Uri.joinPath(this.extensionUri, "assets", "icons", "kilo-dark.svg"), + } + panel.webview.html = this.html(panel.webview) + this.panel = panel + this.disposables.push( + panel.webview.onDidReceiveMessage((message) => this.message(message as Record)), + panel.onDidDispose(() => { + this.panel = undefined + this.pending = undefined + this.currentKey = "" + }), + ) + } + + private message(message: Record): void { + if (message.type === "webviewReady") return this.ready() + if (message.type === "document.request") { + return this.request(message) + } + if (message.type === "document.sendComments" && Array.isArray(message.comments)) { + this.options.onComments(message.comments as Comment[], message.autoSend === true) + return + } + if (message.type === "document.openFile" && typeof message.file === "string") { + const context = this.contexts.get(this.currentKey) + this.openFromCommand({ + file: message.file, + sessionId: context?.sessionId, + directory: context?.directory, + line: typeof message.line === "number" ? message.line : undefined, + column: typeof message.column === "number" ? message.column : undefined, + }) + return + } + if (message.type === "document.close") this.panel?.dispose() + } + + private ready(): void { + if (!this.pending || !this.panel) return + const input = this.pending + this.pending = undefined + void this.panel.webview.postMessage({ + type: "document.open", + ...input, + contextKey: this.contextKey(input.sessionId, input.directory), + }) + } + + private request(message: Record): void { + const file = typeof message.file === "string" ? message.file : undefined + const contextKey = typeof message.contextKey === "string" ? message.contextKey : undefined + if (!file || !contextKey) return + const context = this.contexts.get(contextKey) + const result = context?.directory + ? readDocument(context.directory, file) + : { error: "The document context is no longer available." } + this.panel?.webview.postMessage({ + type: "document.result", + sessionId: context?.sessionId ?? "", + contextKey, + requestedFile: file, + ...result, + }) + } + + private html(webview: vscode.Webview): string { + return buildWebviewHtml(webview, { + scriptUri: webview.asWebviewUri(vscode.Uri.joinPath(this.extensionUri, "dist", "documents.js")), + styleUri: webview.asWebviewUri(vscode.Uri.joinPath(this.extensionUri, "dist", "documents.css")), + iconsBaseUri: webview.asWebviewUri(vscode.Uri.joinPath(this.extensionUri, "assets", "icons")), + workerUri: webview.asWebviewUri(vscode.Uri.joinPath(this.extensionUri, "dist", "shiki-worker.js")), + title: "Documents", + port: this.connection.getServerInfo()?.port, + }) + } +} diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index d9e144a530..58db489f1d 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -465,6 +465,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper private diffVirtualProvider: import("./DiffVirtualProvider").DiffVirtualProvider | undefined private diffViewerProvider: import("./diff/DiffViewerProvider").DiffViewerProvider | undefined + private documentViewerProvider: import("./DocumentViewerProvider").DocumentViewerProvider | undefined private remoteService: RemoteStatusService | null = null private unsubscribeRemote: (() => void) | null = null @@ -566,6 +567,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.diffViewerProvider = provider } + public setDocumentViewerProvider(provider: import("./DocumentViewerProvider").DocumentViewerProvider): void { + this.documentViewerProvider = provider + } + getTelemetryProperties(): Record { return { appName: "kilo-code", @@ -1598,8 +1603,12 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper dir: (sessionID) => this.getWorkspaceDirectory(sessionID ?? this.currentSession?.id), diff: this.diffVirtualProvider, openMarkdown: (file, sessionID) => { - if (!this.diffViewerProvider) return false - this.diffViewerProvider.openFromCommand({ sessionId: sessionID, file }) + if (!this.documentViewerProvider) return false + this.documentViewerProvider.openFromCommand({ + sessionId: sessionID, + directory: this.getWorkspaceDirectory(sessionID ?? this.currentSession?.id), + file, + }) return true }, storage: this.extensionContext?.globalStorageUri, diff --git a/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts b/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts index ba3278a61b..d4ca705992 100644 --- a/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts +++ b/packages/kilo-vscode/src/agent-manager/worktree-diff-controller.ts @@ -8,7 +8,7 @@ import type { ApplyConflict, GitOps } from "./GitOps" import { shouldStopDiffPolling } from "./delete-worktree" import { remoteRef, type ManagedSession, type WorktreeStateManager } from "./WorktreeStateManager" import { parseDiffId, scopeToSourceId } from "./diff-scope" -import { readDocument } from "./document-reader" +import { readDocument } from "../documents/document-reader" import type { AgentManagerOutMessage, WorktreeDiffEntry } from "./types" const LOCAL_DIFF_ID = "local" as const diff --git a/packages/kilo-vscode/src/agent-manager/document-reader.ts b/packages/kilo-vscode/src/documents/document-reader.ts similarity index 100% rename from packages/kilo-vscode/src/agent-manager/document-reader.ts rename to packages/kilo-vscode/src/documents/document-reader.ts diff --git a/packages/kilo-vscode/src/extension.ts b/packages/kilo-vscode/src/extension.ts index 4ca34b3791..1de4f7f6d6 100644 --- a/packages/kilo-vscode/src/extension.ts +++ b/packages/kilo-vscode/src/extension.ts @@ -4,6 +4,7 @@ import { AgentManagerProvider } from "./agent-manager/AgentManagerProvider" import { VscodeHost } from "./agent-manager/vscode-host" import { KiloClawProvider } from "./kiloclaw/KiloClawProvider" import { DiffViewerProvider } from "./diff/DiffViewerProvider" +import { DocumentViewerProvider } from "./DocumentViewerProvider" import { DiffSourceCatalog } from "./diff/sources/catalog" import { DiffVirtualProvider } from "./DiffVirtualProvider" import { SettingsEditorProvider } from "./SettingsEditorProvider" @@ -281,6 +282,12 @@ export function activate(context: vscode.ExtensionContext) { provider.setDiffViewerProvider(diffViewerProvider) context.subscriptions.push(diffViewerProvider) + const documentViewerProvider = new DocumentViewerProvider(context.extensionUri, connectionService, { + onComments: (comments, autoSend) => void provider.appendReviewComments(comments, autoSend), + }) + provider.setDocumentViewerProvider(documentViewerProvider) + context.subscriptions.push(documentViewerProvider) + // Create diff virtual provider (lightweight single-file diff for permission approval) const diffVirtualProvider = new DiffVirtualProvider(context.extensionUri) provider.setDiffVirtualProvider(diffVirtualProvider) @@ -326,6 +333,15 @@ export function activate(context: vscode.ExtensionContext) { }), ) + context.subscriptions.push( + vscode.window.registerWebviewPanelSerializer(DocumentViewerProvider.viewType, { + deserializeWebviewPanel(panel: vscode.WebviewPanel) { + panel.dispose() + return Promise.resolve() + }, + }), + ) + context.subscriptions.push( vscode.window.registerWebviewPanelSerializer(DiffViewerProvider.viewType, { deserializeWebviewPanel(panel: vscode.WebviewPanel) { diff --git a/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts index fb9112ae3b..5f0f1df1d5 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts @@ -27,8 +27,7 @@ const TSX_FILES = [ path.join(ROOT, "webview-ui/agent-manager/ProjectSelect.tsx"), path.join(ROOT, "webview-ui/agent-manager/sortable-tab.tsx"), path.join(ROOT, "webview-ui/agent-manager/DiffPanel.tsx"), - path.join(ROOT, "webview-ui/agent-manager/documents/DocumentPanel.tsx"), - path.join(ROOT, "webview-ui/agent-manager/documents/DocumentPanelHost.tsx"), + path.join(ROOT, "webview-ui/documents/DocumentPanel.tsx"), path.join(ROOT, "webview-ui/diff-viewer/FullScreenDiffView.tsx"), path.join(ROOT, "webview-ui/diff-viewer/ImageDiffView.tsx"), path.join(ROOT, "webview-ui/diff-viewer/MarkdownDiffView.tsx"), diff --git a/packages/kilo-vscode/tests/unit/agent-manager-documents.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-documents.test.ts index 78e422ffe9..4d73a993e9 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-documents.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-documents.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "bun:test" import { createRoot, createSignal } from "solid-js" -import { createDocumentComments, createDocuments } from "../../webview-ui/agent-manager/documents/state" +import { createDocumentComments, createDocuments } from "../../webview-ui/documents/state" import type { AgentManagerDocumentMessage } from "../../webview-ui/src/types/messages" describe("Agent Manager document state", () => { diff --git a/packages/kilo-vscode/tests/unit/agent-manager-i18n.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-i18n.test.ts index bf9cbea424..50f7958210 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-i18n.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-i18n.test.ts @@ -28,8 +28,7 @@ const TSX_FILES = [ path.join(ROOT, "webview-ui/agent-manager/sortable-tab.tsx"), path.join(ROOT, "webview-ui/agent-manager/terminal/SideTerminalPanel.tsx"), path.join(ROOT, "webview-ui/agent-manager/terminal/TerminalDestinationButton.tsx"), - path.join(ROOT, "webview-ui/agent-manager/documents/DocumentPanel.tsx"), - path.join(ROOT, "webview-ui/agent-manager/documents/DocumentPanelHost.tsx"), + path.join(ROOT, "webview-ui/documents/DocumentPanel.tsx"), ] /** diff --git a/packages/kilo-vscode/tests/unit/document-reader.test.ts b/packages/kilo-vscode/tests/unit/document-reader.test.ts index 3de360d0ba..114674c00c 100644 --- a/packages/kilo-vscode/tests/unit/document-reader.test.ts +++ b/packages/kilo-vscode/tests/unit/document-reader.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from "bun:test" import * as fs from "node:fs" import * as os from "node:os" import * as path from "node:path" -import { readDocument } from "../../src/agent-manager/document-reader" +import { readDocument } from "../../src/documents/document-reader" function workspace() { return fs.mkdtempSync(path.join(os.tmpdir(), "kilo-document-")) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx index 0ffdb78674..f520353b59 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx @@ -180,7 +180,7 @@ import { setTabWidths } from "./tab-widths" import { clampPanelWidth, createPanelResize, maxPanelWidth, minPanelWidth, SidePanel } from "./side-panel-layout" import { SubagentPanel } from "./SubagentPanel" import { DocumentPanelHost } from "./documents/DocumentPanelHost" -import { createDocumentInspector } from "./documents/state" +import { createDocumentInspector } from "../documents/state" import { createSubagentController } from "./subagent-tabs" import { buildShortcutCategories } from "./shortcuts" import { tracker } from "./telemetry" diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx index 2717e1434e..4c96ca0f91 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx @@ -1,6 +1,6 @@ import type { Accessor, Component } from "solid-js" -import { DocumentPanel } from "./DocumentPanel" -import { createDocumentInspector } from "./state" +import { DocumentPanel } from "../../documents/DocumentPanel" +import { createDocumentInspector } from "../../documents/state" interface Props { inspector: ReturnType diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx b/packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx similarity index 96% rename from packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx rename to packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx index f4fd7c90da..c3dfcf0a17 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanel.tsx +++ b/packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx @@ -1,9 +1,9 @@ import { Dynamic } from "solid-js/web" import { Component, Show, Accessor, createMemo, createSignal, createEffect, on } from "solid-js" -import { MarkdownPane } from "../../diff-viewer/MarkdownDiffView" +import { MarkdownPane } from "../diff-viewer/MarkdownDiffView" import { isMarkdownPath, type DocumentData, type DocumentTab } from "./state" -import { InspectorTabStrip } from "../InspectorTabStrip" -import { SortableClosableTab } from "../ClosableTab" +import { InspectorTabStrip } from "../agent-manager/InspectorTabStrip" +import { SortableClosableTab } from "../agent-manager/ClosableTab" import { useCodeComponent } from "@kilocode/kilo-ui/context/code" import { FileIcon } from "@kilocode/kilo-ui/file-icon" import { Icon } from "@kilocode/kilo-ui/icon" @@ -11,8 +11,8 @@ import { IconButton } from "@kilocode/kilo-ui/icon-button" import { Button } from "@kilocode/kilo-ui/button" import { Tooltip, TooltipKeybind } from "@kilocode/kilo-ui/tooltip" import type { DiffLineAnnotation, AnnotationSide, SelectedLineRange } from "@pierre/diffs" -import type { WorktreeFileDiff } from "../../src/types/messages" -import type { ReviewComment } from "../../diff-viewer/review-comments" +import type { WorktreeFileDiff } from "../src/types/messages" +import type { ReviewComment } from "../diff-viewer/review-comments" import { buildFileAnnotations, buildReviewAnnotation, @@ -22,9 +22,9 @@ import { type AnnotationMeta, type ReviewComposer, type ReviewDraft, -} from "../../diff-viewer/review-annotations" -import { lineCount } from "../../diff-viewer/review-comments" -import { useLanguage } from "../../src/context/language" +} from "../diff-viewer/review-annotations" +import { lineCount } from "../diff-viewer/review-comments" +import { useLanguage } from "../src/context/language" export interface DocumentPanelProps { tabs: Accessor diff --git a/packages/kilo-vscode/webview-ui/documents/index.tsx b/packages/kilo-vscode/webview-ui/documents/index.tsx new file mode 100644 index 0000000000..c1726ae1ea --- /dev/null +++ b/packages/kilo-vscode/webview-ui/documents/index.tsx @@ -0,0 +1,87 @@ +import { onCleanup, onMount, type Component, createSignal } from "solid-js" +import { render } from "solid-js/web" +import "@kilocode/kilo-ui/styles" +import "../src/styles/chat.css" +import "../agent-manager/agent-manager.css" +import "../agent-manager/agent-manager-review.css" +import { ProviderShell } from "../src/context/provider-shell" +import { useVSCode } from "../src/context/vscode" +import { DocumentPanel } from "./DocumentPanel" +import { createDocumentComments, createDocuments, type DocumentMessage } from "./state" + +const App: Component = () => { + const vscode = useVSCode() + const [scope, setScope] = createSignal(null) + const [session, setSession] = createSignal(null) + const docs = createDocuments(vscode, scope, session, (id, file, contextKey) => + vscode.postMessage({ type: "document.request", sessionId: id, file, contextKey }), + ) + const comments = createDocumentComments(scope) + const [visible, setVisible] = createSignal(true) + + const open = (message: { sessionId?: string; contextKey: string; file: string; line?: number; column?: number }) => { + setScope(message.contextKey) + setSession(message.sessionId ?? null) + docs.open(message.file, message.sessionId ?? "", message.line, message.column) + setVisible(true) + } + + onMount(() => { + const message = vscode.onMessage((item) => { + if (item.type === "document.open") { + open(item) + return + } + if (item.type === "document.result") docs.onMessage(item as DocumentMessage) + if (item.type === "appendReviewComments" && Array.isArray(item.comments)) { + comments.setComments([...comments.comments(), ...item.comments]) + if (item.autoSend) + vscode.postMessage({ type: "document.sendComments", comments: item.comments, autoSend: true }) + } + }) + const review = (event: MessageEvent) => { + if (event.data?.type !== "appendReviewComments" || !Array.isArray(event.data.comments)) return + vscode.postMessage({ + type: "document.sendComments", + comments: event.data.comments, + autoSend: !!event.data.autoSend, + }) + } + window.addEventListener("message", review) + onCleanup(() => { + message() + window.removeEventListener("message", review) + }) + }) + + return ( + vscode.postMessage({ type: "document.openFile", file, line, column })} + onClosePanel={() => { + setVisible(false) + vscode.postMessage({ type: "document.close" }) + }} + visible={visible} + /> + ) +} + +const root = document.getElementById("root") +if (!root) throw new Error("Root element not found") +render( + () => ( + + + + ), + root, +) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts b/packages/kilo-vscode/webview-ui/documents/state.ts similarity index 86% rename from packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts rename to packages/kilo-vscode/webview-ui/documents/state.ts index 10c46fec80..c78307898c 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/documents/state.ts +++ b/packages/kilo-vscode/webview-ui/documents/state.ts @@ -1,11 +1,23 @@ import { createSignal, onCleanup, onMount, type Accessor } from "solid-js" -import type { useVSCode } from "../../src/context/vscode" -import type { ReviewComment } from "../../diff-viewer/review-comments" -import type { AgentManagerDocumentMessage } from "../../src/types/messages" +import type { useVSCode } from "../src/context/vscode" +import type { ReviewComment } from "../diff-viewer/review-comments" +export interface DocumentMessage { + type?: "document.result" | "agentManager.document" + sessionId: string + contextKey?: string + file: string + requestedFile?: string + content?: string + kind?: "text" | "image" + mime?: string + data?: string + error?: string +} export interface DocumentTab { id: string file: string + sessionId?: string line?: number column?: number } @@ -32,6 +44,8 @@ export function createDocuments( vscode: ReturnType, context: Accessor, session: Accessor = context, + send: (sessionId: string, file: string, contextKey: string) => void = (sessionId, file, contextKey) => + vscode.postMessage({ type: "agentManager.requestDocument", sessionId, file, contextKey }), ) { const [tabs, setTabs] = createSignal>({}) const [active, setActive] = createSignal>({}) @@ -42,12 +56,12 @@ export function createDocuments( const selected = () => active()[current()] const document = (file: string) => data()[key(current(), file)] - const request = (file: string, sessionId = session() ?? "") => { + const request = (file: string, sessionId = session() ?? "", contextKey = current()) => { const ctx = current() if (!ctx) return const id = key(ctx, file) setData((prev) => ({ ...prev, [id]: { ...(prev[id] ?? { file }), file, loading: true, error: undefined } })) - vscode.postMessage({ type: "agentManager.requestDocument", sessionId, file, contextKey: ctx }) + send(sessionId, file, contextKey) } const open = (file: string, sessionId = session() ?? "", line?: number, column?: number) => { @@ -57,9 +71,9 @@ export function createDocuments( const list = prev[ctx] ?? [] const id = key(ctx, file) if (list.some((tab) => tab.id === id)) { - return { ...prev, [ctx]: list.map((tab) => (tab.id === id ? { ...tab, line, column } : tab)) } + return { ...prev, [ctx]: list.map((tab) => (tab.id === id ? { ...tab, sessionId, line, column } : tab)) } } - return { ...prev, [ctx]: [...list, { id, file, line, column }] } + return { ...prev, [ctx]: [...list, { id, file, sessionId, line, column }] } }) setActive((prev) => ({ ...prev, [ctx]: key(ctx, file) })) request(file, sessionId) @@ -72,7 +86,7 @@ export function createDocuments( const tab = (tabs()[ctx] ?? []).find((item) => item.id === id) if (!tab) return setActive((prev) => ({ ...prev, [ctx]: id })) - if (!document(tab.file)) request(tab.file) + if (!document(tab.file)) request(tab.file, tab.sessionId) } const close = (id: string) => { @@ -107,7 +121,7 @@ export function createDocuments( setTabs((prev) => ({ ...prev, [ctx]: next })) } - const onMessage = (message: AgentManagerDocumentMessage) => { + const onMessage = (message: DocumentMessage) => { const id = key(message.contextKey ?? message.sessionId, message.requestedFile ?? message.file) setData((prev) => ({ ...prev, @@ -164,7 +178,7 @@ export function createDocumentInspector( onMount(() => { const handler = (event: Event) => handleDocumentOpen(event, open) const message = vscode.onMessage((item) => { - if (item.type === "agentManager.document") documents.onMessage(item) + if (item.type === "document.result" || item.type === "agentManager.document") documents.onMessage(item) }) window.addEventListener("kilo:open-file", handler) onCleanup(() => { diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts index d999b21d85..854d73974f 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts @@ -309,6 +309,28 @@ export interface AppendReviewCommentsMessage { autoSend?: boolean } +export interface DocumentResultMessage { + type: "document.result" + sessionId: string + contextKey?: string + file: string + requestedFile?: string + content?: string + kind?: "text" | "image" + mime?: string + data?: string + error?: string +} + +export interface DocumentOpenMessage { + type: "document.open" + sessionId?: string + contextKey: string + file: string + line?: number + column?: number +} + export interface AppendReviewCommentsToTerminalMessage { type: "appendReviewCommentsToTerminal" comments: ReviewCommentEntry[] @@ -1307,6 +1329,8 @@ export interface AgentManagerFocusContextRequestedMessage { } export type ExtensionMessage = + | DocumentResultMessage + | DocumentOpenMessage | AgentManagerFocusContextRequestedMessage | ReadyMessage | FontSizeChangedMessage diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts index 9af631dd3c..cd9f19f776 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts @@ -874,6 +874,30 @@ export interface AgentManagerRequestDocumentMessage { contextKey?: string } +export interface DocumentRequestMessage { + type: "document.request" + sessionId?: string + file: string + contextKey?: string +} + +export interface DocumentOpenFileMessage { + type: "document.openFile" + file: string + line?: number + column?: number +} + +export interface DocumentCloseMessage { + type: "document.close" +} + +export interface DocumentSendCommentsMessage { + type: "document.sendComments" + comments: ReviewCommentEntry[] + autoSend?: boolean +} + // Create multiple worktree sessions for the same prompt (multi-version mode) export interface CreateMultiVersionRequest { type: "agentManager.createMultiVersion" @@ -1403,6 +1427,10 @@ export interface DismissAgentMigrationBannerMessage { } export type WebviewMessage = + | DocumentRequestMessage + | DocumentOpenFileMessage + | DocumentCloseMessage + | DocumentSendCommentsMessage | SendMessageRequest | AbortRequest | RevertSessionRequest From eda1e9c80f712d1af48191e58d61ba5ed6ecea07 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 20 Aug 2026 13:27:57 +0200 Subject: [PATCH 12/18] fix(vscode): register documents webview with knip --- packages/kilo-vscode/knip.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/kilo-vscode/knip.json b/packages/kilo-vscode/knip.json index 18a96ea110..497095ed5c 100644 --- a/packages/kilo-vscode/knip.json +++ b/packages/kilo-vscode/knip.json @@ -3,6 +3,7 @@ "entry": [ "src/extension.ts", "webview-ui/agent-manager/index.tsx", + "webview-ui/documents/index.tsx", "webview-ui/diff-viewer/index.tsx", "webview-ui/diff-virtual/index.tsx", "webview-ui/kiloclaw/index.tsx", From dc362322f06784fc83780b54a7c08d6ad1575d07 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 20 Aug 2026 13:31:01 +0200 Subject: [PATCH 13/18] fix(vscode): keep session scroll pinned during layout corrections --- .changeset/fix-streaming-scroll-follow.md | 2 +- .../src/hooks/create-auto-scroll.test.tsx | 164 +++++++++++++++++- .../kilo-ui/src/hooks/create-auto-scroll.tsx | 13 +- .../kilo-ui/src/hooks/scroll-user-activity.ts | 27 ++- .../tests/chat-auto-scroll.spec.ts | 66 +++++++ .../src/components/chat/MessageList.tsx | 4 +- .../webview-ui/src/stories/chat.stories.tsx | 63 +++++++ 7 files changed, 322 insertions(+), 17 deletions(-) create mode 100644 packages/kilo-vscode/tests/chat-auto-scroll.spec.ts diff --git a/.changeset/fix-streaming-scroll-follow.md b/.changeset/fix-streaming-scroll-follow.md index 30600ba02e..0620e5efaf 100644 --- a/.changeset/fix-streaming-scroll-follow.md +++ b/.changeset/fix-streaming-scroll-follow.md @@ -2,4 +2,4 @@ "@kilocode/kilo-ui": patch --- -Keep chat pinned to the latest streaming output through layout reflows and downward scrolling. +Keep chat pinned to the latest streaming output through virtualized layout corrections, reflows, and downward scrolling. diff --git a/packages/kilo-ui/src/hooks/create-auto-scroll.test.tsx b/packages/kilo-ui/src/hooks/create-auto-scroll.test.tsx index 463c58c08c..e793f16693 100644 --- a/packages/kilo-ui/src/hooks/create-auto-scroll.test.tsx +++ b/packages/kilo-ui/src/hooks/create-auto-scroll.test.tsx @@ -10,6 +10,7 @@ mock.module("@solid-primitives/resize-observer", () => ({ })) const originalElement = globalThis.Element +const originalNode = globalThis.Node const originalWheelEvent = globalThis.WheelEvent type Listener = { @@ -22,12 +23,28 @@ class FakeElement { clientHeight = 100 scrollTop = 0 style = { overflowAnchor: "" } + hovered = false + ownerDocument!: FakeDocument + private children = new Set() private listeners = new Map() closest() { return null } + contains(node: unknown) { + return node === this || (node instanceof FakeElement && [...this.children].some((child) => child.contains(node))) + } + + append(child: FakeElement) { + child.ownerDocument = this.ownerDocument + this.children.add(child) + } + + matches(selector: string) { + return selector === ":hover" && this.hovered + } + scrollTo(options: ScrollToOptions) { this.scrollTop = options.top ?? this.scrollTop } @@ -65,6 +82,20 @@ class FakeElement { } } +class FakeDocument extends FakeElement { + body: FakeElement + documentElement: FakeElement + + constructor() { + super() + this.ownerDocument = this + this.body = new FakeElement() + this.body.ownerDocument = this + this.documentElement = new FakeElement() + this.documentElement.ownerDocument = this + } +} + class FakeWheelEvent { constructor( readonly deltaY: number, @@ -72,13 +103,26 @@ class FakeWheelEvent { ) {} } +class FakeKeyboardEvent { + readonly defaultPrevented = false + readonly shiftKey = false + + constructor( + readonly key: string, + readonly target: FakeElement, + ) {} +} + globalThis.Element = FakeElement as unknown as typeof Element +globalThis.Node = FakeElement as unknown as typeof Node globalThis.WheelEvent = FakeWheelEvent as unknown as typeof WheelEvent const { createAutoScroll } = await import("./create-auto-scroll") -function setup(options?: { interacted?: () => void; working?: boolean }) { +function setup(options?: { doc?: FakeDocument; interacted?: () => void; working?: boolean }) { + const doc = options?.doc ?? new FakeDocument() const el = new FakeElement() + el.ownerDocument = doc const root = createRoot((dispose) => ({ dispose, scroll: createAutoScroll({ @@ -97,7 +141,7 @@ function setup(options?: { interacted?: () => void; working?: boolean }) { observers.forEach((callback) => callback()) } - return { ...root, el, resize } + return { ...root, doc, el, resize } } beforeEach(() => { @@ -107,6 +151,8 @@ beforeEach(() => { afterAll(() => { if (originalElement) globalThis.Element = originalElement else Reflect.deleteProperty(globalThis, "Element") + if (originalNode) globalThis.Node = originalNode + else Reflect.deleteProperty(globalThis, "Node") if (originalWheelEvent) globalThis.WheelEvent = originalWheelEvent else Reflect.deleteProperty(globalThis, "WheelEvent") }) @@ -236,6 +282,117 @@ describe("createAutoScroll non-scrollable layouts", () => { ctx.dispose() }) + test("continues following after a programmatic scroll correction", () => { + const ctx = setup({ working: true }) + ctx.el.scrollHeight = 1000 + ctx.el.clientHeight = 200 + ctx.el.scrollTop = 800 + ctx.scroll.handleScroll() + + ctx.el.scrollTop = 760 + ctx.scroll.handleScroll() + + expect(ctx.scroll.userScrolled()).toBe(false) + + ctx.el.scrollHeight = 1100 + ctx.resize(0) + + expect(ctx.scroll.userScrolled()).toBe(false) + expect(ctx.el.scrollTop).toBe(1100) + ctx.dispose() + }) + + test("pauses for a body-targeted keyboard scroll over the transcript", () => { + const ctx = setup({ working: true }) + ctx.el.scrollHeight = 1000 + ctx.el.clientHeight = 200 + ctx.el.scrollTop = 800 + ctx.el.hovered = true + + ctx.doc.fire("keydown", new FakeKeyboardEvent("PageUp", ctx.doc.body) as unknown as Event) + ctx.el.scrollTop = 600 + ctx.scroll.handleScroll() + + expect(ctx.scroll.userScrolled()).toBe(true) + + ctx.el.scrollHeight = 1100 + ctx.resize(0) + + expect(ctx.el.scrollTop).toBe(600) + ctx.dispose() + }) + + test("routes body-targeted keyboard scroll to the deepest hovered container", () => { + const doc = new FakeDocument() + const outer = setup({ doc, working: true }) + const inner = setup({ doc, working: true }) + outer.el.append(inner.el) + outer.el.scrollHeight = 1000 + outer.el.clientHeight = 200 + outer.el.scrollTop = 800 + inner.el.scrollHeight = 500 + inner.el.clientHeight = 100 + inner.el.scrollTop = 400 + outer.el.hovered = true + inner.el.hovered = true + + doc.fire("keydown", new FakeKeyboardEvent("PageUp", doc.body) as unknown as Event) + inner.el.scrollTop = 300 + inner.scroll.handleScroll() + + expect(inner.scroll.userScrolled()).toBe(true) + expect(outer.scroll.userScrolled()).toBe(false) + inner.dispose() + outer.dispose() + }) + + test("routes keyboard scroll past a nested container boundary", () => { + const doc = new FakeDocument() + const outer = setup({ doc, working: true }) + const inner = setup({ doc, working: true }) + outer.el.append(inner.el) + outer.el.scrollHeight = 1000 + outer.el.clientHeight = 200 + outer.el.scrollTop = 800 + inner.el.scrollHeight = 500 + inner.el.clientHeight = 100 + inner.el.scrollTop = 0 + outer.el.hovered = true + inner.el.hovered = true + + doc.fire("keydown", new FakeKeyboardEvent("PageUp", doc.body) as unknown as Event) + outer.el.scrollTop = 700 + outer.scroll.handleScroll() + + expect(outer.scroll.userScrolled()).toBe(true) + expect(inner.scroll.userScrolled()).toBe(false) + inner.dispose() + outer.dispose() + }) + + test("removes disposed containers from keyboard ownership", () => { + const doc = new FakeDocument() + const outer = setup({ doc, working: true }) + const inner = setup({ doc, working: true }) + outer.el.append(inner.el) + outer.el.scrollHeight = 1000 + outer.el.clientHeight = 200 + outer.el.scrollTop = 800 + inner.el.scrollHeight = 500 + inner.el.clientHeight = 100 + inner.el.scrollTop = 400 + outer.el.hovered = true + inner.el.hovered = true + inner.dispose() + + doc.fire("keydown", new FakeKeyboardEvent("PageUp", doc.body) as unknown as Event) + outer.el.scrollTop = 700 + outer.scroll.handleScroll() + + expect(outer.scroll.userScrolled()).toBe(true) + outer.dispose() + }) + test("follows when initially short content starts overflowing", () => { const ctx = setup() ctx.resize() @@ -296,13 +453,14 @@ describe("createAutoScroll non-scrollable layouts", () => { ctx.dispose() }) - test("pauses when a native scrollbar drag changes scroll position without input events", () => { + test("pauses after pointer input moves the scroll position", () => { const ctx = setup({ working: true }) ctx.el.scrollHeight = 1000 ctx.el.clientHeight = 200 ctx.el.scrollTop = 800 ctx.scroll.handleScroll() + ctx.el.fire("pointerdown", new Event("pointerdown")) ctx.el.scrollTop = 600 ctx.scroll.handleScroll() diff --git a/packages/kilo-ui/src/hooks/create-auto-scroll.tsx b/packages/kilo-ui/src/hooks/create-auto-scroll.tsx index a41cdbb0f0..3e8d83dd6c 100644 --- a/packages/kilo-ui/src/hooks/create-auto-scroll.tsx +++ b/packages/kilo-ui/src/hooks/create-auto-scroll.tsx @@ -25,8 +25,6 @@ export function createAutoScroll(options: AutoScrollOptions) { let settling = false let settleTimer: ReturnType | undefined let cleanup: (() => void) | undefined - let lastTop = 0 - let lastHeight = 0 const [store, setStore] = createStore({ contentRef: undefined as HTMLElement | undefined, @@ -103,9 +101,6 @@ export function createAutoScroll(options: AutoScrollOptions) { const input = userActivity.consumeScroll() const distance = distanceFromBottom(scroll) - const moved = Math.abs(scroll.scrollTop - lastTop) > 1 && Math.abs(scroll.scrollHeight - lastHeight) <= 1 - lastTop = scroll.scrollTop - lastHeight = scroll.scrollHeight if (!canScroll(scroll)) return @@ -114,9 +109,9 @@ export function createAutoScroll(options: AutoScrollOptions) { return } - // Virtualizer and layout remeasurement can emit scroll before the - // ResizeObserver restores bottom-follow. Only user input should pause it. - if (!store.userScrolled && !input && !userActivity.isRecent() && !moved) return + // Virtualizer and layout corrections can move the viewport without + // changing content height. Only an input event should pause auto-follow. + if (!store.userScrolled && !input && !userActivity.isRecent()) return stop() } @@ -209,8 +204,6 @@ export function createAutoScroll(options: AutoScrollOptions) { if (!el) return - lastTop = el.scrollTop - lastHeight = el.scrollHeight updateOverflowAnchor(el) cleanup = userActivity.listen(el) } diff --git a/packages/kilo-ui/src/hooks/scroll-user-activity.ts b/packages/kilo-ui/src/hooks/scroll-user-activity.ts index 2cd5b8a76b..65175ac2d7 100644 --- a/packages/kilo-ui/src/hooks/scroll-user-activity.ts +++ b/packages/kilo-ui/src/hooks/scroll-user-activity.ts @@ -3,6 +3,9 @@ interface UserActivityOptions { onWheelUp: () => void } +const SCROLL_KEYS = new Set(["ArrowDown", "ArrowUp", "End", "Home", "PageDown", "PageUp", " "]) +const owners = new WeakMap>() + const isPotentialScrollInput = (event: Event) => { if (!(event.target instanceof Element)) return true const editable = event.target.closest("[contenteditable]") @@ -31,20 +34,40 @@ export const createUserActivity = (options: UserActivityOptions) => { options.onWheelUp() } + const handleKey = (event: KeyboardEvent) => { + if (!scroll || event.defaultPrevented || !SCROLL_KEYS.has(event.key)) return + const target = event.target + const root = target === scroll.ownerDocument.body || target === scroll.ownerDocument.documentElement + const up = event.key === "ArrowUp" || event.key === "Home" || event.key === "PageUp" || (event.key === " " && event.shiftKey) + const matches = [...(owners.get(scroll.ownerDocument) ?? [])].filter((el) => { + const owns = root ? el.matches(":hover") : target instanceof Node && el.contains(target) + if (!owns) return false + return up ? el.scrollTop > 1 : el.scrollHeight - el.clientHeight - el.scrollTop > 1 + }) + const owner = matches.find((el) => !matches.some((candidate) => candidate !== el && el.contains(candidate))) + if (owner !== scroll) return + mark(event) + } + return { listen: (el: HTMLElement) => { scroll = el + const registered = owners.get(el.ownerDocument) ?? new Set() + registered.add(el) + owners.set(el.ownerDocument, registered) el.addEventListener("wheel", handleWheel, { passive: true, capture: true }) el.addEventListener("pointerdown", mark, { passive: true }) - el.addEventListener("keydown", mark, { passive: true }) el.addEventListener("touchstart", mark, { passive: true }) + el.ownerDocument.addEventListener("keydown", handleKey, { passive: true }) return () => { if (scroll === el) scroll = undefined + registered.delete(el) + if (registered.size === 0) owners.delete(el.ownerDocument) el.removeEventListener("wheel", handleWheel, { capture: true }) el.removeEventListener("pointerdown", mark) - el.removeEventListener("keydown", mark) el.removeEventListener("touchstart", mark) + el.ownerDocument.removeEventListener("keydown", handleKey) } }, consumeScroll: () => { diff --git a/packages/kilo-vscode/tests/chat-auto-scroll.spec.ts b/packages/kilo-vscode/tests/chat-auto-scroll.spec.ts new file mode 100644 index 0000000000..c1e69c27ab --- /dev/null +++ b/packages/kilo-vscode/tests/chat-auto-scroll.spec.ts @@ -0,0 +1,66 @@ +import { expect, test, type Page } from "@playwright/test" + +const GLOBALS = "colorScheme:dark;theme:kilo-vscode;vscodeTheme:dark-modern" +const STORY_ID = "chat--message-list-layout-correction" + +async function settle(page: Page, frames = 2) { + await page.evaluate( + (count) => + new Promise((resolve) => { + const next = (left: number) => { + if (left === 0) return resolve() + requestAnimationFrame(() => next(left - 1)) + } + next(count) + }), + frames, + ) +} + +async function distance(page: Page) { + return page.locator(".message-list").evaluate((el) => el.scrollHeight - el.clientHeight - el.scrollTop) +} + +test("keeps following after a stable-height layout correction", async ({ page }) => { + await page.goto(`/iframe.html?id=${STORY_ID}&viewMode=story&globals=${GLOBALS}`, { waitUntil: "load" }) + const list = page.locator(".message-list") + await expect(list).toBeVisible() + await settle(page, 10) + await expect.poll(() => distance(page)).toBeLessThanOrEqual(2) + + const before = await list.evaluate((el) => ({ height: el.scrollHeight, top: el.scrollTop })) + const corrected = await list.evaluate((el) => { + el.scrollTop -= 120 + return { height: el.scrollHeight, top: el.scrollTop } + }) + await settle(page) + + expect(corrected.height).toBe(before.height) + expect(before.top - corrected.top).toBe(120) + await expect(page.getByRole("button", { name: "Scroll to bottom" })).toBeHidden() + + await page.getByTestId("append-stream").click() + + await expect.poll(() => distance(page)).toBeLessThanOrEqual(2) + await expect(page.getByRole("button", { name: "Scroll to bottom" })).toBeHidden() +}) + +test("keeps the reading position when the prompt rail scrolls upward", async ({ page }) => { + await page.goto(`/iframe.html?id=${STORY_ID}&viewMode=story&globals=${GLOBALS}`, { waitUntil: "load" }) + const list = page.locator(".message-list") + await expect(list).toBeVisible() + await settle(page, 10) + await expect.poll(() => distance(page)).toBeLessThanOrEqual(2) + + await page.locator(".prompt-rail").hover() + await page.mouse.wheel(0, -240) + + await expect.poll(() => distance(page)).toBeGreaterThan(40) + await expect(page.getByRole("button", { name: "Scroll to bottom" })).toBeVisible() + const top = await list.evaluate((el) => el.scrollTop) + + await page.getByTestId("append-stream").click() + + await expect.poll(() => list.evaluate((el) => el.scrollTop)).toBe(top) + await expect(page.getByRole("button", { name: "Scroll to bottom" })).toBeVisible() +}) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx index 510ffa11d7..63b8ec7d94 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx @@ -1383,7 +1383,9 @@ export const MessageList: Component = (props) => { onLoadOlder={() => session.loadOlderMessages()} onWheel={(deltaY: number) => { const el = scrollEl() - if (el) el.scrollTop += deltaY + if (!el) return + if (deltaY < 0 && el.scrollHeight - el.clientHeight > 1) autoScroll.pause() + el.scrollTop += deltaY }} height={height} hasOlder={session.hasOlderMessages} diff --git a/packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx b/packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx index 1ee0d93bc5..95ff3c5026 100644 --- a/packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx +++ b/packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx @@ -692,6 +692,69 @@ export const PromptRailManyPrompts: Story = { }, } +const correctionTurns = Array.from({ length: 30 }, (_, i) => + railTurn(300 + i, `Virtualized prompt ${i + 1}`, `Virtualized answer ${i + 1}.`), +) +const correctionActive = railTurn(400, "Continue streaming", "Initial streamed response.") +const correctionMessages = [...correctionTurns.flatMap((turn) => turn.messages), ...correctionActive.messages] +const correctionAssistant = correctionActive.messages[1]! +correctionAssistant.finish = "tool-calls" +const correctionParts = Object.assign( + {}, + ...correctionTurns.map((turn) => turn.parts), + correctionActive.parts, +) as Record +const correctionData = { + ...defaultMockData, + message: { [SESSION_ID]: correctionMessages }, + part: correctionParts, +} + +export const MessageListLayoutCorrection: Story = { + name: "MessageList - follow after layout correction", + render: () => { + const [output, setOutput] = createSignal("Initial streamed response.") + const session = { + ...mockSessionValue({ id: SESSION_ID, status: "busy" }), + messages: () => correctionMessages, + userMessages: () => correctionMessages.filter((msg) => msg.role === "user"), + getParts: (id: string) => { + if (id !== correctionAssistant.id) return correctionParts[id] ?? [] + const part = correctionParts[id]![0]! + return [{ ...part, text: output() }] + }, + } + return ( + + +
+ +
+ +
+ +
+
+
+ ) + }, +} + export const MessageListToolToQueuedUserSpacing: Story = { name: "MessageList — queued users stay at bottom", render: () => { From 0309d6ed887b2162bb4cc5340914140325e09bd9 Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Thu, 20 Aug 2026 11:34:29 +0000 Subject: [PATCH 14/18] chore: update kilo-vscode visual regression baselines --- .../chat/message-list-layout-correction-chromium-linux.png | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/message-list-layout-correction-chromium-linux.png diff --git a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/message-list-layout-correction-chromium-linux.png b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/message-list-layout-correction-chromium-linux.png new file mode 100644 index 0000000000..e91143f145 --- /dev/null +++ b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/message-list-layout-correction-chromium-linux.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c913b1d73750765dd88b170364776f0a6ffbeb65f7fa5fcfce953a8082c5d46c +size 28560 From ba1c3c60e157736b1691940633cf38a03f210def Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 20 Aug 2026 13:55:13 +0200 Subject: [PATCH 15/18] fix(vscode): avoid duplicate document review sends --- packages/kilo-vscode/src/DocumentViewerProvider.ts | 14 +++++++------- .../kilo-vscode/webview-ui/documents/index.tsx | 5 ----- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/kilo-vscode/src/DocumentViewerProvider.ts b/packages/kilo-vscode/src/DocumentViewerProvider.ts index 8390ded5ff..41f1409900 100644 --- a/packages/kilo-vscode/src/DocumentViewerProvider.ts +++ b/packages/kilo-vscode/src/DocumentViewerProvider.ts @@ -1,6 +1,7 @@ import * as vscode from "vscode" import type { ReviewCommentEntry } from "./shared/review-comments" import { readDocument } from "./documents/document-reader" +import { openRelativeFile } from "./review-utils" import { buildWebviewHtml } from "./utils" import type { KiloConnectionService } from "./services/cli-backend" @@ -98,13 +99,12 @@ export class DocumentViewerProvider implements vscode.Disposable { } if (message.type === "document.openFile" && typeof message.file === "string") { const context = this.contexts.get(this.currentKey) - this.openFromCommand({ - file: message.file, - sessionId: context?.sessionId, - directory: context?.directory, - line: typeof message.line === "number" ? message.line : undefined, - column: typeof message.column === "number" ? message.column : undefined, - }) + openRelativeFile( + context?.directory, + message.file, + typeof message.line === "number" ? message.line : undefined, + typeof message.column === "number" ? message.column : undefined, + ) return } if (message.type === "document.close") this.panel?.dispose() diff --git a/packages/kilo-vscode/webview-ui/documents/index.tsx b/packages/kilo-vscode/webview-ui/documents/index.tsx index c1726ae1ea..bde3e404a4 100644 --- a/packages/kilo-vscode/webview-ui/documents/index.tsx +++ b/packages/kilo-vscode/webview-ui/documents/index.tsx @@ -33,11 +33,6 @@ const App: Component = () => { return } if (item.type === "document.result") docs.onMessage(item as DocumentMessage) - if (item.type === "appendReviewComments" && Array.isArray(item.comments)) { - comments.setComments([...comments.comments(), ...item.comments]) - if (item.autoSend) - vscode.postMessage({ type: "document.sendComments", comments: item.comments, autoSend: true }) - } }) const review = (event: MessageEvent) => { if (event.data?.type !== "appendReviewComments" || !Array.isArray(event.data.comments)) return From 386af9a636623967eb2b58b7162db648b52b1070 Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Thu, 20 Aug 2026 11:58:01 +0000 Subject: [PATCH 16/18] chore: update kilo-vscode visual regression baselines --- .../labs-tool-call-lab/search-previews-chromium-linux.png | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/labs-tool-call-lab/search-previews-chromium-linux.png b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/labs-tool-call-lab/search-previews-chromium-linux.png index 0178a46d92..2a0fedc6d1 100644 --- a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/labs-tool-call-lab/search-previews-chromium-linux.png +++ b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/labs-tool-call-lab/search-previews-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a9f984fc6d004e151c6e82bd095e9038423d8fa6443a91bf1834c44f0af62ce -size 748576 +oid sha256:96a537574ebee768dab6914ffb449665d6930d2d577bf1dc42eb38d975e9be10 +size 749704 From 0d5d334480bc2093a12b27a34b03cac88cf33422 Mon Sep 17 00:00:00 2001 From: Johnny Eric Amancio Date: Thu, 20 Aug 2026 14:05:01 +0200 Subject: [PATCH 17/18] fix(tui): order live transcript by message created time so wrapped ids stay visible (#13247) * fix(tui): order live transcript by message created time so wrapped ids stay visible * test(tui): cover window eviction and versioned sync channel for wrapped ids --- .changeset/tui-message-time-order.md | 5 + packages/tui/src/context/sync.tsx | 15 +- packages/tui/src/kilocode/message-order.ts | 22 +++ .../test/kilocode/message-order-sync.test.tsx | 138 ++++++++++++++++++ .../tui/test/kilocode/message-order.test.ts | 34 +++++ 5 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 .changeset/tui-message-time-order.md create mode 100644 packages/tui/src/kilocode/message-order.ts create mode 100644 packages/tui/test/kilocode/message-order-sync.test.tsx create mode 100644 packages/tui/test/kilocode/message-order.test.ts diff --git a/.changeset/tui-message-time-order.md b/.changeset/tui-message-time-order.md new file mode 100644 index 0000000000..8e3bc72f59 --- /dev/null +++ b/.changeset/tui-message-time-order.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Fix TUI sessions where new turns stopped appearing until the session was reopened diff --git a/packages/tui/src/context/sync.tsx b/packages/tui/src/context/sync.tsx index 703c9d0e8f..1f21520a2c 100644 --- a/packages/tui/src/context/sync.tsx +++ b/packages/tui/src/context/sync.tsx @@ -38,6 +38,7 @@ import path from "path" import { useKV } from "./kv" import { handleSuggestionEvent } from "@/kilocode/suggestion/tui/sync" // kilocode_change import { appendTerminalOutput } from "@/kilocode/interactive-terminal/output" // kilocode_change +import { at, recent, slot } from "../kilocode/message-order" // kilocode_change import { useToast } from "../ui/toast" // kilocode_change import { usePermission } from "./permission" @@ -501,7 +502,7 @@ export const { setStore("message", event.properties.info.sessionID, [event.properties.info]) break } - const result = search(messages, event.properties.info.id, (m) => m.id) + const result = slot(messages, event.properties.info) // kilocode_change - order by created time, ids wrap if (result.found) { setStore("message", event.properties.info.sessionID, result.index, reconcile(event.properties.info)) break @@ -537,7 +538,7 @@ export const { case "message.removed": { touchMessage(event.properties.sessionID, event.properties.messageID) const messages = store.message[event.properties.sessionID] - const result = search(messages, event.properties.messageID, (m) => m.id) + const result = at(messages, event.properties.messageID) // kilocode_change - list is time-ordered, not id-sorted if (result.found) { setStore( "message", @@ -680,7 +681,7 @@ export const { setStore("message", info.sessionID, [info]) break } - const match = search(messages, info.id, (item) => item.id) + const match = slot(messages, info) // kilocode_change - order by created time, ids wrap if (match.found) { setStore("message", info.sessionID, match.index, reconcile(info)) break @@ -710,7 +711,7 @@ export const { touchMessage(event.data.sessionID, event.data.messageID) const messages = store.message[event.data.sessionID] if (!messages) break - const match = search(messages, event.data.messageID, (item) => item.id) + const match = at(messages, event.data.messageID) // kilocode_change - list is time-ordered, not id-sorted if (!match.found) break setStore( "message", @@ -1008,9 +1009,11 @@ export const { (message) => tracker.messages.has(message.id) && !infos.some((item) => item.id === message.id), ), ) - const removed = infos.slice(0, -100) - const visible = infos.slice(-100) + // kilocode_change start - window by created time so wrapped ids stay visible + const visible = recent(infos) const visibleIDs = new Set(visible.map((message) => message.id)) + const removed = infos.filter((message) => !visibleIDs.has(message.id)) + // kilocode_change end for (const message of messages.data ?? []) { if (!visibleIDs.has(message.info.id)) { delete draft.part[message.info.id] diff --git a/packages/tui/src/kilocode/message-order.ts b/packages/tui/src/kilocode/message-order.ts new file mode 100644 index 0000000000..011f9dbfaf --- /dev/null +++ b/packages/tui/src/kilocode/message-order.ts @@ -0,0 +1,22 @@ +type Stamped = { id: string; time: { created: number } } + +export function older(a: Stamped, b: Stamped) { + if (a.time.created !== b.time.created) return a.time.created - b.time.created + return a.id < b.id ? -1 : a.id > b.id ? 1 : 0 +} + +export function at(list: readonly { id: string }[], id: string) { + const index = list.findIndex((item) => item.id === id) + return { found: index >= 0, index } +} + +export function slot(list: readonly T[], item: T) { + const hit = at(list, item.id) + if (hit.found) return hit + const index = list.findIndex((entry) => older(item, entry) < 0) + return { found: false, index: index < 0 ? list.length : index } +} + +export function recent(list: readonly T[], cap = 100) { + return list.toSorted(older).slice(-cap) +} diff --git a/packages/tui/test/kilocode/message-order-sync.test.tsx b/packages/tui/test/kilocode/message-order-sync.test.tsx new file mode 100644 index 0000000000..f6a032a8f1 --- /dev/null +++ b/packages/tui/test/kilocode/message-order-sync.test.tsx @@ -0,0 +1,138 @@ +/** @jsxImportSource @opentui/solid */ +import { expect, test } from "bun:test" +import type { GlobalEvent } from "@kilocode/sdk/v2" +import { tmpdir } from "../fixture/fixture" +import { json, mount, wait } from "../cli/cmd/tui/sync-fixture" + +const sessionID = "ses_order" +const partID = "prt_order" +const directory = "/tmp/opencode/packages/tui" +let seq = 0 +const session = { + id: sessionID, + title: "order", + time: { created: 0, updated: 0 }, + version: "1.15.13", + directory, +} +const base = { + sessionID, + role: "assistant" as const, + agent: "build", + modelID: "model", + providerID: "test", + mode: "build", + parentID: "msg_user", + path: { cwd: directory, root: directory }, + cost: 0, + tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }, +} +const old = { ...base, id: "msg_ff0cb2300001Z6YIo5V52u114f", time: { created: 1, completed: 2 } } +const next = { ...base, id: "msg_019f1d3da001955TwEJ8qKEbj3", time: { created: 3 } } + +function wrap(payload: GlobalEvent["payload"]): GlobalEvent { + return { directory, project: "proj_test", payload } +} + +function sync1(id: string, info: (typeof base & { id: string; time: { created: number } }) | undefined): GlobalEvent { + return { + directory, + project: "proj_test", + payload: { + type: "sync", + syncEvent: { + id, + type: "message.updated.1", + seq: ++seq, + aggregateID: sessionID, + data: { sessionID, info }, + }, + }, + } as GlobalEvent +} + +function serve(infos: (typeof old)[]) { + return (url: URL) => { + if (url.pathname === `/session/${sessionID}`) return json(session) + if (url.pathname === `/session/${sessionID}/message`) { + return json(infos.map((info) => ({ info, parts: [] }))) + } + if (url.pathname === `/session/${sessionID}/todo` || url.pathname === `/session/${sessionID}/diff`) return json([]) + return undefined + } +} + +test("a later message with a lexicographically earlier id stays at the tail", async () => { + await using tmp = await tmpdir() + await Bun.write(`${tmp.path}/kv.json`, "{}") + const { app, emit, sync } = await mount((url) => { + if (url.pathname === `/session/${sessionID}/message`) { + return json([{ info: old, parts: [{ id: partID, sessionID, messageID: old.id, type: "text", text: "old" }] }]) + } + return serve([])(url) + }, tmp.path) + try { + await sync.session.sync(sessionID) + await wait(() => sync.data.message[sessionID]?.some((item) => item.id === old.id) ?? false) + emit( + wrap({ + id: "evt_next", + type: "message.updated", + properties: { sessionID, info: next }, + }), + ) + await wait(() => sync.data.message[sessionID]?.some((item) => item.id === next.id) ?? false) + const ids = (sync.data.message[sessionID] ?? []).map((item) => item.id) + expect(ids[0]).toBe(old.id) + expect(ids.at(-1)).toBe(next.id) + } finally { + app.renderer.destroy() + } +}) + +test("eviction at the window cap drops the oldest message, not the newest", async () => { + await using tmp = await tmpdir() + await Bun.write(`${tmp.path}/kv.json`, "{}") + const infos = Array.from({ length: 100 }, (_, index) => ({ + ...base, + id: `msg_ff0c${String(index).padStart(4, "0")}`, + time: { created: index + 1, completed: index + 2 }, + })) + const { app, emit, sync } = await mount(serve(infos), tmp.path) + try { + await sync.session.sync(sessionID) + await wait(() => sync.data.message[sessionID]?.length === 100) + emit( + wrap({ + id: "evt_next", + type: "message.updated", + properties: { sessionID, info: { ...next, time: { created: 200 } } }, + }), + ) + await wait(() => sync.data.message[sessionID]?.some((item) => item.id === next.id) ?? false) + const ids = (sync.data.message[sessionID] ?? []).map((item) => item.id) + expect(ids).toHaveLength(100) + expect(ids.at(-1)).toBe(next.id) + expect(ids).not.toContain(infos[0].id) + expect(ids[0]).toBe(infos[1].id) + } finally { + app.renderer.destroy() + } +}) + +test("the versioned sync channel also keeps a wrapped id at the tail", async () => { + await using tmp = await tmpdir() + await Bun.write(`${tmp.path}/kv.json`, "{}") + const { app, emit, sync } = await mount(serve([old]), tmp.path) + try { + await sync.session.sync(sessionID) + await wait(() => sync.data.message[sessionID]?.some((item) => item.id === old.id) ?? false) + emit(sync1("evt_next_v1", next)) + await wait(() => sync.data.message[sessionID]?.some((item) => item.id === next.id) ?? false) + const ids = (sync.data.message[sessionID] ?? []).map((item) => item.id) + expect(ids[0]).toBe(old.id) + expect(ids.at(-1)).toBe(next.id) + } finally { + app.renderer.destroy() + } +}) diff --git a/packages/tui/test/kilocode/message-order.test.ts b/packages/tui/test/kilocode/message-order.test.ts new file mode 100644 index 0000000000..2f98dd6fb7 --- /dev/null +++ b/packages/tui/test/kilocode/message-order.test.ts @@ -0,0 +1,34 @@ +import { expect, test } from "bun:test" +import { at, older, recent, slot } from "../../src/kilocode/message-order" + +const old = { id: "msg_ff0cb2300001Z6YIo5V52u114f", time: { created: 1 } } +const next = { id: "msg_019f1d3da001955TwEJ8qKEbj3", time: { created: 2 } } + +test("a later message with an earlier id sorts after the older one", () => { + expect(older(old, next)).toBeLessThan(0) + expect(older(next, old)).toBeGreaterThan(0) +}) + +test("equal created times fall back to id order", () => { + const a = { id: "msg_a", time: { created: 1 } } + const b = { id: "msg_b", time: { created: 1 } } + expect(older(a, b)).toBeLessThan(0) + expect(older(a, a)).toBe(0) +}) + +test("a later message with an earlier id inserts at the tail", () => { + expect(slot([old], next)).toEqual({ found: false, index: 1 }) +}) + +test("slot finds an existing message by id", () => { + expect(slot([old, next], next)).toEqual({ found: true, index: 1 }) +}) + +test("the message window keeps newest by created time, not id", () => { + expect(recent([next, old], 1).map((item) => item.id)).toEqual([next.id]) +}) + +test("lookup by id is linear so time-ordered lists still find removals", () => { + expect(at([old, next], next.id)).toEqual({ found: true, index: 1 }) + expect(at([old, next], "msg_missing")).toEqual({ found: false, index: -1 }) +}) From 67cd629f3c5212fa5326c5ea0b86b68db21bc90a Mon Sep 17 00:00:00 2001 From: "kilo-maintainer[bot]" Date: Thu, 20 Aug 2026 12:26:15 +0000 Subject: [PATCH 18/18] release: v7.4.23 --- .changeset/active-list-equal-rows.md | 5 - .../agent-manager-nullable-tool-fields.md | 5 - .../agent-manager-project-skeleton-loading.md | 5 - .changeset/agent-manager-terminal-context.md | 5 - .changeset/ask-mode-permission-boundary.md | 5 - .changeset/ask-to-code-agent-switch.md | 6 -- .changeset/blocking-shell-waits.md | 5 - .changeset/borderless-jetbrains-session.md | 5 - .changeset/calm-diff-scroll.md | 5 - .changeset/calm-diffs-use-current-trunk.md | 5 - .changeset/calm-sqlite-recovery.md | 5 - .changeset/center-jetbrains-session-width.md | 5 - .changeset/clean-agent-removal.md | 5 - .changeset/compact-model-trigger-label.md | 5 - .changeset/durable-agent-manager-terminals.md | 6 -- .changeset/dynamic-speech-to-text-models.md | 5 - .changeset/fallback-state-directory.md | 5 - .changeset/fix-duplicate-skill-catalog.md | 5 - .changeset/fix-import-jwt-share-url.md | 6 -- .changeset/fix-pr-branch-refspec.md | 5 - .changeset/fix-pr-check-duration.md | 5 - .changeset/fix-streaming-scroll-follow.md | 5 - .changeset/fix-subagent-sidebar-context.md | 5 - .changeset/fix-text-streaming.md | 5 - .changeset/fix-tool-output-actions.md | 5 - .changeset/fix-worktree-base-branch.md | 5 - .changeset/fresh-file-mentions.md | 5 - .changeset/fresh-worktree-prompt.md | 5 - .changeset/fresh-worktrees-move.md | 5 - .changeset/gh-status-banners.md | 5 - .changeset/gpt-56-oauth-context.md | 5 - .changeset/hover-agent-manager-actions.md | 5 - .changeset/incremental-todo-guidance.md | 5 - .changeset/islands-button-borders.md | 5 - .changeset/jetbrains-agent-manager-beta.md | 5 - .../jetbrains-expandable-hover-popups.md | 5 - .changeset/jetbrains-history-hover-rename.md | 5 - .changeset/jetbrains-pr-worktree-tooltips.md | 5 - .changeset/jetbrains-profile-400-ready.md | 5 - .changeset/jetbrains-session-colors.md | 5 - .changeset/jetbrains-session-errors.md | 5 - .../jetbrains-session-secondary-text.md | 5 - .../jetbrains-worktree-activity-badge.md | 5 - .../jetbrains-worktree-adopt-session-name.md | 5 - .../jetbrains-worktree-change-badges.md | 5 - .../jetbrains-worktree-delete-reappear.md | 5 - .../jetbrains-worktree-delete-selection.md | 5 - .../jetbrains-worktree-list-stability.md | 5 - .changeset/jetbrains-worktree-open-focus.md | 5 - .../jetbrains-worktree-open-in-new-window.md | 5 - .changeset/jetbrains-worktree-order.md | 5 - .../jetbrains-worktree-session-deleting.md | 5 - .changeset/jetbrains-worktree-session-list.md | 5 - .changeset/jetbrains-worktree-terminal.md | 5 - .changeset/mcp-tool-display-setting.md | 5 - .changeset/memory-show-preserve-text.md | 5 - .changeset/memory-sse-json.md | 5 - .../optimize-agent-manager-tab-latency.md | 5 - .changeset/optimize-large-session-loading.md | 5 - .changeset/optimize-top-bar-performance.md | 5 - .changeset/permission-prompt-scroll.md | 5 - .changeset/persist-snapshot-disable.md | 5 - .changeset/pierre-pr-comment-diff.md | 5 - .changeset/plan-to-code-model-switch.md | 5 - .changeset/polite-history-rows.md | 5 - .changeset/pr-comments-github-style.md | 5 - .changeset/prompt-bubble-outline.md | 5 - .changeset/prompt-focus-scroll-polish.md | 5 - .changeset/quiet-branches-search.md | 5 - .changeset/quiet-variants-cache.md | 5 - .changeset/quiet-worktrees-filter.md | 5 - .../refine-jetbrains-session-spacing.md | 5 - .../remove-agent-manager-project-trust.md | 5 - .changeset/remove-agent-requirements.md | 6 -- ...emove-alibaba-mistral-gateway-providers.md | 5 - .changeset/remove-pr-sidebar-scroll-button.md | 5 - .../remove-task-aware-output-pruning.md | 7 -- .changeset/rename-jetbrains-worktrees.md | 5 - .../restore-agent-manager-diff-stats.md | 5 - .../restore-kilo-upgrade-version-lookup.md | 5 - .changeset/sandbox-git-escalation.md | 5 - .../scoped-interactive-terminal-state.md | 5 - .changeset/scroll-resize-dialog-fixes.md | 5 - .../selected-agent-over-stale-session.md | 5 - .changeset/session-background-contrast.md | 5 - .changeset/session-card-content-surfaces.md | 5 - .changeset/session-pr-link.md | 5 - .changeset/session-status-copy-overlay.md | 5 - .changeset/show-empty-jetbrains-sessions.md | 5 - .changeset/show-model-provider-hints.md | 5 - .changeset/show-queued-prompts.md | 5 - .../show-token-throughput-by-default.md | 5 - .changeset/slash-command-preserve-text.md | 5 - .changeset/smooth-session-backdrop.md | 5 - .changeset/steady-session-dock.md | 5 - .changeset/steady-working-status.md | 5 - .changeset/subagent-inspector-tabs.md | 5 - .changeset/terminal-shortcut-focus.md | 5 - .changeset/trim-inferred-variants.md | 5 - .changeset/tui-gateway-model-picker.md | 5 - .changeset/tui-message-time-order.md | 5 - .changeset/worktree-dependencies.md | 5 - .changeset/worktree-editor-selection.md | 5 - .changeset/worktree-history-default.md | 5 - .changeset/worktree-session-history-rows.md | 5 - artifacts/glm52-rise-video/package.json | 2 +- bun.lock | 66 ++++++------ package.json | 2 +- packages/client/package.json | 2 +- packages/codemode/package.json | 2 +- packages/core/package.json | 2 +- packages/effect-drizzle-sqlite/package.json | 2 +- packages/effect-sqlite-node/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +-- packages/http-recorder/package.json | 2 +- packages/httpapi-codegen/package.json | 2 +- packages/kilo-console/package.json | 2 +- packages/kilo-docs/package.json | 2 +- packages/kilo-gateway/package.json | 2 +- packages/kilo-i18n/package.json | 2 +- packages/kilo-indexing/package.json | 2 +- packages/kilo-jetbrains/CHANGELOG.md | 97 +++++++++++++++++ packages/kilo-memory/package.json | 2 +- packages/kilo-sandbox/package.json | 2 +- packages/kilo-telemetry/package.json | 2 +- packages/kilo-ui/package.json | 2 +- packages/kilo-vscode/CHANGELOG.md | 102 +++++++++++++++++- packages/kilo-vscode/package.json | 2 +- packages/kilo-vscode/tests/package.json | 2 +- packages/kilo-web-ui/package.json | 2 +- packages/llm/package.json | 2 +- packages/opencode/CHANGELOG.md | 56 ++++++++++ packages/opencode/package.json | 2 +- packages/plugin-atomic-chat/package.json | 2 +- packages/plugin/package.json | 2 +- packages/protocol/package.json | 2 +- packages/schema/package.json | 2 +- packages/script/package.json | 2 +- packages/sdk-next/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/server/package.json | 2 +- packages/session-ui/package.json | 2 +- packages/storybook/package.json | 2 +- packages/tui/package.json | 2 +- packages/ui/package.json | 2 +- script/upstream/package.json | 2 +- 146 files changed, 329 insertions(+), 607 deletions(-) delete mode 100644 .changeset/active-list-equal-rows.md delete mode 100644 .changeset/agent-manager-nullable-tool-fields.md delete mode 100644 .changeset/agent-manager-project-skeleton-loading.md delete mode 100644 .changeset/agent-manager-terminal-context.md delete mode 100644 .changeset/ask-mode-permission-boundary.md delete mode 100644 .changeset/ask-to-code-agent-switch.md delete mode 100644 .changeset/blocking-shell-waits.md delete mode 100644 .changeset/borderless-jetbrains-session.md delete mode 100644 .changeset/calm-diff-scroll.md delete mode 100644 .changeset/calm-diffs-use-current-trunk.md delete mode 100644 .changeset/calm-sqlite-recovery.md delete mode 100644 .changeset/center-jetbrains-session-width.md delete mode 100644 .changeset/clean-agent-removal.md delete mode 100644 .changeset/compact-model-trigger-label.md delete mode 100644 .changeset/durable-agent-manager-terminals.md delete mode 100644 .changeset/dynamic-speech-to-text-models.md delete mode 100644 .changeset/fallback-state-directory.md delete mode 100644 .changeset/fix-duplicate-skill-catalog.md delete mode 100644 .changeset/fix-import-jwt-share-url.md delete mode 100644 .changeset/fix-pr-branch-refspec.md delete mode 100644 .changeset/fix-pr-check-duration.md delete mode 100644 .changeset/fix-streaming-scroll-follow.md delete mode 100644 .changeset/fix-subagent-sidebar-context.md delete mode 100644 .changeset/fix-text-streaming.md delete mode 100644 .changeset/fix-tool-output-actions.md delete mode 100644 .changeset/fix-worktree-base-branch.md delete mode 100644 .changeset/fresh-file-mentions.md delete mode 100644 .changeset/fresh-worktree-prompt.md delete mode 100644 .changeset/fresh-worktrees-move.md delete mode 100644 .changeset/gh-status-banners.md delete mode 100644 .changeset/gpt-56-oauth-context.md delete mode 100644 .changeset/hover-agent-manager-actions.md delete mode 100644 .changeset/incremental-todo-guidance.md delete mode 100644 .changeset/islands-button-borders.md delete mode 100644 .changeset/jetbrains-agent-manager-beta.md delete mode 100644 .changeset/jetbrains-expandable-hover-popups.md delete mode 100644 .changeset/jetbrains-history-hover-rename.md delete mode 100644 .changeset/jetbrains-pr-worktree-tooltips.md delete mode 100644 .changeset/jetbrains-profile-400-ready.md delete mode 100644 .changeset/jetbrains-session-colors.md delete mode 100644 .changeset/jetbrains-session-errors.md delete mode 100644 .changeset/jetbrains-session-secondary-text.md delete mode 100644 .changeset/jetbrains-worktree-activity-badge.md delete mode 100644 .changeset/jetbrains-worktree-adopt-session-name.md delete mode 100644 .changeset/jetbrains-worktree-change-badges.md delete mode 100644 .changeset/jetbrains-worktree-delete-reappear.md delete mode 100644 .changeset/jetbrains-worktree-delete-selection.md delete mode 100644 .changeset/jetbrains-worktree-list-stability.md delete mode 100644 .changeset/jetbrains-worktree-open-focus.md delete mode 100644 .changeset/jetbrains-worktree-open-in-new-window.md delete mode 100644 .changeset/jetbrains-worktree-order.md delete mode 100644 .changeset/jetbrains-worktree-session-deleting.md delete mode 100644 .changeset/jetbrains-worktree-session-list.md delete mode 100644 .changeset/jetbrains-worktree-terminal.md delete mode 100644 .changeset/mcp-tool-display-setting.md delete mode 100644 .changeset/memory-show-preserve-text.md delete mode 100644 .changeset/memory-sse-json.md delete mode 100644 .changeset/optimize-agent-manager-tab-latency.md delete mode 100644 .changeset/optimize-large-session-loading.md delete mode 100644 .changeset/optimize-top-bar-performance.md delete mode 100644 .changeset/permission-prompt-scroll.md delete mode 100644 .changeset/persist-snapshot-disable.md delete mode 100644 .changeset/pierre-pr-comment-diff.md delete mode 100644 .changeset/plan-to-code-model-switch.md delete mode 100644 .changeset/polite-history-rows.md delete mode 100644 .changeset/pr-comments-github-style.md delete mode 100644 .changeset/prompt-bubble-outline.md delete mode 100644 .changeset/prompt-focus-scroll-polish.md delete mode 100644 .changeset/quiet-branches-search.md delete mode 100644 .changeset/quiet-variants-cache.md delete mode 100644 .changeset/quiet-worktrees-filter.md delete mode 100644 .changeset/refine-jetbrains-session-spacing.md delete mode 100644 .changeset/remove-agent-manager-project-trust.md delete mode 100644 .changeset/remove-agent-requirements.md delete mode 100644 .changeset/remove-alibaba-mistral-gateway-providers.md delete mode 100644 .changeset/remove-pr-sidebar-scroll-button.md delete mode 100644 .changeset/remove-task-aware-output-pruning.md delete mode 100644 .changeset/rename-jetbrains-worktrees.md delete mode 100644 .changeset/restore-agent-manager-diff-stats.md delete mode 100644 .changeset/restore-kilo-upgrade-version-lookup.md delete mode 100644 .changeset/sandbox-git-escalation.md delete mode 100644 .changeset/scoped-interactive-terminal-state.md delete mode 100644 .changeset/scroll-resize-dialog-fixes.md delete mode 100644 .changeset/selected-agent-over-stale-session.md delete mode 100644 .changeset/session-background-contrast.md delete mode 100644 .changeset/session-card-content-surfaces.md delete mode 100644 .changeset/session-pr-link.md delete mode 100644 .changeset/session-status-copy-overlay.md delete mode 100644 .changeset/show-empty-jetbrains-sessions.md delete mode 100644 .changeset/show-model-provider-hints.md delete mode 100644 .changeset/show-queued-prompts.md delete mode 100644 .changeset/show-token-throughput-by-default.md delete mode 100644 .changeset/slash-command-preserve-text.md delete mode 100644 .changeset/smooth-session-backdrop.md delete mode 100644 .changeset/steady-session-dock.md delete mode 100644 .changeset/steady-working-status.md delete mode 100644 .changeset/subagent-inspector-tabs.md delete mode 100644 .changeset/terminal-shortcut-focus.md delete mode 100644 .changeset/trim-inferred-variants.md delete mode 100644 .changeset/tui-gateway-model-picker.md delete mode 100644 .changeset/tui-message-time-order.md delete mode 100644 .changeset/worktree-dependencies.md delete mode 100644 .changeset/worktree-editor-selection.md delete mode 100644 .changeset/worktree-history-default.md delete mode 100644 .changeset/worktree-session-history-rows.md diff --git a/.changeset/active-list-equal-rows.md b/.changeset/active-list-equal-rows.md deleted file mode 100644 index 181ea56e84..0000000000 --- a/.changeset/active-list-equal-rows.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Use equal-height rows by default in Agent Manager and settings lists, keeping variable-height rows only for provider settings. diff --git a/.changeset/agent-manager-nullable-tool-fields.md b/.changeset/agent-manager-nullable-tool-fields.md deleted file mode 100644 index 5b073b9dd0..0000000000 --- a/.changeset/agent-manager-nullable-tool-fields.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Fix Agent Manager ignoring requests to start new sessions on OpenAI Responses API models, where a start request was answered with a list of existing sessions instead of creating the worktree or session. diff --git a/.changeset/agent-manager-project-skeleton-loading.md b/.changeset/agent-manager-project-skeleton-loading.md deleted file mode 100644 index 7be42a0908..0000000000 --- a/.changeset/agent-manager-project-skeleton-loading.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Fix Agent Manager project accordions that stayed on a loading indicator until you clicked into them. Expanded projects other than the active one now receive their worktrees, sessions, and git stats as soon as Agent Manager opens and again after the panel reloads. While a project is still loading, its local row and section headings stay in place and the rows below fade in as skeleton placeholders instead of showing a single centered spinner, so several projects loading at once look consistent. diff --git a/.changeset/agent-manager-terminal-context.md b/.changeset/agent-manager-terminal-context.md deleted file mode 100644 index bfc2ad8df8..0000000000 --- a/.changeset/agent-manager-terminal-context.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Capture `@terminal` from the focused Agent Manager terminal, including embedded Run and Setup terminals, instead of using an unrelated active VS Code terminal. diff --git a/.changeset/ask-mode-permission-boundary.md b/.changeset/ask-mode-permission-boundary.md deleted file mode 100644 index 6e57b34275..0000000000 --- a/.changeset/ask-mode-permission-boundary.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Stop broad permission rules from letting Ask and Plan modes change your workspace. Catch-all approvals, the "Allow everything" toggle, and the ` *` rules that "Always allow" persists no longer grant these modes shell commands, subagents, notebook edits or other mutating tools, and MCP tools go back to prompting. To opt a single mode in, set `agent.ask.permission` or `agent.plan.permission` instead of a top-level `permission` rule. diff --git a/.changeset/ask-to-code-agent-switch.md b/.changeset/ask-to-code-agent-switch.md deleted file mode 100644 index 15c6b31ba5..0000000000 --- a/.changeset/ask-to-code-agent-switch.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"kilo-code": patch -"@kilocode/cli": patch ---- - -Keep the selected agent after switching from Ask to Code, and remind the model that previous Ask-mode restrictions no longer apply. diff --git a/.changeset/blocking-shell-waits.md b/.changeset/blocking-shell-waits.md deleted file mode 100644 index 8f7829ee24..0000000000 --- a/.changeset/blocking-shell-waits.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Keep one-time waits in the blocking shell tool instead of tracking them as background processes. diff --git a/.changeset/borderless-jetbrains-session.md b/.changeset/borderless-jetbrains-session.md deleted file mode 100644 index d4cc08d1ee..0000000000 --- a/.changeset/borderless-jetbrains-session.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Remove borders around JetBrains prompt bubbles and markdown code surfaces, and round the collapsed card hover highlight and markdown code blocks to match the prompt bubble. diff --git a/.changeset/calm-diff-scroll.md b/.changeset/calm-diff-scroll.md deleted file mode 100644 index f33b52455f..0000000000 --- a/.changeset/calm-diff-scroll.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Keep the Agent Manager inline diff position stable while scrolling upward through large reviews diff --git a/.changeset/calm-diffs-use-current-trunk.md b/.changeset/calm-diffs-use-current-trunk.md deleted file mode 100644 index a03cf400c9..0000000000 --- a/.changeset/calm-diffs-use-current-trunk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Use the remote's current default branch for diff totals and new worktrees when local Git metadata still points to a retired trunk. diff --git a/.changeset/calm-sqlite-recovery.md b/.changeset/calm-sqlite-recovery.md deleted file mode 100644 index 6337f811db..0000000000 --- a/.changeset/calm-sqlite-recovery.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@opencode-ai/core": patch ---- - -Prevent concurrent Kilo processes from crashing while recovering the shared SQLite WAL. diff --git a/.changeset/center-jetbrains-session-width.md b/.changeset/center-jetbrains-session-width.md deleted file mode 100644 index 2ea65486c0..0000000000 --- a/.changeset/center-jetbrains-session-width.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Center JetBrains session content at a 98-column readable width on wide panels. diff --git a/.changeset/clean-agent-removal.md b/.changeset/clean-agent-removal.md deleted file mode 100644 index c1639c43f8..0000000000 --- a/.changeset/clean-agent-removal.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Remove installed agents from every writable configuration source and report removal failures. diff --git a/.changeset/compact-model-trigger-label.md b/.changeset/compact-model-trigger-label.md deleted file mode 100644 index c15c4ac38a..0000000000 --- a/.changeset/compact-model-trigger-label.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Keep provider names out of the compact prompt model selector label while retaining them in the expanded picker. diff --git a/.changeset/durable-agent-manager-terminals.md b/.changeset/durable-agent-manager-terminals.md deleted file mode 100644 index dc673e7bb2..0000000000 --- a/.changeset/durable-agent-manager-terminals.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"kilo-code": patch -"@kilocode/cli": patch ---- - -Keep Agent Manager terminals and nested Kilo sessions alive across configuration reloads and location idle eviction, while cleaning them up on explicit close, worktree deletion, and server shutdown. diff --git a/.changeset/dynamic-speech-to-text-models.md b/.changeset/dynamic-speech-to-text-models.md deleted file mode 100644 index ebe68f7913..0000000000 --- a/.changeset/dynamic-speech-to-text-models.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Use NVIDIA Parakeet TDT 0.6B v3 as the default speech-to-text model while retaining dynamic model discovery and offline fallback support. diff --git a/.changeset/fallback-state-directory.md b/.changeset/fallback-state-directory.md deleted file mode 100644 index 5d3b95c9f9..0000000000 --- a/.changeset/fallback-state-directory.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Start Kilo with a persistent fallback when the default runtime state directory is not writable. diff --git a/.changeset/fix-duplicate-skill-catalog.md b/.changeset/fix-duplicate-skill-catalog.md deleted file mode 100644 index 160241cae2..0000000000 --- a/.changeset/fix-duplicate-skill-catalog.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Remove the duplicate skill catalog from the model-facing skill tool description. diff --git a/.changeset/fix-import-jwt-share-url.md b/.changeset/fix-import-jwt-share-url.md deleted file mode 100644 index 4f99030d17..0000000000 --- a/.changeset/fix-import-jwt-share-url.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@kilocode/cli": patch -"kilo-code": patch ---- - -Accept JWT share tokens when importing a session from a Kilo share URL. diff --git a/.changeset/fix-pr-branch-refspec.md b/.changeset/fix-pr-branch-refspec.md deleted file mode 100644 index abc1e27f9d..0000000000 --- a/.changeset/fix-pr-branch-refspec.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Fix Agent Manager PR and base-branch worktrees when a repository uses a restrictive Git fetch refspec. diff --git a/.changeset/fix-pr-check-duration.md b/.changeset/fix-pr-check-duration.md deleted file mode 100644 index d62da47c65..0000000000 --- a/.changeset/fix-pr-check-duration.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Prevent invalid GitHub check timestamps from displaying incorrect PR durations. diff --git a/.changeset/fix-streaming-scroll-follow.md b/.changeset/fix-streaming-scroll-follow.md deleted file mode 100644 index 0620e5efaf..0000000000 --- a/.changeset/fix-streaming-scroll-follow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-ui": patch ---- - -Keep chat pinned to the latest streaming output through virtualized layout corrections, reflows, and downward scrolling. diff --git a/.changeset/fix-subagent-sidebar-context.md b/.changeset/fix-subagent-sidebar-context.md deleted file mode 100644 index 4dd0cc787f..0000000000 --- a/.changeset/fix-subagent-sidebar-context.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Keep Agent Manager subagent inspector tabs aligned with the selected session and worktree. diff --git a/.changeset/fix-text-streaming.md b/.changeset/fix-text-streaming.md deleted file mode 100644 index 98a7778913..0000000000 --- a/.changeset/fix-text-streaming.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Restore incremental assistant text streaming across Kilo chat surfaces. diff --git a/.changeset/fix-tool-output-actions.md b/.changeset/fix-tool-output-actions.md deleted file mode 100644 index e8a1b6662c..0000000000 --- a/.changeset/fix-tool-output-actions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Keep tool-output action buttons visible above streamed output. diff --git a/.changeset/fix-worktree-base-branch.md b/.changeset/fix-worktree-base-branch.md deleted file mode 100644 index a3fcf8610e..0000000000 --- a/.changeset/fix-worktree-base-branch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Use the displayed current branch as the base when creating a worktree from the New Worktree dialog. diff --git a/.changeset/fresh-file-mentions.md b/.changeset/fresh-file-mentions.md deleted file mode 100644 index 9aebe9a418..0000000000 --- a/.changeset/fresh-file-mentions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Keep file mention suggestions current and scoped to the active workspace while preserving instant cached results. diff --git a/.changeset/fresh-worktree-prompt.md b/.changeset/fresh-worktree-prompt.md deleted file mode 100644 index dd9b024aa1..0000000000 --- a/.changeset/fresh-worktree-prompt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Use the standard prompt with mode, model, and effort controls when creating new worktrees. diff --git a/.changeset/fresh-worktrees-move.md b/.changeset/fresh-worktrees-move.md deleted file mode 100644 index 5b300736f1..0000000000 --- a/.changeset/fresh-worktrees-move.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Show worktree row actions in a hover menu instead of inline rename and delete buttons. diff --git a/.changeset/gh-status-banners.md b/.changeset/gh-status-banners.md deleted file mode 100644 index 34a4b27932..0000000000 --- a/.changeset/gh-status-banners.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Show synchronized Agent Manager and worktree editor banners when Git or GitHub CLI PR status checks need installation or authorization. diff --git a/.changeset/gpt-56-oauth-context.md b/.changeset/gpt-56-oauth-context.md deleted file mode 100644 index 4e7b1d8e33..0000000000 --- a/.changeset/gpt-56-oauth-context.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Use the full Codex context window for GPT-5.6 models authenticated through ChatGPT OAuth. diff --git a/.changeset/hover-agent-manager-actions.md b/.changeset/hover-agent-manager-actions.md deleted file mode 100644 index 24c735cec5..0000000000 --- a/.changeset/hover-agent-manager-actions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Show Agent Manager row actions only while hovering worktree and session rows. diff --git a/.changeset/incremental-todo-guidance.md b/.changeset/incremental-todo-guidance.md deleted file mode 100644 index 13b9a1360d..0000000000 --- a/.changeset/incremental-todo-guidance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Require the todo tool to update multi-step lists after each completed task. diff --git a/.changeset/islands-button-borders.md b/.changeset/islands-button-borders.md deleted file mode 100644 index a112ed9981..0000000000 --- a/.changeset/islands-button-borders.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Fix action button border artifacts in JetBrains Islands Light session dialogs. diff --git a/.changeset/jetbrains-agent-manager-beta.md b/.changeset/jetbrains-agent-manager-beta.md deleted file mode 100644 index e8f4b92f27..0000000000 --- a/.changeset/jetbrains-agent-manager-beta.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Show a Beta badge on the Agent Manager tool window tab. diff --git a/.changeset/jetbrains-expandable-hover-popups.md b/.changeset/jetbrains-expandable-hover-popups.md deleted file mode 100644 index 0c425a30f1..0000000000 --- a/.changeset/jetbrains-expandable-hover-popups.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": minor ---- - -Show the collapsed hover preview on more transcript cards: grep, glob, other tool calls, and to-dos now open the same popup that shell and diffs use. diff --git a/.changeset/jetbrains-history-hover-rename.md b/.changeset/jetbrains-history-hover-rename.md deleted file mode 100644 index 4b99fc28ef..0000000000 --- a/.changeset/jetbrains-history-hover-rename.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": minor ---- - -Reveal rename and delete buttons on hover in JetBrains session history, rename sessions through an inline popover instead of a modal dialog, and move the selection to the neighbouring session after deleting the selected one. diff --git a/.changeset/jetbrains-pr-worktree-tooltips.md b/.changeset/jetbrains-pr-worktree-tooltips.md deleted file mode 100644 index cd7d8e5931..0000000000 --- a/.changeset/jetbrains-pr-worktree-tooltips.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Show pull request titles and clearer multi-line badge tooltips in the Agent Manager worktree list. diff --git a/.changeset/jetbrains-profile-400-ready.md b/.changeset/jetbrains-profile-400-ready.md deleted file mode 100644 index 971cc8e171..0000000000 --- a/.changeset/jetbrains-profile-400-ready.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Keep the JetBrains plugin connected when the optional profile request returns Bad Request. diff --git a/.changeset/jetbrains-session-colors.md b/.changeset/jetbrains-session-colors.md deleted file mode 100644 index 85848f9a3a..0000000000 --- a/.changeset/jetbrains-session-colors.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Refresh the session UI colors around three tunable roles — session background, code-block background (shared by code blocks, the prompt bubble, and the input), and foreground — and apply them correctly on first paint instead of only after switching themes. diff --git a/.changeset/jetbrains-session-errors.md b/.changeset/jetbrains-session-errors.md deleted file mode 100644 index 380bb67579..0000000000 --- a/.changeset/jetbrains-session-errors.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": minor ---- - -Show provider errors and interrupted or failed turns in the JetBrains chat instead of returning silently to idle. diff --git a/.changeset/jetbrains-session-secondary-text.md b/.changeset/jetbrains-session-secondary-text.md deleted file mode 100644 index 3f08732f40..0000000000 --- a/.changeset/jetbrains-session-secondary-text.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Use a unified secondary text style for JetBrains session UI labels. diff --git a/.changeset/jetbrains-worktree-activity-badge.md b/.changeset/jetbrains-worktree-activity-badge.md deleted file mode 100644 index 2edd122ccb..0000000000 --- a/.changeset/jetbrains-worktree-activity-badge.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": minor ---- - -Show an activity badge on each Agent Manager worktree row, reflecting whether that worktree's sessions are running or waiting on a question or permission — even when the worktree's editor tab is not open. diff --git a/.changeset/jetbrains-worktree-adopt-session-name.md b/.changeset/jetbrains-worktree-adopt-session-name.md deleted file mode 100644 index f936a159cf..0000000000 --- a/.changeset/jetbrains-worktree-adopt-session-name.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": minor ---- - -Name Agent Manager worktrees from the first session's title. When a worktree still uses its default branch name, the title the agent generates for its first session becomes the worktree name — updating both the worktree list and the editor live as the name arrives. Placeholder session names are ignored so only the real agent title is adopted, and worktrees you have renamed yourself are left untouched. The worktree session list now also shows agent-generated session titles as they stream in. diff --git a/.changeset/jetbrains-worktree-change-badges.md b/.changeset/jetbrains-worktree-change-badges.md deleted file mode 100644 index 788be41920..0000000000 --- a/.changeset/jetbrains-worktree-change-badges.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": minor ---- - -Show worktree change counts, ahead/behind counts, and pull request badges in JetBrains Agent Manager worktree rows and editor headers. diff --git a/.changeset/jetbrains-worktree-delete-reappear.md b/.changeset/jetbrains-worktree-delete-reappear.md deleted file mode 100644 index 09edcee98c..0000000000 --- a/.changeset/jetbrains-worktree-delete-reappear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Fix the Agent Manager panel showing a deleted worktree again after switching tabs when the git removal did not actually succeed. Locked worktrees are now marked in the list, the delete dialog asks for explicit confirmation before force-removing a locked worktree, a failed deletion shows a notification with a one-click force-delete retry, and selecting a worktree opens a dedicated worktree session editor tab. diff --git a/.changeset/jetbrains-worktree-delete-selection.md b/.changeset/jetbrains-worktree-delete-selection.md deleted file mode 100644 index f68566d45d..0000000000 --- a/.changeset/jetbrains-worktree-delete-selection.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Move the JetBrains Agent Manager selection to the neighbouring worktree after deleting the one on screen, instead of jumping unpredictably. diff --git a/.changeset/jetbrains-worktree-list-stability.md b/.changeset/jetbrains-worktree-list-stability.md deleted file mode 100644 index 0017f346a5..0000000000 --- a/.changeset/jetbrains-worktree-list-stability.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Improve Agent Manager worktree activity refreshes and keep worktree list filtering responsive. diff --git a/.changeset/jetbrains-worktree-open-focus.md b/.changeset/jetbrains-worktree-open-focus.md deleted file mode 100644 index f1729790c4..0000000000 --- a/.changeset/jetbrains-worktree-open-focus.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Match IntelliJ Project view open and focus behavior for Agent Manager worktrees and sessions. diff --git a/.changeset/jetbrains-worktree-open-in-new-window.md b/.changeset/jetbrains-worktree-open-in-new-window.md deleted file mode 100644 index 1e9235a3f2..0000000000 --- a/.changeset/jetbrains-worktree-open-in-new-window.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": minor ---- - -Add an "Open worktree in new window" button to the Agent Manager worktree toolbar that opens the worktree directory in a new IDE frame. The project is opened on the backend/host, so it also works in remote development. diff --git a/.changeset/jetbrains-worktree-order.md b/.changeset/jetbrains-worktree-order.md deleted file mode 100644 index e0ec3c50d9..0000000000 --- a/.changeset/jetbrains-worktree-order.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Keep JetBrains Agent Manager worktrees in a stable creation order after switching panels or reloading. diff --git a/.changeset/jetbrains-worktree-session-deleting.md b/.changeset/jetbrains-worktree-session-deleting.md deleted file mode 100644 index 18f37d390e..0000000000 --- a/.changeset/jetbrains-worktree-session-deleting.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Show worktree sessions as deleting while removal is in progress and notify when deletion fails. diff --git a/.changeset/jetbrains-worktree-session-list.md b/.changeset/jetbrains-worktree-session-list.md deleted file mode 100644 index c9c8f51765..0000000000 --- a/.changeset/jetbrains-worktree-session-list.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": minor ---- - -Support managing sessions directly from Agent Manager worktree editor tabs, start a new session when opening an empty worktree editor, and hide non-Agent-Manager git worktrees from the worktree list. diff --git a/.changeset/jetbrains-worktree-terminal.md b/.changeset/jetbrains-worktree-terminal.md deleted file mode 100644 index d5a2076759..0000000000 --- a/.changeset/jetbrains-worktree-terminal.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": minor ---- - -Add a Terminal button to the Agent Manager worktree header that opens (or focuses) a terminal in the worktree's directory, reusing one terminal tab per worktree. The terminal tab is labelled with the same worktree name shown in the worktree list and editor tab, and it updates when the worktree is renamed or its pull request changes. The worktree header actions now use flat, hoverable toolbar buttons, and the branch-changes badge shows the changed-file count and lines added/removed, opening the branch diff when clicked. diff --git a/.changeset/mcp-tool-display-setting.md b/.changeset/mcp-tool-display-setting.md deleted file mode 100644 index 9575b176b6..0000000000 --- a/.changeset/mcp-tool-display-setting.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": minor ---- - -Support setting default open or collapsed state for MCP and generic tool blocks in Display settings diff --git a/.changeset/memory-show-preserve-text.md b/.changeset/memory-show-preserve-text.md deleted file mode 100644 index 87a21b08ab..0000000000 --- a/.changeset/memory-show-preserve-text.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Typing extra text after the `/memory show` command (for example `/memory show my notes`) used to clear that text from the chat input when the command ran. The text now stays in the input so you don't lose what you typed. diff --git a/.changeset/memory-sse-json.md b/.changeset/memory-sse-json.md deleted file mode 100644 index 122737bf60..0000000000 --- a/.changeset/memory-sse-json.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Stop memory auto-save from failing on OpenAI-compatible providers that stream by default. diff --git a/.changeset/optimize-agent-manager-tab-latency.md b/.changeset/optimize-agent-manager-tab-latency.md deleted file mode 100644 index b82b17ab26..0000000000 --- a/.changeset/optimize-agent-manager-tab-latency.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Optimize Agent Manager tab switching and context transition latency diff --git a/.changeset/optimize-large-session-loading.md b/.changeset/optimize-large-session-loading.md deleted file mode 100644 index 8bce7c260b..0000000000 --- a/.changeset/optimize-large-session-loading.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Optimize large session loading performance and reduce reactive re-render overhead in the webview. diff --git a/.changeset/optimize-top-bar-performance.md b/.changeset/optimize-top-bar-performance.md deleted file mode 100644 index 860433a6aa..0000000000 --- a/.changeset/optimize-top-bar-performance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Optimize TaskHeader and timeline bar calculation performance in the webview. diff --git a/.changeset/permission-prompt-scroll.md b/.changeset/permission-prompt-scroll.md deleted file mode 100644 index 0c139a2b60..0000000000 --- a/.changeset/permission-prompt-scroll.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Keep the Allow and Deny buttons reachable when a permission prompt contains a large diff or a long command: the prompt now scrolls its own content and shrinks with the available chat height instead of pushing its buttons out of view diff --git a/.changeset/persist-snapshot-disable.md b/.changeset/persist-snapshot-disable.md deleted file mode 100644 index f433da002e..0000000000 --- a/.changeset/persist-snapshot-disable.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Persist disabling snapshots from the slow-repo prompt across restarts. diff --git a/.changeset/pierre-pr-comment-diff.md b/.changeset/pierre-pr-comment-diff.md deleted file mode 100644 index 2c782516b6..0000000000 --- a/.changeset/pierre-pr-comment-diff.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Render Agent Manager pull request comment diffs with the Pierre-backed diff viewer and syntax highlighting. diff --git a/.changeset/plan-to-code-model-switch.md b/.changeset/plan-to-code-model-switch.md deleted file mode 100644 index 7600aa5d24..0000000000 --- a/.changeset/plan-to-code-model-switch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Switch to the code model when starting implementation after a planning session. diff --git a/.changeset/polite-history-rows.md b/.changeset/polite-history-rows.md deleted file mode 100644 index 2ebbc04443..0000000000 --- a/.changeset/polite-history-rows.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Use the shared active list for session history rows with hover-revealed local delete actions. diff --git a/.changeset/pr-comments-github-style.md b/.changeset/pr-comments-github-style.md deleted file mode 100644 index 5fe95f6a13..0000000000 --- a/.changeset/pr-comments-github-style.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": minor ---- - -Rework PR review comments in the Agent Manager PR panel: resolved threads now collapse into one-line rows in a Resolved group instead of being dimmed, each thread shows its replies, and every card has prominent Send to agent, Resolve, Copy, Open file, and Open on GitHub actions. A single button sends all unresolved comments to the agent, and comments arrive as structured review comments instead of pasted text. diff --git a/.changeset/prompt-bubble-outline.md b/.changeset/prompt-bubble-outline.md deleted file mode 100644 index b48361de99..0000000000 --- a/.changeset/prompt-bubble-outline.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Always outline JetBrains prompt bubbles and use a rounder prompt bubble shape. diff --git a/.changeset/prompt-focus-scroll-polish.md b/.changeset/prompt-focus-scroll-polish.md deleted file mode 100644 index 84fb7749d5..0000000000 --- a/.changeset/prompt-focus-scroll-polish.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Polish the JetBrains session prompt background, editor-tab focus ring, and centered jump-to-bottom button alignment. diff --git a/.changeset/quiet-branches-search.md b/.changeset/quiet-branches-search.md deleted file mode 100644 index 3c517fa378..0000000000 --- a/.changeset/quiet-branches-search.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Improve the New Worktree base branch selector with fuzzy matching, default fallback, and validation for unknown branches. diff --git a/.changeset/quiet-variants-cache.md b/.changeset/quiet-variants-cache.md deleted file mode 100644 index 79a835c158..0000000000 --- a/.changeset/quiet-variants-cache.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Preserve cached reasoning variants when starting new VS Code sessions. diff --git a/.changeset/quiet-worktrees-filter.md b/.changeset/quiet-worktrees-filter.md deleted file mode 100644 index 5e4763e59b..0000000000 --- a/.changeset/quiet-worktrees-filter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Prevent subagent descriptions from appearing as Agent Manager worktree titles. diff --git a/.changeset/refine-jetbrains-session-spacing.md b/.changeset/refine-jetbrains-session-spacing.md deleted file mode 100644 index 59fd75b31e..0000000000 --- a/.changeset/refine-jetbrains-session-spacing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Refine transcript card spacing, plan-ready styling, and diff scrollbar layout, and remove the stray stripe and gap left by empty messages at the top of turns. diff --git a/.changeset/remove-agent-manager-project-trust.md b/.changeset/remove-agent-manager-project-trust.md deleted file mode 100644 index 88022a81f5..0000000000 --- a/.changeset/remove-agent-manager-project-trust.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Remove the separate trust action from Agent Manager multi-project repositories. Added projects are now immediately available, while VS Code workspace trust still protects setup and run scripts. diff --git a/.changeset/remove-agent-requirements.md b/.changeset/remove-agent-requirements.md deleted file mode 100644 index 0d1136dbfd..0000000000 --- a/.changeset/remove-agent-requirements.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@kilocode/cli": patch -"kilo-code": patch ---- - -Remove the experimental agent requirements check and its configuration flag. diff --git a/.changeset/remove-alibaba-mistral-gateway-providers.md b/.changeset/remove-alibaba-mistral-gateway-providers.md deleted file mode 100644 index 58aa523b6d..0000000000 --- a/.changeset/remove-alibaba-mistral-gateway-providers.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-gateway": major ---- - -Remove Alibaba and Mistral as native AI SDK providers from Kilo Gateway. diff --git a/.changeset/remove-pr-sidebar-scroll-button.md b/.changeset/remove-pr-sidebar-scroll-button.md deleted file mode 100644 index 864fc27192..0000000000 --- a/.changeset/remove-pr-sidebar-scroll-button.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Remove the floating scroll-to-top button from the Agent Manager PR sidebar. diff --git a/.changeset/remove-task-aware-output-pruning.md b/.changeset/remove-task-aware-output-pruning.md deleted file mode 100644 index 5eb7aa56cc..0000000000 --- a/.changeset/remove-task-aware-output-pruning.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@kilocode/cli": patch -"@kilocode/kilo-ui": patch -"kilo-code": patch ---- - -Remove the experimental task-aware tool-output pruning feature and its related settings and indicators. diff --git a/.changeset/rename-jetbrains-worktrees.md b/.changeset/rename-jetbrains-worktrees.md deleted file mode 100644 index c0f522234d..0000000000 --- a/.changeset/rename-jetbrains-worktrees.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": minor ---- - -Support renaming Agent Manager worktrees and worktree sessions from the JetBrains plugin. diff --git a/.changeset/restore-agent-manager-diff-stats.md b/.changeset/restore-agent-manager-diff-stats.md deleted file mode 100644 index 41e3cb56f6..0000000000 --- a/.changeset/restore-agent-manager-diff-stats.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Restore live Git change statistics on the Agent Manager diff toggle for local and worktree selections. diff --git a/.changeset/restore-kilo-upgrade-version-lookup.md b/.changeset/restore-kilo-upgrade-version-lookup.md deleted file mode 100644 index 9bc312c4bc..0000000000 --- a/.changeset/restore-kilo-upgrade-version-lookup.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Keep `kilo upgrade` on the Kilo CLI release channel when GitHub's latest release is a JetBrains release. diff --git a/.changeset/sandbox-git-escalation.md b/.changeset/sandbox-git-escalation.md deleted file mode 100644 index c8eaefbb22..0000000000 --- a/.changeset/sandbox-git-escalation.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Prompt for explicit, one-shot approval before mutating Git commands run outside the sandbox. diff --git a/.changeset/scoped-interactive-terminal-state.md b/.changeset/scoped-interactive-terminal-state.md deleted file mode 100644 index c41d6db24f..0000000000 --- a/.changeset/scoped-interactive-terminal-state.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Ensure interactive terminal state is isolated per directory and cleaned up when its scope closes. diff --git a/.changeset/scroll-resize-dialog-fixes.md b/.changeset/scroll-resize-dialog-fixes.md deleted file mode 100644 index 84877c3be4..0000000000 --- a/.changeset/scroll-resize-dialog-fixes.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Keep JetBrains chat sessions pinned to the bottom during viewport resizes, expandable view changes, and action dialog reveals when already following the transcript. diff --git a/.changeset/selected-agent-over-stale-session.md b/.changeset/selected-agent-over-stale-session.md deleted file mode 100644 index d327483155..0000000000 --- a/.changeset/selected-agent-over-stale-session.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Fix agent mode switch getting stuck on draft/cloud-import sessions: apply the explicitly selected agent instead of reverting to the stale session agent. diff --git a/.changeset/session-background-contrast.md b/.changeset/session-background-contrast.md deleted file mode 100644 index dba72ede1d..0000000000 --- a/.changeset/session-background-contrast.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Keep JetBrains session prompts visible in themes where the panel and editor backgrounds match. diff --git a/.changeset/session-card-content-surfaces.md b/.changeset/session-card-content-surfaces.md deleted file mode 100644 index d4e6471ed1..0000000000 --- a/.changeset/session-card-content-surfaces.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Improve JetBrains session card header clicks and align raised content backgrounds with the editor surface. diff --git a/.changeset/session-pr-link.md b/.changeset/session-pr-link.md deleted file mode 100644 index 763ef462c0..0000000000 --- a/.changeset/session-pr-link.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": minor ---- - -Add `kilo pr link `, `kilo pr unlink`, and `kilo pr status` to link the current worktree to a pull request. The checkout command moves to `kilo pr checkout `; `kilo pr ` no longer checks out a PR. diff --git a/.changeset/session-status-copy-overlay.md b/.changeset/session-status-copy-overlay.md deleted file mode 100644 index 0bdebd2a64..0000000000 --- a/.changeset/session-status-copy-overlay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Keep JetBrains session status and copy controls visually bounded to the transcript area. diff --git a/.changeset/show-empty-jetbrains-sessions.md b/.changeset/show-empty-jetbrains-sessions.md deleted file mode 100644 index d46794d7de..0000000000 --- a/.changeset/show-empty-jetbrains-sessions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Show the empty session panel for empty JetBrains worktree sessions. diff --git a/.changeset/show-model-provider-hints.md b/.changeset/show-model-provider-hints.md deleted file mode 100644 index 996f82d107..0000000000 --- a/.changeset/show-model-provider-hints.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Show the model provider next to every model in the model selector. diff --git a/.changeset/show-queued-prompts.md b/.changeset/show-queued-prompts.md deleted file mode 100644 index 7431d4ee06..0000000000 --- a/.changeset/show-queued-prompts.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Keep queued prompts visible while the server confirms and loads their message parts. diff --git a/.changeset/show-token-throughput-by-default.md b/.changeset/show-token-throughput-by-default.md deleted file mode 100644 index f729fc1838..0000000000 --- a/.changeset/show-token-throughput-by-default.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Show token throughput by default, with a Display setting to hide it when needed. diff --git a/.changeset/slash-command-preserve-text.md b/.changeset/slash-command-preserve-text.md deleted file mode 100644 index 58878bb4da..0000000000 --- a/.changeset/slash-command-preserve-text.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Preserve existing text when selecting a slash command at the start of the chat input. Previously, typing `/new` or another slash command with text before the cursor would wipe the existing content entirely. diff --git a/.changeset/smooth-session-backdrop.md b/.changeset/smooth-session-backdrop.md deleted file mode 100644 index a521cd2320..0000000000 --- a/.changeset/smooth-session-backdrop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Render the JetBrains session backdrop consistently and keep transcript hover backgrounds from getting stuck. diff --git a/.changeset/steady-session-dock.md b/.changeset/steady-session-dock.md deleted file mode 100644 index 258599af31..0000000000 --- a/.changeset/steady-session-dock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Keep the conversation from shifting when a turn starts or finishes. The working indicator and the session actions now share one row above the composer that keeps its height in both states, instead of resizing two separate areas. diff --git a/.changeset/steady-working-status.md b/.changeset/steady-working-status.md deleted file mode 100644 index 3a60661fe3..0000000000 --- a/.changeset/steady-working-status.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Keep the working indicator steady while the agent works: the status label now shimmers and glides into its new width instead of jumping the spinner sideways on every status change. diff --git a/.changeset/subagent-inspector-tabs.md b/.changeset/subagent-inspector-tabs.md deleted file mode 100644 index 0ab93ea7e5..0000000000 --- a/.changeset/subagent-inspector-tabs.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": minor ---- - -Open delegated subagent sessions in Agent Manager inspector tabs alongside terminals. diff --git a/.changeset/terminal-shortcut-focus.md b/.changeset/terminal-shortcut-focus.md deleted file mode 100644 index 1bd5ab3f54..0000000000 --- a/.changeset/terminal-shortcut-focus.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Make Agent Manager shortcuts follow the focused area. In the center, Cmd/Ctrl+T creates a new session tab and Cmd/Ctrl+Shift+T creates a central terminal tab, whether the prompt or a central terminal is focused. In the right sidebar terminal, Cmd/Ctrl+T creates another sidebar terminal tab and Cmd/Ctrl+Shift+T does nothing. Returning from a terminal with Cmd/Ctrl+Shift+M restores the previous session tab before focusing its prompt. Update the shortcut dialog and hints to show the distinct actions. diff --git a/.changeset/trim-inferred-variants.md b/.changeset/trim-inferred-variants.md deleted file mode 100644 index ca56b201b3..0000000000 --- a/.changeset/trim-inferred-variants.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Use provider model catalogs instead of hardcoded model-name heuristics for reasoning variants. diff --git a/.changeset/tui-gateway-model-picker.md b/.changeset/tui-gateway-model-picker.md deleted file mode 100644 index 2ea0f32ccd..0000000000 --- a/.changeset/tui-gateway-model-picker.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Keep recently used Kilo Gateway models visible in the TUI picker, and find them when filtering by kilo. diff --git a/.changeset/tui-message-time-order.md b/.changeset/tui-message-time-order.md deleted file mode 100644 index 8e3bc72f59..0000000000 --- a/.changeset/tui-message-time-order.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/cli": patch ---- - -Fix TUI sessions where new turns stopped appearing until the session was reopened diff --git a/.changeset/worktree-dependencies.md b/.changeset/worktree-dependencies.md deleted file mode 100644 index 899991670f..0000000000 --- a/.changeset/worktree-dependencies.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Bootstrap missing locked workspace dependencies before building the extension from an Agent Manager worktree. diff --git a/.changeset/worktree-editor-selection.md b/.changeset/worktree-editor-selection.md deleted file mode 100644 index 9da6ad27e3..0000000000 --- a/.changeset/worktree-editor-selection.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Keep the Agent Manager worktree selection in sync with the active editor tab. diff --git a/.changeset/worktree-history-default.md b/.changeset/worktree-history-default.md deleted file mode 100644 index 2241a12d90..0000000000 --- a/.changeset/worktree-history-default.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Open `/sessions` on a git worktree with the Worktree history filter selected by default. diff --git a/.changeset/worktree-session-history-rows.md b/.changeset/worktree-session-history-rows.md deleted file mode 100644 index 26b68a0f33..0000000000 --- a/.changeset/worktree-session-history-rows.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@kilocode/kilo-jetbrains": patch ---- - -Show Agent Manager worktree sessions with History-style activity badges, relative timestamps, and date sections. diff --git a/artifacts/glm52-rise-video/package.json b/artifacts/glm52-rise-video/package.json index 1cb5063cb4..6e8b5a6962 100644 --- a/artifacts/glm52-rise-video/package.json +++ b/artifacts/glm52-rise-video/package.json @@ -21,5 +21,5 @@ "@types/react-dom": "^19.2.3", "typescript": "^5.8.2" }, - "version": "7.4.22" + "version": "7.4.23" } diff --git a/bun.lock b/bun.lock index dd4ec72d32..ee02897b47 100644 --- a/bun.lock +++ b/bun.lock @@ -32,7 +32,7 @@ }, "packages/client": { "name": "@opencode-ai/client", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@opencode-ai/protocol": "workspace:*", "@opencode-ai/schema": "workspace:*", @@ -56,7 +56,7 @@ }, "packages/codemode": { "name": "@opencode-ai/codemode", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "acorn": "8.15.0", "effect": "catalog:", @@ -70,7 +70,7 @@ }, "packages/core": { "name": "@opencode-ai/core", - "version": "7.4.22", + "version": "7.4.23", "bin": { "opencode": "./bin/opencode", }, @@ -168,7 +168,7 @@ }, "packages/effect-drizzle-sqlite": { "name": "@opencode-ai/effect-drizzle-sqlite", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "drizzle-orm": "catalog:", "effect": "catalog:", @@ -182,7 +182,7 @@ }, "packages/effect-sqlite-node": { "name": "@opencode-ai/effect-sqlite-node", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "effect": "catalog:", }, @@ -194,7 +194,7 @@ }, "packages/http-recorder": { "name": "@opencode-ai/http-recorder", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@effect/platform-node": "4.0.0-beta.83", "@effect/platform-node-shared": "4.0.0-beta.83", @@ -215,7 +215,7 @@ }, "packages/httpapi-codegen": { "name": "@opencode-ai/httpapi-codegen", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "effect": "catalog:", "prettier": "3.6.2", @@ -228,7 +228,7 @@ }, "packages/kilo-console": { "name": "@kilocode/kilo-console", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@kilocode/kilo-indexing": "workspace:*", "@kilocode/kilo-web-ui": "workspace:*", @@ -251,7 +251,7 @@ }, "packages/kilo-docs": { "name": "@kilocode/kilo-docs", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@docsearch/css": "^4", "@docsearch/js": "^4", @@ -281,7 +281,7 @@ }, "packages/kilo-gateway": { "name": "@kilocode/kilo-gateway", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@ai-sdk/anthropic": "3.0.82", "@ai-sdk/openai": "3.0.88", @@ -315,7 +315,7 @@ }, "packages/kilo-i18n": { "name": "@kilocode/kilo-i18n", - "version": "7.4.22", + "version": "7.4.23", "devDependencies": { "@tsconfig/node22": "catalog:", "@types/bun": "catalog:", @@ -325,7 +325,7 @@ }, "packages/kilo-indexing": { "name": "@kilocode/kilo-indexing", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@aws-sdk/client-bedrock-runtime": "3.1005.0", "@aws-sdk/credential-provider-ini": "3.972.31", @@ -357,11 +357,11 @@ }, "packages/kilo-jetbrains": { "name": "@kilocode/kilo-jetbrains", - "version": "7.4.21", + "version": "7.4.22", }, "packages/kilo-memory": { "name": "@kilocode/kilo-memory", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "effect": "catalog:", "zod": "catalog:", @@ -375,7 +375,7 @@ }, "packages/kilo-sandbox": { "name": "@kilocode/sandbox", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@anthropic-ai/sandbox-runtime": "catalog:", "effect": "catalog:", @@ -390,7 +390,7 @@ }, "packages/kilo-telemetry": { "name": "@kilocode/kilo-telemetry", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@kilocode/kilo-gateway": "workspace:*", "posthog-node": "4.4.0", @@ -404,7 +404,7 @@ }, "packages/kilo-ui": { "name": "@kilocode/kilo-ui", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "0.13.11", @@ -442,7 +442,7 @@ }, "packages/kilo-vscode": { "name": "kilo-code", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@anthropic-ai/sdk": "^0.39.0", "@kilocode/kilo-gateway": "workspace:*", @@ -515,7 +515,7 @@ }, "packages/kilo-web-ui": { "name": "@kilocode/kilo-web-ui", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@kilocode/kilo-ui": "workspace:*", "@kobalte/core": "catalog:", @@ -532,7 +532,7 @@ }, "packages/llm": { "name": "@opencode-ai/llm", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@opencode-ai/schema": "workspace:*", "@smithy/eventstream-codec": "4.2.14", @@ -551,7 +551,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "7.4.22", + "version": "7.4.23", "bin": { "kilo": "./bin/kilo", "kilocode": "./bin/kilo", @@ -719,7 +719,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@ai-sdk/provider": "3.0.8", "@kilocode/sdk": "workspace:*", @@ -748,7 +748,7 @@ }, "packages/plugin-atomic-chat": { "name": "@kilocode/plugin-atomic-chat", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@kilocode/plugin": "workspace:*", }, @@ -762,7 +762,7 @@ }, "packages/protocol": { "name": "@opencode-ai/protocol", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@opencode-ai/schema": "workspace:*", "effect": "catalog:", @@ -775,7 +775,7 @@ }, "packages/schema": { "name": "@opencode-ai/schema", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "effect": "catalog:", }, @@ -787,7 +787,7 @@ }, "packages/script": { "name": "@opencode-ai/script", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "semver": "^7.6.3", }, @@ -798,7 +798,7 @@ }, "packages/sdk-next": { "name": "@opencode-ai/sdk-next", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@opencode-ai/client": "workspace:*", "@opencode-ai/core": "workspace:*", @@ -813,7 +813,7 @@ }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "cross-spawn": "catalog:", }, @@ -828,7 +828,7 @@ }, "packages/server": { "name": "@opencode-ai/server", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@opencode-ai/core": "workspace:*", "@opencode-ai/protocol": "workspace:*", @@ -843,7 +843,7 @@ }, "packages/session-ui": { "name": "@opencode-ai/session-ui", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -888,7 +888,7 @@ }, "packages/storybook": { "name": "@opencode-ai/storybook", - "version": "7.4.22", + "version": "7.4.23", "devDependencies": { "@opencode-ai/session-ui": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -913,7 +913,7 @@ }, "packages/tui": { "name": "@opencode-ai/tui", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@kilocode/plugin": "workspace:*", "@kilocode/sdk": "workspace:*", @@ -939,7 +939,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "7.4.22", + "version": "7.4.23", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", diff --git a/package.json b/package.json index 76f329ab89..efbc37aeb8 100644 --- a/package.json +++ b/package.json @@ -177,6 +177,6 @@ "@tanstack/virtual-core@3.17.3": "patches/@tanstack%2Fvirtual-core@3.17.3.patch", "solid-js@1.9.12": "patches/solid-js@1.9.12.patch" }, - "version": "7.4.22", + "version": "7.4.23", "peerDependencies": {} } diff --git a/packages/client/package.json b/packages/client/package.json index 15fb5d561f..59cc5fd1db 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -38,5 +38,5 @@ "@typescript/native-preview": "catalog:", "effect": "catalog:" }, - "version": "7.4.22" + "version": "7.4.23" } diff --git a/packages/codemode/package.json b/packages/codemode/package.json index 16a34f331a..fab4911e33 100644 --- a/packages/codemode/package.json +++ b/packages/codemode/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/codemode", - "version": "7.4.22", + "version": "7.4.23", "description": "Effect-native confined code execution over schema-described tools", "private": true, "type": "module", diff --git a/packages/core/package.json b/packages/core/package.json index fbc64130ae..03ed5fec47 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.4.22", + "version": "7.4.23", "name": "@opencode-ai/core", "type": "module", "license": "MIT", diff --git a/packages/effect-drizzle-sqlite/package.json b/packages/effect-drizzle-sqlite/package.json index df8e25d9ce..dd4d70f6a4 100644 --- a/packages/effect-drizzle-sqlite/package.json +++ b/packages/effect-drizzle-sqlite/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.4.22", + "version": "7.4.23", "name": "@opencode-ai/effect-drizzle-sqlite", "type": "module", "license": "MIT", diff --git a/packages/effect-sqlite-node/package.json b/packages/effect-sqlite-node/package.json index 7189856c30..88d60e11a7 100644 --- a/packages/effect-sqlite-node/package.json +++ b/packages/effect-sqlite-node/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.4.22", + "version": "7.4.23", "name": "@opencode-ai/effect-sqlite-node", "type": "module", "license": "MIT", diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 4dc6f5c0f8..881eed953b 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "kilo" name = "Kilo" description = "The open source coding agent." -version = "7.4.22" +version = "7.4.23" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/Kilo-Org/kilocode" @@ -11,26 +11,26 @@ name = "Kilo" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.22/opencode-darwin-arm64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.23/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.22/opencode-darwin-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.23/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.22/opencode-linux-arm64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.23/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.22/opencode-linux-x64.tar.gz" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.23/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.22/opencode-windows-x64.zip" +archive = "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.23/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/http-recorder/package.json b/packages/http-recorder/package.json index 3eb770425a..c7d25b489c 100644 --- a/packages/http-recorder/package.json +++ b/packages/http-recorder/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.4.22", + "version": "7.4.23", "name": "@opencode-ai/http-recorder", "description": "Record and replay Effect HTTP client traffic with deterministic cassettes", "type": "module", diff --git a/packages/httpapi-codegen/package.json b/packages/httpapi-codegen/package.json index 65c5b6bc0b..e240e912da 100644 --- a/packages/httpapi-codegen/package.json +++ b/packages/httpapi-codegen/package.json @@ -20,5 +20,5 @@ "@types/bun": "catalog:", "@typescript/native-preview": "catalog:" }, - "version": "7.4.22" + "version": "7.4.23" } diff --git a/packages/kilo-console/package.json b/packages/kilo-console/package.json index 71f04943e6..297ac05833 100755 --- a/packages/kilo-console/package.json +++ b/packages/kilo-console/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-console", - "version": "7.4.22", + "version": "7.4.23", "private": true, "type": "module", "scripts": { diff --git a/packages/kilo-docs/package.json b/packages/kilo-docs/package.json index c5f4049255..3a7773c627 100644 --- a/packages/kilo-docs/package.json +++ b/packages/kilo-docs/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-docs", - "version": "7.4.22", + "version": "7.4.23", "private": true, "scripts": { "dev": "next dev --webpack --port 3002", diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index 20abd6441c..1ee145de15 100644 --- a/packages/kilo-gateway/package.json +++ b/packages/kilo-gateway/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-gateway", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration", diff --git a/packages/kilo-i18n/package.json b/packages/kilo-i18n/package.json index 3c043908fb..8d36de8b70 100644 --- a/packages/kilo-i18n/package.json +++ b/packages/kilo-i18n/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-i18n", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "description": "Kilo-specific i18n translations and overrides", diff --git a/packages/kilo-indexing/package.json b/packages/kilo-indexing/package.json index f4e85fd925..36276595be 100644 --- a/packages/kilo-indexing/package.json +++ b/packages/kilo-indexing/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-indexing", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "description": "Standalone indexing engine and host helpers for Kilo Code", diff --git a/packages/kilo-jetbrains/CHANGELOG.md b/packages/kilo-jetbrains/CHANGELOG.md index b45755a2b2..f85bf7408c 100644 --- a/packages/kilo-jetbrains/CHANGELOG.md +++ b/packages/kilo-jetbrains/CHANGELOG.md @@ -4,6 +4,96 @@ ### Minor Changes +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`1500843`](https://github.com/Kilo-Org/kilocode/commit/1500843a342d66b56bc64ac26fa6f9d60e7d255f) - Show the collapsed hover preview on more transcript cards: grep, glob, other tool calls, and to-dos now open the same popup that shell and diffs use. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`46eac53`](https://github.com/Kilo-Org/kilocode/commit/46eac53716dd4c5eb31e782f55f08bcf13772ad7) - Reveal rename and delete buttons on hover in JetBrains session history, rename sessions through an inline popover instead of a modal dialog, and move the selection to the neighbouring session after deleting the selected one. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`b1a8893`](https://github.com/Kilo-Org/kilocode/commit/b1a8893f142807085c4312efac62379fbcc953d5) - Show provider errors and interrupted or failed turns in the JetBrains chat instead of returning silently to idle. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`919d312`](https://github.com/Kilo-Org/kilocode/commit/919d312fa4e14f44f0ad88283bbf60a1bb8a79a0) - Show an activity badge on each Agent Manager worktree row, reflecting whether that worktree's sessions are running or waiting on a question or permission — even when the worktree's editor tab is not open. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`a678e54`](https://github.com/Kilo-Org/kilocode/commit/a678e549f5381db7625cc61e0897e9cb54465595) - Name Agent Manager worktrees from the first session's title. When a worktree still uses its default branch name, the title the agent generates for its first session becomes the worktree name — updating both the worktree list and the editor live as the name arrives. Placeholder session names are ignored so only the real agent title is adopted, and worktrees you have renamed yourself are left untouched. The worktree session list now also shows agent-generated session titles as they stream in. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`4100415`](https://github.com/Kilo-Org/kilocode/commit/4100415acab6efaacf438ccb0648e29acd7b22a2) - Show worktree change counts, ahead/behind counts, and pull request badges in JetBrains Agent Manager worktree rows and editor headers. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`106b5f4`](https://github.com/Kilo-Org/kilocode/commit/106b5f4d5aea047e21a0ddc923d98e49c78ccef8) - Add an "Open worktree in new window" button to the Agent Manager worktree toolbar that opens the worktree directory in a new IDE frame. The project is opened on the backend/host, so it also works in remote development. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`b6bd9f2`](https://github.com/Kilo-Org/kilocode/commit/b6bd9f224c8c7dda632bfa16f961211f66f49a25) - Support managing sessions directly from Agent Manager worktree editor tabs, start a new session when opening an empty worktree editor, and hide non-Agent-Manager git worktrees from the worktree list. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`1d964e0`](https://github.com/Kilo-Org/kilocode/commit/1d964e08254bf06de4c395bcc63a71b12f37142b) - Add a Terminal button to the Agent Manager worktree header that opens (or focuses) a terminal in the worktree's directory, reusing one terminal tab per worktree. The terminal tab is labelled with the same worktree name shown in the worktree list and editor tab, and it updates when the worktree is renamed or its pull request changes. The worktree header actions now use flat, hoverable toolbar buttons, and the branch-changes badge shows the changed-file count and lines added/removed, opening the branch diff when clicked. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`d522ff8`](https://github.com/Kilo-Org/kilocode/commit/d522ff80e25e220c46cda6ed621e29025c302259) - Support renaming Agent Manager worktrees and worktree sessions from the JetBrains plugin. + +### Patch Changes + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`f3d1134`](https://github.com/Kilo-Org/kilocode/commit/f3d11341c4b6d47a047e7f04dd46817e64a77bb1) - Use equal-height rows by default in Agent Manager and settings lists, keeping variable-height rows only for provider settings. + +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`e8a40e1`](https://github.com/Kilo-Org/kilocode/commit/e8a40e1502c03a996d1452c2c9cf49c99f288e83) - Remove borders around JetBrains prompt bubbles and markdown code surfaces, and round the collapsed card hover highlight and markdown code blocks to match the prompt bubble. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`8db5a8c`](https://github.com/Kilo-Org/kilocode/commit/8db5a8c5c962bcbd3093e7561e224350d3a11f4c) - Center JetBrains session content at a 98-column readable width on wide panels. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`579245d`](https://github.com/Kilo-Org/kilocode/commit/579245d8f24310f93a923f3a630922141341a386) - Use the standard prompt with mode, model, and effort controls when creating new worktrees. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`d1ae907`](https://github.com/Kilo-Org/kilocode/commit/d1ae907746e0fc74c1f7f85d933db4214665fd3c) - Show worktree row actions in a hover menu instead of inline rename and delete buttons. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`430306e`](https://github.com/Kilo-Org/kilocode/commit/430306e37dc26b87c57df77c34f9c9f9b76dffb0) - Show synchronized Agent Manager and worktree editor banners when Git or GitHub CLI PR status checks need installation or authorization. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`aafde0b`](https://github.com/Kilo-Org/kilocode/commit/aafde0bf7e1b3263aacbff3a9c476af89dc2929d) - Show Agent Manager row actions only while hovering worktree and session rows. + +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`3e617c1`](https://github.com/Kilo-Org/kilocode/commit/3e617c12aa6204e3aea48ef692f1e5b6b3c35dfb) - Fix action button border artifacts in JetBrains Islands Light session dialogs. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`aadf773`](https://github.com/Kilo-Org/kilocode/commit/aadf773f281c837bf53a1978bb9d0ccc4ea5e707) - Show a Beta badge on the Agent Manager tool window tab. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`89532bb`](https://github.com/Kilo-Org/kilocode/commit/89532bb897102ca64369a67dd62513e72d92828b) - Show pull request titles and clearer multi-line badge tooltips in the Agent Manager worktree list. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`b2015b8`](https://github.com/Kilo-Org/kilocode/commit/b2015b864208601aa290a1c05c7eb1384e0e7034) - Keep the JetBrains plugin connected when the optional profile request returns Bad Request. + +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`06fc620`](https://github.com/Kilo-Org/kilocode/commit/06fc620ba01cd725345d4bc457a1acb67a65a820) - Refresh the session UI colors around three tunable roles — session background, code-block background (shared by code blocks, the prompt bubble, and the input), and foreground — and apply them correctly on first paint instead of only after switching themes. + +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`340172a`](https://github.com/Kilo-Org/kilocode/commit/340172af19bff6d31840984da600d4849b6db231) - Use a unified secondary text style for JetBrains session UI labels. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`e5193c5`](https://github.com/Kilo-Org/kilocode/commit/e5193c5493fb9b76e899aee7cb35ad7af9bf637a) - Fix the Agent Manager panel showing a deleted worktree again after switching tabs when the git removal did not actually succeed. Locked worktrees are now marked in the list, the delete dialog asks for explicit confirmation before force-removing a locked worktree, a failed deletion shows a notification with a one-click force-delete retry, and selecting a worktree opens a dedicated worktree session editor tab. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`38e8220`](https://github.com/Kilo-Org/kilocode/commit/38e822042c2fe9ee074f72a4001e8e2852e6ba9c) - Move the JetBrains Agent Manager selection to the neighbouring worktree after deleting the one on screen, instead of jumping unpredictably. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`319d1f4`](https://github.com/Kilo-Org/kilocode/commit/319d1f485917266cc4a56d620c903afa2e96125d) - Improve Agent Manager worktree activity refreshes and keep worktree list filtering responsive. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`15efe98`](https://github.com/Kilo-Org/kilocode/commit/15efe98cb8a36859acbd8aaac31b22d31d94d36e) - Match IntelliJ Project view open and focus behavior for Agent Manager worktrees and sessions. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`916548a`](https://github.com/Kilo-Org/kilocode/commit/916548a8cc55b69f9a9f08341db4569f6f7dcaeb) - Keep JetBrains Agent Manager worktrees in a stable creation order after switching panels or reloading. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`5b0acee`](https://github.com/Kilo-Org/kilocode/commit/5b0acee0167aa333895c611d6681a7ed40f7c777) - Show worktree sessions as deleting while removal is in progress and notify when deletion fails. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`a89936b`](https://github.com/Kilo-Org/kilocode/commit/a89936bf8e197358b8be6ce40a319a75d3478ae1) - Use the shared active list for session history rows with hover-revealed local delete actions. + +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`ff8e470`](https://github.com/Kilo-Org/kilocode/commit/ff8e47030057f6d3191ca4c1c26d374dceb4d8ff) - Always outline JetBrains prompt bubbles and use a rounder prompt bubble shape. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`a417b22`](https://github.com/Kilo-Org/kilocode/commit/a417b220fa75ceef14c2653afff2b227bb78757f) - Polish the JetBrains session prompt background, editor-tab focus ring, and centered jump-to-bottom button alignment. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`f5ff70e`](https://github.com/Kilo-Org/kilocode/commit/f5ff70ea3b26c9eb7994193cb9f8371691bdd73c) - Improve the New Worktree base branch selector with fuzzy matching, default fallback, and validation for unknown branches. + +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`9f1afe1`](https://github.com/Kilo-Org/kilocode/commit/9f1afe1057b0c15f9e123d992a7503d284d544df) - Refine transcript card spacing, plan-ready styling, and diff scrollbar layout, and remove the stray stripe and gap left by empty messages at the top of turns. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`c22ca3a`](https://github.com/Kilo-Org/kilocode/commit/c22ca3ab7bac81b638d1441f5ef52459e287e6c5) - Keep JetBrains chat sessions pinned to the bottom during viewport resizes, expandable view changes, and action dialog reveals when already following the transcript. + +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`706a3c3`](https://github.com/Kilo-Org/kilocode/commit/706a3c3ce74110f2c0433b7a416ee9ddc02770a4) - Keep JetBrains session prompts visible in themes where the panel and editor backgrounds match. + +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`0209c64`](https://github.com/Kilo-Org/kilocode/commit/0209c649fdf918b17b4e578dd70bc38befa5cd24) - Improve JetBrains session card header clicks and align raised content backgrounds with the editor surface. + +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`bf0c6c7`](https://github.com/Kilo-Org/kilocode/commit/bf0c6c7a9ecec955c0b367bcec722b28d00c49d6) - Keep JetBrains session status and copy controls visually bounded to the transcript area. + +- [#13215](https://github.com/Kilo-Org/kilocode/pull/13215) [`ae3eb9b`](https://github.com/Kilo-Org/kilocode/commit/ae3eb9b405c4992cc3da9bbcb273e242887ca2ed) - Show the empty session panel for empty JetBrains worktree sessions. + +- [#13092](https://github.com/Kilo-Org/kilocode/pull/13092) [`5496466`](https://github.com/Kilo-Org/kilocode/commit/5496466bff9a3a3e1e5cd9b964a1e3d61fb6130e) - Render the JetBrains session backdrop consistently and keep transcript hover backgrounds from getting stuck. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`5ab0ba2`](https://github.com/Kilo-Org/kilocode/commit/5ab0ba24b3934a04ad9dc02b0fc67cc888a34c0c) - Keep the Agent Manager worktree selection in sync with the active editor tab. + +- [#12433](https://github.com/Kilo-Org/kilocode/pull/12433) [`89163e7`](https://github.com/Kilo-Org/kilocode/commit/89163e7e02bdf86b4c0f19bc6eba93e08d105afc) - Show Agent Manager worktree sessions with History-style activity badges, relative timestamps, and date sections. + +## 7.5.0 + +### Minor Changes + - [#13015](https://github.com/Kilo-Org/kilocode/pull/13015) [`62923ad`](https://github.com/Kilo-Org/kilocode/commit/62923adb518371d1659ea65e5519768e4abf231b) - Include the active editor file, open files, visible files, and selected text in JetBrains chat context by default, with a Context settings toggle to disable it. Files matched by `.kilocodeignore` (or `.gitignore` plus `.env` files) are excluded, and the default shell is reported to the agent. - [#12895](https://github.com/Kilo-Org/kilocode/pull/12895) [`a340d61`](https://github.com/Kilo-Org/kilocode/commit/a340d61716b6fdec89943bff438c151b513fd1f3) - Log whether the JetBrains plugin downloads Core or uses the bundled/cached version, and mark the Core version shown in the popup as "Bundled" when it wasn't downloaded. @@ -153,11 +243,13 @@ ## [7.1.0-rc.2] - 2026-08-18 ### Added + - Add the JetBrains Agent Manager beta for creating, opening, organizing, renaming, and deleting worktree-based tasks and their sessions from the IDE. - Show worktree activity, change, ahead/behind, and pull request badges in Agent Manager, with clearer row actions, menus, and tooltips. - Support opening Agent Manager worktrees in new windows and dedicated terminal tabs. ### Fixed + - Improve JetBrains chat readability and scrolling with centered readable width, refreshed prompt chrome, stable tail-follow behavior, and clearer failed-turn outcome cards. - Unblock JetBrains release verification by replacing internal and override-only IntelliJ API usage with verifier-safe public API paths. - Keep the migration wizard visible across reconnects and restore worktree session creation after migration completes. @@ -168,16 +260,19 @@ - Remove duplicated skill catalog content from Kilo Core prompts to reduce request size while preserving lazy skill loading. ### Changed + - Reuse the session modal layout for the JetBrains migration wizard. ## [7.1.0-rc.1] - 2026-08-18 ### Added + - Add the JetBrains Agent Manager beta for creating, opening, organizing, renaming, and deleting worktree-based tasks and their sessions from the IDE. - Show worktree activity, change, ahead/behind, and pull request badges in Agent Manager, with clearer row actions, menus, and tooltips. - Support opening Agent Manager worktrees in new windows and dedicated terminal tabs. ### Fixed + - Improve JetBrains chat readability and scrolling with centered readable width, refreshed prompt chrome, stable tail-follow behavior, and clearer failed-turn outcome cards. - Keep Ask and Plan modes read-only even when broad global permission rules are configured. - Preserve project-level snapshot disabling across restarts after choosing to disable snapshots from the slow-repo prompt. @@ -189,10 +284,12 @@ ### Added ### Fixed + - Improve JetBrains chat readability with refreshed session surfaces, softer spacing, clearer prompt bubbles, and more consistent hover states. - Make JetBrains CLI downloads more reliable by retrying transient failures and rate limits, and by avoiding authentication on public CLI asset fetches. ### Changed + - Update the JetBrains plugin CLI pin to Kilo Core 7.4.22. - Refresh Kilo Core with upstream provider, model variant, and session runtime updates. diff --git a/packages/kilo-memory/package.json b/packages/kilo-memory/package.json index a612e2f3eb..1954a7e3e9 100644 --- a/packages/kilo-memory/package.json +++ b/packages/kilo-memory/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-memory", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "description": "Project memory storage, indexing, recall, and command helpers for Kilo Code", diff --git a/packages/kilo-sandbox/package.json b/packages/kilo-sandbox/package.json index d46a44fcd0..a05e30087f 100644 --- a/packages/kilo-sandbox/package.json +++ b/packages/kilo-sandbox/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/sandbox", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "private": true, diff --git a/packages/kilo-telemetry/package.json b/packages/kilo-telemetry/package.json index 91cf054363..74070fc390 100644 --- a/packages/kilo-telemetry/package.json +++ b/packages/kilo-telemetry/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-telemetry", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "description": "Telemetry for Kilo CLI - PostHog analytics integration", diff --git a/packages/kilo-ui/package.json b/packages/kilo-ui/package.json index b0059815f4..018f3863f5 100644 --- a/packages/kilo-ui/package.json +++ b/packages/kilo-ui/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-ui", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "exports": { diff --git a/packages/kilo-vscode/CHANGELOG.md b/packages/kilo-vscode/CHANGELOG.md index 60e2b8af2b..52092dab1b 100644 --- a/packages/kilo-vscode/CHANGELOG.md +++ b/packages/kilo-vscode/CHANGELOG.md @@ -1,10 +1,110 @@ # kilo-code +## 7.4.23 + +### Minor Changes + +- [#13010](https://github.com/Kilo-Org/kilocode/pull/13010) [`b5bf1d9`](https://github.com/Kilo-Org/kilocode/commit/b5bf1d996b2d314674d086e0574971c51d33d43e) - Support setting default open or collapsed state for MCP and generic tool blocks in Display settings + +- [#13241](https://github.com/Kilo-Org/kilocode/pull/13241) [`ea4f9e0`](https://github.com/Kilo-Org/kilocode/commit/ea4f9e0f0d7352427670291ffe92de2adc477e65) - Rework PR review comments in the Agent Manager PR panel: resolved threads now collapse into one-line rows in a Resolved group instead of being dimmed, each thread shows its replies, and every card has prominent Send to agent, Resolve, Copy, Open file, and Open on GitHub actions. A single button sends all unresolved comments to the agent, and comments arrive as structured review comments instead of pasted text. + +- [#13173](https://github.com/Kilo-Org/kilocode/pull/13173) [`53d0af7`](https://github.com/Kilo-Org/kilocode/commit/53d0af74f61c1d5760ad10d0fddafde6ddef4bad) - Open delegated subagent sessions in Agent Manager inspector tabs alongside terminals. + +### Patch Changes + +- [#12977](https://github.com/Kilo-Org/kilocode/pull/12977) [`b9a48bf`](https://github.com/Kilo-Org/kilocode/commit/b9a48bff94702bd25549bb53200df6f43b541084) - Fix Agent Manager project accordions that stayed on a loading indicator until you clicked into them. Expanded projects other than the active one now receive their worktrees, sessions, and git stats as soon as Agent Manager opens and again after the panel reloads. While a project is still loading, its local row and section headings stay in place and the rows below fade in as skeleton placeholders instead of showing a single centered spinner, so several projects loading at once look consistent. + +- [#13230](https://github.com/Kilo-Org/kilocode/pull/13230) [`99e0e81`](https://github.com/Kilo-Org/kilocode/commit/99e0e81185560bd43b45ca2007c3029acaec5edb) - Capture `@terminal` from the focused Agent Manager terminal, including embedded Run and Setup terminals, instead of using an unrelated active VS Code terminal. + +- [#13121](https://github.com/Kilo-Org/kilocode/pull/13121) [`e2966ab`](https://github.com/Kilo-Org/kilocode/commit/e2966abcba4906383d13b385d61ecd50016e4d7d) - Keep the selected agent after switching from Ask to Code, and remind the model that previous Ask-mode restrictions no longer apply. + +- [#13200](https://github.com/Kilo-Org/kilocode/pull/13200) [`59048c4`](https://github.com/Kilo-Org/kilocode/commit/59048c44bdd1a443503b416fde6fa81034460642) - Keep the Agent Manager inline diff position stable while scrolling upward through large reviews + +- [#13263](https://github.com/Kilo-Org/kilocode/pull/13263) [`27ba156`](https://github.com/Kilo-Org/kilocode/commit/27ba156ce129bf86b4fd548c7d0246f51339cb4e) - Use the remote's current default branch for diff totals and new worktrees when local Git metadata still points to a retired trunk. + +- [#12542](https://github.com/Kilo-Org/kilocode/pull/12542) [`5d713f7`](https://github.com/Kilo-Org/kilocode/commit/5d713f7d9602db301452292d20f83b87c22f6a30) Thanks [@Githubguy132010](https://github.com/Githubguy132010)! - Remove installed agents from every writable configuration source and report removal failures. + +- [#13175](https://github.com/Kilo-Org/kilocode/pull/13175) [`ae26eed`](https://github.com/Kilo-Org/kilocode/commit/ae26eed9b14741dede333c4093ded1281cb73c0b) - Keep provider names out of the compact prompt model selector label while retaining them in the expanded picker. + +- [#13209](https://github.com/Kilo-Org/kilocode/pull/13209) [`ff16bc2`](https://github.com/Kilo-Org/kilocode/commit/ff16bc2c9c25d4f11af5303cd79267546456cb1e) - Keep Agent Manager terminals and nested Kilo sessions alive across configuration reloads and location idle eviction, while cleaning them up on explicit close, worktree deletion, and server shutdown. + +- [#13162](https://github.com/Kilo-Org/kilocode/pull/13162) [`8ad3f90`](https://github.com/Kilo-Org/kilocode/commit/8ad3f9088989c234c8161d0f820a501e3a33ffc4) - Use NVIDIA Parakeet TDT 0.6B v3 as the default speech-to-text model while retaining dynamic model discovery and offline fallback support. + +- [#13183](https://github.com/Kilo-Org/kilocode/pull/13183) [`017410b`](https://github.com/Kilo-Org/kilocode/commit/017410bf6fbfdaa1e3a050f00f7e0cd3dd5371ad) - Accept JWT share tokens when importing a session from a Kilo share URL. + +- [#13196](https://github.com/Kilo-Org/kilocode/pull/13196) [`b4c8387`](https://github.com/Kilo-Org/kilocode/commit/b4c83878e94be07d2f7b9f7c219635ee76792ee0) - Fix Agent Manager PR and base-branch worktrees when a repository uses a restrictive Git fetch refspec. + +- [#13264](https://github.com/Kilo-Org/kilocode/pull/13264) [`10b73a4`](https://github.com/Kilo-Org/kilocode/commit/10b73a4ca722cea7f18d021b579e30a63cdff354) - Prevent invalid GitHub check timestamps from displaying incorrect PR durations. + +- [#13261](https://github.com/Kilo-Org/kilocode/pull/13261) [`ab08cba`](https://github.com/Kilo-Org/kilocode/commit/ab08cbaa03683e6bef969ce18a5f7cd32af43beb) - Keep Agent Manager subagent inspector tabs aligned with the selected session and worktree. + +- [#13168](https://github.com/Kilo-Org/kilocode/pull/13168) [`ba2e20a`](https://github.com/Kilo-Org/kilocode/commit/ba2e20a87dead59858b2af5c6b63d8fd81eac798) - Restore incremental assistant text streaming across Kilo chat surfaces. + +- [#13246](https://github.com/Kilo-Org/kilocode/pull/13246) [`efa48c8`](https://github.com/Kilo-Org/kilocode/commit/efa48c8cda9e81cdc1dccc841f1bd237976428c2) - Keep tool-output action buttons visible above streamed output. + +- [#13262](https://github.com/Kilo-Org/kilocode/pull/13262) [`5300ce5`](https://github.com/Kilo-Org/kilocode/commit/5300ce51f3e0fcaebc1068dc57f467a86083b006) - Use the displayed current branch as the base when creating a worktree from the New Worktree dialog. + +- [#13158](https://github.com/Kilo-Org/kilocode/pull/13158) [`c4dcb3d`](https://github.com/Kilo-Org/kilocode/commit/c4dcb3d225feb571c71b08c85f129aba5600dc3e) - Keep file mention suggestions current and scoped to the active workspace while preserving instant cached results. + +- [#11728](https://github.com/Kilo-Org/kilocode/pull/11728) [`2246ef7`](https://github.com/Kilo-Org/kilocode/commit/2246ef70b55b93db9b84cb8a6a9e1ae9dbc29fa2) Thanks [@rakshith1928](https://github.com/rakshith1928)! - Typing extra text after the `/memory show` command (for example `/memory show my notes`) used to clear that text from the chat input when the command ran. The text now stays in the input so you don't lose what you typed. + +- [#13156](https://github.com/Kilo-Org/kilocode/pull/13156) [`be8b85c`](https://github.com/Kilo-Org/kilocode/commit/be8b85c8ce5222edd94d9fa5b8cbe11136e06d5a) - Optimize Agent Manager tab switching and context transition latency + +- [#13154](https://github.com/Kilo-Org/kilocode/pull/13154) [`5b06d7d`](https://github.com/Kilo-Org/kilocode/commit/5b06d7dea047795b882ead9896902bcf3d0bf4ea) - Optimize large session loading performance and reduce reactive re-render overhead in the webview. + +- [#13155](https://github.com/Kilo-Org/kilocode/pull/13155) [`f9df66c`](https://github.com/Kilo-Org/kilocode/commit/f9df66c9c57ec6346782c7062f328ea881f05734) - Optimize TaskHeader and timeline bar calculation performance in the webview. + +- [#13201](https://github.com/Kilo-Org/kilocode/pull/13201) [`bee6fb3`](https://github.com/Kilo-Org/kilocode/commit/bee6fb3b237ff5be73d76eba9d69ec7237cebcc5) - Keep the Allow and Deny buttons reachable when a permission prompt contains a large diff or a long command: the prompt now scrolls its own content and shrinks with the available chat height instead of pushing its buttons out of view + +- [#13213](https://github.com/Kilo-Org/kilocode/pull/13213) [`3793736`](https://github.com/Kilo-Org/kilocode/commit/3793736c82feae46b462ed9195d3b1253387f6bd) - Render Agent Manager pull request comment diffs with the Pierre-backed diff viewer and syntax highlighting. + +- [#13174](https://github.com/Kilo-Org/kilocode/pull/13174) [`60aee11`](https://github.com/Kilo-Org/kilocode/commit/60aee1118e24f7fc27a6bb6f1df114bc9f5d702b) - Preserve cached reasoning variants when starting new VS Code sessions. + +- [#13194](https://github.com/Kilo-Org/kilocode/pull/13194) [`af158e6`](https://github.com/Kilo-Org/kilocode/commit/af158e6156f6906e6e34846afe9bbe6e7679f246) - Prevent subagent descriptions from appearing as Agent Manager worktree titles. + +- [#13222](https://github.com/Kilo-Org/kilocode/pull/13222) [`26a9c44`](https://github.com/Kilo-Org/kilocode/commit/26a9c44f63ef10f545c36b67651cda0b0c4d1036) - Remove the separate trust action from Agent Manager multi-project repositories. Added projects are now immediately available, while VS Code workspace trust still protects setup and run scripts. + +- [#13225](https://github.com/Kilo-Org/kilocode/pull/13225) [`da10638`](https://github.com/Kilo-Org/kilocode/commit/da1063865480bb7cd2aeeb8c18a949a805bd4872) - Remove the experimental agent requirements check and its configuration flag. + +- [#13226](https://github.com/Kilo-Org/kilocode/pull/13226) [`ba45731`](https://github.com/Kilo-Org/kilocode/commit/ba4573185031583079ffff9c2b4c8c2f1112e6ba) - Remove the floating scroll-to-top button from the Agent Manager PR sidebar. + +- [#13214](https://github.com/Kilo-Org/kilocode/pull/13214) [`e1bcb32`](https://github.com/Kilo-Org/kilocode/commit/e1bcb320d94efe6ed8abf7c33fe6475a67a2e1e7) - Remove the experimental task-aware tool-output pruning feature and its related settings and indicators. + +- [#13167](https://github.com/Kilo-Org/kilocode/pull/13167) [`bc395d6`](https://github.com/Kilo-Org/kilocode/commit/bc395d6b40962ed8c0b4e4cdd0bb42ea20612cba) - Restore live Git change statistics on the Agent Manager diff toggle for local and worktree selections. + +- [#13236](https://github.com/Kilo-Org/kilocode/pull/13236) [`dd8947a`](https://github.com/Kilo-Org/kilocode/commit/dd8947abb5b5a11a49aa75be6f6d60312ee76bbc) - Ensure interactive terminal state is isolated per directory and cleaned up when its scope closes. + +- [#13142](https://github.com/Kilo-Org/kilocode/pull/13142) [`f8dce5b`](https://github.com/Kilo-Org/kilocode/commit/f8dce5b457474800f89a38ed69aa0ade380ccf80) Thanks [@hdcodedev](https://github.com/hdcodedev)! - Fix agent mode switch getting stuck on draft/cloud-import sessions: apply the explicitly selected agent instead of reverting to the stale session agent. + +- [#13177](https://github.com/Kilo-Org/kilocode/pull/13177) [`3387172`](https://github.com/Kilo-Org/kilocode/commit/3387172a5380ccd0239d494f55a92eba00891ae1) - Show the model provider next to every model in the model selector. + +- [#13176](https://github.com/Kilo-Org/kilocode/pull/13176) [`f1909f9`](https://github.com/Kilo-Org/kilocode/commit/f1909f9c4e5a74f367df9d10ad8b1e17f44d2b65) - Keep queued prompts visible while the server confirms and loads their message parts. + +- [#13164](https://github.com/Kilo-Org/kilocode/pull/13164) [`181363e`](https://github.com/Kilo-Org/kilocode/commit/181363e1d148cce9229365bc20f77ecf1c912101) - Show token throughput by default, with a Display setting to hide it when needed. + +- [#11728](https://github.com/Kilo-Org/kilocode/pull/11728) [`2246ef7`](https://github.com/Kilo-Org/kilocode/commit/2246ef70b55b93db9b84cb8a6a9e1ae9dbc29fa2) Thanks [@rakshith1928](https://github.com/rakshith1928)! - Preserve existing text when selecting a slash command at the start of the chat input. Previously, typing `/new` or another slash command with text before the cursor would wipe the existing content entirely. + +- [#13231](https://github.com/Kilo-Org/kilocode/pull/13231) [`c995fd1`](https://github.com/Kilo-Org/kilocode/commit/c995fd1ae7b0e4ed47be729edcc9c07347c867d4) - Keep the conversation from shifting when a turn starts or finishes. The working indicator and the session actions now share one row above the composer that keeps its height in both states, instead of resizing two separate areas. + +- [#13270](https://github.com/Kilo-Org/kilocode/pull/13270) [`10b6701`](https://github.com/Kilo-Org/kilocode/commit/10b67018693b75443dcc3b15912c91c085d8ae3b) - Keep the working indicator steady while the agent works: the status label now shimmers and glides into its new width instead of jumping the spinner sideways on every status change. + +- [#13229](https://github.com/Kilo-Org/kilocode/pull/13229) [`76d6ce3`](https://github.com/Kilo-Org/kilocode/commit/76d6ce3e7e96f7c4c0be323e9059353c3d8a89ae) - Make Agent Manager shortcuts follow the focused area. In the center, Cmd/Ctrl+T creates a new session tab and Cmd/Ctrl+Shift+T creates a central terminal tab, whether the prompt or a central terminal is focused. In the right sidebar terminal, Cmd/Ctrl+T creates another sidebar terminal tab and Cmd/Ctrl+Shift+T does nothing. Returning from a terminal with Cmd/Ctrl+Shift+M restores the previous session tab before focusing its prompt. Update the shortcut dialog and hints to show the distinct actions. + +- [#13265](https://github.com/Kilo-Org/kilocode/pull/13265) [`8461a2f`](https://github.com/Kilo-Org/kilocode/commit/8461a2f7762687886d8284c49eb17ed137091969) - Bootstrap missing locked workspace dependencies before building the extension from an Agent Manager worktree. + +- [#13179](https://github.com/Kilo-Org/kilocode/pull/13179) [`2477bde`](https://github.com/Kilo-Org/kilocode/commit/2477bde2c25e46a46489be436de0c332f195837b) - Open `/sessions` on a git worktree with the Worktree history filter selected by default. + +- Updated dependencies [[`97abdab`](https://github.com/Kilo-Org/kilocode/commit/97abdab66cf0bc01c8f3364e5f640dadde15b7d3), [`cba6ebc`](https://github.com/Kilo-Org/kilocode/commit/cba6ebc6fa7ba313bc0aae51550389626621d9c5), [`f39e163`](https://github.com/Kilo-Org/kilocode/commit/f39e1631855859222966350bd5fae373b9877297), [`e1bcb32`](https://github.com/Kilo-Org/kilocode/commit/e1bcb320d94efe6ed8abf7c33fe6475a67a2e1e7)]: + - @opencode-ai/core@7.4.23 + - @kilocode/kilo-ui@7.4.23 + - @kilocode/kilo-gateway@8.0.0 + - @opencode-ai/ui@7.4.23 + - @kilocode/kilo-indexing@7.4.23 + ## 7.4.22 ### Minor Changes - - [#11219](https://github.com/Kilo-Org/kilocode/pull/11219) [`8013e5f`](https://github.com/Kilo-Org/kilocode/commit/8013e5f50451225bb32b1284579322c137f497e3) Thanks [@sylwester-liljegren](https://github.com/sylwester-liljegren)! - Make file references in agent responses clickable by validating inline code spans against the filesystem. Code spans that match real files in the workspace become clickable links that open the file at the referenced line. Non-existent paths stay as plain code. Also adds fallback workspace search and "File not found" warning when clicking dead links. - [#13071](https://github.com/Kilo-Org/kilocode/pull/13071) [`3e3dd3d`](https://github.com/Kilo-Org/kilocode/commit/3e3dd3dcb2a711192ec2477ef7c0532b11f67886) Thanks [@cosi-conda](https://github.com/cosi-conda)! - Add Agent Manager PR comment actions: resolve/unresolve review threads, jump to comments section, and scroll-to-top for PR diff view. diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 5e33b35d27..5b938177b2 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -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.4.22", + "version": "7.4.23", "icon": "assets/icons/logo-outline-black.png", "galleryBanner": { "color": "#FFFFFF", diff --git a/packages/kilo-vscode/tests/package.json b/packages/kilo-vscode/tests/package.json index 8ef1cf455e..b9e172a0ea 100644 --- a/packages/kilo-vscode/tests/package.json +++ b/packages/kilo-vscode/tests/package.json @@ -1,6 +1,6 @@ { "type": "module", - "version": "7.4.22", + "version": "7.4.23", "dependencies": {}, "devDependencies": {}, "peerDependencies": {} diff --git a/packages/kilo-web-ui/package.json b/packages/kilo-web-ui/package.json index 57f38a12d6..9df29e27d7 100644 --- a/packages/kilo-web-ui/package.json +++ b/packages/kilo-web-ui/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/kilo-web-ui", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "exports": { diff --git a/packages/llm/package.json b/packages/llm/package.json index 02b3d922f8..dd2e356c1f 100644 --- a/packages/llm/package.json +++ b/packages/llm/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.4.22", + "version": "7.4.23", "name": "@opencode-ai/llm", "type": "module", "license": "MIT", diff --git a/packages/opencode/CHANGELOG.md b/packages/opencode/CHANGELOG.md index 619e66b2fc..4d3a326f22 100644 --- a/packages/opencode/CHANGELOG.md +++ b/packages/opencode/CHANGELOG.md @@ -1,5 +1,61 @@ # @kilocode/cli +## 7.4.23 + +### Minor Changes + +- [#13137](https://github.com/Kilo-Org/kilocode/pull/13137) [`90a93a7`](https://github.com/Kilo-Org/kilocode/commit/90a93a7aa25950d5894fa67f6e4e6545ef55017c) - Add `kilo pr link `, `kilo pr unlink`, and `kilo pr status` to link the current worktree to a pull request. The checkout command moves to `kilo pr checkout `; `kilo pr ` no longer checks out a PR. + +### Patch Changes + +- [#13206](https://github.com/Kilo-Org/kilocode/pull/13206) [`e13c6d3`](https://github.com/Kilo-Org/kilocode/commit/e13c6d3ee93d123c6fc187592fc28324c8840fc2) - Fix Agent Manager ignoring requests to start new sessions on OpenAI Responses API models, where a start request was answered with a list of existing sessions instead of creating the worktree or session. + +- [#13124](https://github.com/Kilo-Org/kilocode/pull/13124) [`d4f3a3a`](https://github.com/Kilo-Org/kilocode/commit/d4f3a3a9e63a3954214887563dc3816ea179858f) - Stop broad permission rules from letting Ask and Plan modes change your workspace. Catch-all approvals, the "Allow everything" toggle, and the ` *` rules that "Always allow" persists no longer grant these modes shell commands, subagents, notebook edits or other mutating tools, and MCP tools go back to prompting. To opt a single mode in, set `agent.ask.permission` or `agent.plan.permission` instead of a top-level `permission` rule. + +- [#13121](https://github.com/Kilo-Org/kilocode/pull/13121) [`e2966ab`](https://github.com/Kilo-Org/kilocode/commit/e2966abcba4906383d13b385d61ecd50016e4d7d) - Keep the selected agent after switching from Ask to Code, and remind the model that previous Ask-mode restrictions no longer apply. + +- [#13224](https://github.com/Kilo-Org/kilocode/pull/13224) [`b1755f9`](https://github.com/Kilo-Org/kilocode/commit/b1755f91848b083533e675ba38750063862344d4) - Keep one-time waits in the blocking shell tool instead of tracking them as background processes. + +- [#13209](https://github.com/Kilo-Org/kilocode/pull/13209) [`ff16bc2`](https://github.com/Kilo-Org/kilocode/commit/ff16bc2c9c25d4f11af5303cd79267546456cb1e) - Keep Agent Manager terminals and nested Kilo sessions alive across configuration reloads and location idle eviction, while cleaning them up on explicit close, worktree deletion, and server shutdown. + +- [#13115](https://github.com/Kilo-Org/kilocode/pull/13115) [`d9f0eff`](https://github.com/Kilo-Org/kilocode/commit/d9f0eff30634410738c82355641b4e6353c135bb) - Start Kilo with a persistent fallback when the default runtime state directory is not writable. + +- [#13210](https://github.com/Kilo-Org/kilocode/pull/13210) [`8d717a0`](https://github.com/Kilo-Org/kilocode/commit/8d717a05d322a2382af05d8265ec2354c893a674) - Remove the duplicate skill catalog from the model-facing skill tool description. + +- [#13183](https://github.com/Kilo-Org/kilocode/pull/13183) [`017410b`](https://github.com/Kilo-Org/kilocode/commit/017410bf6fbfdaa1e3a050f00f7e0cd3dd5371ad) - Accept JWT share tokens when importing a session from a Kilo share URL. + +- [#13165](https://github.com/Kilo-Org/kilocode/pull/13165) [`5e6e93a`](https://github.com/Kilo-Org/kilocode/commit/5e6e93aa19e984d8699d1a3199b49f8e726e899c) - Use the full Codex context window for GPT-5.6 models authenticated through ChatGPT OAuth. + +- [#13249](https://github.com/Kilo-Org/kilocode/pull/13249) [`3de7df2`](https://github.com/Kilo-Org/kilocode/commit/3de7df279bceab97fc1fd75eb0a9e45e735c472d) - Require the todo tool to update multi-step lists after each completed task. + +- [#13122](https://github.com/Kilo-Org/kilocode/pull/13122) [`c34a2a3`](https://github.com/Kilo-Org/kilocode/commit/c34a2a3a42f9f07d6ae2643ec655720bdb84c820) - Stop memory auto-save from failing on OpenAI-compatible providers that stream by default. + +- [#13195](https://github.com/Kilo-Org/kilocode/pull/13195) [`f54c215`](https://github.com/Kilo-Org/kilocode/commit/f54c215e6ab2f22e055790ccc4a2d122992dba48) Thanks [@quanzhuo](https://github.com/quanzhuo)! - Persist disabling snapshots from the slow-repo prompt across restarts. + +- [#13112](https://github.com/Kilo-Org/kilocode/pull/13112) [`2eb6300`](https://github.com/Kilo-Org/kilocode/commit/2eb630053f5bb822eb6a2b9e830afecfd0f6163c) - Switch to the code model when starting implementation after a planning session. + +- [#13225](https://github.com/Kilo-Org/kilocode/pull/13225) [`da10638`](https://github.com/Kilo-Org/kilocode/commit/da1063865480bb7cd2aeeb8c18a949a805bd4872) - Remove the experimental agent requirements check and its configuration flag. + +- [#13214](https://github.com/Kilo-Org/kilocode/pull/13214) [`e1bcb32`](https://github.com/Kilo-Org/kilocode/commit/e1bcb320d94efe6ed8abf7c33fe6475a67a2e1e7) - Remove the experimental task-aware tool-output pruning feature and its related settings and indicators. + +- [#13199](https://github.com/Kilo-Org/kilocode/pull/13199) [`6131ed2`](https://github.com/Kilo-Org/kilocode/commit/6131ed269f37ae8e258c1b91929c3170a4cf2767) - Keep `kilo upgrade` on the Kilo CLI release channel when GitHub's latest release is a JetBrains release. + +- [#13178](https://github.com/Kilo-Org/kilocode/pull/13178) [`86af8dd`](https://github.com/Kilo-Org/kilocode/commit/86af8dd7c700fcb6229f28471126b5e7b0f6f654) - Prompt for explicit, one-shot approval before mutating Git commands run outside the sandbox. + +- [#13103](https://github.com/Kilo-Org/kilocode/pull/13103) [`591772d`](https://github.com/Kilo-Org/kilocode/commit/591772d92875762460636b42233ad1ad552e8596) - Use provider model catalogs instead of hardcoded model-name heuristics for reasoning variants. + +- [#13170](https://github.com/Kilo-Org/kilocode/pull/13170) [`3acb1ec`](https://github.com/Kilo-Org/kilocode/commit/3acb1ec38693e7f75bb38e832a23ace097c7440a) - Keep recently used Kilo Gateway models visible in the TUI picker, and find them when filtering by kilo. + +- [#13247](https://github.com/Kilo-Org/kilocode/pull/13247) [`0d5d334`](https://github.com/Kilo-Org/kilocode/commit/0d5d334480bc2093a12b27a34b03cac88cf33422) - Fix TUI sessions where new turns stopped appearing until the session was reopened + +- Updated dependencies [[`f39e163`](https://github.com/Kilo-Org/kilocode/commit/f39e1631855859222966350bd5fae373b9877297)]: + - @kilocode/kilo-gateway@8.0.0 + - @opencode-ai/server@7.4.23 + - @opencode-ai/tui@7.4.23 + - @opencode-ai/ui@7.4.23 + - @kilocode/kilo-indexing@7.4.23 + - @kilocode/kilo-telemetry@7.4.23 + ## 7.4.22 ### Minor Changes diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 4a6b8c9f66..c0071a984a 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "7.4.22", + "version": "7.4.23", "name": "@kilocode/cli", "type": "module", "license": "MIT", diff --git a/packages/plugin-atomic-chat/package.json b/packages/plugin-atomic-chat/package.json index f73579b55d..2f2bbbf759 100644 --- a/packages/plugin-atomic-chat/package.json +++ b/packages/plugin-atomic-chat/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/plugin-atomic-chat", - "version": "7.4.22", + "version": "7.4.23", "description": "Kilo Code plugin for Atomic Chat: auto-detection and dynamic model discovery (OpenAI-compatible local API)", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index cda5c215c0..2e2e5e1d0a 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/plugin", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/protocol/package.json b/packages/protocol/package.json index 396e2d4da8..9d65864d3b 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -19,5 +19,5 @@ "@types/bun": "catalog:", "@typescript/native-preview": "catalog:" }, - "version": "7.4.22" + "version": "7.4.23" } diff --git a/packages/schema/package.json b/packages/schema/package.json index ce0dd8c07b..90481587f6 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -19,5 +19,5 @@ "@types/bun": "catalog:", "@typescript/native-preview": "catalog:" }, - "version": "7.4.22" + "version": "7.4.23" } diff --git a/packages/script/package.json b/packages/script/package.json index 4cb5f00a0e..9aee69b3a6 100644 --- a/packages/script/package.json +++ b/packages/script/package.json @@ -12,6 +12,6 @@ "exports": { ".": "./src/index.ts" }, - "version": "7.4.22", + "version": "7.4.23", "peerDependencies": {} } diff --git a/packages/sdk-next/package.json b/packages/sdk-next/package.json index 66efb5d136..411676544e 100644 --- a/packages/sdk-next/package.json +++ b/packages/sdk-next/package.json @@ -23,5 +23,5 @@ "@types/bun": "catalog:", "@typescript/native-preview": "catalog:" }, - "version": "7.4.22" + "version": "7.4.23" } diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 74af1b864e..dd504ea6f3 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/sdk", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index d49cf76b2d..05a03b90ae 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/server", - "version": "7.4.22", + "version": "7.4.23", "private": true, "type": "module", "license": "MIT", diff --git a/packages/session-ui/package.json b/packages/session-ui/package.json index 68f605afd9..9e700347ac 100644 --- a/packages/session-ui/package.json +++ b/packages/session-ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/session-ui", - "version": "7.4.22", + "version": "7.4.23", "private": true, "type": "module", "license": "MIT", diff --git a/packages/storybook/package.json b/packages/storybook/package.json index 78af204a97..3c726f6295 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -28,7 +28,7 @@ "@opencode-ai/session-ui": "workspace:*", "react-dom": "18.2.0" }, - "version": "7.4.22", + "version": "7.4.23", "dependencies": {}, "peerDependencies": {} } diff --git a/packages/tui/package.json b/packages/tui/package.json index 85bc479f0f..3ce311fbe2 100644 --- a/packages/tui/package.json +++ b/packages/tui/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/tui", - "version": "7.4.22", + "version": "7.4.23", "private": true, "type": "module", "license": "MIT", diff --git a/packages/ui/package.json b/packages/ui/package.json index c5fb53ed5f..752ea70ed0 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "7.4.22", + "version": "7.4.23", "type": "module", "license": "MIT", "repository": { diff --git a/script/upstream/package.json b/script/upstream/package.json index 37b0a8f4e6..1705aea7ae 100644 --- a/script/upstream/package.json +++ b/script/upstream/package.json @@ -1,6 +1,6 @@ { "name": "@kilocode/upstream-merge", - "version": "7.4.22", + "version": "7.4.23", "private": true, "type": "module", "description": "Scripts for automating upstream opencode merges into Kilo",