diff --git a/.changeset/fix-secondary-sidebar-nav-bar.md b/.changeset/fix-secondary-sidebar-nav-bar.md deleted file mode 100644 index 070b89d5f80..00000000000 --- a/.changeset/fix-secondary-sidebar-nav-bar.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"kilo-code": patch ---- - -Fix the sidebar navigation bar (New Task, History, Agent Manager, KiloClaw, Marketplace, Profile, Settings) disappearing when the Kilo Code view is docked in the Secondary Side Bar. The navigation is now rendered inside the webview itself, so it stays visible regardless of where the view is docked. diff --git a/bun.lock b/bun.lock index 9e1efe75bf4..0f1a05b52c8 100644 --- a/bun.lock +++ b/bun.lock @@ -444,7 +444,6 @@ "@opencode-ai/ui": "workspace:*", "@pierre/diffs": "catalog:", "@thisbeyond/solid-dnd": "0.7.5", - "@vscode/codicons": "^0.0.44", "@xterm/addon-clipboard": "0.2.0", "@xterm/addon-fit": "0.11.0", "@xterm/addon-unicode-graphemes": "0.4.0", diff --git a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/sidebar-top-bar-default-chromium-linux.png b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/sidebar-top-bar-default-chromium-linux.png deleted file mode 100644 index d5298111b8c..00000000000 --- a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/sidebar-top-bar-default-chromium-linux.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1bc2a28b80d8dc5aea4c03609efc13a23a2c88103e56df741155d9e794fc96f7 -size 2422 diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 1ce8210b661..1870f7eab10 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -141,6 +141,41 @@ "category": "Kilo Code", "icon": "$(settings-gear)" }, + { + "command": "kilo-code.new.sidebarTitle.plusButtonClicked", + "title": "New Task", + "icon": "$(add)" + }, + { + "command": "kilo-code.new.sidebarTitle.agentManagerOpen", + "title": "Agent Manager", + "icon": "$(organization)" + }, + { + "command": "kilo-code.new.sidebarTitle.kiloClawOpen", + "title": "KiloClaw", + "icon": "$(comment-discussion)" + }, + { + "command": "kilo-code.new.sidebarTitle.marketplaceButtonClicked", + "title": "Marketplace", + "icon": "$(extensions)" + }, + { + "command": "kilo-code.new.sidebarTitle.historyButtonClicked", + "title": "History", + "icon": "$(history)" + }, + { + "command": "kilo-code.new.sidebarTitle.profileButtonClicked", + "title": "Profile", + "icon": "$(account)" + }, + { + "command": "kilo-code.new.sidebarTitle.settingsButtonClicked", + "title": "Settings", + "icon": "$(settings-gear)" + }, { "command": "kilo-code.new.openInTab", "title": "Open in Tab", @@ -436,12 +471,76 @@ ], "menus": { "commandPalette": [ + { + "command": "kilo-code.new.sidebarTitle.plusButtonClicked", + "when": "false" + }, + { + "command": "kilo-code.new.sidebarTitle.historyButtonClicked", + "when": "false" + }, + { + "command": "kilo-code.new.sidebarTitle.agentManagerOpen", + "when": "false" + }, + { + "command": "kilo-code.new.sidebarTitle.kiloClawOpen", + "when": "false" + }, { "command": "kilo-code.new.agentManager.advancedWorktree", "when": "false" + }, + { + "command": "kilo-code.new.sidebarTitle.marketplaceButtonClicked", + "when": "false" + }, + { + "command": "kilo-code.new.sidebarTitle.profileButtonClicked", + "when": "false" + }, + { + "command": "kilo-code.new.sidebarTitle.settingsButtonClicked", + "when": "false" + } + ], + "view/title": [ + { + "command": "kilo-code.new.sidebarTitle.plusButtonClicked", + "group": "navigation@0", + "when": "view == kilo-code.SidebarProvider" + }, + { + "command": "kilo-code.new.sidebarTitle.historyButtonClicked", + "group": "navigation@1", + "when": "view == kilo-code.SidebarProvider" + }, + { + "command": "kilo-code.new.sidebarTitle.agentManagerOpen", + "group": "navigation@2", + "when": "view == kilo-code.SidebarProvider" + }, + { + "command": "kilo-code.new.sidebarTitle.kiloClawOpen", + "group": "navigation@3", + "when": "view == kilo-code.SidebarProvider" + }, + { + "command": "kilo-code.new.sidebarTitle.marketplaceButtonClicked", + "group": "navigation@4", + "when": "view == kilo-code.SidebarProvider" + }, + { + "command": "kilo-code.new.sidebarTitle.profileButtonClicked", + "group": "navigation@5", + "when": "view == kilo-code.SidebarProvider" + }, + { + "command": "kilo-code.new.sidebarTitle.settingsButtonClicked", + "group": "navigation@6", + "when": "view == kilo-code.SidebarProvider" } ], - "view/title": [], "scm/title": [ { "command": "kilo-code.new.generateCommitMessage", @@ -461,6 +560,26 @@ "command": "kilo-code.new.openInTab", "group": "navigation", "when": "true" + }, + { + "command": "kilo-code.new.plusButtonClicked", + "group": "navigation@0", + "when": "activeWebviewPanelId == kilo-code.new.TabPanel" + }, + { + "command": "kilo-code.new.historyButtonClicked", + "group": "navigation@1", + "when": "activeWebviewPanelId == kilo-code.new.TabPanel" + }, + { + "command": "kilo-code.new.profileButtonClicked", + "group": "navigation@2", + "when": "activeWebviewPanelId == kilo-code.new.TabPanel" + }, + { + "command": "kilo-code.new.settingsButtonClicked", + "group": "navigation@3", + "when": "activeWebviewPanelId == kilo-code.new.TabPanel" } ], "editor/context": [ @@ -1179,7 +1298,6 @@ "@opencode-ai/ui": "workspace:*", "@pierre/diffs": "catalog:", "@thisbeyond/solid-dnd": "0.7.5", - "@vscode/codicons": "^0.0.44", "@xterm/addon-clipboard": "0.2.0", "@xterm/addon-fit": "0.11.0", "@xterm/addon-unicode-graphemes": "0.4.0", diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index 15e8ec95749..1b9a9a5244e 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -1048,7 +1048,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper openAdvancedWorktree: () => vscode.commands.executeCommand("kilo-code.new.agentManager.advancedWorktree"), openChanges: (sessionId?: string, turnId?: string) => vscode.commands.executeCommand("kilo-code.new.showChanges", { sessionId, turnId }), - openProfile: () => vscode.commands.executeCommand("kilo-code.new.profileButtonClicked"), currentSessionId: this.currentSession?.id, createWorktree: async (baseBranch, branchName) => { await this.createWorktreeHandler?.(baseBranch, branchName) @@ -4909,8 +4908,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper title: "Kilo Code", port: this.connectionService.getServerInfo()?.port, extraStyles: `.container { height: 100vh; }`, - topBar: this.opts.hideTopBar !== true, - topBarSurface: this.opts.topBarSurface === "tab" ? "tab_title" : "sidebar_title", }) } diff --git a/packages/kilo-vscode/src/SettingsEditorProvider.ts b/packages/kilo-vscode/src/SettingsEditorProvider.ts index f03657921a8..84dc741d6d2 100644 --- a/packages/kilo-vscode/src/SettingsEditorProvider.ts +++ b/packages/kilo-vscode/src/SettingsEditorProvider.ts @@ -103,7 +103,6 @@ export class SettingsEditorProvider implements vscode.Disposable { // backend connectivity (config, providers, agents, profile, auth). const provider = new KiloProvider(this.extensionUri, this.connectionService, this.context, { projectDirectory, - hideTopBar: true, }) if (this.remoteService) { provider.setRemoteService(this.remoteService) diff --git a/packages/kilo-vscode/src/SubAgentViewerProvider.ts b/packages/kilo-vscode/src/SubAgentViewerProvider.ts index 11dfd75e8ef..e1693cc18bb 100644 --- a/packages/kilo-vscode/src/SubAgentViewerProvider.ts +++ b/packages/kilo-vscode/src/SubAgentViewerProvider.ts @@ -41,7 +41,7 @@ export class SubAgentViewerProvider implements vscode.Disposable { dark: vscode.Uri.joinPath(this.extensionUri, "assets", "icons", "kilo-dark.svg"), } - const provider = new KiloProvider(this.extensionUri, this.connectionService, this.context, { hideTopBar: true }) + const provider = new KiloProvider(this.extensionUri, this.connectionService, this.context) // Start accepting this session's SSE events as soon as the panel subscribes. // Reasoning deltas are not persisted until the reasoning part finishes. provider.trackSession(sessionID) diff --git a/packages/kilo-vscode/src/extension.ts b/packages/kilo-vscode/src/extension.ts index 43843650dd4..4803e15c6e5 100644 --- a/packages/kilo-vscode/src/extension.ts +++ b/packages/kilo-vscode/src/extension.ts @@ -17,7 +17,7 @@ import { ensureBackendForAutocomplete } from "./services/autocomplete/ensure-bac import { AutocompleteServiceManager } from "./services/autocomplete/AutocompleteServiceManager" import { AttentionService } from "./services/attention" import { BrowserAutomationService } from "./services/browser-automation" -import { TelemetryProxy } from "./services/telemetry" +import { TelemetryEventName, TelemetryProxy } from "./services/telemetry" import { registerCommitMessageService } from "./services/commit-message" import { registerCodeActions, registerTerminalActions, KiloCodeActionProvider } from "./services/code-actions" import { registerToggleAutoApprove } from "./commands/toggle-auto-approve" @@ -237,7 +237,6 @@ export function activate(context: vscode.ExtensionContext) { deserializeWebviewPanel(panel: vscode.WebviewPanel) { const tabProvider = new KiloProvider(context.extensionUri, connectionService, context, { tabTitle: panelTitleHandler(panel), - topBarSurface: "tab", }) tabProvider.setRemoteService(remoteService) tabProvider.setAutoApproveController(autoApprove) @@ -339,8 +338,39 @@ export function activate(context: vscode.ExtensionContext) { }), ) + // Sidebar menus use wrapper commands so this event measures real title button presses, + // not programmatic opens, shortcuts, or editor title commands. + const track = (button: string, command: string) => { + TelemetryProxy.capture(TelemetryEventName.TITLE_BUTTON_CLICKED, { + button, + surface: "sidebar_title", + }) + void vscode.commands.executeCommand(command) + } + // Register toolbar button command handlers context.subscriptions.push( + vscode.commands.registerCommand("kilo-code.new.sidebarTitle.plusButtonClicked", () => { + track("new_task", "kilo-code.new.plusButtonClicked") + }), + vscode.commands.registerCommand("kilo-code.new.sidebarTitle.historyButtonClicked", () => { + track("history", "kilo-code.new.historyButtonClicked") + }), + vscode.commands.registerCommand("kilo-code.new.sidebarTitle.agentManagerOpen", () => { + track("agent_manager", "kilo-code.new.agentManagerOpen") + }), + vscode.commands.registerCommand("kilo-code.new.sidebarTitle.kiloClawOpen", () => { + track("kiloclaw", "kilo-code.new.kiloClawOpen") + }), + vscode.commands.registerCommand("kilo-code.new.sidebarTitle.marketplaceButtonClicked", () => { + track("marketplace", "kilo-code.new.marketplaceButtonClicked") + }), + vscode.commands.registerCommand("kilo-code.new.sidebarTitle.profileButtonClicked", () => { + track("profile", "kilo-code.new.profileButtonClicked") + }), + vscode.commands.registerCommand("kilo-code.new.sidebarTitle.settingsButtonClicked", () => { + track("settings", "kilo-code.new.settingsButtonClicked") + }), vscode.commands.registerCommand("kilo-code.new.plusButtonClicked", () => { const tab = activeTabProvider() if (tab) tab.postMessage({ type: "action", action: "plusButtonClicked" }) @@ -608,7 +638,6 @@ function openKiloInNewTab( const tabProvider = new KiloProvider(context.extensionUri, connectionService, context, { tabTitle: panelTitleHandler(panel), - topBarSurface: "tab", }) tabProvider.setRemoteService(remoteService) tabProvider.setAutoApproveController(autoApprove) diff --git a/packages/kilo-vscode/src/kilo-provider/options.ts b/packages/kilo-vscode/src/kilo-provider/options.ts index 0e23e9d8dbc..fcd8481bbe5 100644 --- a/packages/kilo-vscode/src/kilo-provider/options.ts +++ b/packages/kilo-vscode/src/kilo-provider/options.ts @@ -32,13 +32,4 @@ export type KiloProviderOptions = { * is ambiguous. */ projectQualifier?: () => { projectId: string } | undefined - /** - * Hides the in-webview sidebar top bar (New Task, History, Agent Manager, - * etc.) for dedicated single-purpose panels — Settings, Profile, and the - * Sub-Agent Viewer — where it doesn't apply and would let users navigate - * away from the panel's one job. Sidebar and "Open in Tab" leave this unset. - */ - hideTopBar?: boolean - /** Reports "Open in Tab" as the top bar's telemetry surface instead of the sidebar default. */ - topBarSurface?: "tab" } diff --git a/packages/kilo-vscode/src/kilo-provider/sidebar-worktree.ts b/packages/kilo-vscode/src/kilo-provider/sidebar-worktree.ts index 10963338214..dc4d54fe5b0 100644 --- a/packages/kilo-vscode/src/kilo-provider/sidebar-worktree.ts +++ b/packages/kilo-vscode/src/kilo-provider/sidebar-worktree.ts @@ -15,7 +15,6 @@ interface Ctx { openAgentManager: () => Thenable openAdvancedWorktree: () => Thenable openChanges: (sessionId?: string, turnId?: string) => Thenable - openProfile: () => Thenable currentSessionId?: string createWorktree?: (baseBranch?: string, branchName?: string) => Promise continueInWorktree?: ( @@ -60,11 +59,6 @@ export async function handleSidebarWorktreeMessage(message: Msg, ctx: Ctx) { return true } - if (message.type === "openProfilePanel") { - await ctx.openProfile() - return true - } - if (message.type !== "continueInWorktree") return false handleContinueInWorktree({ sessionId: message.sessionId, diff --git a/packages/kilo-vscode/src/utils.ts b/packages/kilo-vscode/src/utils.ts index 23479043e8b..fba6bb74b70 100644 --- a/packages/kilo-vscode/src/utils.ts +++ b/packages/kilo-vscode/src/utils.ts @@ -41,9 +41,6 @@ export function buildWebviewHtml( title: string port?: number extraStyles?: string - /** Sidebar top bar visibility and telemetry surface for the shared webview bundle (App.tsx). Unused by the Agent Manager bundle. */ - topBar?: boolean - topBarSurface?: string }, ): string { const nonce = getNonce() @@ -86,7 +83,7 @@ export function buildWebviewHtml(
- + ` diff --git a/packages/kilo-vscode/webview-ui/src/App.tsx b/packages/kilo-vscode/webview-ui/src/App.tsx index 6dc0e4da1c9..7fa356e8482 100644 --- a/packages/kilo-vscode/webview-ui/src/App.tsx +++ b/packages/kilo-vscode/webview-ui/src/App.tsx @@ -11,7 +11,6 @@ import { LocalTabsProvider, useLocalTabs } from "./context/local-tabs" import { ProviderShell } from "./context/provider-shell" import { ChatView } from "./components/chat" import { SidebarEmptyState } from "./components/chat/SidebarEmptyState" -import { SidebarTopBar } from "./components/chat/SidebarTopBar" import { registerExpandedTaskTool } from "./components/chat/TaskToolExpanded" import { registerVscodeToolOverrides } from "./components/chat/VscodeToolOverrides" @@ -309,23 +308,8 @@ const AppContent: Component = () => { setCurrentView("history")} /> ) - // Set synchronously in the webview HTML by KiloProvider so it's available - // before this component ever mounts (see buildWebviewHtml/_getHtmlForWebview). - // Dedicated single-purpose panels (Settings, Profile, Sub-Agent Viewer) set - // KILO_TOP_BAR = false since navigating away from them makes no sense. - const host = window as { KILO_TOP_BAR?: boolean; KILO_TOP_BAR_SURFACE?: string } - const showTopBar = host.KILO_TOP_BAR !== false - const topBarSurface = host.KILO_TOP_BAR_SURFACE ?? "sidebar_title" - return (
- - handleViewAction("plusButtonClicked")} - onHistory={() => handleViewAction("historyButtonClicked")} - surface={topBarSurface} - /> - {/* legacy-migration start — state-driven overlay, independent of currentView */} void - onHistory: () => void - /** Telemetry surface — distinguishes the sidebar from the "Open in Tab" panel, which shares this component. */ - surface: string -} - -/** Codicon names used below. */ -type Codicon = "add" | "history" | "organization" | "comment-discussion" | "extensions" | "account" | "settings-gear" - -interface Action { - key: string - codicon: Codicon - button: string - run: () => void -} - -export const SidebarTopBar: Component = (props) => { - const vscode = useVSCode() - const language = useLanguage() - - // Mirrors the telemetry the native toolbar buttons used to record, so analytics aren't lost. - const track = (button: string) => - vscode.postMessage({ - type: "telemetry", - event: TelemetryEventName.TITLE_BUTTON_CLICKED, - properties: { button, surface: props.surface }, - }) - - const open = ( - type: "openAgentManager" | "openKiloClaw" | "openMarketplacePanel" | "openProfilePanel" | "openSettingsPanel", - ) => vscode.postMessage({ type }) - - const actions: (Action | "spacer")[] = [ - { key: "newTask", codicon: "add", button: "new_task", run: () => props.onNewTask() }, - { key: "history", codicon: "history", button: "history", run: () => props.onHistory() }, - { key: "agentManager", codicon: "organization", button: "agent_manager", run: () => open("openAgentManager") }, - { key: "kiloClaw", codicon: "comment-discussion", button: "kiloclaw", run: () => open("openKiloClaw") }, - { key: "marketplace", codicon: "extensions", button: "marketplace", run: () => open("openMarketplacePanel") }, - "spacer", - { key: "profile", codicon: "account", button: "profile", run: () => open("openProfilePanel") }, - { key: "settings", codicon: "settings-gear", button: "settings", run: () => open("openSettingsPanel") }, - ] - - return ( -