Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/agent-manager-toolbar-groups.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"kilo-code": patch
---

Regroup the Agent Manager toolbar: optional session panels (documents, subagents) sit left of a separator, and the fixed workbench (changes, PR, apply, open in VS Code, browser, run, terminal) keeps stable positions on the right. Toolbar icons render at a uniform 1px stroke and dim when disabled. Open the full-screen review from the changes panel header instead of a toolbar button.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion packages/kilo-ui/src/components/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const icons: Record<string, { path: string; viewBox: string }> = {
},
"pull-request": {
viewBox: "0 0 20 20",
path: `<path d="M1.875 4.0625a2.8125 2.8125 0 1 1 3.75 2.6525v6.57a2.8138 2.8138 0 1 1-1.875 0V6.715A2.8125 2.8125 0 0 1 1.875 4.0625Zm7.096-.22125L11.96625.84625A.3125.3125 0 0 1 12.5 1.0675V3.125h1.25A3.125 3.125 0 0 1 16.875 6.25v7.035a2.8138 2.8138 0 1 1-1.875 0V6.25a1.25 1.25 0 0 0-1.25-1.25H12.5v2.0575a.3125.3125 0 0 1-.53375.22125L8.97125 4.34125a.3125.3125 0 0 1 0-.4425ZM4.6875 3.125a.9375.9375 0 1 0 0 1.875.9375.9375 0 0 0 0-1.875Zm0 11.875a.9375.9375 0 1 0 0 1.875.9375.9375 0 0 0 0-1.875Zm10.3125.9375a.9375.9375 0 1 0 1.875 0 .9375.9375 0 0 0-1.875 0Z" fill="currentColor"/>`,
// Stroked at 1.25 on the 20-unit grid (1px at 16px) to match the other outline icons.
path: `<circle cx="4.6875" cy="4.0625" r="1.875" stroke="currentColor" stroke-width="1.25"/><circle cx="4.6875" cy="15.9375" r="1.875" stroke="currentColor" stroke-width="1.25"/><circle cx="15.9375" cy="15.9375" r="1.875" stroke="currentColor" stroke-width="1.25"/><path d="M4.6875 5.9375V14.0625M15.9375 14.0625V6.25A2.5 2.5 0 0 0 13.4375 3.75H9.6875M11.5625 1.875L9.6875 3.75L11.5625 5.625" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>`,
},
refresh: {
viewBox: "0 0 20 20",
Expand Down
26 changes: 13 additions & 13 deletions packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1716,14 +1716,6 @@ const AgentManagerContent: Component = () => {
setReviewActive(true)
}

const toggleReviewTab = () => {
if (reviewActive()) {
closeReviewTab()
return
}
openReviewTab()
}

// Deferred close: flip signal immediately for instant UI feedback,
// the <Show> unmount triggers heavy FileDiff cleanup but the tab bar
// and chat view are already visible before that work runs.
Expand Down Expand Up @@ -2365,8 +2357,8 @@ const AgentManagerContent: Component = () => {
worktreeStats={worktreeStats}
applyState={apply.applyStateForSelection}
reviewScope={review.scope}
onApply={metrics.click("apply_to_local", "tab_toolbar", openApplyDialog)}
onOpen={openWindow}
onApply={openApplyDialog}
runStatuses={runStatuses}
runConfigured={runScriptConfigured}
onRun={(id) => runWorktree(id, sideCtl.destination())}
Expand All @@ -2375,16 +2367,24 @@ const AgentManagerContent: Component = () => {
reviewActive={reviewActive}
onToggleDiff={toggleDiffPanel}
{...browser.tabs}
onToggleReview={metrics.click("fullscreen_review", "tab_toolbar", toggleReviewTab)}
onToggleBrowser={metrics.click("browser", "tab_toolbar", browser.tabs.onToggleBrowser, () => ({
action: browser.tabs.browserOpen() ? "close" : "open",
}))}
prStatus={() => activePR()?.pr}
prOpen={prOpen}
onTogglePR={togglePRPanel}
onTogglePR={metrics.click("pull_request", "tab_toolbar", togglePRPanel, () => ({
action: prOpen() ? "close" : "open",
}))}
documentsOpen={documentInspector.isOpen}
documentsAvailable={documentInspector.available}
onToggleDocuments={documentInspector.toggle}
onToggleDocuments={metrics.click("documents", "tab_toolbar", documentInspector.toggle, () => ({
action: documentInspector.isOpen() ? "close" : "open",
}))}
subagentsAvailable={() => subagentCtl.tabs.tabs().length > 0 || subagentCtl.toolbar.available().length > 0}
subagentsOpen={() => sidePanel() === SidePanel.Subagents}
onToggleSubagents={subagentCtl.toolbar.toggle}
onToggleSubagents={metrics.click("subagents", "tab_toolbar", subagentCtl.toolbar.toggle, () => ({
action: sidePanel() === SidePanel.Subagents ? "close" : "open",
}))}
terminalDestination={sideCtl.destination}
terminalDestinationActive={() => sidePanel() === SidePanel.Terminal}
terminalKeybind={() => kb().showTerminal ?? ""}
Expand Down
231 changes: 114 additions & 117 deletions packages/kilo-vscode/webview-ui/agent-manager/TabBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export interface TabBarProps {
applyState: () => { status: string } | undefined
/** Active diff scope; applying to local is only possible from the branch scope. */
reviewScope: () => DiffScope
onOpen: () => void
onApply: () => void
onOpen: () => void
runStatuses: () => Record<string, RunStatus>
runConfigured: () => boolean
onRun: (id: string) => void
Expand All @@ -56,7 +56,6 @@ export interface TabBarProps {
onToggleBrowser: () => void
reviewActive: () => boolean
onToggleDiff: () => void
onToggleReview: () => void
prStatus: () => PRStatus | undefined
prOpen: () => boolean
onTogglePR: () => void
Expand Down Expand Up @@ -138,45 +137,128 @@ export const TabBar: Component<TabBarProps> = (props) => (
if (!state) return false
return state.status === "checking" || state.status === "applying"
}
const panels = () => props.documentsAvailable() || props.subagentsAvailable()
return (
<>
<Show when={isWorktree()}>
<>
<Tooltip value={props.t("agentManager.open.tooltip")} placement="bottom" openDelay={0}>
<IconButton
size="small"
variant="ghost"
icon="folder"
aria-label={props.t("agentManager.open.button")}
onClick={props.onOpen}
/>
</Tooltip>
<Tooltip
value={
props.reviewScope() === "branch"
? props.t("agentManager.apply.tooltip")
: props.t("agentManager.diff.applyBranchOnly")
}
placement="bottom"
openDelay={0}
>
<span class="am-tab-apply">
{/* Session panels: re-open handles for panels this session produced.
They grow outward to the left so the workbench never shifts. */}
<Show when={panels()}>
<span class="am-tab-session-panels">
<Show when={props.documentsAvailable()}>
<Tooltip value={props.t("agentManager.documents.toggle")} placement="bottom" openDelay={0}>
<IconButton
icon="book-open-check"
size="small"
variant="ghost"
icon="check"
aria-label={props.t("agentManager.apply.globalButton")}
aria-busy={applyBusy()}
onClick={props.onApply}
disabled={!hasChanges() || applyBusy() || props.reviewScope() !== "branch"}
aria-label={props.t("agentManager.documents.toggle")}
class={props.documentsOpen() ? "am-tab-diff-btn-active" : ""}
onClick={props.onToggleDocuments}
/>
<Show when={applyBusy()}>
<Spinner class="am-apply-spinner" />
</Tooltip>
</Show>
<Show when={props.subagentsAvailable()}>
<Tooltip value="Subagents" placement="bottom" openDelay={0}>
<IconButton
icon="task"
size="small"
variant="ghost"
aria-label="Subagents"
class={props.subagentsOpen() ? "am-tab-diff-btn-active" : ""}
onClick={props.onToggleSubagents}
/>
</Tooltip>
</Show>
<span class="am-tab-actions-separator" />
</span>
</Show>
{/* Workbench: fixed slots anchored to the right edge.
Changes first so its stats can grow without moving a pillar. */}
<TooltipKeybind
title={props.t("agentManager.diff.toggle")}
keybind={props.bindings().toggleDiff ?? ""}
placement="bottom"
openDelay={0}
>
<button
class={`am-diff-toggle-btn ${props.diffOpen() && !props.reviewActive() ? "am-tab-diff-btn-active" : ""} ${hasChanges() ? "am-diff-toggle-has-changes" : ""}`}
onClick={props.onToggleDiff}
aria-label={props.t("agentManager.diff.toggle")}
>
<Icon name="layers" size="small" />
<Show when={hasChanges()}>
<span class="am-diff-toggle-stats">
<Show when={stats()!.files > 0}>
<span class="am-stat-files">{stats()!.files}f</span>
</Show>
<span class="am-stat-additions">+{stats()!.additions}</span>
<span class="am-stat-deletions">−{stats()!.deletions}</span>
</span>
</Show>
</button>
</TooltipKeybind>
<Show when={props.prStatus()}>
{(pr) => (
<Tooltip value={`PR #${pr().number}`} placement="bottom" openDelay={0}>
<IconButton
icon="pull-request"
size="small"
variant="ghost"
aria-label={`PR #${pr().number}`}
class={props.prOpen() ? "am-tab-diff-btn-active" : ""}
onClick={props.onTogglePR}
/>
</Tooltip>
</>
)}
</Show>
<Show when={isWorktree()}>
<Tooltip
value={
props.reviewScope() === "branch"
? props.t("agentManager.apply.tooltip")
: props.t("agentManager.diff.applyBranchOnly")
}
placement="bottom"
openDelay={0}
>
<span class="am-tab-apply">
<IconButton
size="small"
variant="ghost"
icon="check"
aria-label={props.t("agentManager.apply.globalButton")}
aria-busy={applyBusy()}
onClick={props.onApply}
disabled={!hasChanges() || applyBusy() || props.reviewScope() !== "branch"}
/>
<Show when={applyBusy()}>
<Spinner class="am-apply-spinner" />
</Show>
</span>
</Tooltip>
<Tooltip value={props.t("agentManager.open.tooltip")} placement="bottom" openDelay={0}>
<IconButton
size="small"
variant="ghost"
icon="folder"
aria-label={props.t("agentManager.open.button")}
onClick={props.onOpen}
/>
</Tooltip>
</Show>
<Show when={props.browserAutomation()}>
<Tooltip value={props.t("agentManager.browser.title")} placement="bottom" openDelay={0}>
<IconButton
icon="globe"
size="small"
variant="ghost"
aria-label={props.t("agentManager.browser.title")}
class={props.browserOpen() ? "am-tab-diff-btn-active" : ""}
onClick={props.onToggleBrowser}
/>
</Tooltip>
</Show>
{/* Run and Terminal form the fixed tail: a run sends its output
to the terminal destination, so cause and effect stay adjacent. */}
<Show when={sel()}>
{(() => {
const rid = () => (sel() === LOCAL ? LOCAL : (sel() as string))
Expand All @@ -185,7 +267,7 @@ export const TabBar: Component<TabBarProps> = (props) => (
const configured = props.runConfigured
const title = () => (configured() ? (active() ? "Stop" : "Run") : "Configure run script")
return (
<span class={`am-split-button ${active() ? "am-run-active" : ""}`}>
<span class="am-split-button">
<TooltipKeybind
title={title()}
keybind={props.bindings().runScript ?? ""}
Expand Down Expand Up @@ -232,94 +314,9 @@ export const TabBar: Component<TabBarProps> = (props) => (
)
})()}
</Show>
<Show when={props.prStatus()}>
{(pr) => (
<Tooltip value={`PR #${pr().number}`} placement="bottom" openDelay={0}>
<IconButton
icon="pull-request"
size="small"
variant="ghost"
aria-label={`PR #${pr().number}`}
class={props.prOpen() ? "am-tab-diff-btn-active" : ""}
onClick={props.onTogglePR}
/>
</Tooltip>
)}
</Show>
<Show when={props.documentsAvailable()}>
<Tooltip value={props.t("agentManager.documents.toggle")} placement="bottom" openDelay={0}>
<IconButton
icon="book-open-check"
size="small"
variant="ghost"
aria-label={props.t("agentManager.documents.toggle")}
class={props.documentsOpen() ? "am-tab-diff-btn-active" : ""}
onClick={props.onToggleDocuments}
/>
</Tooltip>
</Show>
<Show when={props.subagentsAvailable()}>
<Tooltip value="Subagents" placement="bottom" openDelay={0}>
<IconButton
icon="task"
size="small"
variant="ghost"
aria-label="Subagents"
class={props.subagentsOpen() ? "am-tab-diff-btn-active" : ""}
onClick={props.onToggleSubagents}
/>
</Tooltip>
</Show>
<TooltipKeybind
title={props.t("agentManager.diff.toggle")}
keybind={props.bindings().toggleDiff ?? ""}
placement="bottom"
openDelay={0}
>
<button
class={`am-diff-toggle-btn ${props.diffOpen() && !props.reviewActive() ? "am-tab-diff-btn-active" : ""} ${hasChanges() ? "am-diff-toggle-has-changes" : ""}`}
onClick={props.onToggleDiff}
aria-label={props.t("agentManager.diff.toggle")}
>
<Icon name="layers" size="small" />
<Show when={hasChanges()}>
<span class="am-diff-toggle-stats">
<Show when={stats()!.files > 0}>
<span class="am-stat-files">{stats()!.files}f</span>
</Show>
<span class="am-stat-additions">+{stats()!.additions}</span>
<span class="am-stat-deletions">−{stats()!.deletions}</span>
</span>
</Show>
</button>
</TooltipKeybind>
<Show when={props.browserAutomation()}>
<Tooltip value={props.t("agentManager.browser.title")} placement="bottom" openDelay={0}>
<IconButton
icon="globe"
size="small"
variant="ghost"
aria-label={props.t("agentManager.browser.title")}
class={props.browserOpen() ? "am-tab-diff-btn-active" : ""}
onClick={props.onToggleBrowser}
/>
</Tooltip>
</Show>
</>
)
})()}
<Show when={props.selection() !== null}>
<Tooltip value={props.t("command.review.toggle")} placement="bottom" openDelay={0}>
<IconButton
icon="expand"
size="small"
variant="ghost"
aria-label={props.t("command.review.toggle")}
class={props.reviewActive() ? "am-tab-diff-btn-active" : ""}
onClick={props.onToggleReview}
/>
</Tooltip>
</Show>
{/* Terminal destination split button: the primary action
follows the user's setting (VS Code integrated terminal
or the embedded side panel), the dropdown picks which.
Expand Down
Loading
Loading