export interface ActiveTool { context?: string id: string name: string verboseArgs?: string startedAt?: number } export interface TodoItem { content: string id: string /** Optional id of another item — renders this as a nested subtask. */ parent?: string status: 'cancelled' | 'completed' | 'in_progress' | 'pending' } export interface ActivityItem { id: number text: string tone: 'error' | 'info' | 'warn' } export type SubagentStatus = 'completed' | 'error' | 'failed' | 'interrupted' | 'queued' | 'running' | 'timeout' export interface SubagentProgress { apiCalls?: number costUsd?: number /** Batch (delegation) id — tags `[n/N]` rows so concurrent/nested fan-outs * are distinguishable. Absent on older gateways. */ delegationId?: string depth: number durationSeconds?: number filesRead?: string[] filesWritten?: string[] goal: string id: string index: number inputTokens?: number iteration?: number model?: string notes: string[] outputTail?: SubagentOutputEntry[] outputTokens?: number parentId: null | string reasoningTokens?: number startedAt?: number status: SubagentStatus summary?: string taskCount: number thinking: string[] toolCount: number tools: string[] toolsets?: string[] } export interface SubagentOutputEntry { isError: boolean preview: string tool: string } export interface SubagentNode { aggregate: SubagentAggregate children: SubagentNode[] item: SubagentProgress } export interface SubagentAggregate { activeCount: number costUsd: number descendantCount: number filesTouched: number hotness: number inputTokens: number maxDepthFromHere: number outputTokens: number totalDuration: number totalTools: number } export interface DelegationStatus { active: { depth?: number goal?: string model?: null | string parent_id?: null | string started_at?: number status?: string subagent_id?: string tool_count?: number }[] max_concurrent_children?: number max_spawn_depth?: number paused: boolean } export interface ApprovalReq { // false when the backend won't honor a permanent allow (tirith warning) → hide "Always allow". allowPermanent?: boolean choices?: string[] command: string description: string smartDenied?: boolean } export interface ConfirmReq { cancelLabel?: string confirmLabel?: string danger?: boolean detail?: string onConfirm: () => void title: string } export interface ClarifyBatchQuestion { choices: string[] | null multiSelect?: boolean qid: string question: string } export interface ClarifyReq { choices: string[] | null question: string requestId: string /** Batch (multi-question) clarify: present instead of question/choices. */ questions?: ClarifyBatchQuestion[] /** Answers already locked server-side (qid → answer): seeded from the * reconnect replay, updated as the user locks each question. */ answers?: Record } export interface Msg { info?: SessionInfo kind?: 'diff' | 'event' | 'intro' | 'panel' | 'slash' | 'trail' panelData?: PanelData role: Role text: string // Unix seconds the message was authored (persisted transcript timestamp on // rehydrate, wall clock at append time for live rows). Rendered as a dim // [HH:MM] label when `display.timestamps` is on (#41531). createdAt?: number thinking?: string // MoA reference-model output stored in `thinking` (see turnController's // recordMoaReference): unlike ordinary model reasoning, this is the // user-facing mixture-of-agents process the user opted into, so it stays // visible even when `display.sections.thinking` is hidden. isMoaReference?: boolean // True only while this trail segment's reasoning is being streamed live by // the current turn (see turnController's syncReasoningSegment). Sealed // reasoning segments from earlier in the turn carry no flag, so the TUI can // tell "the reasoning happening right now" apart from finished blocks. isLiveReasoning?: boolean thinkingTokens?: number toolTokens?: number tools?: string[] todos?: TodoItem[] todoIncomplete?: boolean todoCollapsedByDefault?: boolean } export type Role = 'assistant' | 'system' | 'tool' | 'user' export type DetailsMode = 'hidden' | 'collapsed' | 'expanded' export type ThinkingMode = 'collapsed' | 'truncated' | 'full' // Per-section overrides for the agent details accordion. Resolution order // at lookup time is: explicit `display.sections.` → built-in // SECTION_DEFAULTS → global `details_mode`. Today the built-in defaults // expand `thinking`/`tools` and hide `activity`; `subagents` falls through // to the global mode. Any explicit value still wins for that one section. export type SectionName = 'thinking' | 'tools' | 'subagents' | 'activity' export type SectionVisibility = Partial> export interface McpServerStatus { connected: boolean disabled?: boolean status?: 'configured' | 'connecting' | 'connected' | 'disabled' | 'failed' name: string tools: number transport: string } export interface ProjectInfo { id: string name: string primary_path?: null | string slug: string } export interface SessionInfo { cwd?: string fast?: boolean install_warning?: string lazy?: boolean mcp_servers?: McpServerStatus[] model: string profile_name?: string project?: null | ProjectInfo reasoning_effort?: string release_date?: string service_tier?: string skills: Record system_prompt?: string tools: Record update_behind?: number | null update_command?: string usage?: Usage version?: string } export interface Usage { active_subagents?: number /** Rolling mean API latency over the last 10 calls (seconds). */ avg_latency_s?: number /** Rolling output tokens/sec over the last 10 calls. */ avg_tps?: number /** Session prompt-cache hit ratio (cache_read / prompt tokens, %). */ cache_hit_pct?: number calls: number compressions?: number context_max?: number context_percent?: number context_used?: number cost_status?: string cost_usd?: number dev_credits_spent_micros?: number input: number output: number reasoning?: number total: number } export interface SudoReq { requestId: string } export interface SecretReq { envVar: string prompt: string requestId: string } export interface PanelData { sections: PanelSection[] title: string } export interface PanelSection { items?: string[] rows?: [string, string][] text?: string title?: string } export interface SlashCatalog { canon: Record categories: SlashCategory[] pairs: [string, string][] skillCount: number sub: Record } export interface SlashCategory { name: string pairs: [string, string][] }