/** * Custom editor that handles app-level keybindings for Mastra Code. */ import { Editor } from '@earendil-works/pi-tui'; import type { EditorTheme, TUI } from '@earendil-works/pi-tui'; import type { ClipboardImage } from '@mastra/code-sdk/clipboard/index'; import type { GradientAnimator } from './obi-loader.js'; /** * Push-to-talk voice input interface the editor drives. Implemented by * VoiceController. Terminals do not emit key-up events, so a held space is * inferred from auto-repeat: a burst of rapid repeated spaces means the key is * held (start recording); recording stops once those repeats stop arriving. */ export interface VoiceInputHook { isEnabled(): boolean; isRecording(): boolean; startRecording(): void; stopRecording(): void | Promise; } export type AppAction = 'clear' | 'exit' | 'suspend' | 'undo' | 'toggleThinking' | 'expandTools' | 'followUp' | 'queueFollowUp' | 'cycleMode' | 'toggleYolo'; export declare class CustomEditor extends Editor { private actionHandlers; onCtrlD?: () => void; escapeEnabled: boolean; onImagePaste?: (image: ClipboardImage) => void; getModeColor?: () => string | undefined; getPromptAnimator?: () => GradientAnimator | undefined; requestRender?: () => void; private pendingBracketedPaste; /** * Push-to-talk voice hook. When set and enabled, holding the space bar starts * recording; releasing it (auto-repeat stops) transcribes and inserts at the * cursor. */ voiceInput?: VoiceInputHook; private lastSpaceAt; private spaceRepeatCount; private voiceRecordingActive; private spaceReleaseTimer; private voiceListening; private voiceListenTimer; private voiceListenPhase; private voiceTranscriptText; private voicePrefix; private voiceSuffix; private voiceDictationActive; private _cachedModeColorHex?; private _cachedColorFn?; private promptIcon; private lastPromptWasInvisible; private requestEditorRender; constructor(tui: TUI, theme: EditorTheme); onAction(action: AppAction, handler: () => unknown): void; render(width: number): string[]; private maybeHandleBracketedPaste; private shouldPasteClipboardImage; private getClipboardImageForPastedRemoteImageUrl; private readPastedImageSource; private normalizePastedPathLike; private normalizePastedImageUrl; private normalizePastedFilePath; private getImageMimeType; private handleExplicitPaste; private completeAutocompleteSelection; /** * Capture the cursor position where dictation begins so the dictated run can be * inserted (and later replaced) in place, even when the cursor sits in the * middle of existing input. */ private beginDictation; /** * Flatten the editor's {line, col} cursor into a single string offset over the * newline-joined text. */ private getCursorOffset; /** * Restore the cursor to a flat string offset over the newline-joined text. * Uses the editor's internal state directly since pi-tui exposes no public * cursor setter. */ private setCursorOffset; /** * Insert dictated text at the captured dictation anchor. Used for the final * (non-live) transcript path. */ insertVoiceTranscript(text: string): void; /** * Replace the current dictated run with a new transcript. Used for live * transcription, where each partial result supersedes the previous one as the * user keeps speaking. */ replaceVoiceTranscript(text: string): void; /** * Rebuild the input as prefix + dictated payload + suffix, keeping the dictated * run anchored at the cursor position where dictation began and leaving the * cursor just after the dictated text. */ private applyDictation; /** * Wrap up to `count` trailing dictated characters of a rendered content line in * the grey (muted) color. The underlying pi-tui editor produces plain text plus * a few artifacts that must be skipped: an APC hardware-cursor marker * (`\x1b_pi:c\x07`), a reverse-video cursor highlight (`\x1b[7m…\x1b[0m`), and * trailing padding spaces. We isolate the real content region (everything * before the cursor highlight / padding) and grey only its trailing characters, * leaving the cursor and padding untouched. * * Returns the recolored line and how many content characters were greyed. */ private greyifyTrailing; /** * Start or stop the "listening" prompt animation. While listening, the prompt * indicator pulses on its own timer so the user gets clear visual feedback * that the mic is recording. */ setVoiceListening(listening: boolean): void; /** * Push-to-talk space handling. Returns true when the space was consumed by * voice handling and must not be processed further. * * Normal spaces are typed instantly (no deferral, no lag). A held space is * detected from terminal auto-repeat: once SPACE_HOLD_REPEAT_THRESHOLD rapid * spaces arrive, the literal spaces already typed are deleted and recording * begins. While recording, repeats are swallowed and reset a release timer; * when repeats stop (key released) recording stops and transcribes. */ private maybeHandleVoiceSpace; private armSpaceReleaseTimer; handleInput(data: string): void; } //# sourceMappingURL=custom-editor.d.ts.map