export type SessionStartReason = "startup" | "reload" | "new" | "resume" | "fork"; export type SessionStartEvent = { reason: SessionStartReason; previousSessionFile?: string; }; export type SessionShutdownEvent = { reason: string; targetSessionFile?: string; }; /** A custom session entry, as built by sessionManager.appendCustomEntry(customType, data). */ export type CustomEntry = { type?: string; customType?: string; data?: unknown; id?: string; }; export type EntryAppendedEvent = { entry: CustomEntry; }; export type TurnEndEvent = Record; /** Themed rendering primitives handed to a widget callback. */ export interface Theme { fg(color: string, text: string): string; bold(text: string): string; } /** Minimal TUI handle passed to the widget factory. */ export interface TuiApi { width?: number; requestRender?(): void; } /** A widget component: `render(width)` returns the text to draw. pi's layout calls this * with the available column width (Container.render(width) → child.render(width)); every * returned line MUST fit within it or the TUI aborts doRender. `invalidate` is called on * theme change so the factory can re-capture. */ export interface WidgetComponent { render(width?: number): string[]; invalidate?(): void; } /** The widget factory registered via setWidget — returns a component, NOT a raw string. */ export type WidgetFactory = (tui: TuiApi, theme: Theme) => WidgetComponent; /** The UI surface (present only in a TUI session). Captured from a hook's ctx. */ export interface UIContext { setWidget(key: string, factory: WidgetFactory | undefined, options?: { placement?: "aboveEditor" | "belowEditor" | string; }): void; setStatus(key: string, text: string | undefined): void; setFooter(render: ((tui: TuiApi, theme: Theme, footerData?: unknown) => string) | undefined): void; notify?(message: string, level?: "info" | "warn" | "error"): void; } export interface ExtensionContext { cwd: string; mode: "tui" | "rpc" | "json" | "print"; hasUI: boolean; signal?: AbortSignal; ui?: UIContext; } export type AutocompleteItem = { value: string; label?: string; }; export type CommandSpec = { description: string; handler: (args: string, ctx: ExtensionContext) => void | Promise; getArgumentCompletions?: (prefix: string) => AutocompleteItem[] | null; }; type BusHandler = (data: unknown) => void; export interface ExtensionAPI { on(event: "session_start", handler: (event: SessionStartEvent, ctx: ExtensionContext) => void | Promise): void; on(event: "session_shutdown", handler: (event: SessionShutdownEvent, ctx: ExtensionContext) => void | Promise): void; on(event: "entry_appended", handler: (event: EntryAppendedEvent, ctx: ExtensionContext) => void | Promise): void; on(event: "turn_end", handler: (event: TurnEndEvent, ctx: ExtensionContext) => void | Promise): void; /** In-process pub/sub bus (subagents:* etc.). Handler gets only data, no ctx. */ events: { on(channel: string, handler: BusHandler): () => void; emit(channel: string, data?: unknown): void; }; /** Persist a custom session entry; emits `entry_appended` (also forwarded over RPC). */ appendEntry(customType: string, data?: unknown): string; /** Register a slash command (e.g. `/plan`). */ registerCommand(name: string, spec: CommandSpec): void; } export {};