/** * Shared TUI state — the single source of truth for all mutable state * in the Mastra TUI. Extracted so that slash commands, event handlers, * and other modules can operate on the state without coupling to the * MastraTUI class. */ import { Container, TUI } from '@earendil-works/pi-tui'; import type { CombinedAutocompleteProvider, Component, Terminal, Text } from '@earendil-works/pi-tui'; import type { MastraCodeAnalytics } from '@mastra/code-sdk/analytics'; import type { AuthStorage } from '@mastra/code-sdk/auth/storage'; import type { HookManager } from '@mastra/code-sdk/hooks/index'; import type { McpManager } from '@mastra/code-sdk/mcp/manager'; import type { PluginManager } from '@mastra/code-sdk/plugins/manager'; import type { ProjectInfo } from '@mastra/code-sdk/utils/project'; import type { SlashCommandMetadata } from '@mastra/code-sdk/utils/slash-command-loader'; import type { StorageMaintenance } from '@mastra/code-sdk/utils/storage-maintenance'; import type { AgentController, MastraDBMessage, Session } from '@mastra/core/agent-controller'; import type { SkillMetadata, Workspace } from '@mastra/core/workspace'; import type { GithubSignals } from '@mastra/github-signals'; import type { AskQuestionInlineComponent } from './components/ask-question-inline.js'; import type { AssistantMessageComponent } from './components/assistant-message.js'; import { CustomEditor } from './components/custom-editor.js'; import type { IdleCounterComponent } from './components/idle-counter.js'; import type { JudgeDisplayComponent } from './components/judge-display.js'; import type { GradientAnimator } from './components/obi-loader.js'; import type { OMMarkerComponent, OMMarkerData } from './components/om-marker.js'; import type { OMProgressComponent } from './components/om-progress.js'; import type { PlanApprovalInlineComponent } from './components/plan-approval-inline.js'; import type { ShellStreamComponent } from './components/shell-output.js'; import type { SlashCommandComponent } from './components/slash-command.js'; import type { SubagentExecutionComponent } from './components/subagent-execution.js'; import type { SystemReminderComponent } from './components/system-reminder.js'; import type { TaskProgressComponent } from './components/task-progress.js'; import type { TemporalGapComponent } from './components/temporal-gap.js'; import type { IToolExecutionComponent } from './components/tool-execution-interface.js'; import type { UserMessageComponent } from './components/user-message.js'; import { GoalManager } from './goal-manager.js'; import type { OnboardingInlineComponent } from './onboarding-inline.js'; import { RenderScheduler } from './render-scheduler.js'; import { VoiceController } from './voice/voice-controller.js'; export interface PendingSignalMessage { component: Component; text: string; images?: Array<{ data: string; mimeType: string; }>; isInterjection?: boolean; } export interface GithubPrSubscriptionBadge { owner?: string; repo?: string; prNumber: number; lastSyncStatus?: string; lastNotificationKind?: string; lastNotificationPriority?: string; } export declare function getGithubPrSubscriptionsFromMetadata(metadata: Record | undefined): GithubPrSubscriptionBadge[]; export interface MastraTUIOptions { /** The controller instance */ controller: AgentController; /** The session created from the controller that all work runs through */ session: Session; /** Hook manager for session lifecycle hooks */ hookManager?: HookManager; /** Analytics client for product telemetry */ analytics?: MastraCodeAnalytics; /** Auth storage for OAuth login/logout */ authStorage?: AuthStorage; /** MCP manager for server status and reload */ mcpManager?: McpManager; /** Plugin manager for /plugins. */ pluginManager?: PluginManager; /** * @deprecated Workspace is now obtained from the AgentController. * Configure workspace via AgentControllerConfig.workspace instead. * Kept as fallback for backward compatibility. */ workspace?: Workspace; /** Initial message to send on startup */ initialMessage?: string; /** Whether to show verbose startup info */ verbose?: boolean; /** App name for header */ appName?: string; /** App version for header */ version?: string; /** Use inline questions instead of dialog overlays */ inlineQuestions?: boolean; /** GitHub PR signal processor used for status-line polling state. */ githubSignals?: GithubSignals; /** Storage maintenance handle for /prune (retention pruning + disk reclamation). */ storageMaintenance?: StorageMaintenance; /** Optional terminal injection for in-process tests. Defaults to ProcessTerminal. */ terminal?: Terminal; } export interface TUIState { controller: AgentController; session: Session; options: MastraTUIOptions; hookManager?: HookManager; analytics?: MastraCodeAnalytics; authStorage?: AuthStorage; mcpManager?: McpManager; pluginManager?: PluginManager; workspace?: Workspace; ui: TUI; renderScheduler?: RenderScheduler; chatContainer: Container; editorContainer: Container; idleCounter?: IdleCounterComponent; lastRenderedMessageAt?: number; editor: CustomEditor; footer: Container; terminal: Terminal; voiceController?: VoiceController; isInitialized: boolean; gradientAnimator?: GradientAnimator; streamingComponent?: AssistantMessageComponent; streamingMessage?: MastraDBMessage; pendingTools: Map; /** Task tools are hidden on success but promoted to normal tool boxes on errors */ pendingTaskToolIds: Set; /** Position hint for inline task-tool rendering when streaming */ taskToolInsertIndex: number; /** Track all tool IDs seen during current stream (prevents duplicates) */ seenToolCallIds: Set; /** Track subagent tool call IDs to skip in trailing content logic */ subagentToolCallIds: Set; /** Track streamed system reminders for the active assistant run */ currentRunSystemReminderKeys: Set; /** Track all tools for expand/collapse */ allToolComponents: IToolExecutionComponent[]; /** Track slash command boxes for expand/collapse */ allSlashCommandComponents: SlashCommandComponent[]; /** Track inline system reminders for expand/collapse */ allSystemReminderComponents: Array; /** Track rendered message components by message id for anchored inserts */ messageComponentsById: Map; /** Track shell passthrough components for expand/collapse */ allShellComponents: ShellStreamComponent[]; /** Track active subagent tasks */ pendingSubagents: Map; toolOutputExpanded: boolean; hideThinkingBlock: boolean; quietMode: boolean; quietModeMaxToolPreviewLines: number; /** Active goal judge status-line override while evaluating the last turn. */ activeGoalJudge?: { modelId: string; abortController: AbortController; component: JudgeDisplayComponent; }; /** True when we want a new thread but haven't created it yet */ pendingNewThread: boolean; /** Current thread title (for display in status line) */ currentThreadTitle?: string; /** GitHub PR subscriptions for the current thread. */ activeGithubPrSubscriptions: GithubPrSubscriptionBadge[]; /** Cached thread previews for the current TUI session */ threadPreviewCache: Map; /** Threads whose preview lookup already returned empty during this session */ attemptedThreadPreviewIds: Set; /** Track the most recent ask_user component for inline question activation */ lastAskUserComponent?: AskQuestionInlineComponent; /** Map toolCallId → AskQuestionInlineComponent for streaming arg updates */ pendingAskUserComponents: Map; /** Saved editor text for Alt+Z undo */ lastClearedText: string; activeInlineQuestion?: AskQuestionInlineComponent; /** Queue of pending inline questions waiting to be shown (when one is already active) */ pendingInlineQuestions: Array<() => void>; activeInlinePlanApproval?: PlanApprovalInlineComponent; /** * Focus deferred because a command overlay was open when a plan approval * arrived. Handed off (setFocus) when the overlay stack empties, guarded by * `pendingFocus === activeInlinePlanApproval` so a stale value never steals * focus. See installOverlayFocusHandoff in setup.ts. */ pendingFocus?: Component; activeOnboarding?: OnboardingInlineComponent; lastSubmitPlanComponent?: Component; pendingSubmitPlanComponents: Map; /** Previous plan snapshot (keyed by plan file path) for diff display on resubmission */ previousPlanSnapshot?: { path: string; plan: string; }; /** User-message follow-ups queued while the agent is running */ pendingFollowUpMessages: Array<{ content: string; images?: Array<{ data: string; mimeType: string; }>; }>; /** FIFO ordering across queued follow-up messages and slash commands */ pendingQueuedActions: Array<'message' | 'slash'>; /** Follow-up messages rendered while streaming so tool output stays above them */ followUpComponents: UserMessageComponent[]; /** Pending signal messages waiting for the stream echo */ pendingSignalMessageComponentsById: Map; /** Slash commands queued while the agent is running */ pendingSlashCommands: string[]; /** Pending user-message component ids for queued slash commands */ pendingSlashCommandMessageIds: string[]; /** Active approval dialog dismiss callback — called on Ctrl+C or user interruption to unblock the dialog */ pendingApprovalDismiss: ((context?: { reason?: string; message?: string; }) => void) | null; projectInfo: ProjectInfo; statusLine?: Text; memoryStatusLine?: Text; modelAuthStatus: { hasAuth: boolean; apiKeyEnvVar?: string; }; githubPrGradientAnimator?: GradientAnimator; githubPrPollingActive: boolean; /** Timestamp (ms) when the current agent run started. */ agentRunStartedAt?: number; /** Timestamp (ms) when the current agent run last received streamed content. */ agentRunLastStreamPartAt?: number; /** Duration (ms) of the most recently completed agent run. */ lastAgentRunDurationMs?: number; /** Timestamp (ms) when the most recent agent run ended. */ lastAgentRunEndedAt?: number; /** End state of the most recent agent run. */ lastAgentRunEndReason?: 'done' | 'aborted' | 'error'; /** * Timestamp (ms) of the first streamed content delta of the current step — * i.e. when decoding began. tokens/sec is measured over decode time only * (excludes TTFT and inter-step tool gaps). 0 means decode not yet started. */ decodeStartedAt: number; /** Current computed tokens/sec rate (0 when idle) */ tokensPerSec: number; omProgressComponent?: OMProgressComponent; activeOMMarker?: OMMarkerComponent; activeBufferingMarker?: OMMarkerComponent; activeActivationMarker?: OMMarkerComponent; activeActivationData?: OMMarkerData; activeActivationProviderChangeMarker?: OMMarkerComponent; taskProgress?: TaskProgressComponent; goalManager: GoalManager; /** Track a goal started from plan approval — return to plan mode when it completes */ planStartedGoalId?: string; autocompleteProvider?: CombinedAutocompleteProvider; customSlashCommands: SlashCommandMetadata[]; skillCommands: SkillMetadata[]; goalSkillCommands: SkillMetadata[]; /** Pending images from clipboard paste */ pendingImages: Array<{ data: string; mimeType: string; }>; /** Texts of queued messages that were locally rendered and fired — used to * suppress the subscription echo that would otherwise create a duplicate. */ firedQueuedMessageTexts?: Map; lastCtrlCTime: number; /** Track user-initiated aborts (Ctrl+C/Esc) vs system aborts */ userInitiatedAbort: boolean; /** * Set when the run is aborted because the user clicked "Request Changes" on a * plan approval. Suppresses the "Interrupted" abort UI so the rejection ends * cleanly and the user can type revision feedback. */ planRejectionAbort: boolean; unsubscribe?: () => void; } /** * Create the initial TUIState from options. * Instantiates TUI framework objects (terminal, containers, editor) * and sets all mutable fields to their defaults. */ export declare function createTUIState(options: MastraTUIOptions): TUIState; //# sourceMappingURL=state.d.ts.map