Merge pull request #12894 from Kilo-Org/fix/kilo-navigation-secondary-sidebar

fix(vscode/cursor): keep sidebar navigation visible in the secondary side bar
This commit is contained in:
bagatao@anaconda.com
2026-08-06 16:21:22 +02:00
committed by GitHub
37 changed files with 361 additions and 154 deletions
@@ -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.
+1
View File
@@ -444,6 +444,7 @@
"@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",
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1bc2a28b80d8dc5aea4c03609efc13a23a2c88103e56df741155d9e794fc96f7
size 2422
+2 -120
View File
@@ -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": [
@@ -1271,6 +1152,7 @@
"@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",
+3
View File
@@ -1048,6 +1048,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)
@@ -4908,6 +4909,8 @@ 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",
})
}
@@ -103,6 +103,7 @@ 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)
@@ -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)
const provider = new KiloProvider(this.extensionUri, this.connectionService, this.context, { hideTopBar: true })
// 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)
+3 -32
View File
@@ -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"
@@ -232,6 +232,7 @@ 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)
@@ -333,39 +334,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" })
@@ -627,6 +597,7 @@ function openKiloInNewTab(
const tabProvider = new KiloProvider(context.extensionUri, connectionService, context, {
tabTitle: panelTitleHandler(panel),
topBarSurface: "tab",
})
tabProvider.setRemoteService(remoteService)
tabProvider.setAutoApproveController(autoApprove)
@@ -32,4 +32,13 @@ 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"
}
@@ -15,6 +15,7 @@ interface Ctx {
openAgentManager: () => Thenable<unknown>
openAdvancedWorktree: () => Thenable<unknown>
openChanges: (sessionId?: string, turnId?: string) => Thenable<unknown>
openProfile: () => Thenable<unknown>
currentSessionId?: string
createWorktree?: (baseBranch?: string, branchName?: string) => Promise<void>
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,
+4 -1
View File
@@ -41,6 +41,9 @@ 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()
@@ -83,7 +86,7 @@ export function buildWebviewHtml(
</head>
<body>
<div id="root"></div>
<script nonce="${nonce}">window.ICONS_BASE_URI = "${opts.iconsBaseUri}"; window.KILO_SHIKI_WORKER_URI = "${opts.workerUri}"; window.KILO_MARKDOWN_SHIKI_WORKER_URI = "${markdownWorkerUri}";</script>
<script nonce="${nonce}">window.ICONS_BASE_URI = "${opts.iconsBaseUri}"; window.KILO_SHIKI_WORKER_URI = "${opts.workerUri}"; window.KILO_MARKDOWN_SHIKI_WORKER_URI = "${markdownWorkerUri}"; window.KILO_TOP_BAR = ${opts.topBar !== false}; window.KILO_TOP_BAR_SURFACE = "${opts.topBarSurface ?? "sidebar_title"}";</script>
<script nonce="${nonce}" src="${opts.scriptUri}"></script>
</body>
</html>`
@@ -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"
@@ -308,8 +309,23 @@ const AppContent: Component = () => {
<SidebarEmptyState onSelectSession={handleSelectSession} onShowHistory={() => 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 (
<div class="container">
<Show when={showTopBar}>
<SidebarTopBar
onNewTask={() => handleViewAction("plusButtonClicked")}
onHistory={() => handleViewAction("historyButtonClicked")}
surface={topBarSurface}
/>
</Show>
{/* legacy-migration start — state-driven overlay, independent of currentView */}
<Show
when={migrationNeeded()}
@@ -0,0 +1,88 @@
/**
* Renders New Task, History, Agent Manager, KiloClaw, Marketplace, Profile, and
* Settings inside the webview. VS Code's native `view/title` toolbar renders
* outside the webview DOM and disappears in the Secondary Side Bar with no way
* to detect or work around that — this bar guarantees the actions stay visible.
*/
import { Component, For } from "solid-js"
import { Tooltip } from "@kilocode/kilo-ui/tooltip"
import { useVSCode } from "../../context/vscode"
import { useLanguage } from "../../context/language"
import { TelemetryEventName } from "../../../../src/services/telemetry/types"
import "@vscode/codicons/dist/codicon.css"
export interface SidebarTopBarProps {
onNewTask: () => 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<SidebarTopBarProps> = (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 (
<div class="sidebar-top-bar" role="toolbar" aria-label={language.t("sidebar.topBar.label")}>
<For each={actions}>
{(action) => {
if (action === "spacer") return <div class="sidebar-top-bar-spacer" />
const label = language.t(`sidebar.topBar.${action.key}`)
return (
<Tooltip value={label} placement="bottom">
<button
type="button"
data-component="icon-button"
data-variant="ghost"
data-size="small"
aria-label={label}
onClick={() => {
track(action.button)
action.run()
}}
>
<div data-component="icon" data-size="small">
<i class={`codicon codicon-${action.codicon}`} aria-hidden="true" />
</div>
</button>
</Tooltip>
)
}}
</For>
</div>
)
}
+8
View File
@@ -306,6 +306,14 @@ export const dict = {
"session.messages.loadEarlier": "تحميل الرسائل السابقة",
"session.messages.loading": "جارٍ تحميل الرسائل...",
"sidebar.topBar.label": "التنقل في Kilo Code",
"sidebar.topBar.newTask": "مهمة جديدة",
"sidebar.topBar.history": "السجل",
"sidebar.topBar.agentManager": "مدير الوكلاء",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "المتجر",
"sidebar.topBar.profile": "الملف الشخصي",
"sidebar.topBar.settings": "الإعدادات",
"sidebar.session.newSession": "جلسة جديدة",
"sidebar.session.newSession.tooltip": "ابدأ محادثة جديدة مع الاحتفاظ بالجلسة الحالية كما هي.",
"sidebar.session.newWorktree": "Worktree جديد",
+8
View File
@@ -316,6 +316,14 @@ export const dict = {
"session.messages.loadEarlier": "Carregar mensagens anteriores",
"session.messages.loading": "Carregando mensagens...",
"sidebar.topBar.label": "Navegação do Kilo Code",
"sidebar.topBar.newTask": "Nova Tarefa",
"sidebar.topBar.history": "Histórico",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Marketplace",
"sidebar.topBar.profile": "Perfil",
"sidebar.topBar.settings": "Configurações",
"sidebar.session.newSession": "Nova Sessão",
"sidebar.session.newSession.tooltip": "Inicie uma nova conversa mantendo a sessão atual intacta.",
"sidebar.session.newWorktree": "Novo Worktree",
+8
View File
@@ -315,6 +315,14 @@ export const dict = {
"session.messages.loadEarlier": "Učitaj ranije poruke",
"session.messages.loading": "Učitavanje poruka...",
"sidebar.topBar.label": "Navigacija Kilo Code",
"sidebar.topBar.newTask": "Novi Zadatak",
"sidebar.topBar.history": "Historija",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Marketplace",
"sidebar.topBar.profile": "Profil",
"sidebar.topBar.settings": "Postavke",
"sidebar.session.newSession": "Nova Sesija",
"sidebar.session.newSession.tooltip": "Započnite novi razgovor držeći trenutnu sesiju netaknutom.",
"sidebar.session.newWorktree": "Novi Worktree",
+8
View File
@@ -313,6 +313,14 @@ export const dict = {
"session.messages.loadEarlier": "Indlæs tidligere beskeder",
"session.messages.loading": "Indlæser beskeder...",
"sidebar.topBar.label": "Kilo Code-navigation",
"sidebar.topBar.newTask": "Ny Opgave",
"sidebar.topBar.history": "Historik",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Markedsplads",
"sidebar.topBar.profile": "Profil",
"sidebar.topBar.settings": "Indstillinger",
"sidebar.session.newSession": "Ny Session",
"sidebar.session.newSession.tooltip": "Start en frisk samtale, mens den nuværende session holdes intakt.",
"sidebar.session.newWorktree": "Nyt Worktree",
@@ -322,6 +322,14 @@ export const dict = {
"session.messages.loadEarlier": "Frühere Nachrichten laden",
"session.messages.loading": "Lade Nachrichten...",
"sidebar.topBar.label": "Kilo Code Navigation",
"sidebar.topBar.newTask": "Neue Aufgabe",
"sidebar.topBar.history": "Verlauf",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Marktplatz",
"sidebar.topBar.profile": "Profil",
"sidebar.topBar.settings": "Einstellungen",
"sidebar.session.newSession": "Neue Sitzung",
"sidebar.session.newSession.tooltip": "Starte eine neue Unterhaltung, während die aktuelle Sitzung intakt bleibt.",
"sidebar.session.newWorktree": "Neuer Worktree",
@@ -708,6 +708,14 @@ export const dict = {
"session.costAlert.question":
"This session just went above your {{limit}} per-session alert threshold and cost {{cost}}. Keep going?",
"session.costAlert.stop": "Stop",
"sidebar.topBar.label": "Kilo Code navigation",
"sidebar.topBar.newTask": "New Task",
"sidebar.topBar.history": "History",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Marketplace",
"sidebar.topBar.profile": "Profile",
"sidebar.topBar.settings": "Settings",
"sidebar.session.newSession": "New Session",
"sidebar.session.newSession.tooltip": "Start a fresh conversation while keeping the current session intact.",
"sidebar.session.newWorktree": "New Worktree",
+8
View File
@@ -317,6 +317,14 @@ export const dict = {
"session.messages.loadEarlier": "Cargar mensajes anteriores",
"session.messages.loading": "Cargando mensajes...",
"sidebar.topBar.label": "Navegación de Kilo Code",
"sidebar.topBar.newTask": "Nueva Tarea",
"sidebar.topBar.history": "Historial",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Marketplace",
"sidebar.topBar.profile": "Perfil",
"sidebar.topBar.settings": "Configuración",
"sidebar.session.newSession": "Nueva Sesión",
"sidebar.session.newSession.tooltip": "Inicia una nueva conversación manteniendo intacta la sesión actual.",
"sidebar.session.newWorktree": "Nuevo Worktree",
+8
View File
@@ -712,6 +712,14 @@ export const dict = {
"session.costAlert.continue": "ادامه",
"session.costAlert.question": "هزینه این جلسه از آستانه هشدار {{limit}} شما فراتر رفت و {{cost}} شد. ادامه می‌دهید؟",
"session.costAlert.stop": "توقف",
"sidebar.topBar.label": "پیمایش Kilo Code",
"sidebar.topBar.newTask": "وظیفه جدید",
"sidebar.topBar.history": "تاریخچه",
"sidebar.topBar.agentManager": "مدیر عامل‌ها",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "بازارچه",
"sidebar.topBar.profile": "پروفایل",
"sidebar.topBar.settings": "تنظیمات",
"sidebar.session.newSession": "جلسه جدید",
"sidebar.session.newSession.tooltip": "یک مکالمه تازه شروع کنید و جلسه فعلی را دست‌نخورده نگه دارید.",
"sidebar.session.newWorktree": "Worktree جدید",
+8
View File
@@ -316,6 +316,14 @@ export const dict = {
"session.messages.loadEarlier": "Charger les messages précédents",
"session.messages.loading": "Chargement des messages...",
"sidebar.topBar.label": "Navigation Kilo Code",
"sidebar.topBar.newTask": "Nouvelle Tâche",
"sidebar.topBar.history": "Historique",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Marketplace",
"sidebar.topBar.profile": "Profil",
"sidebar.topBar.settings": "Paramètres",
"sidebar.session.newSession": "Nouvelle Session",
"sidebar.session.newSession.tooltip":
"Démarrer une nouvelle conversation tout en gardant la session actuelle intacte.",
+8
View File
@@ -591,6 +591,14 @@ export const dict = {
"session.status.retry": "Riprovo...",
"session.status.working": "Al lavoro...",
"session.status.offline": "Rete disconnessa - riconnessione...",
"sidebar.topBar.label": "Navigazione Kilo Code",
"sidebar.topBar.newTask": "Nuova Attività",
"sidebar.topBar.history": "Cronologia",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Marketplace",
"sidebar.topBar.profile": "Profilo",
"sidebar.topBar.settings": "Impostazioni",
"sidebar.session.newSession": "Nuova sessione",
"sidebar.session.newSession.tooltip": "Avvia una nuova conversazione mantenendo intatta la sessione corrente.",
"sidebar.session.newWorktree": "Nuovo worktree",
+8
View File
@@ -313,6 +313,14 @@ export const dict = {
"session.messages.loadEarlier": "以前のメッセージを読み込む",
"session.messages.loading": "メッセージを読み込み中...",
"sidebar.topBar.label": "Kilo Code ナビゲーション",
"sidebar.topBar.newTask": "新規タスク",
"sidebar.topBar.history": "履歴",
"sidebar.topBar.agentManager": "エージェントマネージャー",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "マーケットプレイス",
"sidebar.topBar.profile": "プロフィール",
"sidebar.topBar.settings": "設定",
"sidebar.session.newSession": "新規セッション",
"sidebar.session.newSession.tooltip": "現在のセッションを維持したまま、新しい会話を開始します。",
"sidebar.session.newWorktree": "新規 Worktree",
+8
View File
@@ -314,6 +314,14 @@ export const dict = {
"session.messages.loadEarlier": "이전 메시지 로드",
"session.messages.loading": "메시지 로드 중...",
"sidebar.topBar.label": "Kilo Code 탐색",
"sidebar.topBar.newTask": "새 작업",
"sidebar.topBar.history": "기록",
"sidebar.topBar.agentManager": "에이전트 관리자",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "마켓플레이스",
"sidebar.topBar.profile": "프로필",
"sidebar.topBar.settings": "설정",
"sidebar.session.newSession": "새 세션",
"sidebar.session.newSession.tooltip": "현재 세션을 그대로 유지하면서 새로운 대화를 시작합니다.",
"sidebar.session.newWorktree": "새 Worktree",
+8
View File
@@ -318,6 +318,14 @@ export const dict = {
"session.messages.loadEarlier": "Eerdere berichten laden",
"session.messages.loading": "Berichten laden...",
"sidebar.topBar.label": "Kilo Code-navigatie",
"sidebar.topBar.newTask": "Nieuwe Taak",
"sidebar.topBar.history": "Geschiedenis",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Marketplace",
"sidebar.topBar.profile": "Profiel",
"sidebar.topBar.settings": "Instellingen",
"sidebar.session.newSession": "Nieuwe Sessie",
"sidebar.session.newSession.tooltip": "Start een nieuw gesprek terwijl je de huidige sessie intact houdt.",
"sidebar.session.newWorktree": "Nieuwe Worktree",
+8
View File
@@ -320,6 +320,14 @@ export const dict = {
"session.messages.loadEarlier": "Last inn tidligere meldinger",
"session.messages.loading": "Laster meldinger...",
"sidebar.topBar.label": "Kilo Code-navigasjon",
"sidebar.topBar.newTask": "Ny Oppgave",
"sidebar.topBar.history": "Historikk",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Markedsplass",
"sidebar.topBar.profile": "Profil",
"sidebar.topBar.settings": "Innstillinger",
"sidebar.session.newSession": "Ny Økt",
"sidebar.session.newSession.tooltip": "Start en ny samtale mens den nåværende økten holdes intakt.",
"sidebar.session.newWorktree": "Nytt Worktree",
+8
View File
@@ -314,6 +314,14 @@ export const dict = {
"session.messages.loadEarlier": "Załaduj wcześniejsze wiadomości",
"session.messages.loading": "Ładowanie wiadomości...",
"sidebar.topBar.label": "Nawigacja Kilo Code",
"sidebar.topBar.newTask": "Nowe Zadanie",
"sidebar.topBar.history": "Historia",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Marketplace",
"sidebar.topBar.profile": "Profil",
"sidebar.topBar.settings": "Ustawienia",
"sidebar.session.newSession": "Nowa Sesja",
"sidebar.session.newSession.tooltip": "Rozpocznij nową konwersację, zachowując obecną sesję bez zmian.",
"sidebar.session.newWorktree": "Nowe Worktree",
+8
View File
@@ -312,6 +312,14 @@ export const dict = {
"session.messages.loadEarlier": "Загрузить предыдущие сообщения",
"session.messages.loading": "Загрузка сообщений...",
"sidebar.topBar.label": "Навигация Kilo Code",
"sidebar.topBar.newTask": "Новая задача",
"sidebar.topBar.history": "История",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Маркетплейс",
"sidebar.topBar.profile": "Профиль",
"sidebar.topBar.settings": "Настройки",
"sidebar.session.newSession": "Новая сессия",
"sidebar.session.newSession.tooltip": "Начать новую беседу, сохранив текущую сессию нетронутой.",
"sidebar.session.newWorktree": "Новое Worktree",
+8
View File
@@ -312,6 +312,14 @@ export const dict = {
"session.messages.loadEarlier": "โหลดข้อความก่อนหน้า",
"session.messages.loading": "กำลังโหลดข้อความ...",
"sidebar.topBar.label": "การนำทาง Kilo Code",
"sidebar.topBar.newTask": "งานใหม่",
"sidebar.topBar.history": "ประวัติ",
"sidebar.topBar.agentManager": "ตัวจัดการเอเจนต์",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "มาร์เก็ตเพลส",
"sidebar.topBar.profile": "โปรไฟล์",
"sidebar.topBar.settings": "การตั้งค่า",
"sidebar.session.newSession": "เซสชันใหม่",
"sidebar.session.newSession.tooltip": "เริ่มการสนทนาใหม่โดยที่ยังคงเซสชันปัจจุบันไว้",
"sidebar.session.newWorktree": "Worktree ใหม่",
+8
View File
@@ -313,6 +313,14 @@ export const dict = {
"session.messages.loadEarlier": "Önceki mesajları yükle",
"session.messages.loading": "Mesajlar yükleniyor...",
"sidebar.topBar.label": "Kilo Code Gezinme",
"sidebar.topBar.newTask": "Yeni Görev",
"sidebar.topBar.history": "Geçmiş",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Marketplace",
"sidebar.topBar.profile": "Profil",
"sidebar.topBar.settings": "Ayarlar",
"sidebar.session.newSession": "Yeni Oturum",
"sidebar.session.newSession.tooltip": "Mevcut oturumu koruyarak yeni bir konuşma başlatın.",
"sidebar.session.newWorktree": "Yeni Worktree",
+8
View File
@@ -317,6 +317,14 @@ export const dict = {
"session.messages.loadEarlier": "Завантажити попередні повідомлення",
"session.messages.loading": "Завантаження повідомлень...",
"sidebar.topBar.label": "Навігація Kilo Code",
"sidebar.topBar.newTask": "Нове завдання",
"sidebar.topBar.history": "Історія",
"sidebar.topBar.agentManager": "Agent Manager",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "Маркетплейс",
"sidebar.topBar.profile": "Профіль",
"sidebar.topBar.settings": "Налаштування",
"sidebar.session.newSession": "Нова сесія",
"sidebar.session.newSession.tooltip": "Почати нову розмову, зберігши поточну сесію незмінною.",
"sidebar.session.newWorktree": "Нове Worktree",
+8
View File
@@ -301,6 +301,14 @@ export const dict = {
"session.messages.loadEarlier": "加载更早的消息",
"session.messages.loading": "正在加载消息...",
"sidebar.topBar.label": "Kilo Code 导航",
"sidebar.topBar.newTask": "新建任务",
"sidebar.topBar.history": "历史记录",
"sidebar.topBar.agentManager": "代理管理器",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "市场",
"sidebar.topBar.profile": "个人资料",
"sidebar.topBar.settings": "设置",
"sidebar.session.newSession": "新会话",
"sidebar.session.newSession.tooltip": "在保持当前会话完整的同时开始全新的对话。",
"sidebar.session.newWorktree": "新 Worktree",
+8
View File
@@ -299,6 +299,14 @@ export const dict = {
"session.messages.loadEarlier": "載入更早的訊息",
"session.messages.loading": "正在載入訊息...",
"sidebar.topBar.label": "Kilo Code 導覽",
"sidebar.topBar.newTask": "新建任務",
"sidebar.topBar.history": "歷史記錄",
"sidebar.topBar.agentManager": "代理管理器",
"sidebar.topBar.kiloClaw": "KiloClaw",
"sidebar.topBar.marketplace": "市集",
"sidebar.topBar.profile": "個人資料",
"sidebar.topBar.settings": "設定",
"sidebar.session.newSession": "新會話",
"sidebar.session.newSession.tooltip": "在保持當前會話完整的同時開始全新的對話。",
"sidebar.session.newWorktree": "新 Worktree",
@@ -19,6 +19,7 @@ import { QuestionDock } from "../components/chat/QuestionDock"
import { SuggestBar } from "../components/chat/SuggestBar"
import { MessageList } from "../components/chat/MessageList"
import { VscodeUserMessage } from "../components/chat/VscodeUserMessage"
import { SidebarTopBar } from "../components/chat/SidebarTopBar"
import { TurnOutcome } from "../components/shared/TurnOutcome"
import { SessionContext } from "../context/session"
import { ProviderContext } from "../context/provider"
@@ -1265,6 +1266,21 @@ const mockServer = {
gitInstalled: () => true,
}
// ---------------------------------------------------------------------------
// SidebarTopBar — in-webview replacement for the native view/title toolbar
// ---------------------------------------------------------------------------
export const SidebarTopBarDefault: Story = {
name: "SidebarTopBar — default actions",
render: () => (
<StoryProviders sessionID={SESSION_ID} status="idle" noPadding>
<div style={{ width: "340px" }}>
<SidebarTopBar onNewTask={() => undefined} onHistory={() => undefined} surface="sidebar_title" />
</div>
</StoryProviders>
),
}
export const WelcomeWithSwitcherAndNotification: Story = {
name: "Welcome — account switcher + notification",
render: () => (
@@ -23,6 +23,36 @@
--chat-scrollbar-width: 10px;
}
/* ============================================
Sidebar Top Bar
============================================ */
/* Always-visible in-webview equivalent of the native `view/title` toolbar, which
disappears in the Secondary Side Bar with no way to detect or work around
that. border-top/-bottom rule it off from the native pane title above (which
a webview can't render into) and the chat content below. */
.sidebar-top-bar {
--top-bar-border: 1px solid var(--vscode-sideBar-border, var(--vscode-widget-border));
display: flex;
align-items: center;
gap: 2px;
flex-shrink: 0;
padding: 4px 6px;
border-top: var(--top-bar-border);
border-bottom: var(--top-bar-border);
overflow-x: auto;
scrollbar-width: none;
}
.sidebar-top-bar::-webkit-scrollbar {
display: none;
}
.sidebar-top-bar-spacer {
flex: 1;
min-width: 4px;
}
.chat-messages-wrapper {
position: relative;
flex: 1;
@@ -202,6 +202,10 @@ export interface OpenSettingsPanelRequest {
tab?: string
}
export interface OpenProfilePanelRequest {
type: "openProfilePanel"
}
export interface OpenVSCodeSettingsRequest {
type: "openVSCodeSettings"
query: string
@@ -1388,6 +1392,7 @@ export type WebviewMessage =
| RefreshProfileRequest
| OpenExternalRequest
| OpenSettingsPanelRequest
| OpenProfilePanelRequest
| OpenVSCodeSettingsRequest
| OpenConfigFileRequest
| OpenMarketplacePanelRequest