/** * agent-widget.ts — Persistent widget showing running/completed agents above the editor. * * Displays a tree of agents with animated spinners, live stats, and activity descriptions. * Uses the callback form of setWidget for themed rendering. */ import type { AgentManager } from "../agent-manager.js"; import type { AgentInvocation, AgentRecord, SubagentType, WidgetMode } from "../types.js"; import { type LifetimeUsage, type SessionLike } from "../usage.js"; /** Maximum number of rendered lines before overflow collapse kicks in. */ export declare const MAX_WIDGET_LINES = 12; /** * Derive the widget ceiling from the terminal height while retaining the * historical MAX_WIDGET_LINES ceiling. Very short terminals may have no room * for the widget; that is preferable to consuming the editor/input area. */ export declare function getWidgetLineBudget(rows: number): number; /** Braille spinner frames for animated running indicator. */ export declare const SPINNER: string[]; /** Statuses that indicate an error/non-success outcome (used for linger behavior and icon rendering). */ export declare const ERROR_STATUSES: Set; export type Theme = { fg(color: string, text: string): string; bold(text: string): string; }; export type AgentWidgetOpenMode = "live" | "history"; export type AgentWidgetOpenCallback = (record: AgentRecord, mode: AgentWidgetOpenMode) => void | Promise; export type AgentWidgetOptions = { canOpenHistory: (record: AgentRecord) => boolean; onOpen: AgentWidgetOpenCallback; }; /** @deprecated Use AgentWidgetOpenMode. */ export type AgentOpenMode = AgentWidgetOpenMode; /** @deprecated Use AgentWidgetOpenCallback. */ export type AgentOpenCallback = AgentWidgetOpenCallback; /** @deprecated Use AgentWidgetOptions.canOpenHistory. */ export type AgentHistoryCapability = AgentWidgetOptions["canOpenHistory"]; export type UICtx = { setStatus(key: string, text: string | undefined): void; setWidget(key: string, content: undefined | ((tui: any, theme: Theme) => { render(): string[]; invalidate(): void; }), options?: { placement?: "aboveEditor" | "belowEditor"; }): void; onTerminalInput(handler: (data: string) => { consume?: boolean; data?: string; } | undefined): () => void; getEditorText(): string; }; /** Per-agent live activity state. */ export interface AgentActivity { activeTools: Map; toolUses: number; responseText: string; session?: SessionLike; /** Current turn count. */ turnCount: number; /** Effective max turns for this agent (undefined = unlimited). */ maxTurns?: number; /** Lifetime usage breakdown — see LifetimeUsage docs. */ lifetimeUsage: LifetimeUsage; } /** Metadata attached to Agent tool results for custom rendering. */ export interface AgentDetails { displayName: string; description: string; subagentType: string; toolUses: number; tokens: string; durationMs: number; status: "queued" | "running" | "completed" | "steered" | "aborted" | "stopped" | "error" | "background"; /** Human-readable description of what the agent is currently doing. */ activity?: string; /** Current spinner frame index (for animated running indicator). */ spinnerFrame?: number; /** Short model name if different from parent (e.g. "haiku", "sonnet"). */ modelName?: string; /** Notable config tags (e.g. ["thinking: high", "isolated"]). */ tags?: string[]; /** Current turn count. */ turnCount?: number; /** Effective max turns (undefined = unlimited). */ maxTurns?: number; agentId?: string; error?: string; } /** Apply foreground styling while restoring it after nested foreground/full ANSI resets. */ export declare function fgPreservingNestedStyles(theme: Theme, color: string, text: string): string; /** Format a token count compactly: "33.8k token", "1.2M token". */ export declare function formatTokens(count: number): string; /** * Token count with optional context-fill % and compaction-count annotations. * Thresholds for percent: <70% dim, 70–85% warning, ≥85% error. * Compaction count rendered as `⇊N` in dim. * * "12.3k token" — no annotations * "12.3k token (45%)" — percent only * "12.3k token (⇊2)" — compactions only (e.g. right after compact) * "12.3k token (45% · ⇊2)" — both */ export declare function formatSessionTokens(tokens: number, percent: number | null, theme: Theme, compactions?: number): string; /** Format turn count with optional max limit: "↻5≤30" or "↻5". */ export declare function formatTurns(turnCount: number, maxTurns?: number | null): string; /** Format milliseconds as human-readable duration. */ export declare function formatMs(ms: number): string; /** Format duration from start/completed timestamps. */ export declare function formatDuration(startedAt: number, completedAt?: number): string; /** Get display name for any agent type (built-in or custom). */ export declare function getDisplayName(type: SubagentType): string; /** Short label for prompt mode: "twin" for append, nothing for replace (the default). */ export declare function getPromptModeLabel(type: SubagentType): string | undefined; /** Mode label is not included — callers add it where they want it. */ export declare function buildInvocationTags(invocation: AgentInvocation | undefined): { modelName?: string; tags: string[]; }; /** Build a human-readable activity string from currently-running tools or response text. */ export declare function describeActivity(activeTools: Map, responseText?: string): string; export declare class AgentWidget { private manager; private agentActivity; /** Read live at render time. Selects which agents the widget shows. */ private mode; private options; private uiCtx; private widgetFrame; private widgetInterval; private inputUnsub; /** Whether arrow keys currently navigate the agent roster. */ private navigationActive; /** Stable identity of the selected row, so roster changes do not jump selection. */ private selectedAgentId; /** Last logical roster index of the selected row, used when it disappears. */ private selectedRosterIndex; /** First logical row currently represented by the bounded viewport. */ private viewportStart; /** Whether the widget callback is currently registered with the TUI. */ private widgetRegistered; /** Cached TUI reference from widget factory callback, used for requestRender(). */ private tui; /** Last status bar text, used to avoid redundant setStatus calls. */ private lastStatusText; /** Snapshot of the state used for the last widget registration/render request. */ private lastRenderKey; constructor(manager: AgentManager, agentActivity: Map, /** Read live at render time. Selects which agents the widget shows. */ mode?: () => WidgetMode, options?: AgentWidgetOptions); /** * Agents eligible for the widget, per the current `WidgetMode`: * - `off`: none (the widget's existing empty-state path hides it entirely). * - `background`: drop only agents *known* to be foreground * (`isBackground === false`); keep everything else — background, queued, * scheduled, or RPC-spawned (`undefined`). Keying off the `isBackground` * record flag rather than the UI-only `invocation` snapshot (which only the * Agent-tool path sets), and excluding rather than allow-listing, means * only proven-foreground runs drop out — nothing else silently vanishes. * - `all`: every agent. */ private widgetAgents; /** Set the UI context (grabbed from first tool execution). */ setUICtx(ctx: UICtx): boolean; /** Request a render on the currently registered TUI without touching input. */ requestUiRefresh(force?: boolean): boolean; /** Called on each new turn (tool_execution_start). */ onTurnStart(): void; /** Keep the spinner/elapsed-time timer alive only while a visible agent runs. */ ensureTimer(): void; private syncTimer; /** * Retained for the lifecycle call sites. Terminal visibility is determined * by the manager record and the history capability, not a one-turn timer. */ markFinished(_agentId: string): void; /** * Records represented by selectable rows in the above-editor widget. * * Keep this order as the single source of truth for both rendering and key * navigation. `listAgents()` is newest-first; active rows come first so the * panel exposes currently useful work before terminal history. */ private roster; /** True when pi's prompt editor owns the keyboard. */ private editorHasFocus; private selectedIndexOf; private deactivate; /** Resume navigation from the retained row, or select the first row. */ private activate; /** Move the selected row, activating only from an empty focused editor. */ private moveSelection; private openSelected; /** Handle terminal input before it reaches the focused prompt editor. */ handleKey(data: string): { consume?: boolean; data?: string; } | undefined; /** Render a finished agent line. */ private renderFinishedLine; /** * Render the widget content. Called from the registered widget's render() callback, * reading live state each time instead of capturing it in a closure. */ private renderWidget; /** Build a render-relevant snapshot without capturing mutable records. */ private renderKey; /** Force an immediate widget update. `advanceSpinner` is reserved for the timer. */ update(advanceSpinner?: boolean): void; dispose(): void; } //# sourceMappingURL=agent-widget.d.ts.map