import { type KeyEvent as TuiKeyEvent, type InputSource, type OutputTarget } from "../tui/index.js"; import type { Frame } from "../tui/frame.js"; type ChoiceItem = { key: string; label: string; }; type ChoiceRequest = { title: string; body: string; items: ChoiceItem[]; allowFreeText?: boolean; }; /** TEST ONLY — inject an `InputSource` (e.g. `ScriptedInput`) for the * declarative bridge. Pass `null` to clear between tests. */ export declare function _setInputSource(src: InputSource | null): void; /** TEST ONLY — inject an `OutputTarget` (e.g. `FrameRecorder`) for the * declarative bridge. Pass `null` to clear between tests. */ export declare function _setOutputTarget(out: OutputTarget | null): void; /** TEST ONLY — extract the recorded frames from the injected * `FrameRecorder` as plain-text per-frame strings. Returns `[]` * when no recorder is installed (production path). */ export declare function _recordedFrameTexts(): string[]; /** TEST ONLY — set the viewport (width / height) the bridge passes * to `Screen`. Production reads `process.stdout.columns` / `.rows`. */ export declare function _setSize(w: number, h: number): void; /** Returns true while a `_runLoop` (or future `_runLoopHybrid`) call * is in flight. Used by `std::policy.cliPolicyHandler` to probe * whether a REPL owns the screen and route prompts accordingly. */ export declare function _hasActiveScreen(): boolean; /** * Wake the active runLoop so it repaints immediately. Used by * `_beginSubmit` (the async-callback path) and by Agency-side * `pushMessage` so transcript updates show up without waiting for * the user to press another key. No-op when no input source supports * synthetic injection (we keep the check defensive since custom * `InputSource`s aren't required to implement `feedKey`). */ export declare function _triggerRender(): void; /** Shape of the `state` arg `_beginSubmit` mutates while the async * onSubmit settles. Defined locally because the Agency `ReplState` * is record-typed and the bridge only cares about these two fields. * The exit-on-`false`-return path uses the `_signalReplExit` bridge * flag rather than mutating `state.done` here — see that function's * comment for why. */ type SubmitTargetState = { submit?: { busy?: boolean; label?: string; startedAtMs?: number; }; transcript: { messages: string[]; }; }; export declare function truncateForTui(text: string): string; export declare function _installConsoleCapture(messages: string[]): void; export declare function _uninstallConsoleCapture(): void; export declare function _nowMs(): number; export declare function _elapsedSeconds(startedAtMs: number, nowMs?: number): number; export declare function _spinnerFrame(startedAtMs: number, nowMs?: number): string; /** Signal that the active `repl()` should exit on its next isDone * check. Called from `_beginSubmit` when `onSubmit` returns `false`, * and from any future "force exit" plumbing. Wakes the loop so * `_replIsDone` runs immediately. */ export declare function _signalReplExit(): void; /** Read the exit signal without clearing it. The Agency `_replIsDone` * calls this on every tick; once true the loop terminates and the * flag is reset by `_runReplLoop` in its finally block so the next * REPL invocation starts fresh. */ export declare function _peekReplExitSignal(): boolean; /** Reset the exit signal. Called by `_runReplLoop` before and after * the loop runs, so a leftover signal from a prior REPL session * doesn't cause the next one to exit on first frame. */ export declare function _resetReplExitSignal(): void; export declare function _beginSubmit(state: SubmitTargetState, submitted: string, onSubmit: unknown): void; export declare function _runLoop(initialState: any, renderFn: unknown, handleKeyFn: unknown, isDoneFn: unknown, tickMs?: number | null): Promise; /** * REPL-only wrapper around `_runLoop` that guarantees the * console-capture install is reversed even if the loop (or any * Agency callback it invokes) throws. Agency has no `finally`, so * the cleanup pair `_installConsoleCapture` / `_uninstallConsoleCapture` * has to live on the TS side of the bridge to keep stdout / console * from staying monkeypatched after a failed REPL. * * `transcriptMessages` is the same array `repl()` renders from; we * pass it through to `_installConsoleCapture` so console / print * output appends to the live transcript. */ export declare function _runReplLoop(initialState: any, renderFn: unknown, handleKeyFn: unknown, isDoneFn: unknown, tickMs: number | null | undefined, transcriptMessages: string[]): Promise; /** Single-shot render of an element tree. Useful for non-interactive * output or for tests that want to inspect a rendered frame * without entering a loop. */ export declare function _renderOnce(element: any): void; /** Read one key from the active screen's input source if a loop is * running, else construct a one-off screen for the read. Blocks * until a key arrives. */ export declare function _readKey(): Promise; /** * `OutputTarget` for `repl()`'s hybrid rendering. Renders each frame * directly inside the terminal's reserved bottom region: * `withBottomCursor` saves the cursor, positions it at the start of * the bottom region, writes the frame ANSI (no `CURSOR_HOME` prefix, * no alt-screen entry — both would defeat the hybrid scrollback * goal), and restores the cursor so subsequent plain stdout writes * still scroll inside the top region. * * Does NOT wrap an inner OutputTarget. The bridge's default * `TerminalOutput` enters the alt-screen and prepends `CURSOR_HOME` * to every write, which is exactly what hybrid mode must avoid; this * target sidesteps both by talking to `process.stdout` itself via * `toANSI`. `destroy()` is a no-op: this target owns no resources * (the scroll region itself is torn down by `_resetScrollRegion`). */ export declare class BottomRegionOutputTarget implements OutputTarget { write(frame: Frame, _label?: string): void; destroy(): void; } /** * Append a raw text line to the scroll region. Plain * `process.stdout.write` — no ANSI; the scroll region installed by * `installRegion` in `./ui-region.ts` does the scrolling. Used by * `repl()` to stream `output()` lines into the terminal's native * scrollback as new tail elements appear. */ export declare function _writeScrollLine(text: string): void; type PromptsChoiceItem = { key: string; label: string; }; export declare function __suggestForTest(input: string, items: PromptsChoiceItem[], allowFreeText: boolean): Promise<{ title: string; value: string; }[]>; export declare function _promptsAutocomplete(message: string, items: PromptsChoiceItem[], allowFreeText: boolean, hint?: string, cancelOnEscape?: boolean): Promise; export declare function _promptsSelect(message: string, items: PromptsChoiceItem[], allowFreeText: boolean, hint?: string): Promise; export declare function _promptsText(message: string, initial: string, hint?: string, validate?: ((value: string) => boolean | string) | null): Promise; export declare function _promptsConfirm(message: string, initial: boolean): Promise; /** * Open a modal choice prompt over the currently-running REPL. Stores * the request in the active context's UI-state slot that the Agency * reducer reads via `_peekPendingChoiceRequest()` on every tick (so a * fresh frame sees the modal even though reducers return new state * records), then returns a Promise that the Agency reducer resolves * via `_resolveChoice(answer)` (Enter) or rejects via `_cancelChoice` * (Escape, or REPL torn down). * * Rejects if another prompt is already open in this context — the * caller should serialize. */ export declare function _openChoicePrompt(request: ChoiceRequest): Promise; /** * Read the pending choice request without consuming it. Returns * `null` when no prompt is open. The Agency reducer calls this on * every keystroke to sync `state.choice` with the TS-side request: * if TS has a request but state.choice is null, the reducer * initializes it; if TS has no request but state.choice is set, * the reducer clears it. */ export declare function _peekPendingChoiceRequest(): ChoiceRequest | null; /** Resolve the pending choice promise with `answer` and clear both * the promise slot and the request slot. Called by the Agency * reducer when Enter is pressed on a filtered, non-empty list. * No-op when no prompt is open. */ export declare function _resolveChoice(answer: string): void; /** Reject the pending choice promise with `reason` and clear both * the promise slot and the request slot. Called by the Agency * reducer on Escape, or by `_runReplLoop` in its finally block to * break out of any prompt left hanging by an exception. No-op when * no prompt is open. */ export declare function _cancelChoice(reason: string): void; /** Test/debug hook. Returns true while a choice prompt is awaiting a * reducer callback. */ export declare function _hasPendingChoice(): boolean; /** Install a `bottomRows`-row reserved region at the bottom of the * terminal. The top `H - bottomRows` rows scroll natively. No-op on * non-TTY. Idempotent — call again to resize the region. */ export declare function _installScrollRegion(bottomRows: number): void; /** Tear down the reserved region. Restores the default scroll region * (the whole terminal) and prints a trailing newline so the next * shell prompt lands below the bottom region. */ export declare function _resetScrollRegion(): void; /** Hybrid-mode variant of `_runLoop`. Drives the `repl()` widget's * bounded `Screen` (bottom `bottomRows` rows only); frames render * into the terminal's reserved bottom region while plain stdout * writes keep scrolling in the top region. The scroll region itself * is installed by `repl()` via `_installScrollRegion` before this * call and torn down via `_resetScrollRegion` afterwards (including * on exception paths via the Agency `handle` block). * * Output target selection: * - **Test mode** (`bridgeOutputTarget` is a `FrameRecorder`, * injected by `_setOutputTarget`): frames go straight into the * recorder so tests can inspect them. * - **Real terminal mode**: a fresh `BottomRegionOutputTarget` * writes ANSI to stdout via `withBottomCursor`, bypassing the * default `TerminalOutput` (which would enter the alt screen and * prepend `CURSOR_HOME` — both fatal to hybrid scrollback). */ export declare function _runLoopHybrid(initialState: any, renderFn: unknown, handleKeyFn: unknown, isDoneFn: unknown, tickMs: number, bottomRows: number): Promise; export {};