From 573a660cc1026469338b2fabcff52b8012a4f78a Mon Sep 17 00:00:00 2001 From: Bruno Agatao Date: Wed, 5 Aug 2026 15:26:55 +0200 Subject: [PATCH 1/8] fix(vscode): keep sidebar navigation visible in the secondary side bar --- .changeset/fix-secondary-sidebar-nav-bar.md | 5 + packages/kilo-vscode/package.json | 121 +----------------- packages/kilo-vscode/src/KiloProvider.ts | 1 + packages/kilo-vscode/src/extension.ts | 33 +---- .../src/kilo-provider/sidebar-worktree.ts | 6 + packages/kilo-vscode/webview-ui/src/App.tsx | 5 + .../src/components/chat/SidebarTopBar.tsx | 88 +++++++++++++ .../kilo-vscode/webview-ui/src/i18n/en.ts | 8 ++ .../webview-ui/src/styles/chat-layout.css | 29 +++++ .../src/types/messages/webview-messages.ts | 5 + 10 files changed, 149 insertions(+), 152 deletions(-) create mode 100644 .changeset/fix-secondary-sidebar-nav-bar.md create mode 100644 packages/kilo-vscode/webview-ui/src/components/chat/SidebarTopBar.tsx diff --git a/.changeset/fix-secondary-sidebar-nav-bar.md b/.changeset/fix-secondary-sidebar-nav-bar.md new file mode 100644 index 00000000000..070b89d5f80 --- /dev/null +++ b/.changeset/fix-secondary-sidebar-nav-bar.md @@ -0,0 +1,5 @@ +--- +"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/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 26d6af3ffad..bf4a1ed088c 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -141,41 +141,6 @@ "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", @@ -461,76 +426,12 @@ ], "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", @@ -550,26 +451,6 @@ "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": [ diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index c04d818b4b8..15c4f706bd6 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -1046,6 +1046,7 @@ 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) diff --git a/packages/kilo-vscode/src/extension.ts b/packages/kilo-vscode/src/extension.ts index b1549e3c479..0cef572e1b1 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 { TelemetryEventName, TelemetryProxy } from "./services/telemetry" +import { 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" @@ -329,39 +329,8 @@ 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" }) diff --git a/packages/kilo-vscode/src/kilo-provider/sidebar-worktree.ts b/packages/kilo-vscode/src/kilo-provider/sidebar-worktree.ts index dc4d54fe5b0..10963338214 100644 --- a/packages/kilo-vscode/src/kilo-provider/sidebar-worktree.ts +++ b/packages/kilo-vscode/src/kilo-provider/sidebar-worktree.ts @@ -15,6 +15,7 @@ interface Ctx { openAgentManager: () => Thenable openAdvancedWorktree: () => Thenable openChanges: (sessionId?: string, turnId?: string) => Thenable + openProfile: () => Thenable currentSessionId?: string createWorktree?: (baseBranch?: string, branchName?: string) => Promise continueInWorktree?: ( @@ -59,6 +60,11 @@ 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/webview-ui/src/App.tsx b/packages/kilo-vscode/webview-ui/src/App.tsx index 7fa356e8482..d44a4092b96 100644 --- a/packages/kilo-vscode/webview-ui/src/App.tsx +++ b/packages/kilo-vscode/webview-ui/src/App.tsx @@ -11,6 +11,7 @@ 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" @@ -310,6 +311,10 @@ const AppContent: Component = () => { return (
+ handleViewAction("plusButtonClicked")} + onHistory={() => handleViewAction("historyButtonClicked")} + /> {/* legacy-migration start — state-driven overlay, independent of currentView */} void + onHistory: () => void +} + +interface Action { + key: string + icon: IconButtonProps["icon"] + button: string + run: () => void +} + +export const SidebarTopBar: Component = (props) => { + const vscode = useVSCode() + const language = useLanguage() + + // Mirrors the telemetry the native `view/title` toolbar buttons used to + // record before this bar replaced them (see kilo-code.new.sidebarTitle.* + // history in extension.ts), so button-usage analytics aren't silently lost. + const track = (button: string) => + vscode.postMessage({ + type: "telemetry", + event: TelemetryEventName.TITLE_BUTTON_CLICKED, + properties: { button, surface: "sidebar_title" }, + }) + + const open = ( + type: "openAgentManager" | "openKiloClaw" | "openMarketplacePanel" | "openProfilePanel" | "openSettingsPanel", + ) => vscode.postMessage({ type }) + + const actions: (Action | "spacer")[] = [ + { key: "newTask", icon: "plus", button: "new_task", run: props.onNewTask }, + { key: "history", icon: "history", button: "history", run: props.onHistory }, + { key: "agentManager", icon: "layers", button: "agent_manager", run: () => open("openAgentManager") }, + { key: "kiloClaw", icon: "comment", button: "kiloclaw", run: () => open("openKiloClaw") }, + { key: "marketplace", icon: "providers", button: "marketplace", run: () => open("openMarketplacePanel") }, + "spacer", + { key: "profile", icon: "status", button: "profile", run: () => open("openProfilePanel") }, + { key: "settings", icon: "settings-gear", button: "settings", run: () => open("openSettingsPanel") }, + ] + + return ( +