From 44ccf7c1cb3f59262affbd86e612bdacac711e9c Mon Sep 17 00:00:00 2001 From: can1357 Date: Sat, 3 Jan 2026 21:53:01 +0100 Subject: [PATCH] feat(coding-agent): replaced 3-column layout with tabbed interface - Redesigned Extension Control Center from 3-column layout to tabbed interface with provider tabs. - Replaced sidebar tree navigation with horizontal tab bar supporting TAB/Shift+TAB cycling. - Added session header/footer output in text mode showing version, model, provider, and thinking level. - Removed HolyGrailLayout and SidebarTree components in favor of TwoColumnBody with tabs. --- assets/discovery.webp | Bin 105646 -> 63212 bytes packages/coding-agent/CHANGELOG.md | 6 + .../coding-agent/src/core/system-prompt.ts | 4 +- packages/coding-agent/src/core/tools/index.ts | 12 +- .../extensions/extension-dashboard.ts | 425 +++++---- .../components/extensions/extension-list.ts | 806 ++++++++--------- .../extensions/holy-grail-layout.ts | 235 ----- .../components/extensions/index.ts | 2 - .../components/extensions/inspector-panel.ts | 495 +++++------ .../components/extensions/sidebar-tree.ts | 174 ---- .../components/extensions/state-manager.ts | 817 ++++++++++-------- .../components/extensions/types.ts | 47 +- .../src/modes/interactive/interactive-mode.ts | 18 +- packages/coding-agent/src/modes/print-mode.ts | 34 + 14 files changed, 1446 insertions(+), 1629 deletions(-) delete mode 100644 packages/coding-agent/src/modes/interactive/components/extensions/holy-grail-layout.ts delete mode 100644 packages/coding-agent/src/modes/interactive/components/extensions/sidebar-tree.ts diff --git a/assets/discovery.webp b/assets/discovery.webp index 9052684c2e111384a45a32e33fd67ffc3bae65ec..89f1675c1267d1f39889f12eed789e9288d746a9 100644 GIT binary patch literal 63212 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

0{7cC-|5okuL}b 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%0DPuO6l!Xs2N_An{ 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 diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 1bd0a156d..09ec94df6 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -4,12 +4,18 @@ ### Added +- Added session header and footer output in text mode showing version, model, provider, thinking level, and session ID - Added Extension Control Center dashboard accessible via `/extensions` command for unified management of all providers and extensions - Added ability to enable/disable individual extensions with persistent settings - Added three-column dashboard layout with sidebar tree, extension list, and inspector panel - Added fuzzy search filtering for extensions in the dashboard - Added keyboard navigation with Tab to cycle panes, j/k for navigation, Space to toggle, Enter to expand/collapse +### Changed + +- Redesigned Extension Control Center from 3-column layout to tabbed interface with horizontal provider tabs and 2-column grid +- Replaced sidebar tree navigation with provider tabs using TAB/Shift+TAB cycling + ### Fixed - Fixed title generation flag not resetting when starting a new session diff --git a/packages/coding-agent/src/core/system-prompt.ts b/packages/coding-agent/src/core/system-prompt.ts index c594434b7..a2c40f4be 100644 --- a/packages/coding-agent/src/core/system-prompt.ts +++ b/packages/coding-agent/src/core/system-prompt.ts @@ -5,14 +5,14 @@ import { existsSync, readFileSync } from "node:fs"; import chalk from "chalk"; import { contextFileCapability } from "../capability/context-file"; +import type { Rule } from "../capability/rule"; import { systemPromptCapability } from "../capability/system-prompt"; import { getDocsPath, getExamplesPath, getReadmePath } from "../config"; import { type ContextFile, loadSync, type SystemPrompt as SystemPromptFile } from "../discovery/index"; -import type { Rule } from "../capability/rule"; import type { SkillsSettings } from "./settings-manager"; import { formatSkillsForPrompt, loadSkills, type Skill } from "./skills"; -import { formatRulesForPrompt } from "./tools/rulebook"; import type { ToolName } from "./tools/index"; +import { formatRulesForPrompt } from "./tools/rulebook"; /** * Execute a git command synchronously and return stdout or null on failure. diff --git a/packages/coding-agent/src/core/tools/index.ts b/packages/coding-agent/src/core/tools/index.ts index b1f00fd59..0a9522f50 100644 --- a/packages/coding-agent/src/core/tools/index.ts +++ b/packages/coding-agent/src/core/tools/index.ts @@ -24,6 +24,12 @@ export { createNotebookTool, type NotebookToolDetails, notebookTool } from "./no export { createOutputTool, type OutputToolDetails, outputTool } from "./output"; export { createReadTool, type ReadToolDetails, readTool } from "./read"; export { createReportFindingTool, createSubmitReviewTool, reportFindingTool, submitReviewTool } from "./review"; +export { + createRulebookTool, + filterRulebookRules, + formatRulesForPrompt, + type RulebookToolDetails, +} from "./rulebook"; export { BUNDLED_AGENTS, createTaskTool, taskTool } from "./task/index"; export type { TruncationResult } from "./truncate"; export { createWebFetchTool, type WebFetchToolDetails, webFetchCustomTool, webFetchTool } from "./web-fetch"; @@ -46,12 +52,6 @@ export { webSearchTool, } from "./web-search/index"; export { createWriteTool, type WriteToolDetails, type WriteToolOptions, writeTool } from "./write"; -export { - createRulebookTool, - filterRulebookRules, - formatRulesForPrompt, - type RulebookToolDetails, -} from "./rulebook"; import type { AgentTool } from "@oh-my-pi/pi-agent-core"; import { askTool, createAskTool } from "./ask"; diff --git a/packages/coding-agent/src/modes/interactive/components/extensions/extension-dashboard.ts b/packages/coding-agent/src/modes/interactive/components/extensions/extension-dashboard.ts index 83cad1e42..a486952ce 100644 --- a/packages/coding-agent/src/modes/interactive/components/extensions/extension-dashboard.ts +++ b/packages/coding-agent/src/modes/interactive/components/extensions/extension-dashboard.ts @@ -1,196 +1,297 @@ /** - * ExtensionDashboard - Main container for the Extension Control Center. + * ExtensionDashboard - Tabbed layout for the Extension Control Center. * - * Orchestrates the 3-column layout, handles keyboard navigation between panes, - * and manages state updates. + * Layout: + * - Top: Horizontal tab bar for provider selection + * - Body: 2-column grid (inventory list | preview panel) + * + * Navigation: + * - TAB/Shift+TAB: Cycle through provider tabs + * - Up/Down/j/k: Navigate list + * - Space: Toggle selected item (or master switch) + * - Esc: Close dashboard (clears search first if active) */ import { - Container, - isCtrlC, - isEnter, - isEscape, - isShiftTab, - isTab, - Spacer, - Text, + type Component, + Container, + isCtrlC, + isEscape, + isShiftTab, + isTab, + Spacer, + Text, + truncateToWidth, + visibleWidth, } from "@oh-my-pi/pi-tui"; import type { SettingsManager } from "../../../../core/settings-manager"; import { theme } from "../../theme/theme"; import { DynamicBorder } from "../dynamic-border"; import { ExtensionList } from "./extension-list"; -import { HolyGrailLayout } from "./holy-grail-layout"; import { InspectorPanel } from "./inspector-panel"; -import { SidebarTree } from "./sidebar-tree"; -import { createInitialState, refreshState } from "./state-manager"; -import type { DashboardCallbacks, DashboardState, FocusPane } from "./types"; +import { applyFilter, createInitialState, filterByProvider, refreshState, toggleProvider } from "./state-manager"; +import type { DashboardState } from "./types"; export class ExtensionDashboard extends Container { - private state: DashboardState; - private layout: HolyGrailLayout; - private sidebar: SidebarTree; - private mainList: ExtensionList; - private inspector: InspectorPanel; - private settingsManager: SettingsManager | null; - private cwd: string; + private state: DashboardState; + private mainList: ExtensionList; + private inspector: InspectorPanel; + private settingsManager: SettingsManager | null; + private cwd: string; - public onClose?: () => void; + public onClose?: () => void; - constructor(cwd: string, settingsManager: SettingsManager | null = null) { - super(); - this.cwd = cwd; - this.settingsManager = settingsManager; - const disabledIds = settingsManager?.getDisabledExtensions() ?? []; - this.state = createInitialState(cwd, disabledIds); + constructor(cwd: string, settingsManager: SettingsManager | null = null) { + super(); + this.cwd = cwd; + this.settingsManager = settingsManager; + const disabledIds = settingsManager?.getDisabledExtensions() ?? []; + this.state = createInitialState(cwd, disabledIds); - // Create sidebar - this.sidebar = new SidebarTree(this.state.sidebarTree, { - onProviderToggle: (providerId, enabled) => { - this.refreshFromState(); - }, - onSelectionChange: (nodeId) => { - // Could filter main list by provider - }, - onTreeChange: () => { - // Refresh flat tree in state - }, - }); + // Create main list - always focused + this.mainList = new ExtensionList(this.state.searchFiltered, { + onSelectionChange: (ext) => { + this.state.selected = ext; + this.inspector.setExtension(ext); + }, + onToggle: (extensionId, enabled) => { + this.handleExtensionToggle(extensionId, enabled); + }, + onMasterToggle: (providerId) => { + this.handleProviderToggle(providerId); + }, + masterSwitchProvider: this.getActiveProviderId(), + }); + this.mainList.setFocused(true); - // Create main list - this.mainList = new ExtensionList(this.state.extensions, { - onSelectionChange: (ext) => { - this.state.selected = ext; - this.inspector.setExtension(ext); - }, - onToggle: (extensionId, enabled) => { - this.handleExtensionToggle(extensionId, enabled); - }, - }); + // Create inspector + this.inspector = new InspectorPanel(); + if (this.state.selected) { + this.inspector.setExtension(this.state.selected); + } - // Create inspector - this.inspector = new InspectorPanel(); - if (this.state.selected) { - this.inspector.setExtension(this.state.selected); - } + this.buildLayout(); + } - // Create layout - this.layout = new HolyGrailLayout(this.sidebar, this.mainList, this.inspector); + private getActiveProviderId(): string | null { + const tab = this.state.tabs[this.state.activeTabIndex]; + return tab && tab.id !== "all" ? tab.id : null; + } - // Set initial focus - this.updateFocus(); + private buildLayout(): void { + this.clear(); - // Build component tree - this.addChild(new DynamicBorder()); - this.addChild(new Text(theme.bold(theme.fg("accent", " Extension Control Center")), 0, 0)); - this.addChild( - new Text( - theme.fg("dim", " Tab: pane j/k: nav Space: toggle Enter: expand type: search Esc: close"), - 0, - 0, - ), - ); - this.addChild(new Spacer(1)); - this.addChild(this.layout); - this.addChild(new DynamicBorder()); - } + // Top border + this.addChild(new DynamicBorder()); - private updateFocus(): void { - this.sidebar.setFocused(this.state.focusPane === "sidebar"); - this.mainList.setFocused(this.state.focusPane === "main"); - this.layout.setFocusedPane(this.state.focusPane); - } + // Title + this.addChild(new Text(theme.bold(theme.fg("accent", " Extension Control Center")), 0, 0)); - private cycleFocusRight(): void { - switch (this.state.focusPane) { - case "sidebar": - this.state.focusPane = "main"; - break; - case "main": - this.state.focusPane = "inspector"; - break; - case "inspector": - this.state.focusPane = "sidebar"; - break; - } - this.updateFocus(); - } + // Tab bar + this.addChild(new Text(this.renderTabBar(), 0, 0)); + this.addChild(new Spacer(1)); - private cycleFocusLeft(): void { - switch (this.state.focusPane) { - case "sidebar": - this.state.focusPane = "inspector"; - break; - case "main": - this.state.focusPane = "sidebar"; - break; - case "inspector": - this.state.focusPane = "main"; - break; - } - this.updateFocus(); - } + // Help text + // 2-column body + this.addChild(new TwoColumnBody(this.mainList, this.inspector)); - private handleExtensionToggle(extensionId: string, enabled: boolean): void { - if (!this.settingsManager) return; + this.addChild(new Spacer(1)); + this.addChild(new Text(theme.fg("dim", " ↑/↓: navigate Space: toggle Tab: next provider Esc: close"), 0, 0)); - if (enabled) { - this.settingsManager.enableExtension(extensionId); - } else { - this.settingsManager.disableExtension(extensionId); - } + // Bottom border + this.addChild(new DynamicBorder()); + } - this.refreshFromState(); - } + private renderTabBar(): string { + const parts: string[] = [" "]; - private refreshFromState(): void { - const disabledIds = this.settingsManager?.getDisabledExtensions() ?? []; - this.state = refreshState(this.state, this.cwd, disabledIds); - this.sidebar.setTree(this.state.sidebarTree); - this.mainList.setExtensions(this.state.extensions); - if (this.state.selected) { - this.inspector.setExtension(this.state.selected); - } - } + for (let i = 0; i < this.state.tabs.length; i++) { + const tab = this.state.tabs[i]; + const isActive = i === this.state.activeTabIndex; + const isEmpty = tab.count === 0 && tab.id !== "all"; + const isDisabled = !tab.enabled && tab.id !== "all"; - handleInput(data: string): void { - // Ctrl+C - close dashboard - if (isCtrlC(data)) { - this.onClose?.(); - return; - } + // Build label with count + let label = tab.label; + if (tab.count > 0) { + label += ` (${tab.count})`; + } - // Escape: Clear search if in main pane with query, otherwise close - if (isEscape(data)) { - if (this.state.focusPane === "main") { - this.mainList.clearSearch(); - } - this.onClose?.(); - return; - } + // Apply strikethrough for disabled providers + const displayLabel = isDisabled ? label.split("").join("\u0336") + "\u0336" : label; - // Tab: Cycle focus right - if (isTab(data)) { - this.cycleFocusRight(); - return; - } + if (isActive) { + // Active tab: background highlight + parts.push(theme.bg("selectedBg", ` ${displayLabel} `)); + } else if (isDisabled) { + // Disabled provider: strikethrough + dim + parts.push(theme.fg("dim", ` ${displayLabel} `)); + } else if (isEmpty) { + // Empty enabled provider: very dim, unselectable + parts.push(`\x1b[38;5;238m ${label} \x1b[0m`); + } else { + // Normal enabled provider + parts.push(theme.fg("muted", ` ${label} `)); + } + } - // Shift+Tab: Cycle focus left - if (isShiftTab(data)) { - this.cycleFocusLeft(); - return; - } + return parts.join(""); + } - // Delegate to focused pane - switch (this.state.focusPane) { - case "sidebar": - this.sidebar.handleInput(data); - break; - case "main": - this.mainList.handleInput(data); - break; - case "inspector": - // Inspector is read-only - break; - } - } + private handleProviderToggle(providerId: string): void { + toggleProvider(providerId); + this.refreshFromState(); + } + + private handleExtensionToggle(extensionId: string, enabled: boolean): void { + if (!this.settingsManager) return; + + if (enabled) { + this.settingsManager.enableExtension(extensionId); + } else { + this.settingsManager.disableExtension(extensionId); + } + + this.refreshFromState(); + } + + private refreshFromState(): void { + // Remember current tab ID before refresh + const currentTabId = this.state.tabs[this.state.activeTabIndex]?.id; + + const disabledIds = this.settingsManager?.getDisabledExtensions() ?? []; + this.state = refreshState(this.state, this.cwd, disabledIds); + + // Find the same tab in the new (re-sorted) list + if (currentTabId) { + const newIndex = this.state.tabs.findIndex((t) => t.id === currentTabId); + if (newIndex >= 0) { + this.state.activeTabIndex = newIndex; + } + } + + this.mainList.setExtensions(this.state.searchFiltered); + this.mainList.setMasterSwitchProvider(this.getActiveProviderId()); + + if (this.state.selected) { + this.inspector.setExtension(this.state.selected); + } + + this.buildLayout(); + } + + private switchTab(direction: 1 | -1): void { + const numTabs = this.state.tabs.length; + if (numTabs === 0) return; + + // Find next selectable tab (skip empty+enabled providers) + let nextIndex = this.state.activeTabIndex; + for (let i = 0; i < numTabs; i++) { + nextIndex = (nextIndex + direction + numTabs) % numTabs; + const tab = this.state.tabs[nextIndex]; + const isEmptyEnabled = tab.count === 0 && tab.enabled && tab.id !== "all"; + if (!isEmptyEnabled) break; + } + this.state.activeTabIndex = nextIndex; + + // Re-filter for new tab + const tab = this.state.tabs[this.state.activeTabIndex]; + this.state.tabFiltered = filterByProvider(this.state.extensions, tab.id); + this.state.searchFiltered = applyFilter(this.state.tabFiltered, this.state.searchQuery); + this.state.listIndex = 0; + this.state.scrollOffset = 0; + this.state.selected = this.state.searchFiltered[0] ?? null; + + // Update list + this.mainList.setExtensions(this.state.searchFiltered); + this.mainList.setMasterSwitchProvider(this.getActiveProviderId()); + this.mainList.resetSelection(); + + if (this.state.selected) { + this.inspector.setExtension(this.state.selected); + } + + this.buildLayout(); + } + + handleInput(data: string): void { + // Ctrl+C - close immediately + if (isCtrlC(data)) { + this.onClose?.(); + return; + } + + // Escape - clear search first, then close + if (isEscape(data)) { + if (this.state.searchQuery.length > 0) { + this.state.searchQuery = ""; + this.state.searchFiltered = this.state.tabFiltered; + this.mainList.setExtensions(this.state.searchFiltered); + this.mainList.clearSearch(); + this.buildLayout(); + return; + } + this.onClose?.(); + return; + } + + // Tab/Shift+Tab: Cycle through tabs + if (isTab(data)) { + this.switchTab(1); + return; + } + if (isShiftTab(data)) { + this.switchTab(-1); + return; + } + + // All other input goes to the list + this.mainList.handleInput(data); + + // Sync search query back to state + const query = this.mainList.getSearchQuery(); + if (query !== this.state.searchQuery) { + this.state.searchQuery = query; + this.state.searchFiltered = applyFilter(this.state.tabFiltered, query); + } + } +} + +/** + * Two-column body component for side-by-side rendering. + */ +class TwoColumnBody implements Component { + private leftPane: ExtensionList; + private rightPane: InspectorPanel; + + constructor(left: ExtensionList, right: InspectorPanel) { + this.leftPane = left; + this.rightPane = right; + } + + render(width: number): string[] { + const leftWidth = Math.floor(width * 0.5); + const rightWidth = width - leftWidth - 3; + + const leftLines = this.leftPane.render(leftWidth); + const rightLines = this.rightPane.render(rightWidth); + + const maxLines = Math.max(leftLines.length, rightLines.length); + const combined: string[] = []; + const separator = theme.fg("dim", " │ "); + + for (let i = 0; i < maxLines; i++) { + const left = truncateToWidth(leftLines[i] ?? "", leftWidth); + const leftPadded = left + " ".repeat(Math.max(0, leftWidth - visibleWidth(left))); + const right = truncateToWidth(rightLines[i] ?? "", rightWidth); + combined.push(leftPadded + separator + right); + } + + return combined; + } + + invalidate(): void { + this.leftPane.invalidate?.(); + this.rightPane.invalidate?.(); + } } diff --git a/packages/coding-agent/src/modes/interactive/components/extensions/extension-list.ts b/packages/coding-agent/src/modes/interactive/components/extensions/extension-list.ts index d01a88a0a..d5be4e5d0 100644 --- a/packages/coding-agent/src/modes/interactive/components/extensions/extension-list.ts +++ b/packages/coding-agent/src/modes/interactive/components/extensions/extension-list.ts @@ -1,475 +1,477 @@ /** - * ExtensionList - Tree view with grouping and fuzzy search. + * ExtensionList - Inventory list with Master Switch and fuzzy search. * - * Displays extensions grouped by kind with collapsible headers. - * Supports filtering via fuzzy search (flattens tree when active). + * When viewing a specific provider (not "ALL"), Row #0 is the Master Switch + * that toggles the entire provider. All items below are dimmed when the + * master switch is off. */ import { - type Component, - isArrowDown, - isArrowLeft, - isArrowRight, - isArrowUp, - isBackspace, - isEnter, - truncateToWidth, - visibleWidth, + type Component, + isArrowDown, + isArrowUp, + isBackspace, + isEnter, + truncateToWidth, + visibleWidth, } from "@oh-my-pi/pi-tui"; +import { isProviderEnabled } from "../../../../discovery"; import { theme } from "../../theme/theme"; import { applyFilter } from "./state-manager"; import type { Extension, ExtensionKind, ExtensionState } from "./types"; export interface ExtensionListCallbacks { - /** Called when selection changes */ - onSelectionChange?: (extension: Extension | null) => void; - /** Called when extension is toggled (Enter pressed on item) */ - onToggle?: (extensionId: string, enabled: boolean) => void; + /** Called when selection changes */ + onSelectionChange?: (extension: Extension | null) => void; + /** Called when extension is toggled */ + onToggle?: (extensionId: string, enabled: boolean) => void; + /** Called when master switch is toggled */ + onMasterToggle?: (providerId: string) => void; + /** Provider ID for master switch (null = no master switch) */ + masterSwitchProvider?: string | null; } -const MAX_VISIBLE = 30; +const MAX_VISIBLE = 25; -/** Tree group for a kind of extensions */ -interface TreeGroup { - id: string; - kind: ExtensionKind; - label: string; - icon: string; - collapsed: boolean; - items: Extension[]; -} - -/** Flattened tree item for rendering */ -type FlatItem = - | { type: "group"; group: TreeGroup } - | { type: "item"; item: Extension; group: TreeGroup }; +/** Flattened list item for rendering */ +type ListItem = + | { type: "master"; providerId: string; providerName: string; enabled: boolean } + | { type: "kind-header"; kind: ExtensionKind; label: string; icon: string; count: number } + | { type: "extension"; item: Extension }; export class ExtensionList implements Component { - private extensions: Extension[] = []; - private groups: TreeGroup[] = []; - private flatItems: FlatItem[] = []; - private selectedIndex = 0; - private scrollOffset = 0; - private searchQuery = ""; - private focused = false; - private callbacks: ExtensionListCallbacks; - /** True when there's an active filter (query.length > 0) */ - private hasFilter = false; + private extensions: Extension[] = []; + private listItems: ListItem[] = []; + private selectedIndex = 0; + private scrollOffset = 0; + private searchQuery = ""; + private focused = false; + private callbacks: ExtensionListCallbacks; + private masterSwitchProvider: string | null = null; - constructor(extensions: Extension[], callbacks: ExtensionListCallbacks = {}) { - this.extensions = extensions; - this.callbacks = callbacks; - this.rebuildGroups(); - } + constructor(extensions: Extension[], callbacks: ExtensionListCallbacks = {}) { + this.extensions = extensions; + this.callbacks = callbacks; + this.masterSwitchProvider = callbacks.masterSwitchProvider ?? null; + this.rebuildList(); + } - setExtensions(extensions: Extension[]): void { - this.extensions = extensions; - this.rebuildGroups(); - this.clampSelection(); - } + setExtensions(extensions: Extension[]): void { + this.extensions = extensions; + this.rebuildList(); + this.clampSelection(); + } - setFocused(focused: boolean): void { - this.focused = focused; - } + setFocused(focused: boolean): void { + this.focused = focused; + } - getSelectedExtension(): Extension | null { - const item = this.flatItems[this.selectedIndex]; - if (item?.type === "item") { - return item.item; - } - return null; - } + setMasterSwitchProvider(providerId: string | null): void { + this.masterSwitchProvider = providerId; + this.rebuildList(); + } - setSearchQuery(query: string): void { - this.searchQuery = query; - this.hasFilter = query.length > 0; - this.rebuildGroups(); - this.selectedIndex = 0; - this.scrollOffset = 0; - this.notifySelectionChange(); - } + getSearchQuery(): string { + return this.searchQuery; + } - /** Clear search filter */ - clearSearch(): void { - this.setSearchQuery(""); - } + resetSelection(): void { + this.selectedIndex = 0; + this.scrollOffset = 0; + this.notifySelectionChange(); + } - invalidate(): void {} + getSelectedExtension(): Extension | null { + const item = this.listItems[this.selectedIndex]; + return item?.type === "extension" ? item.item : null; + } - render(width: number): string[] { - const lines: string[] = []; + /** Get the currently selected kind header (for preview purposes) */ + getSelectedKind(): ExtensionKind | null { + const item = this.listItems[this.selectedIndex]; + return item?.type === "kind-header" ? item.kind : null; + } - // Search bar - cursor shown when focused - const searchPrefix = theme.fg("muted", "Search: "); - const searchText = this.searchQuery || (this.focused ? "" : theme.fg("dim", "type to filter")); - const cursor = this.focused ? theme.fg("accent", "_") : ""; - lines.push(searchPrefix + searchText + cursor); - lines.push(""); + setSearchQuery(query: string): void { + this.searchQuery = query; + this.rebuildList(); + this.selectedIndex = 0; + this.scrollOffset = 0; + this.notifySelectionChange(); + } - if (this.flatItems.length === 0) { - lines.push(theme.fg("muted", " No extensions found")); - return lines; - } + clearSearch(): void { + this.setSearchQuery(""); + } - // Calculate visible range - const startIdx = this.scrollOffset; - const endIdx = Math.min(startIdx + MAX_VISIBLE, this.flatItems.length); + invalidate(): void {} - // Render visible items - for (let i = startIdx; i < endIdx; i++) { - const flatItem = this.flatItems[i]; - const isSelected = this.focused && i === this.selectedIndex; + render(width: number): string[] { + const lines: string[] = []; - if (flatItem.type === "group") { - lines.push(this.renderGroupHeader(flatItem.group, isSelected, width)); - } else { - lines.push(this.renderExtensionRow(flatItem.item, isSelected, width)); - } - } + // Search bar + const searchPrefix = theme.fg("muted", "Search: "); + const searchText = this.searchQuery || (this.focused ? "" : theme.fg("dim", "type to filter")); + const cursor = this.focused ? theme.fg("accent", "_") : ""; + lines.push(searchPrefix + searchText + cursor); + lines.push(""); - // Scroll indicator - if (this.flatItems.length > MAX_VISIBLE) { - const indicator = theme.fg("muted", ` (${this.selectedIndex + 1}/${this.flatItems.length})`); - lines.push(indicator); - } + if (this.listItems.length === 0) { + lines.push(theme.fg("muted", " No extensions found for this provider.")); + return lines; + } - return lines; - } + // Determine if master switch is off (for dimming child items) + const masterDisabled = this.masterSwitchProvider !== null && !isProviderEnabled(this.masterSwitchProvider); - private renderGroupHeader(group: TreeGroup, isSelected: boolean, width: number): string { - const kindIcon = group.icon; - const countStr = `(${group.items.length})`; + // Calculate visible range + const startIdx = this.scrollOffset; + const endIdx = Math.min(startIdx + MAX_VISIBLE, this.listItems.length); - let line = `${kindIcon} ${group.label} ${theme.fg("muted", countStr)}`; + // Render visible items + for (let i = startIdx; i < endIdx; i++) { + const listItem = this.listItems[i]; + const isSelected = this.focused && i === this.selectedIndex; - if (isSelected) { - line = theme.bold(theme.fg("accent", line)); - line = theme.bg("selectedBg", line); - } + if (listItem.type === "master") { + lines.push(this.renderMasterSwitch(listItem, isSelected, width)); + } else if (listItem.type === "kind-header") { + lines.push(this.renderKindHeader(listItem, isSelected, width)); + } else { + lines.push(this.renderExtensionRow(listItem.item, isSelected, width, masterDisabled)); + } + } - return truncateToWidth(line, width); - } + // Scroll indicator + if (this.listItems.length > MAX_VISIBLE) { + const indicator = theme.fg("muted", ` (${this.selectedIndex + 1}/${this.listItems.length})`); + lines.push(indicator); + } - private renderExtensionRow(ext: Extension, isSelected: boolean, width: number): string { - // Status icon - const stateIcon = this.getStateIcon(ext.state); + return lines; + } - // Name - let name = ext.displayName; - const nameWidth = Math.min(28, width - 10); + private renderMasterSwitch(item: ListItem & { type: "master" }, isSelected: boolean, width: number): string { + const checkbox = item.enabled ? theme.fg("success", "[x]") : theme.fg("dim", "[ ]"); + const icon = "📦"; + let label = `Enable ${item.providerName}`; + const badge = theme.fg("warning", "(Master Switch)"); - // Trigger (if present) - const trigger = ext.trigger ? theme.fg("dim", ext.trigger) : ""; + let line = `${checkbox} ${icon} ${label} ${badge}`; - // Build the line with tree branch structure - let line = ` ├─ ${stateIcon} `; + if (isSelected) { + line = theme.bold(theme.fg("accent", line)); + line = theme.bg("selectedBg", line); + } else if (!item.enabled) { + line = theme.fg("dim", line); + } - if (isSelected) { - name = theme.bold(theme.fg("accent", name)); - } else if (ext.state === "disabled") { - name = theme.fg("dim", name); - } else if (ext.state === "shadowed") { - name = theme.fg("warning", name); - } + return truncateToWidth(line, width); + } - // Pad name - const namePadded = this.padText(name, nameWidth); - line += namePadded; + private renderKindHeader(item: ListItem & { type: "kind-header" }, isSelected: boolean, width: number): string { + const countBadge = theme.fg("muted", `(${item.count})`); + let line = `${item.icon} ${item.label} ${countBadge}`; - // Add trigger with spacing - if (trigger) { - const remainingWidth = width - visibleWidth(line) - 2; - if (remainingWidth > 5) { - line += " " + truncateToWidth(trigger, remainingWidth); - } - } + if (isSelected) { + line = theme.bold(theme.fg("accent", line)); + line = theme.bg("selectedBg", line); + } else { + line = theme.fg("muted", line); + } - // Apply selection background - if (isSelected) { - line = theme.bg("selectedBg", line); - } + return truncateToWidth(line, width); + } - return truncateToWidth(line, width); - } + private renderExtensionRow(ext: Extension, isSelected: boolean, width: number, masterDisabled: boolean): string { + // When master is disabled, all items appear dimmed + const effectivelyDisabled = masterDisabled || ext.state === "disabled"; - private getKindIcon(kind: ExtensionKind): string { - switch (kind) { - case "skill": - return "⚡"; - case "tool": - case "slash-command": - return "🛠️"; - case "mcp": - return "📦"; - case "rule": - return "📋"; - case "hook": - return "🪝"; - case "prompt": - return "💬"; - case "context-file": - return "📄"; - case "instruction": - return "📌"; - default: - return "•"; - } - } + // Status icon + const stateIcon = this.getStateIcon(ext.state, masterDisabled); - private getStateIcon(state: ExtensionState): string { - switch (state) { - case "active": - return theme.fg("success", "●"); - case "disabled": - return theme.fg("dim", "○"); - case "shadowed": - return theme.fg("warning", "◐"); - } - } + // Name + let name = ext.displayName; + const nameWidth = Math.min(24, width - 16); - private padText(text: string, targetWidth: number): string { - const width = visibleWidth(text); - if (width >= targetWidth) { - return truncateToWidth(text, targetWidth); - } - return text + " ".repeat(targetWidth - width); - } + // Build the line with indentation (visually "inside" the master switch) + let line = ` ${stateIcon} `; - private rebuildGroups(): void { - if (this.hasFilter) { - // Flatten: show only matching items, no group headers - const filtered = applyFilter(this.extensions, this.searchQuery); - this.flatItems = filtered.map((item) => ({ - type: "item" as const, - item, - group: this.findGroupForKind(item.kind), - })); - } else { - // Build groups from extensions - this.groups = this.buildGroupsFromExtensions(); + if (isSelected && !masterDisabled) { + name = theme.bold(theme.fg("accent", name)); + } else if (effectivelyDisabled) { + name = theme.fg("dim", name); + } else if (ext.state === "shadowed") { + name = theme.fg("warning", name); + } - // Flatten tree based on collapsed state - this.flatItems = []; - for (const group of this.groups) { - // Add group header - this.flatItems.push({ type: "group", group }); + // Pad name + const namePadded = this.padText(name, nameWidth); + line += namePadded; - // Add items if not collapsed - if (!group.collapsed) { - for (const item of group.items) { - this.flatItems.push({ type: "item", item, group }); - } - } - } - } - } + // Trigger hint + if (ext.trigger) { + const triggerStyle = effectivelyDisabled ? "dim" : "muted"; + const remainingWidth = width - visibleWidth(line) - 2; + if (remainingWidth > 5) { + line += " " + truncateToWidth(theme.fg(triggerStyle as "dim" | "muted", ext.trigger), remainingWidth); + } + } - private buildGroupsFromExtensions(): TreeGroup[] { - // Group extensions by kind - const kindMap = new Map(); + // Apply selection background + if (isSelected) { + line = theme.bg("selectedBg", line); + } - for (const ext of this.extensions) { - const items = kindMap.get(ext.kind) ?? []; - items.push(ext); - kindMap.set(ext.kind, items); - } + return truncateToWidth(line, width); + } - // Create groups with labels and icons - const groups: TreeGroup[] = []; - const kindOrder: ExtensionKind[] = [ - "skill", - "tool", - "slash-command", - "context-file", - "rule", - "mcp", - "hook", - "prompt", - "instruction", - ]; + private getKindIcon(kind: ExtensionKind): string { + switch (kind) { + case "skill": + return "⚡"; + case "tool": + return "🔧"; + case "slash-command": + return "🔗"; + case "mcp": + return "🔄"; + case "rule": + return "📋"; + case "hook": + return "🪝"; + case "prompt": + return "💬"; + case "context-file": + return "📄"; + case "instruction": + return "📌"; + default: + return "•"; + } + } - for (const kind of kindOrder) { - const items = kindMap.get(kind); - if (items && items.length > 0) { - groups.push({ - id: `group:${kind}`, - kind, - label: this.getKindLabel(kind), - icon: this.getKindIcon(kind), - collapsed: false, - items, - }); - } - } + private getStateIcon(state: ExtensionState, masterDisabled: boolean): string { + if (masterDisabled) { + return theme.fg("dim", "○"); + } + switch (state) { + case "active": + return theme.fg("success", "●"); + case "disabled": + return theme.fg("dim", "⊘"); + case "shadowed": + return theme.fg("warning", "◐"); + } + } - return groups; - } + private padText(text: string, targetWidth: number): string { + const width = visibleWidth(text); + if (width >= targetWidth) { + return truncateToWidth(text, targetWidth); + } + return text + " ".repeat(targetWidth - width); + } - private findGroupForKind(kind: ExtensionKind): TreeGroup { - return ( - this.groups.find((g) => g.kind === kind) ?? { - id: `group:${kind}`, - kind, - label: this.getKindLabel(kind), - icon: this.getKindIcon(kind), - collapsed: false, - items: [], - } - ); - } + private rebuildList(): void { + this.listItems = []; - private getKindLabel(kind: ExtensionKind): string { - switch (kind) { - case "skill": - return "Skills"; - case "tool": - return "Custom Tools"; - case "slash-command": - return "Slash Commands"; - case "mcp": - return "MCP Servers"; - case "rule": - return "Rules"; - case "hook": - return "Hooks"; - case "prompt": - return "Prompts"; - case "context-file": - return "Context Files"; - case "instruction": - return "Instructions"; - default: - return "Other"; - } - } + // Apply search filter + const filtered = this.searchQuery.length > 0 ? applyFilter(this.extensions, this.searchQuery) : this.extensions; - private clampSelection(): void { - if (this.flatItems.length === 0) { - this.selectedIndex = 0; - this.scrollOffset = 0; - return; - } + // When searching, show flat list + if (this.searchQuery.length > 0) { + for (const ext of filtered) { + this.listItems.push({ type: "extension", item: ext }); + } + return; + } - this.selectedIndex = Math.min(this.selectedIndex, this.flatItems.length - 1); - this.selectedIndex = Math.max(0, this.selectedIndex); + // Provider-specific view: Master switch + flat list + if (this.masterSwitchProvider) { + const providerName = filtered[0]?.source.providerName ?? this.masterSwitchProvider; + const enabled = isProviderEnabled(this.masterSwitchProvider); - // Adjust scroll offset - if (this.selectedIndex < this.scrollOffset) { - this.scrollOffset = this.selectedIndex; - } else if (this.selectedIndex >= this.scrollOffset + MAX_VISIBLE) { - this.scrollOffset = this.selectedIndex - MAX_VISIBLE + 1; - } - } + this.listItems.push({ + type: "master", + providerId: this.masterSwitchProvider, + providerName, + enabled, + }); - handleInput(data: string): void { - const charCode = data.length === 1 ? data.charCodeAt(0) : -1; + for (const ext of filtered) { + this.listItems.push({ type: "extension", item: ext }); + } + return; + } - // Navigation - j/k or arrows - if (isArrowUp(data) || data === "k") { - this.moveSelectionUp(); - return; - } + // ALL view: Group by kind with headers + const byKind = new Map(); + for (const ext of filtered) { + const list = byKind.get(ext.kind) ?? []; + list.push(ext); + byKind.set(ext.kind, list); + } - if (isArrowDown(data) || data === "j") { - this.moveSelectionDown(); - return; - } + const kindOrder: ExtensionKind[] = [ + "skill", + "tool", + "slash-command", + "rule", + "mcp", + "hook", + "prompt", + "context-file", + "instruction", + ]; - // Left arrow: collapse current group or move to parent group - if (isArrowLeft(data)) { - const item = this.flatItems[this.selectedIndex]; - if (item?.type === "group" && !item.group.collapsed) { - item.group.collapsed = true; - this.rebuildGroups(); - this.clampSelection(); - } else if (item?.type === "item") { - // Move selection to parent group header - const groupIndex = this.flatItems.findIndex( - (fi) => fi.type === "group" && fi.group.kind === item.group.kind - ); - if (groupIndex >= 0) { - this.selectedIndex = groupIndex; - this.clampSelection(); - this.notifySelectionChange(); - } - } - return; - } + for (const kind of kindOrder) { + const items = byKind.get(kind); + if (!items || items.length === 0) continue; - // Right arrow: expand current group - if (isArrowRight(data)) { - const item = this.flatItems[this.selectedIndex]; - if (item?.type === "group" && item.group.collapsed) { - item.group.collapsed = false; - this.rebuildGroups(); - this.clampSelection(); - } - return; - } + this.listItems.push({ + type: "kind-header", + kind, + label: this.getKindLabel(kind), + icon: this.getKindIcon(kind), + count: items.length, + }); - // Space: TOGGLE item enabled/disabled - if (data === " ") { - const item = this.flatItems[this.selectedIndex]; - if (item?.type === "item") { - const newEnabled = item.item.state === "disabled"; - this.callbacks.onToggle?.(item.item.id, newEnabled); - } - return; - } + for (const ext of items) { + this.listItems.push({ type: "extension", item: ext }); + } + } + } - // Enter: expand/collapse group - if (isEnter(data)) { - const item = this.flatItems[this.selectedIndex]; - if (item?.type === "group") { - item.group.collapsed = !item.group.collapsed; - this.rebuildGroups(); - this.clampSelection(); - } - return; - } + private getKindLabel(kind: ExtensionKind): string { + switch (kind) { + case "skill": + return "Skills"; + case "tool": + return "Tools"; + case "slash-command": + return "Commands"; + case "rule": + return "Rules"; + case "mcp": + return "MCP Servers"; + case "hook": + return "Hooks"; + case "prompt": + return "Prompts"; + case "context-file": + return "Context"; + case "instruction": + return "Instructions"; + default: + return kind; + } + } - // Backspace: delete from search query - if (isBackspace(data)) { - if (this.searchQuery.length > 0) { - this.setSearchQuery(this.searchQuery.slice(0, -1)); - } - return; - } + private clampSelection(): void { + if (this.listItems.length === 0) { + this.selectedIndex = 0; + this.scrollOffset = 0; + return; + } - // Printable characters (except special keys) -> search - // Skip j/k (navigation), skip space, skip control chars - if (data.length === 1 && charCode > 32 && charCode < 127) { - // Skip j/k as they're navigation - if (data === "j" || data === "k") { - return; - } - this.setSearchQuery(this.searchQuery + data); - return; - } - } + this.selectedIndex = Math.min(this.selectedIndex, this.listItems.length - 1); + this.selectedIndex = Math.max(0, this.selectedIndex); - private moveSelectionUp(): void { - if (this.selectedIndex > 0) { - this.selectedIndex--; - if (this.selectedIndex < this.scrollOffset) { - this.scrollOffset = this.selectedIndex; - } - this.notifySelectionChange(); - } - } + // Adjust scroll offset + if (this.selectedIndex < this.scrollOffset) { + this.scrollOffset = this.selectedIndex; + } else if (this.selectedIndex >= this.scrollOffset + MAX_VISIBLE) { + this.scrollOffset = this.selectedIndex - MAX_VISIBLE + 1; + } + } - private moveSelectionDown(): void { - if (this.selectedIndex < this.flatItems.length - 1) { - this.selectedIndex++; - if (this.selectedIndex >= this.scrollOffset + MAX_VISIBLE) { - this.scrollOffset = this.selectedIndex - MAX_VISIBLE + 1; - } - this.notifySelectionChange(); - } - } + handleInput(data: string): void { + const charCode = data.length === 1 ? data.charCodeAt(0) : -1; - private notifySelectionChange(): void { - const ext = this.getSelectedExtension(); - this.callbacks.onSelectionChange?.(ext); - } + // Navigation + if (isArrowUp(data) || data === "k") { + this.moveSelectionUp(); + return; + } + + if (isArrowDown(data) || data === "j") { + this.moveSelectionDown(); + return; + } + + // Space: Toggle selected item + if (data === " ") { + const item = this.listItems[this.selectedIndex]; + if (item?.type === "master") { + this.callbacks.onMasterToggle?.(item.providerId); + } else if (item?.type === "extension") { + // Only allow toggling if master is enabled + const masterDisabled = this.masterSwitchProvider !== null && !isProviderEnabled(this.masterSwitchProvider); + if (!masterDisabled) { + const newEnabled = item.item.state === "disabled"; + this.callbacks.onToggle?.(item.item.id, newEnabled); + } + } + return; + } + + // Enter: Same as space - toggle selected item + if (isEnter(data)) { + const item = this.listItems[this.selectedIndex]; + if (item?.type === "master") { + this.callbacks.onMasterToggle?.(item.providerId); + } else if (item?.type === "extension") { + const masterDisabled = this.masterSwitchProvider !== null && !isProviderEnabled(this.masterSwitchProvider); + if (!masterDisabled) { + const newEnabled = item.item.state === "disabled"; + this.callbacks.onToggle?.(item.item.id, newEnabled); + } + } + return; + } + + // Backspace: Delete from search query + if (isBackspace(data)) { + if (this.searchQuery.length > 0) { + this.setSearchQuery(this.searchQuery.slice(0, -1)); + } + return; + } + + // Printable characters -> search + if (data.length === 1 && charCode > 32 && charCode < 127) { + // Skip j/k as they're navigation + if (data === "j" || data === "k") { + return; + } + this.setSearchQuery(this.searchQuery + data); + return; + } + } + + private moveSelectionUp(): void { + if (this.selectedIndex > 0) { + this.selectedIndex--; + if (this.selectedIndex < this.scrollOffset) { + this.scrollOffset = this.selectedIndex; + } + this.notifySelectionChange(); + } + } + + private moveSelectionDown(): void { + if (this.selectedIndex < this.listItems.length - 1) { + this.selectedIndex++; + if (this.selectedIndex >= this.scrollOffset + MAX_VISIBLE) { + this.scrollOffset = this.selectedIndex - MAX_VISIBLE + 1; + } + this.notifySelectionChange(); + } + } + + private notifySelectionChange(): void { + const ext = this.getSelectedExtension(); + this.callbacks.onSelectionChange?.(ext); + } } diff --git a/packages/coding-agent/src/modes/interactive/components/extensions/holy-grail-layout.ts b/packages/coding-agent/src/modes/interactive/components/extensions/holy-grail-layout.ts deleted file mode 100644 index e0550870b..000000000 --- a/packages/coding-agent/src/modes/interactive/components/extensions/holy-grail-layout.ts +++ /dev/null @@ -1,235 +0,0 @@ -/** - * HolyGrailLayout - 3-column layout with box-drawing borders. - * - * ``` - * ╭──────────┬──────────────────┬──────────────────╮ - * │ Sidebar │ Main List │ Inspector │ - * │ (20%) │ (40%) │ (40%) │ - * ╰──────────┴──────────────────┴──────────────────╯ - * ``` - */ - -import { type Component, visibleWidth } from "@oh-my-pi/pi-tui"; -import { theme } from "../../theme/theme"; -import type { FocusPane } from "./types"; - -/** - * Pad or truncate text to exact visible width. - */ -function padToWidth(text: string, targetWidth: number): string { - const width = visibleWidth(text); - if (width >= targetWidth) { - return truncateToWidth(text, targetWidth); - } - return text + " ".repeat(targetWidth - width); -} - -/** - * Truncate text to fit within width, preserving ANSI codes. - */ -function truncateToWidth(text: string, maxWidth: number): string { - if (maxWidth <= 0) return ""; - - let width = 0; - let result = ""; - let inAnsi = false; - let ansiCode = ""; - - for (let i = 0; i < text.length; i++) { - const char = text[i]; - - // Track ANSI escape sequences - if (char === "\x1b") { - inAnsi = true; - ansiCode = char; - continue; - } - - if (inAnsi) { - ansiCode += char; - if (char === "m" || char === "G" || char === "K" || char === "H" || char === "J") { - result += ansiCode; - inAnsi = false; - ansiCode = ""; - } - continue; - } - - // Calculate character width - const charWidth = visibleWidth(char); - if (width + charWidth > maxWidth) { - break; - } - - result += char; - width += charWidth; - } - - // Reset any active ANSI codes - if (result.includes("\x1b[")) { - result += "\x1b[0m"; - } - - return result; -} - -/** - * Column ratios for the layout. - */ -const SIDEBAR_RATIO = 0.20; -const MAIN_RATIO = 0.40; -const INSPECTOR_RATIO = 0.40; - -/** - * Minimum column widths. - */ -const MIN_SIDEBAR = 15; -const MIN_MAIN = 25; -const MIN_INSPECTOR = 15; - -export class HolyGrailLayout implements Component { - private sidebar: Component; - private mainList: Component; - private inspector: Component; - private focusedPane: FocusPane = "sidebar"; - // Cache widths to prevent layout shifts - private cachedWidth = 0; - private cachedSidebarWidth = 0; - private cachedMainWidth = 0; - private cachedInspectorWidth = 0; - - constructor(sidebar: Component, mainList: Component, inspector: Component) { - this.sidebar = sidebar; - this.mainList = mainList; - this.inspector = inspector; - } - - setFocusedPane(pane: FocusPane): void { - this.focusedPane = pane; - } - - invalidate(): void { - this.sidebar.invalidate?.(); - this.mainList.invalidate?.(); - this.inspector.invalidate?.(); - } - - render(width: number): string[] { - // Only recalculate widths if terminal width changed - if (width !== this.cachedWidth) { - this.cachedWidth = width; - // Content row format: │ sidebar │ main │ inspector │ - // Fixed chars: 4 borders (│) + 3 spaces = 7 - const fixedChars = 7; - const contentWidth = Math.max(0, width - fixedChars); - - // Distribute remaining width across columns - this.cachedSidebarWidth = Math.max(MIN_SIDEBAR, Math.floor(contentWidth * SIDEBAR_RATIO)); - this.cachedMainWidth = Math.max(MIN_MAIN, Math.floor(contentWidth * MAIN_RATIO)); - this.cachedInspectorWidth = Math.max(MIN_INSPECTOR, contentWidth - this.cachedSidebarWidth - this.cachedMainWidth); - - // Ensure total doesn't exceed contentWidth - const total = this.cachedSidebarWidth + this.cachedMainWidth + this.cachedInspectorWidth; - if (total > contentWidth) { - const excess = total - contentWidth; - if (this.cachedMainWidth > MIN_MAIN) { - this.cachedMainWidth = Math.max(MIN_MAIN, this.cachedMainWidth - excess); - } else if (this.cachedSidebarWidth > MIN_SIDEBAR) { - this.cachedSidebarWidth = Math.max(MIN_SIDEBAR, this.cachedSidebarWidth - excess); - } else { - this.cachedInspectorWidth = Math.max(1, this.cachedInspectorWidth - excess); - } - } - } - - const sidebarWidth = this.cachedSidebarWidth; - const mainWidth = this.cachedMainWidth; - const inspectorWidth = this.cachedInspectorWidth; - - // Render each panel - const sidebarLines = this.sidebar.render(sidebarWidth); - const mainLines = this.mainList.render(mainWidth); - const inspectorLines = this.inspector.render(inspectorWidth); - - // Find max height - const maxHeight = Math.max(sidebarLines.length, mainLines.length, inspectorLines.length, 1); - - const lines: string[] = []; - - // Top border - lines.push(this.renderTopBorder(sidebarWidth, mainWidth, inspectorWidth)); - - // Content rows - for (let i = 0; i < maxHeight; i++) { - const sidebarLine = sidebarLines[i] ?? ""; - const mainLine = mainLines[i] ?? ""; - const inspectorLine = inspectorLines[i] ?? ""; - lines.push(this.renderContentRow(sidebarLine, mainLine, inspectorLine, sidebarWidth, mainWidth, inspectorWidth)); - } - - // Bottom border - lines.push(this.renderBottomBorder(sidebarWidth, mainWidth, inspectorWidth)); - - return lines; - } - - /** - * Render top border: ╭──────┬──────────┬──────╮ - */ - private renderTopBorder(sw: number, mw: number, iw: number): string { - const sidebarBorder = this.focusedPane === "sidebar" ? "borderAccent" : "border"; - const mainBorder = this.focusedPane === "main" ? "borderAccent" : "border"; - const inspectorBorder = this.focusedPane === "inspector" ? "borderAccent" : "border"; - - return ( - theme.fg(sidebarBorder as any, "╭" + "─".repeat(sw + 1)) + - theme.fg("border" as any, "┬") + - theme.fg(mainBorder as any, "─".repeat(mw + 1)) + - theme.fg("border" as any, "┬") + - theme.fg(inspectorBorder as any, "─".repeat(iw + 1) + "╮") - ); - } - - /** - * Render content row: │ content │ content │ content │ - */ - private renderContentRow(s: string, m: string, ins: string, sw: number, mw: number, iw: number): string { - const sidebarBorder = this.focusedPane === "sidebar" ? "borderAccent" : "border"; - const mainBorder = this.focusedPane === "main" ? "borderAccent" : "border"; - const inspectorBorder = this.focusedPane === "inspector" ? "borderAccent" : "border"; - - const paddedS = padToWidth(s, sw); - const paddedM = padToWidth(m, mw); - const paddedI = padToWidth(ins, iw); - - return ( - theme.fg(sidebarBorder as any, "│") + - " " + - paddedS + - theme.fg("border" as any, "│") + - " " + - paddedM + - theme.fg("border" as any, "│") + - " " + - paddedI + - theme.fg(inspectorBorder as any, "│") - ); - } - - /** - * Render bottom border: ╰──────┴──────────┴──────╯ - */ - private renderBottomBorder(sw: number, mw: number, iw: number): string { - const sidebarBorder = this.focusedPane === "sidebar" ? "borderAccent" : "border"; - const mainBorder = this.focusedPane === "main" ? "borderAccent" : "border"; - const inspectorBorder = this.focusedPane === "inspector" ? "borderAccent" : "border"; - - return ( - theme.fg(sidebarBorder as any, "╰" + "─".repeat(sw + 1)) + - theme.fg("border" as any, "┴") + - theme.fg(mainBorder as any, "─".repeat(mw + 1)) + - theme.fg("border" as any, "┴") + - theme.fg(inspectorBorder as any, "─".repeat(iw + 1) + "╯") - ); - } -} diff --git a/packages/coding-agent/src/modes/interactive/components/extensions/index.ts b/packages/coding-agent/src/modes/interactive/components/extensions/index.ts index ec8844edb..efd441146 100644 --- a/packages/coding-agent/src/modes/interactive/components/extensions/index.ts +++ b/packages/coding-agent/src/modes/interactive/components/extensions/index.ts @@ -4,8 +4,6 @@ export { ExtensionDashboard } from "./extension-dashboard"; export { ExtensionList } from "./extension-list"; -export { HolyGrailLayout } from "./holy-grail-layout"; export { InspectorPanel } from "./inspector-panel"; -export { SidebarTree } from "./sidebar-tree"; export * from "./state-manager"; export * from "./types"; diff --git a/packages/coding-agent/src/modes/interactive/components/extensions/inspector-panel.ts b/packages/coding-agent/src/modes/interactive/components/extensions/inspector-panel.ts index 9772ef7cf..e12c5ea69 100644 --- a/packages/coding-agent/src/modes/interactive/components/extensions/inspector-panel.ts +++ b/packages/coding-agent/src/modes/interactive/components/extensions/inspector-panel.ts @@ -4,307 +4,310 @@ * Shows name, description, origin, status, and kind-specific preview. */ -import { type Component, truncateToWidth, wrapTextWithAnsi } from "@oh-my-pi/pi-tui"; import { readFileSync } from "node:fs"; import { homedir } from "node:os"; +import { type Component, truncateToWidth, wrapTextWithAnsi } from "@oh-my-pi/pi-tui"; import { theme } from "../../theme/theme"; import type { Extension, ExtensionState } from "./types"; export class InspectorPanel implements Component { - private extension: Extension | null = null; + private extension: Extension | null = null; - setExtension(extension: Extension | null): void { - this.extension = extension; - } + setExtension(extension: Extension | null): void { + this.extension = extension; + } - invalidate(): void {} + invalidate(): void {} - render(width: number): string[] { - if (!this.extension) { - return [ - theme.fg("muted", "Select an extension"), - theme.fg("dim", "to view details"), - ]; - } + render(width: number): string[] { + if (!this.extension) { + return [theme.fg("muted", "Select an extension"), theme.fg("dim", "to view details")]; + } - const ext = this.extension; - const lines: string[] = []; + const ext = this.extension; + const lines: string[] = []; - // Name header - lines.push(theme.bold(theme.fg("accent", ext.displayName))); - lines.push(""); + // Name header + lines.push(theme.bold(theme.fg("accent", ext.displayName))); + lines.push(""); - // Kind badge - lines.push(theme.fg("muted", "Type: ") + this.getKindBadge(ext.kind)); - lines.push(""); + // Kind badge + lines.push(theme.fg("muted", "Type: ") + this.getKindBadge(ext.kind)); + lines.push(""); - // Description (wrapped) - if (ext.description) { - const wrapped = wrapTextWithAnsi(ext.description, width - 2); - for (const line of wrapped) { - lines.push(truncateToWidth(line, width)); - } - lines.push(""); - } + // Description (wrapped) + if (ext.description) { + const wrapped = wrapTextWithAnsi(ext.description, width - 2); + for (const line of wrapped) { + lines.push(truncateToWidth(line, width)); + } + lines.push(""); + } - // Origin - lines.push(theme.fg("muted", "Origin:")); - const levelLabel = ext.source.level === "user" ? "User" : ext.source.level === "project" ? "Project" : "Native"; - lines.push(" " + theme.italic(`via ${ext.source.providerName} (${levelLabel})`)); - lines.push(" " + theme.fg("dim", this.shortenPath(ext.path))); - lines.push(""); + // Origin + lines.push(theme.fg("muted", "Origin:")); + const levelLabel = ext.source.level === "user" ? "User" : ext.source.level === "project" ? "Project" : "Native"; + lines.push(` ${theme.italic(`via ${ext.source.providerName} (${levelLabel})`)}`); + lines.push(` ${theme.fg("dim", this.shortenPath(ext.path))}`); + lines.push(""); - // Status badge - lines.push(theme.fg("muted", "Status:")); - lines.push(" " + this.getStatusBadge(ext.state, ext.disabledReason, ext.shadowedBy)); - lines.push(""); + // Status badge + lines.push(theme.fg("muted", "Status:")); + lines.push(` ${this.getStatusBadge(ext.state, ext.disabledReason, ext.shadowedBy)}`); + lines.push(""); - // Preview section (routed based on kind) - const previewLines = this.renderPreview(ext, width); - lines.push(...previewLines); + // Preview section (routed based on kind) + const previewLines = this.renderPreview(ext, width); + lines.push(...previewLines); - return lines; - } + return lines; + } - private renderPreview(ext: Extension, width: number): string[] { - const lines: string[] = []; - let content: string[] = []; + private renderPreview(ext: Extension, width: number): string[] { + const lines: string[] = []; + let content: string[] = []; - switch (ext.kind) { - case "context-file": - content = this.renderFilePreview(ext.path, width); - break; - case "tool": - content = this.renderToolArgs(ext.raw, width); - break; - case "skill": - content = this.renderSkillContent(ext.raw, width); - break; - case "mcp": - content = this.renderMcpDetails(ext.raw, width); - break; - default: - content = this.renderDefaultPreview(ext, width); - break; - } + switch (ext.kind) { + case "context-file": + content = this.renderFilePreview(ext.path, width); + break; + case "tool": + content = this.renderToolArgs(ext.raw, width); + break; + case "skill": + content = this.renderSkillContent(ext.raw, width); + break; + case "mcp": + content = this.renderMcpDetails(ext.raw, width); + break; + default: + content = this.renderDefaultPreview(ext, width); + break; + } - if (content.length > 0) { - lines.push(...content); - } + if (content.length > 0) { + lines.push(...content); + } - return lines; - } + return lines; + } - private renderFilePreview(path: string, width: number): string[] { - const lines: string[] = []; - lines.push(theme.fg("muted", "Preview:")); - lines.push(theme.fg("dim", "─".repeat(Math.min(width - 2, 40)))); + private renderFilePreview(path: string, width: number): string[] { + const lines: string[] = []; + lines.push(theme.fg("muted", "Preview:")); + lines.push(theme.fg("dim", "─".repeat(Math.min(width - 2, 40)))); - try { - const content = readFileSync(path, "utf-8"); - const fileLines = content.split("\n").slice(0, 20); + try { + const content = readFileSync(path, "utf-8"); + const fileLines = content.split("\n").slice(0, 20); - for (const line of fileLines) { - const highlighted = this.highlightMarkdown(line); - lines.push(truncateToWidth(highlighted, width - 2)); - } + for (const line of fileLines) { + const highlighted = this.highlightMarkdown(line); + lines.push(truncateToWidth(highlighted, width - 2)); + } - if (content.split("\n").length > 20) { - lines.push(theme.fg("dim", "(truncated at line 20)")); - } - } catch (err) { - lines.push(theme.fg("error", `Failed to read file: ${err instanceof Error ? err.message : String(err)}`)); - } + if (content.split("\n").length > 20) { + lines.push(theme.fg("dim", "(truncated at line 20)")); + } + } catch (err) { + lines.push(theme.fg("error", `Failed to read file: ${err instanceof Error ? err.message : String(err)}`)); + } - lines.push(""); - return lines; - } + lines.push(""); + return lines; + } - private highlightMarkdown(line: string): string { - // Basic markdown syntax highlighting - let highlighted = line; + private highlightMarkdown(line: string): string { + // Basic markdown syntax highlighting + let highlighted = line; - // Headers - if (/^#{1,6}\s/.test(highlighted)) { - highlighted = theme.bold(theme.fg("accent", highlighted)); - } - // Code blocks - else if (/^```/.test(highlighted)) { - highlighted = theme.fg("dim", highlighted); - } - // Lists - else if (/^[\s]*[-*+]\s/.test(highlighted)) { - highlighted = highlighted.replace(/^([\s]*[-*+]\s)/, theme.fg("accent", "$1")); - } - // Numbered lists - else if (/^[\s]*\d+\.\s/.test(highlighted)) { - highlighted = highlighted.replace(/^([\s]*\d+\.\s)/, theme.fg("accent", "$1")); - } + // Headers + if (/^#{1,6}\s/.test(highlighted)) { + highlighted = theme.bold(theme.fg("accent", highlighted)); + } + // Code blocks + else if (/^```/.test(highlighted)) { + highlighted = theme.fg("dim", highlighted); + } + // Lists + else if (/^[\s]*[-*+]\s/.test(highlighted)) { + highlighted = highlighted.replace(/^([\s]*[-*+]\s)/, theme.fg("accent", "$1")); + } + // Numbered lists + else if (/^[\s]*\d+\.\s/.test(highlighted)) { + highlighted = highlighted.replace(/^([\s]*\d+\.\s)/, theme.fg("accent", "$1")); + } - return highlighted; - } + return highlighted; + } - private renderToolArgs(raw: unknown, width: number): string[] { - const lines: string[] = []; - lines.push(theme.fg("muted", "Arguments:")); - lines.push(theme.fg("dim", "─".repeat(Math.min(width - 2, 40)))); + private renderToolArgs(raw: unknown, width: number): string[] { + const lines: string[] = []; + lines.push(theme.fg("muted", "Arguments:")); + lines.push(theme.fg("dim", "─".repeat(Math.min(width - 2, 40)))); - try { - const tool = raw as any; - const params = tool?.parameters?.properties || tool?.inputSchema?.properties || {}; + try { + const tool = raw as any; + const params = tool?.parameters?.properties || tool?.inputSchema?.properties || {}; - if (Object.keys(params).length === 0) { - lines.push(theme.fg("dim", " (no arguments)")); - } else { - const required = new Set(tool?.parameters?.required || tool?.inputSchema?.required || []); + if (Object.keys(params).length === 0) { + lines.push(theme.fg("dim", " (no arguments)")); + } else { + const required = new Set(tool?.parameters?.required || tool?.inputSchema?.required || []); - for (const [name, spec] of Object.entries(params)) { - const param = spec as any; - const type = param.type || "any"; - const isRequired = required.has(name); - const defaultVal = param.default !== undefined ? `Default: ${param.default}` : null; + for (const [name, spec] of Object.entries(params)) { + const param = spec as any; + const type = param.type || "any"; + const isRequired = required.has(name); + const defaultVal = param.default !== undefined ? `Default: ${param.default}` : null; - const nameCol = theme.fg("accent", name.padEnd(12)); - const typeCol = theme.fg("muted", type.padEnd(10)); - const reqCol = isRequired - ? theme.fg("warning", "Required") - : defaultVal - ? theme.fg("dim", defaultVal) - : theme.fg("dim", "Optional"); + const nameCol = theme.fg("accent", name.padEnd(12)); + const typeCol = theme.fg("muted", type.padEnd(10)); + const reqCol = isRequired + ? theme.fg("warning", "Required") + : defaultVal + ? theme.fg("dim", defaultVal) + : theme.fg("dim", "Optional"); - lines.push(` ${nameCol} ${typeCol} ${reqCol}`); - } - } - } catch { - lines.push(theme.fg("dim", " (unable to parse tool definition)")); - } + lines.push(` ${nameCol} ${typeCol} ${reqCol}`); + } + } + } catch { + lines.push(theme.fg("dim", " (unable to parse tool definition)")); + } - lines.push(""); - return lines; - } + lines.push(""); + return lines; + } - private renderSkillContent(raw: unknown, width: number): string[] { - const lines: string[] = []; - lines.push(theme.fg("muted", "Instruction:")); - lines.push(theme.fg("dim", "─".repeat(Math.min(width - 2, 40)))); + private renderSkillContent(raw: unknown, width: number): string[] { + const lines: string[] = []; + lines.push(theme.fg("muted", "Instruction:")); + lines.push(theme.fg("dim", "─".repeat(Math.min(width - 2, 40)))); - try { - const skill = raw as any; - const instruction = skill?.prompt || skill?.instruction || skill?.content || ""; + try { + const skill = raw as any; + const instruction = skill?.prompt || skill?.instruction || skill?.content || ""; - if (!instruction) { - lines.push(theme.fg("dim", " (no instruction text)")); - } else { - const instructionLines = instruction.split("\n").slice(0, 15); - for (const line of instructionLines) { - lines.push(truncateToWidth(line, width - 2)); - } + if (!instruction) { + lines.push(theme.fg("dim", " (no instruction text)")); + } else { + const instructionLines = instruction.split("\n").slice(0, 15); + for (const line of instructionLines) { + lines.push(truncateToWidth(line, width - 2)); + } - if (instruction.split("\n").length > 15) { - lines.push(theme.fg("dim", "(truncated at line 15)")); - } - } - } catch { - lines.push(theme.fg("dim", " (unable to parse skill content)")); - } + if (instruction.split("\n").length > 15) { + lines.push(theme.fg("dim", "(truncated at line 15)")); + } + } + } catch { + lines.push(theme.fg("dim", " (unable to parse skill content)")); + } - lines.push(""); - return lines; - } + lines.push(""); + return lines; + } - private renderMcpDetails(raw: unknown, width: number): string[] { - const lines: string[] = []; - lines.push(theme.fg("muted", "Connection:")); - lines.push(theme.fg("dim", "─".repeat(Math.min(width - 2, 40)))); + private renderMcpDetails(raw: unknown, width: number): string[] { + const lines: string[] = []; + lines.push(theme.fg("muted", "Connection:")); + lines.push(theme.fg("dim", "─".repeat(Math.min(width - 2, 40)))); - try { - const mcp = raw as any; - const transport = mcp?.transport || mcp?.type || "unknown"; - const command = mcp?.command || mcp?.cmd || ""; - const args = mcp?.args || mcp?.arguments || []; + try { + const mcp = raw as any; + const transport = mcp?.transport || mcp?.type || "unknown"; + const command = mcp?.command || mcp?.cmd || ""; + const args = mcp?.args || mcp?.arguments || []; - lines.push(` ${theme.fg("muted", "Transport:")} ${theme.fg("accent", transport)}`); + lines.push(` ${theme.fg("muted", "Transport:")} ${theme.fg("accent", transport)}`); - if (command) { - lines.push(` ${theme.fg("muted", "Command:")} ${theme.fg("success", command)}`); - } + if (command) { + lines.push(` ${theme.fg("muted", "Command:")} ${theme.fg("success", command)}`); + } - if (Array.isArray(args) && args.length > 0) { - lines.push(` ${theme.fg("muted", "Args:")} ${theme.fg("dim", args.join(" "))}`); - } + if (Array.isArray(args) && args.length > 0) { + lines.push(` ${theme.fg("muted", "Args:")} ${theme.fg("dim", args.join(" "))}`); + } - // Environment variables if present - if (mcp?.env && typeof mcp.env === "object") { - const envCount = Object.keys(mcp.env).length; - if (envCount > 0) { - lines.push(` ${theme.fg("muted", "Env vars:")} ${theme.fg("dim", `${envCount} defined`)}`); - } - } - } catch { - lines.push(theme.fg("dim", " (unable to parse MCP configuration)")); - } + // Environment variables if present + if (mcp?.env && typeof mcp.env === "object") { + const envCount = Object.keys(mcp.env).length; + if (envCount > 0) { + lines.push(` ${theme.fg("muted", "Env vars:")} ${theme.fg("dim", `${envCount} defined`)}`); + } + } + } catch { + lines.push(theme.fg("dim", " (unable to parse MCP configuration)")); + } - lines.push(""); - return lines; - } + lines.push(""); + return lines; + } - private renderDefaultPreview(ext: Extension, width: number): string[] { - const lines: string[] = []; + private renderDefaultPreview(ext: Extension, width: number): string[] { + const lines: string[] = []; - // Show trigger pattern if present - if (ext.trigger) { - lines.push(theme.fg("muted", "Trigger:")); - lines.push(theme.fg("dim", "─".repeat(Math.min(width - 2, 40)))); - lines.push(` ${theme.fg("accent", ext.trigger)}`); - lines.push(""); - } + // Show trigger pattern if present + if (ext.trigger) { + lines.push(theme.fg("muted", "Trigger:")); + lines.push(theme.fg("dim", "─".repeat(Math.min(width - 2, 40)))); + lines.push(` ${theme.fg("accent", ext.trigger)}`); + lines.push(""); + } - return lines; - } + return lines; + } - private getKindBadge(kind: string): string { - const kindColors: Record = { - skill: "accent", - rule: "success", - tool: "warning", - mcp: "accent", - prompt: "muted", - hook: "warning", - "context-file": "dim", - instruction: "muted", - "slash-command": "accent", - }; + private getKindBadge(kind: string): string { + const kindColors: Record = { + skill: "accent", + rule: "success", + tool: "warning", + mcp: "accent", + prompt: "muted", + hook: "warning", + "context-file": "dim", + instruction: "muted", + "slash-command": "accent", + }; - const color = kindColors[kind] || "muted"; - return theme.fg(color as any, kind); - } + const color = kindColors[kind] || "muted"; + return theme.fg(color as any, kind); + } - private getStatusBadge(state: ExtensionState, reason?: string, shadowedBy?: string): string { - switch (state) { - case "active": - return theme.fg("success", "● Active"); - case "disabled": - const reasonText = reason === "provider-disabled" ? "provider disabled" : reason === "item-disabled" ? "manually disabled" : "unknown"; - return theme.fg("dim", `○ Disabled (${reasonText})`); - case "shadowed": - return theme.fg("warning", `◐ Shadowed` + (shadowedBy ? ` by ${shadowedBy}` : "")); - } - } + private getStatusBadge(state: ExtensionState, reason?: string, shadowedBy?: string): string { + switch (state) { + case "active": + return theme.fg("success", "● Active"); + case "disabled": { + const reasonText = + reason === "provider-disabled" + ? "provider disabled" + : reason === "item-disabled" + ? "manually disabled" + : "unknown"; + return theme.fg("dim", `○ Disabled (${reasonText})`); + } + case "shadowed": + return theme.fg("warning", `◐ Shadowed${shadowedBy ? ` by ${shadowedBy}` : ""}`); + } + } - private shortenPath(path: string): string { - const home = homedir(); - if (path.startsWith(home)) { - return "~" + path.slice(home.length); - } + private shortenPath(path: string): string { + const home = homedir(); + if (path.startsWith(home)) { + return `~${path.slice(home.length)}`; + } - // If path is very long, show just the last parts - if (path.length > 40) { - const parts = path.split("/"); - if (parts.length > 3) { - return ".../" + parts.slice(-3).join("/"); - } - } + // If path is very long, show just the last parts + if (path.length > 40) { + const parts = path.split("/"); + if (parts.length > 3) { + return `.../${parts.slice(-3).join("/")}`; + } + } - return path; - } + return path; + } } diff --git a/packages/coding-agent/src/modes/interactive/components/extensions/sidebar-tree.ts b/packages/coding-agent/src/modes/interactive/components/extensions/sidebar-tree.ts deleted file mode 100644 index 64a9c1019..000000000 --- a/packages/coding-agent/src/modes/interactive/components/extensions/sidebar-tree.ts +++ /dev/null @@ -1,174 +0,0 @@ -/** - * SidebarTree - Hierarchical tree view with provider toggles. - * - * Displays providers grouped by source with toggle checkboxes. - * Supports expand/collapse for categories. - */ - -import { - type Component, - isArrowDown, - isArrowUp, - isEnter, - truncateToWidth, - visibleWidth, -} from "@oh-my-pi/pi-tui"; -import { theme } from "../../theme/theme"; -import { flattenTree, toggleProvider } from "./state-manager"; -import type { FlatTreeItem, TreeNode } from "./types"; - -export interface SidebarTreeCallbacks { - /** Called when provider is toggled */ - onProviderToggle?: (providerId: string, enabled: boolean) => void; - /** Called when selection changes */ - onSelectionChange?: (nodeId: string) => void; - /** Called when tree structure changes (collapse/expand) */ - onTreeChange?: () => void; -} - -export class SidebarTree implements Component { - private tree: TreeNode[]; - private flatItems: FlatTreeItem[] = []; - private selectedIndex = 0; - private focused = false; - private callbacks: SidebarTreeCallbacks; - - constructor(tree: TreeNode[], callbacks: SidebarTreeCallbacks = {}) { - this.tree = tree; - this.callbacks = callbacks; - this.flatItems = flattenTree(tree); - } - - setTree(tree: TreeNode[]): void { - this.tree = tree; - this.flatItems = flattenTree(tree); - // Keep selection in bounds - if (this.selectedIndex >= this.flatItems.length) { - this.selectedIndex = Math.max(0, this.flatItems.length - 1); - } - } - - setFocused(focused: boolean): void { - this.focused = focused; - } - - getSelectedNode(): TreeNode | null { - return this.flatItems[this.selectedIndex]?.node ?? null; - } - - invalidate(): void {} - - render(width: number): string[] { - const lines: string[] = []; - - // Header - lines.push(theme.bold(theme.fg("accent", "Providers"))); - lines.push(""); - - if (this.flatItems.length === 0) { - lines.push(theme.fg("muted", "No providers")); - return lines; - } - - for (let i = 0; i < this.flatItems.length; i++) { - const { node, depth } = this.flatItems[i]; - const isSelected = this.focused && i === this.selectedIndex; - - // Build the line - const indent = " ".repeat(depth); - let checkbox = ""; - let arrow = ""; - let label = node.label; - - // Provider nodes get checkboxes - if (node.type === "provider") { - checkbox = node.enabled - ? theme.fg("success", "[x]") + " " - : theme.fg("muted", "[ ]") + " "; - } - - // Nodes with children get expand/collapse arrows - if (node.children.length > 0) { - arrow = node.collapsed ? "▸ " : "▾ "; - } else if (node.type === "kind") { - arrow = " "; - } - - // Add count if present - if (node.count !== undefined && node.count > 0) { - label += theme.fg("dim", ` (${node.count})`); - } - - // Style based on state - if (isSelected) { - label = theme.bg("selectedBg", theme.bold(theme.fg("text", label))); - } else if (!node.enabled) { - label = theme.fg("dim", label); - } - - const fullLine = `${indent}${checkbox}${arrow}${label}`; - lines.push(truncateToWidth(fullLine, width)); - } - - return lines; - } - - handleInput(data: string): void { - if (this.flatItems.length === 0) return; - - // Navigation - if (isArrowUp(data) || data === "k") { - if (this.selectedIndex > 0) { - this.selectedIndex--; - this.notifySelectionChange(); - } - return; - } - - if (isArrowDown(data) || data === "j") { - if (this.selectedIndex < this.flatItems.length - 1) { - this.selectedIndex++; - this.notifySelectionChange(); - } - return; - } - - // Toggle or expand/collapse - if (data === " ") { - const item = this.flatItems[this.selectedIndex]; - if (!item) return; - - if (item.node.type === "provider") { - // Toggle provider - const newEnabled = toggleProvider(item.node.id); - item.node.enabled = newEnabled; - // Also update children - for (const child of item.node.children) { - child.enabled = newEnabled; - } - this.callbacks.onProviderToggle?.(item.node.id, newEnabled); - } - return; - } - - if (isEnter(data)) { - const item = this.flatItems[this.selectedIndex]; - if (!item) return; - - if (item.node.children.length > 0) { - // Toggle collapse - item.node.collapsed = !item.node.collapsed; - this.flatItems = flattenTree(this.tree); - this.callbacks.onTreeChange?.(); - } - return; - } - } - - private notifySelectionChange(): void { - const node = this.getSelectedNode(); - if (node) { - this.callbacks.onSelectionChange?.(node.id); - } - } -} diff --git a/packages/coding-agent/src/modes/interactive/components/extensions/state-manager.ts b/packages/coding-agent/src/modes/interactive/components/extensions/state-manager.ts index acb8c2f85..341130c9a 100644 --- a/packages/coding-agent/src/modes/interactive/components/extensions/state-manager.ts +++ b/packages/coding-agent/src/modes/interactive/components/extensions/state-manager.ts @@ -3,13 +3,6 @@ * Handles data loading, tree building, filtering, and toggle persistence. */ -import { - disableProvider, - enableProvider, - getAllProvidersInfo, - isProviderEnabled, - loadSync, -} from "../../../../discovery"; import type { ContextFile } from "../../../../capability/context-file"; import type { Hook } from "../../../../capability/hook"; import type { MCPServer } from "../../../../capability/mcp"; @@ -18,13 +11,21 @@ import type { Rule } from "../../../../capability/rule"; import type { Skill } from "../../../../capability/skill"; import type { CustomTool } from "../../../../capability/tool"; import type { SourceMeta } from "../../../../capability/types"; +import { + disableProvider, + enableProvider, + getAllProvidersInfo, + isProviderEnabled, + loadSync, +} from "../../../../discovery"; import type { - DashboardState, - Extension, - ExtensionKind, - ExtensionState, - FlatTreeItem, - TreeNode, + DashboardState, + Extension, + ExtensionKind, + ExtensionState, + FlatTreeItem, + ProviderTab, + TreeNode, } from "./types"; import { makeExtensionId, sourceFromMeta } from "./types"; @@ -32,244 +33,244 @@ import { makeExtensionId, sourceFromMeta } from "./types"; * Settings manager interface for granular toggle persistence. */ export interface ExtensionSettingsManager { - getDisabledExtensions(): string[]; - setDisabledExtensions(ids: string[]): void; + getDisabledExtensions(): string[]; + setDisabledExtensions(ids: string[]): void; } /** * Load all extensions from all capabilities. */ export function loadAllExtensions(cwd?: string, disabledIds?: string[]): Extension[] { - const extensions: Extension[] = []; - const disabledExtensions = new Set(disabledIds ?? []); + const extensions: Extension[] = []; + const disabledExtensions = new Set(disabledIds ?? []); - // Helper to convert capability items to extensions - function addItems( - items: T[], - kind: ExtensionKind, - opts?: { - getDescription?: (item: T) => string | undefined; - getTrigger?: (item: T) => string | undefined; - getShadowedBy?: (item: T) => string | undefined; - }, - ): void { - for (const item of items) { - const id = makeExtensionId(kind, item.name); - const isDisabled = disabledExtensions.has(id); - const isShadowed = (item as { _shadowed?: boolean })._shadowed; - const providerEnabled = isProviderEnabled(item._source.provider); + // Helper to convert capability items to extensions + function addItems( + items: T[], + kind: ExtensionKind, + opts?: { + getDescription?: (item: T) => string | undefined; + getTrigger?: (item: T) => string | undefined; + getShadowedBy?: (item: T) => string | undefined; + }, + ): void { + for (const item of items) { + const id = makeExtensionId(kind, item.name); + const isDisabled = disabledExtensions.has(id); + const isShadowed = (item as { _shadowed?: boolean })._shadowed; + const providerEnabled = isProviderEnabled(item._source.provider); - let state: ExtensionState; - let disabledReason: "shadowed" | "provider-disabled" | "item-disabled" | undefined; + let state: ExtensionState; + let disabledReason: "shadowed" | "provider-disabled" | "item-disabled" | undefined; - // Item-disabled takes precedence over shadowed - if (isDisabled) { - state = "disabled"; - disabledReason = "item-disabled"; - } else if (isShadowed) { - state = "shadowed"; - disabledReason = "shadowed"; - } else if (!providerEnabled) { - state = "disabled"; - disabledReason = "provider-disabled"; - } else { - state = "active"; - } + // Item-disabled takes precedence over shadowed + if (isDisabled) { + state = "disabled"; + disabledReason = "item-disabled"; + } else if (isShadowed) { + state = "shadowed"; + disabledReason = "shadowed"; + } else if (!providerEnabled) { + state = "disabled"; + disabledReason = "provider-disabled"; + } else { + state = "active"; + } - extensions.push({ - id, - kind, - name: item.name, - displayName: item.name, - description: opts?.getDescription?.(item), - trigger: opts?.getTrigger?.(item), - path: item.path, - source: sourceFromMeta(item._source), - state, - disabledReason, - shadowedBy: opts?.getShadowedBy?.(item), - raw: item, - }); - } - } + extensions.push({ + id, + kind, + name: item.name, + displayName: item.name, + description: opts?.getDescription?.(item), + trigger: opts?.getTrigger?.(item), + path: item.path, + source: sourceFromMeta(item._source), + state, + disabledReason, + shadowedBy: opts?.getShadowedBy?.(item), + raw: item, + }); + } + } - const loadOpts = cwd ? { cwd } : {}; + const loadOpts = cwd ? { cwd } : {}; - // Load skills - try { - const skills = loadSync("skills", loadOpts); - addItems(skills.all, "skill", { - getDescription: (s) => s.frontmatter?.description, - getTrigger: (s) => s.frontmatter?.globs?.join(", "), - }); - } catch { - // Capability may not be registered - } + // Load skills + try { + const skills = loadSync("skills", loadOpts); + addItems(skills.all, "skill", { + getDescription: (s) => s.frontmatter?.description, + getTrigger: (s) => s.frontmatter?.globs?.join(", "), + }); + } catch { + // Capability may not be registered + } - // Load rules - try { - const rules = loadSync("rules", loadOpts); - addItems(rules.all, "rule", { - getDescription: (r) => r.description, - getTrigger: (r) => r.globs?.join(", ") || (r.alwaysApply ? "always" : undefined), - }); - } catch { - // Capability may not be registered - } + // Load rules + try { + const rules = loadSync("rules", loadOpts); + addItems(rules.all, "rule", { + getDescription: (r) => r.description, + getTrigger: (r) => r.globs?.join(", ") || (r.alwaysApply ? "always" : undefined), + }); + } catch { + // Capability may not be registered + } - // Load custom tools - try { - const tools = loadSync("tools", loadOpts); - addItems(tools.all, "tool", { - getDescription: (t) => t.description, - }); - } catch { - // Capability may not be registered - } + // Load custom tools + try { + const tools = loadSync("tools", loadOpts); + addItems(tools.all, "tool", { + getDescription: (t) => t.description, + }); + } catch { + // Capability may not be registered + } - // Load MCP servers - try { - const mcps = loadSync("mcps", loadOpts); - for (const server of mcps.all) { - const id = makeExtensionId("mcp", server.name); - const isDisabled = disabledExtensions.has(id); - const isShadowed = (server as { _shadowed?: boolean })._shadowed; - const providerEnabled = isProviderEnabled(server._source.provider); + // Load MCP servers + try { + const mcps = loadSync("mcps", loadOpts); + for (const server of mcps.all) { + const id = makeExtensionId("mcp", server.name); + const isDisabled = disabledExtensions.has(id); + const isShadowed = (server as { _shadowed?: boolean })._shadowed; + const providerEnabled = isProviderEnabled(server._source.provider); - let state: ExtensionState; - let disabledReason: "shadowed" | "provider-disabled" | "item-disabled" | undefined; + let state: ExtensionState; + let disabledReason: "shadowed" | "provider-disabled" | "item-disabled" | undefined; - if (isDisabled) { - state = "disabled"; - disabledReason = "item-disabled"; - } else if (isShadowed) { - state = "shadowed"; - disabledReason = "shadowed"; - } else if (!providerEnabled) { - state = "disabled"; - disabledReason = "provider-disabled"; - } else { - state = "active"; - } + if (isDisabled) { + state = "disabled"; + disabledReason = "item-disabled"; + } else if (isShadowed) { + state = "shadowed"; + disabledReason = "shadowed"; + } else if (!providerEnabled) { + state = "disabled"; + disabledReason = "provider-disabled"; + } else { + state = "active"; + } - extensions.push({ - id, - kind: "mcp", - name: server.name, - displayName: server.name, - description: server.command || server.url, - trigger: server.transport || "stdio", - path: server._source.path, - source: sourceFromMeta(server._source), - state, - disabledReason, - raw: server, - }); - } - } catch { - // Capability may not be registered - } + extensions.push({ + id, + kind: "mcp", + name: server.name, + displayName: server.name, + description: server.command || server.url, + trigger: server.transport || "stdio", + path: server._source.path, + source: sourceFromMeta(server._source), + state, + disabledReason, + raw: server, + }); + } + } catch { + // Capability may not be registered + } - // Load prompts - try { - const prompts = loadSync("prompts", loadOpts); - addItems(prompts.all, "prompt", { - getDescription: () => undefined, - getTrigger: (p) => `/prompts:${p.name}`, - }); - } catch { - // Capability may not be registered - } + // Load prompts + try { + const prompts = loadSync("prompts", loadOpts); + addItems(prompts.all, "prompt", { + getDescription: () => undefined, + getTrigger: (p) => `/prompts:${p.name}`, + }); + } catch { + // Capability may not be registered + } - // Load hooks - try { - const hooks = loadSync("hooks", loadOpts); - for (const hook of hooks.all) { - const id = makeExtensionId("hook", `${hook.type}:${hook.tool}:${hook.name}`); - const isDisabled = disabledExtensions.has(id); - const isShadowed = (hook as { _shadowed?: boolean })._shadowed; - const providerEnabled = isProviderEnabled(hook._source.provider); + // Load hooks + try { + const hooks = loadSync("hooks", loadOpts); + for (const hook of hooks.all) { + const id = makeExtensionId("hook", `${hook.type}:${hook.tool}:${hook.name}`); + const isDisabled = disabledExtensions.has(id); + const isShadowed = (hook as { _shadowed?: boolean })._shadowed; + const providerEnabled = isProviderEnabled(hook._source.provider); - let state: ExtensionState; - let disabledReason: "shadowed" | "provider-disabled" | "item-disabled" | undefined; + let state: ExtensionState; + let disabledReason: "shadowed" | "provider-disabled" | "item-disabled" | undefined; - if (isDisabled) { - state = "disabled"; - disabledReason = "item-disabled"; - } else if (isShadowed) { - state = "shadowed"; - disabledReason = "shadowed"; - } else if (!providerEnabled) { - state = "disabled"; - disabledReason = "provider-disabled"; - } else { - state = "active"; - } + if (isDisabled) { + state = "disabled"; + disabledReason = "item-disabled"; + } else if (isShadowed) { + state = "shadowed"; + disabledReason = "shadowed"; + } else if (!providerEnabled) { + state = "disabled"; + disabledReason = "provider-disabled"; + } else { + state = "active"; + } - extensions.push({ - id, - kind: "hook", - name: hook.name, - displayName: hook.name, - description: `${hook.type}-${hook.tool}`, - trigger: `${hook.type}:${hook.tool}`, - path: hook.path, - source: sourceFromMeta(hook._source), - state, - disabledReason, - raw: hook, - }); - } - } catch { - // Capability may not be registered - } + extensions.push({ + id, + kind: "hook", + name: hook.name, + displayName: hook.name, + description: `${hook.type}-${hook.tool}`, + trigger: `${hook.type}:${hook.tool}`, + path: hook.path, + source: sourceFromMeta(hook._source), + state, + disabledReason, + raw: hook, + }); + } + } catch { + // Capability may not be registered + } - // Load context files - try { - const contextFiles = loadSync("context-files", loadOpts); - for (const file of contextFiles.all) { - // Extract filename from path for display - const name = file.path.split("/").pop() || file.path; - const id = makeExtensionId("context-file", `${file.level}:${name}`); - const isDisabled = disabledExtensions.has(id); - const isShadowed = (file as { _shadowed?: boolean })._shadowed; - const providerEnabled = isProviderEnabled(file._source.provider); + // Load context files + try { + const contextFiles = loadSync("context-files", loadOpts); + for (const file of contextFiles.all) { + // Extract filename from path for display + const name = file.path.split("/").pop() || file.path; + const id = makeExtensionId("context-file", `${file.level}:${name}`); + const isDisabled = disabledExtensions.has(id); + const isShadowed = (file as { _shadowed?: boolean })._shadowed; + const providerEnabled = isProviderEnabled(file._source.provider); - let state: ExtensionState; - let disabledReason: "shadowed" | "provider-disabled" | "item-disabled" | undefined; + let state: ExtensionState; + let disabledReason: "shadowed" | "provider-disabled" | "item-disabled" | undefined; - if (isDisabled) { - state = "disabled"; - disabledReason = "item-disabled"; - } else if (isShadowed) { - state = "shadowed"; - disabledReason = "shadowed"; - } else if (!providerEnabled) { - state = "disabled"; - disabledReason = "provider-disabled"; - } else { - state = "active"; - } + if (isDisabled) { + state = "disabled"; + disabledReason = "item-disabled"; + } else if (isShadowed) { + state = "shadowed"; + disabledReason = "shadowed"; + } else if (!providerEnabled) { + state = "disabled"; + disabledReason = "provider-disabled"; + } else { + state = "active"; + } - extensions.push({ - id, - kind: "context-file", - name, - displayName: name, - description: file.level === "user" ? "User-level context" : "Project-level context", - trigger: file.level, - path: file.path, - source: sourceFromMeta(file._source), - state, - disabledReason, - raw: file, - }); - } - } catch { - // Capability may not be registered - } + extensions.push({ + id, + kind: "context-file", + name, + displayName: name, + description: file.level === "user" ? "User-level context" : "Project-level context", + trigger: file.level, + path: file.path, + source: sourceFromMeta(file._source), + state, + disabledReason, + raw: file, + }); + } + } catch { + // Capability may not be registered + } - return extensions; + return extensions; } /** @@ -277,203 +278,281 @@ export function loadAllExtensions(cwd?: string, disabledIds?: string[]): Extensi * Groups by provider → kind. */ export function buildSidebarTree(extensions: Extension[]): TreeNode[] { - const providers = getAllProvidersInfo(); - const tree: TreeNode[] = []; + const providers = getAllProvidersInfo(); + const tree: TreeNode[] = []; - // Group extensions by provider and kind - const byProvider = new Map>(); + // Group extensions by provider and kind + const byProvider = new Map>(); - for (const ext of extensions) { - const providerId = ext.source.provider; - if (!byProvider.has(providerId)) { - byProvider.set(providerId, new Map()); - } - const byKind = byProvider.get(providerId)!; - if (!byKind.has(ext.kind)) { - byKind.set(ext.kind, []); - } - byKind.get(ext.kind)!.push(ext); - } + for (const ext of extensions) { + const providerId = ext.source.provider; + if (!byProvider.has(providerId)) { + byProvider.set(providerId, new Map()); + } + const byKind = byProvider.get(providerId)!; + if (!byKind.has(ext.kind)) { + byKind.set(ext.kind, []); + } + byKind.get(ext.kind)!.push(ext); + } - // Build tree nodes for each provider (show ALL providers, even if disabled/empty) - for (const provider of providers) { - // Skip the 'native' provider as it cannot be toggled - if (provider.id === "native") continue; + // Build tree nodes for each provider (show ALL providers, even if disabled/empty) + for (const provider of providers) { + // Skip the 'native' provider as it cannot be toggled + if (provider.id === "native") continue; - const byKind = byProvider.get(provider.id); - const kindNodes: TreeNode[] = []; - let totalCount = 0; + const byKind = byProvider.get(provider.id); + const kindNodes: TreeNode[] = []; + let totalCount = 0; - if (byKind && byKind.size > 0) { - for (const [kind, exts] of byKind) { - totalCount += exts.length; - kindNodes.push({ - id: `${provider.id}:${kind}`, - label: getKindDisplayName(kind), - type: "kind", - enabled: provider.enabled, - collapsed: true, - children: [], - count: exts.length, - }); - } + if (byKind && byKind.size > 0) { + for (const [kind, exts] of byKind) { + totalCount += exts.length; + kindNodes.push({ + id: `${provider.id}:${kind}`, + label: getKindDisplayName(kind), + type: "kind", + enabled: provider.enabled, + collapsed: true, + children: [], + count: exts.length, + }); + } - // Sort kind nodes by count (most items first) - kindNodes.sort((a, b) => (b.count || 0) - (a.count || 0)); - } + // Sort kind nodes by count (most items first) + kindNodes.sort((a, b) => (b.count || 0) - (a.count || 0)); + } - tree.push({ - id: provider.id, - label: provider.displayName, - type: "provider", - enabled: provider.enabled, - collapsed: false, - children: kindNodes, - count: totalCount, - }); - } + tree.push({ + id: provider.id, + label: provider.displayName, + type: "provider", + enabled: provider.enabled, + collapsed: false, + children: kindNodes, + count: totalCount, + }); + } - return tree; + return tree; } /** * Flatten tree for keyboard navigation. */ export function flattenTree(tree: TreeNode[]): FlatTreeItem[] { - const flat: FlatTreeItem[] = []; - let index = 0; + const flat: FlatTreeItem[] = []; + let index = 0; - function walk(node: TreeNode, depth: number): void { - flat.push({ node, depth, index: index++ }); - if (!node.collapsed) { - for (const child of node.children) { - walk(child, depth + 1); - } - } - } + function walk(node: TreeNode, depth: number): void { + flat.push({ node, depth, index: index++ }); + if (!node.collapsed) { + for (const child of node.children) { + walk(child, depth + 1); + } + } + } - for (const node of tree) { - walk(node, 0); - } + for (const node of tree) { + walk(node, 0); + } - return flat; + return flat; } /** * Apply fuzzy filter to extensions. */ export function applyFilter(extensions: Extension[], query: string): Extension[] { - if (!query.trim()) { - return extensions; - } + if (!query.trim()) { + return extensions; + } - const tokens = query.toLowerCase().split(/\s+/).filter(Boolean); - if (tokens.length === 0) { - return extensions; - } + const tokens = query.toLowerCase().split(/\s+/).filter(Boolean); + if (tokens.length === 0) { + return extensions; + } - return extensions.filter((ext) => { - const searchable = [ - ext.name, - ext.displayName, - ext.description || "", - ext.trigger || "", - ext.source.providerName, - ext.kind, - ] - .join(" ") - .toLowerCase(); + return extensions.filter((ext) => { + const searchable = [ + ext.name, + ext.displayName, + ext.description || "", + ext.trigger || "", + ext.source.providerName, + ext.kind, + ] + .join(" ") + .toLowerCase(); - return tokens.every((token) => searchable.includes(token)); - }); + return tokens.every((token) => searchable.includes(token)); + }); } /** * Get display name for extension kind. */ function getKindDisplayName(kind: ExtensionKind): string { - switch (kind) { - case "skill": - return "Skills"; - case "rule": - return "Rules"; - case "tool": - return "Tools"; - case "mcp": - return "MCP Servers"; - case "prompt": - return "Prompts"; - case "instruction": - return "Instructions"; - case "context-file": - return "Context Files"; - case "hook": - return "Hooks"; - case "slash-command": - return "Slash Commands"; - default: - return kind; - } + switch (kind) { + case "skill": + return "Skills"; + case "rule": + return "Rules"; + case "tool": + return "Tools"; + case "mcp": + return "MCP Servers"; + case "prompt": + return "Prompts"; + case "instruction": + return "Instructions"; + case "context-file": + return "Context Files"; + case "hook": + return "Hooks"; + case "slash-command": + return "Slash Commands"; + default: + return kind; + } +} + +/** + * Build provider tabs from extensions. + */ +export function buildProviderTabs(extensions: Extension[]): ProviderTab[] { + const providers = getAllProvidersInfo(); + const tabs: ProviderTab[] = []; + + // Count extensions per provider + const countByProvider = new Map(); + for (const ext of extensions) { + const count = countByProvider.get(ext.source.provider) ?? 0; + countByProvider.set(ext.source.provider, count + 1); + } + + // ALL tab first + tabs.push({ + id: "all", + label: "ALL", + enabled: true, + count: extensions.length, + }); + + // Provider tabs (skip native) + for (const provider of providers) { + if (provider.id === "native") continue; + const count = countByProvider.get(provider.id) ?? 0; + tabs.push({ + id: provider.id, + label: provider.displayName, + enabled: provider.enabled, + count, + }); + } + + // Sort: ALL first, then enabled by count, then disabled by count, then empty + tabs.sort((a, b) => { + if (a.id === "all") return -1; + if (b.id === "all") return 1; + + // Categorize: 0 = enabled with content, 1 = disabled, 2 = empty+enabled + const category = (t: ProviderTab) => { + if (t.count === 0 && t.enabled) return 2; // empty + if (!t.enabled) return 1; // disabled + return 0; // enabled with content + }; + + const aCat = category(a); + const bCat = category(b); + if (aCat !== bCat) return aCat - bCat; + + // Within same category, sort by count descending + return b.count - a.count; + }); + + return tabs; +} + +/** + * Filter extensions by provider tab. + */ +export function filterByProvider(extensions: Extension[], providerId: string): Extension[] { + if (providerId === "all") { + return extensions; + } + return extensions.filter((ext) => ext.source.provider === providerId); } /** * Create initial dashboard state. */ export function createInitialState(cwd?: string, disabledIds?: string[]): DashboardState { - const extensions = loadAllExtensions(cwd, disabledIds); - const sidebarTree = buildSidebarTree(extensions); - const flatTree = flattenTree(sidebarTree); + const extensions = loadAllExtensions(cwd, disabledIds); + const tabs = buildProviderTabs(extensions); + const tabFiltered = extensions; // "all" tab by default + const searchFiltered = tabFiltered; - return { - focusPane: "sidebar", - sidebarTree, - flatTree, - sidebarIndex: 0, - extensions, - filtered: extensions, - searchQuery: "", - mainIndex: 0, - scrollOffset: 0, - selected: extensions[0] ?? null, - }; + return { + tabs, + activeTabIndex: 0, + extensions, + tabFiltered, + searchFiltered, + searchQuery: "", + listIndex: 0, + scrollOffset: 0, + selected: searchFiltered[0] ?? null, + }; } /** * Toggle provider enabled state. */ export function toggleProvider(providerId: string): boolean { - if (isProviderEnabled(providerId)) { - disableProvider(providerId); - return false; - } else { - enableProvider(providerId); - return true; - } + if (isProviderEnabled(providerId)) { + disableProvider(providerId); + return false; + } else { + enableProvider(providerId); + return true; + } } /** * Refresh state after toggle. */ export function refreshState(state: DashboardState, cwd?: string, disabledIds?: string[]): DashboardState { - const extensions = loadAllExtensions(cwd, disabledIds); - const sidebarTree = buildSidebarTree(extensions); - const flatTree = flattenTree(sidebarTree); - const filtered = applyFilter(extensions, state.searchQuery); + const extensions = loadAllExtensions(cwd, disabledIds); + const tabs = buildProviderTabs(extensions); - // Try to preserve selection - const selectedId = state.selected?.id; - let selected = selectedId ? filtered.find((e) => e.id === selectedId) : null; - if (!selected && filtered.length > 0) { - selected = filtered[Math.min(state.mainIndex, filtered.length - 1)]; - } + // Get current provider from tabs + const activeTab = state.tabs[state.activeTabIndex]; + const providerId = activeTab?.id ?? "all"; - return { - ...state, - sidebarTree, - flatTree, - extensions, - filtered, - selected: selected ?? null, - mainIndex: selected ? filtered.indexOf(selected) : 0, - }; + // Re-apply filters + const tabFiltered = filterByProvider(extensions, providerId); + const searchFiltered = applyFilter(tabFiltered, state.searchQuery); + + // Find new index for current provider (tabs may have reordered) + const newActiveTabIndex = tabs.findIndex((t) => t.id === providerId); + const activeTabIndex = newActiveTabIndex >= 0 ? newActiveTabIndex : 0; + + // Try to preserve selection + const selectedId = state.selected?.id; + let selected = selectedId ? searchFiltered.find((e) => e.id === selectedId) : null; + if (!selected && searchFiltered.length > 0) { + selected = searchFiltered[Math.min(state.listIndex, searchFiltered.length - 1)]; + } + + return { + ...state, + tabs, + activeTabIndex, + extensions, + tabFiltered, + searchFiltered, + selected: selected ?? null, + listIndex: selected ? searchFiltered.indexOf(selected) : 0, + }; } diff --git a/packages/coding-agent/src/modes/interactive/components/extensions/types.ts b/packages/coding-agent/src/modes/interactive/components/extensions/types.ts index 7fe2bcd30..92b102b5b 100644 --- a/packages/coding-agent/src/modes/interactive/components/extensions/types.ts +++ b/packages/coding-agent/src/modes/interactive/components/extensions/types.ts @@ -98,32 +98,44 @@ export interface FlatTreeItem { } /** - * Focus pane in the dashboard. + * Focus region in the tabbed dashboard. */ -export type FocusPane = "sidebar" | "main" | "inspector"; +export type FocusRegion = "tabs" | "list"; /** - * Dashboard state. + * Provider tab representation. + */ +export interface ProviderTab { + /** Provider ID (or "all" for the ALL tab) */ + id: string; + /** Display label */ + label: string; + /** Whether provider is enabled (always true for "all") */ + enabled: boolean; + /** Extension count for this provider */ + count: number; +} + +/** + * Tabbed dashboard state. */ export interface DashboardState { - /** Currently focused pane */ - focusPane: FocusPane; - - /** Sidebar tree nodes */ - sidebarTree: TreeNode[]; - /** Flattened tree for navigation */ - flatTree: FlatTreeItem[]; - /** Selected index in flattened tree */ - sidebarIndex: number; + /** Provider tabs */ + tabs: ProviderTab[]; + /** Active tab index */ + activeTabIndex: number; /** All extensions (unfiltered) */ extensions: Extension[]; - /** Filtered extensions (after search) */ - filtered: Extension[]; + /** Extensions filtered by active tab */ + tabFiltered: Extension[]; + /** Extensions filtered by search (applied after tab filter) */ + searchFiltered: Extension[]; /** Current search query */ searchQuery: string; + /** Selected index in main list */ - mainIndex: number; + listIndex: number; /** Scroll offset for main list */ scrollOffset: number; @@ -131,6 +143,11 @@ export interface DashboardState { selected: Extension | null; } +/** + * @deprecated Use FocusRegion instead + */ +export type FocusPane = "sidebar" | "main" | "inspector"; + /** * Callbacks from dashboard to parent. */ diff --git a/packages/coding-agent/src/modes/interactive/interactive-mode.ts b/packages/coding-agent/src/modes/interactive/interactive-mode.ts index 9f96aa334..0650e60bd 100644 --- a/packages/coding-agent/src/modes/interactive/interactive-mode.ts +++ b/packages/coding-agent/src/modes/interactive/interactive-mode.ts @@ -6,7 +6,6 @@ import * as fs from "node:fs"; import * as os from "node:os"; import * as path from "node:path"; -import { basename } from "node:path"; import type { AgentMessage, ThinkingLevel } from "@oh-my-pi/pi-agent-core"; import type { AssistantMessage, ImageContent, Message, OAuthProvider } from "@oh-my-pi/pi-ai"; import type { SlashCommand } from "@oh-my-pi/pi-tui"; @@ -24,28 +23,15 @@ import { TUI, visibleWidth, } from "@oh-my-pi/pi-tui"; -import { contextFileCapability } from "../../capability/context-file"; -import { instructionCapability } from "../../capability/instruction"; -import { promptCapability } from "../../capability/prompt"; -import { ruleCapability } from "../../capability/rule"; import { getAuthPath, getDebugLogPath } from "../../config"; import type { AgentSession, AgentSessionEvent } from "../../core/agent-session"; import type { CustomToolSessionEvent, LoadedCustomTool } from "../../core/custom-tools/index"; import type { HookUIContext } from "../../core/hooks/index"; import { createCompactionSummaryMessage } from "../../core/messages"; import { getRecentSessions, type SessionContext, SessionManager } from "../../core/session-manager"; -import { loadSkills } from "../../core/skills"; import { generateSessionTitle, setTerminalTitle } from "../../core/title-generator"; import type { TruncationResult } from "../../core/tools/truncate"; -import { - type ContextFile, - disableProvider, - enableProvider, - type Instruction, - loadSync, - type Prompt, - type Rule, -} from "../../discovery"; +import { disableProvider, enableProvider } from "../../discovery"; import { getChangelogPath, parseChangelog } from "../../utils/changelog"; import { copyToClipboard, readImageFromClipboard } from "../../utils/clipboard"; import { ArminComponent } from "./components/armin"; @@ -56,6 +42,7 @@ import { BranchSummaryMessageComponent } from "./components/branch-summary-messa import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message"; import { CustomEditor } from "./components/custom-editor"; import { DynamicBorder } from "./components/dynamic-border"; +import { ExtensionDashboard } from "./components/extensions"; import { FooterComponent } from "./components/footer"; import { HookEditorComponent } from "./components/hook-editor"; import { HookInputComponent } from "./components/hook-input"; @@ -65,7 +52,6 @@ import { ModelSelectorComponent } from "./components/model-selector"; import { OAuthSelectorComponent } from "./components/oauth-selector"; import { SessionSelectorComponent } from "./components/session-selector"; import { SettingsSelectorComponent } from "./components/settings-selector"; -import { ExtensionDashboard } from "./components/extensions"; import { ToolExecutionComponent } from "./components/tool-execution"; import { TreeSelectorComponent } from "./components/tree-selector"; import { TtsrNotificationComponent } from "./components/ttsr-notification"; diff --git a/packages/coding-agent/src/modes/print-mode.ts b/packages/coding-agent/src/modes/print-mode.ts index 0d5c6e652..a26cc474c 100644 --- a/packages/coding-agent/src/modes/print-mode.ts +++ b/packages/coding-agent/src/modes/print-mode.ts @@ -7,9 +7,35 @@ */ import type { AssistantMessage, ImageContent } from "@oh-my-pi/pi-ai"; +import { APP_NAME, VERSION } from "../config"; import type { AgentSession } from "../core/agent-session"; import { logger } from "../core/logger"; +/** + * Print session header to stderr (text mode only). + */ +function printHeader(session: AgentSession): void { + const model = session.model; + const lines = [ + `${APP_NAME} v${VERSION}`, + "--------", + `workdir: ${process.cwd()}`, + `model: ${model?.id ?? "unknown"}`, + `provider: ${model?.provider ?? "unknown"}`, + `thinking: ${session.thinkingLevel}`, + `session: ${session.sessionId}`, + "--------", + ]; + console.error(lines.join("\n")); +} + +/** + * Print session footer to stderr (text mode only). + */ +function printFooter(): void { + console.error("--------"); +} + /** * Run in print (single-shot) mode. * Sends prompts to the agent and outputs the result. @@ -27,6 +53,11 @@ export async function runPrintMode( initialMessage?: string, initialImages?: ImageContent[], ): Promise { + // Print header to stderr (text mode only) + if (mode === "text") { + printHeader(session); + } + // Hook runner already has no-op UI context by default (set in main.ts) // Set up hooks for print mode (no UI) const hookRunner = session.hookRunner; @@ -116,6 +147,9 @@ export async function runPrintMode( } } } + + // Print footer to stderr + printFooter(); } // Ensure stdout is fully flushed before returning