@orkestrel/terminal 0.0.19 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ESC","CSI","STATUS_ICONS","freezeStyle","isInstance","literalOf","recordOf","isNonEmptyString","isRecord","isNumber","isString","isString","freezeStyle","stripControls","strip","createStyler","isError","Emitter","serializeForm","attempt","isArray","isFormError","isFieldError","isString","Emitter","createSSEParser","parseJSON","parseForm","isRecord","isString","createForm","isBoolean","arrayOf","isFieldError","Emitter","isArray","createMemoryDriver","stringShape","rawShape","createDatabase"],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/validators.ts","../../../src/core/helpers.ts","../../../src/core/Prompt.ts","../../../src/core/PromptClient.ts","../../../src/core/TerminalManager.ts","../../../src/core/stores/MemoryTerminalStore.ts","../../../src/core/stores/DatabaseTerminalStore.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { PromptRole, PromptTheme } from './types.js'\nimport { CSI, ESC, freezeStyle, STATUS_ICONS } from '@orkestrel/console'\n\n// The constant DATA the pure terminal core reads: key decoding, rendering, and transport defaults.\n// UPPER_SNAKE, `Object.freeze`d, every member exported. Control bytes are built with\n// `String.fromCharCode` so no raw control character appears in source, and the escape lead and the\n// CSI prefix come from `@orkestrel/console`, which publishes both.\n\n// === Control bytes (named, no raw control characters in source)\n\n/** Names the carriage return byte (`\\r`, U+000D) — Enter on most terminals. */\nexport const RETURN = String.fromCharCode(13)\n/** Names the line feed byte (`\\n`, U+000A) — Enter on some terminals / pasted input. */\nexport const NEWLINE = String.fromCharCode(10)\n/** Names the tab byte (`\\t`, U+0009). */\nexport const TAB = String.fromCharCode(9)\n/** Names the backspace byte (BS, U+0008) — Ctrl+H / some terminals' Backspace. */\nexport const BACKSPACE = String.fromCharCode(8)\n/** Names the delete byte (DEL, U+007F) — the usual Backspace byte on a Unix TTY. */\nexport const DELETE = String.fromCharCode(127)\n/** Names the space byte (U+0020). */\nexport const SPACE = ' '\n/** Names the Ctrl+C byte (ETX, U+0003) — interrupt / cancel. */\nexport const CTRL_C = String.fromCharCode(3)\n/** Names the Ctrl+D byte (EOT, U+0004) — end-of-transmission / finish (the editor's commit key). */\nexport const CTRL_D = String.fromCharCode(4)\n/** Names the Ctrl+U byte (NAK, U+0015) — clear the current line. */\nexport const CTRL_U = String.fromCharCode(21)\n/** Names the Ctrl+A byte (SOH, U+0001) — move to start of line. */\nexport const CTRL_A = String.fromCharCode(1)\n/** Names the Ctrl+E byte (ENQ, U+0005) — move to end of line. */\nexport const CTRL_E = String.fromCharCode(5)\n\n/**\n * Names the Single Shift Three lead (`ESCO`) — the alternate arrow-key prefix some terminals emit\n * (`ESC O A`). Built from the console module's own {@link import('@orkestrel/console').ESC}; the\n * navigation keys' CSI lead is that module's {@link import('@orkestrel/console').CSI}, which this\n * package reuses rather than redeclaring.\n */\nexport const KEY_SS3 = `${ESC}O`\n\n/**\n * Holds the exact escape sequence to canonical key name table\n * {@link import('./helpers.js').parseKey} consults for the navigation and editing keys. Covers the\n * CSI form (`ESC[A`…) and the SS3 form (`ESCOA`…) of the arrows, plus the `home` / `end` / `delete`\n * CSI sequences with their numeric-tilde variants. The source of truth for the multi-byte key\n * decode; frozen.\n *\n * @remarks\n * Terminals disagree on these: a cursor key is `ESC[A` (normal) or `ESCOA` (application mode),\n * and Home / End / Delete each have a letter form (`ESC[H` / `ESC[F`) and a numeric form\n * (`ESC[1~` / `ESC[4~` / `ESC[3~`). Every accepted spelling maps to one name so a reducer never\n * sees the wire encoding.\n */\nexport const SEQUENCE_NAMES: Readonly<Record<string, string>> = Object.freeze({\n\t[`${CSI}A`]: 'up',\n\t[`${CSI}B`]: 'down',\n\t[`${CSI}C`]: 'right',\n\t[`${CSI}D`]: 'left',\n\t[`${KEY_SS3}A`]: 'up',\n\t[`${KEY_SS3}B`]: 'down',\n\t[`${KEY_SS3}C`]: 'right',\n\t[`${KEY_SS3}D`]: 'left',\n\t[`${CSI}H`]: 'home',\n\t[`${CSI}F`]: 'end',\n\t[`${CSI}1~`]: 'home',\n\t[`${CSI}4~`]: 'end',\n\t[`${CSI}3~`]: 'delete',\n\t[`${CSI}7~`]: 'home',\n\t[`${CSI}8~`]: 'end',\n})\n\n/**\n * Holds the control byte (or CRLF pair) to key descriptor table\n * {@link import('./helpers.js').parseKey} consults for the one-byte keys and the two-byte CRLF\n * Enter chunk. Each entry carries the canonical `name` and whether it is a `ctrl` combination. The\n * source of truth for that decode; frozen.\n *\n * @remarks\n * `return` / `newline` / `return + newline` all map to `return` (one canonical Enter name) — a\n * terminal or a paste can deliver Enter as `\\r`, `\\n`, or the `\\r\\n` pair in one chunk;\n * `delete` / `backspace` both map to `backspace` (the Backspace bytes); the Ctrl combos\n * (`c` / `d` / `u` / `a` / `e`) carry `ctrl: true` so a reducer can match\n * `key.ctrl && key.name === 'c'`. `escape` / `tab` / `space` are plain named keys.\n */\nexport const CONTROL_NAMES: Readonly<\n\tRecord<string, { readonly name: string; readonly ctrl: boolean }>\n> = Object.freeze({\n\t[RETURN]: Object.freeze({ name: 'return', ctrl: false }),\n\t[NEWLINE]: Object.freeze({ name: 'return', ctrl: false }),\n\t[`${RETURN}${NEWLINE}`]: Object.freeze({ name: 'return', ctrl: false }),\n\t[TAB]: Object.freeze({ name: 'tab', ctrl: false }),\n\t[ESC]: Object.freeze({ name: 'escape', ctrl: false }),\n\t[BACKSPACE]: Object.freeze({ name: 'backspace', ctrl: false }),\n\t[DELETE]: Object.freeze({ name: 'backspace', ctrl: false }),\n\t[SPACE]: Object.freeze({ name: 'space', ctrl: false }),\n\t[CTRL_C]: Object.freeze({ name: 'c', ctrl: true }),\n\t[CTRL_D]: Object.freeze({ name: 'd', ctrl: true }),\n\t[CTRL_U]: Object.freeze({ name: 'u', ctrl: true }),\n\t[CTRL_A]: Object.freeze({ name: 'a', ctrl: true }),\n\t[CTRL_E]: Object.freeze({ name: 'e', ctrl: true }),\n})\n\n// === Prompt defaults\n\n/** Names the default mask glyph {@link import('./helpers.js').createPasswordState} uses — `*`. */\nexport const DEFAULT_MASK = '*'\n\n// === Prompt-view icons\n\n/**\n * Holds the terminal-owned glyphs {@link DEFAULT_PROMPT_THEME} assembles its `icons` from, beside\n * the console module's own success and error marks. Read only when the default theme is assembled;\n * a view reads its resolved theme and never this constant. Frozen.\n *\n * @remarks\n * - `question` — the leading mark on a prompt's message line.\n * - `pointer` — the cursor before the input / the focused choice row.\n * - `dot` / `selected` — an unfocused / focused row marker in a select list.\n * - `checked` / `unchecked` — a checked / unchecked box in a checkbox list.\n */\nexport const PROMPT_ICONS = Object.freeze({\n\tquestion: '?',\n\tpointer: '›',\n\tdot: '○',\n\tselected: '●',\n\tchecked: '☑',\n\tunchecked: '☐',\n})\n\n// === The default prompt theme\n\n/**\n * Holds every {@link import('./types.js').PromptRole}, in one frozen list — the role axis's source of\n * truth. {@link import('./helpers.js').createPromptTheme} walks it to merge a partial theme, and\n * a consumer building a complete role map reads it rather than retyping every name.\n */\nexport const PROMPT_ROLES: readonly PromptRole[] = Object.freeze([\n\t'question',\n\t'pointer',\n\t'message',\n\t'content',\n\t'success',\n\t'error',\n\t'selected',\n\t'focus',\n\t'hint',\n\t'muted',\n\t'description',\n])\n\n/**\n * Holds the {@link import('./types.js').PromptTheme} every prompt renders with unless its options supply\n * another — the glyph set assembled from {@link PROMPT_ICONS} plus the console\n * {@link import('@orkestrel/console').STATUS_ICONS} `success` / `error` marks, and the console\n * {@link import('@orkestrel/console').Style} each role is painted with. Deeply frozen through the\n * console module's own {@link import('@orkestrel/console').freezeStyle}; the baseline\n * {@link import('./helpers.js').createPromptTheme} merges a partial theme over.\n *\n * @remarks\n * The default roles reproduce the views' historical coloring exactly: `question` / `pointer` cyan,\n * `message` / `focus` bold, `success` / `selected` green, `error` red, `hint` / `muted` /\n * `description` dim, and `content` the EMPTY style — an empty style renders bare text, so primary\n * content keeps the bytes it had before it became themeable.\n * Two roles sharing a style today are still two roles — re-mapping one leaves the other alone.\n */\nexport const DEFAULT_PROMPT_THEME: PromptTheme = Object.freeze({\n\ticons: Object.freeze({\n\t\tquestion: PROMPT_ICONS.question,\n\t\tpointer: PROMPT_ICONS.pointer,\n\t\tdot: PROMPT_ICONS.dot,\n\t\tselected: PROMPT_ICONS.selected,\n\t\tchecked: PROMPT_ICONS.checked,\n\t\tunchecked: PROMPT_ICONS.unchecked,\n\t\tsuccess: STATUS_ICONS.success,\n\t\terror: STATUS_ICONS.error,\n\t}),\n\troles: Object.freeze({\n\t\tquestion: freezeStyle({ foreground: 'cyan', attributes: [] }),\n\t\tpointer: freezeStyle({ foreground: 'cyan', attributes: [] }),\n\t\tmessage: freezeStyle({ attributes: ['bold'] }),\n\t\tcontent: freezeStyle({ attributes: [] }),\n\t\tsuccess: freezeStyle({ foreground: 'green', attributes: [] }),\n\t\terror: freezeStyle({ foreground: 'red', attributes: [] }),\n\t\tselected: freezeStyle({ foreground: 'green', attributes: [] }),\n\t\tfocus: freezeStyle({ attributes: ['bold'] }),\n\t\thint: freezeStyle({ attributes: ['dim'] }),\n\t\tmuted: freezeStyle({ attributes: ['dim'] }),\n\t\tdescription: freezeStyle({ attributes: ['dim'] }),\n\t}),\n})\n\n// === Broker + SSE-bridge defaults\n\n/** Holds how long (ms) the {@link import('./types.js').PromptInterface} broker parks an unanswered form before it expires — 5 minutes. */\nexport const DEFAULT_PROMPT_TIMEOUT_MS = 300_000\n\n/** Holds how long (ms) the {@link import('./types.js').PromptClientInterface} waits before each reconnect attempt — 2 seconds. */\nexport const DEFAULT_RECONNECT_DELAY_MS = 2_000\n\n/**\n * Holds the SSE `event:` names the broker emits and the\n * {@link import('./types.js').PromptClientInterface} dispatches on — `pending`, `expire`, and\n * `destroy`. Frozen; the source of truth for the wire event vocabulary.\n *\n * @remarks\n * - `pending` — a serialized {@link import('./types.js').PendingForm} to dispatch and answer.\n * - `expire` — an `{ id }` payload: the broker expired or released a parked form (the client drops it).\n * - `destroy` — the broker is going away; the client disconnects (no auto-reconnect) but stays reusable.\n */\nexport const SSE_EVENTS = Object.freeze({\n\tpending: 'pending',\n\texpire: 'expire',\n\tdestroy: 'destroy',\n})\n\n/**\n * Names the auth-token request header the {@link import('./types.js').PromptClientInterface} sends\n * when a `token` is configured — `x-orkestrel-token`.\n */\nexport const HEADER_TOKEN = 'x-orkestrel-token'\n\n/** Names the `Accept` header value that opens the broker's SSE stream — `text/event-stream`. */\nexport const ACCEPT_EVENT_STREAM = 'text/event-stream'\n\n/**\n * Sets the maximum number of characters the {@link import('./types.js').PromptClientInterface} lets its\n * SSE parser buffer before treating the stream as hostile — 1 MiB, comfortably above any\n * legitimate prompt payload. Passed as the `limit` to `createSSEParser` so an unterminated\n * or oversized `data:` field cannot grow the buffer without bound (a memory-exhaustion guard).\n */\nexport const SSE_BUFFER_LIMIT = 1_048_576\n","import type { TerminalErrorCode } from './types.js'\nimport { isInstance } from '@orkestrel/contract'\n\n// `.claude/rules/typescript.md` § Errors and outcomes: a real error type, not a sentinel. Callers\n// branch on the machine-readable\n// `error.code` rather than parsing the message, and the guard narrows with `instanceof`,\n// mirroring the agents-module errors.\n\n/**\n * Represents the error the terminal surfaces for its own refusals: parking on a destroyed or full broker, an\n * unusable driver stream, a manager routing fault, or a ctrl-c cancellation. A parked form's own\n * lifecycle failures reject through the form's `answer` with the form package's error, never with\n * this one.\n *\n * @remarks\n * Carries a {@link TerminalErrorCode} and an optional `context` bag naming the offending values:\n * `{ cap }` on `LIMIT`, `{ to, known }` on `TARGET`, and `{ from, to, path }` on `DEADLOCK`. Narrow\n * a caught value with {@link isTerminalError} and branch on `error.code`.\n */\nexport class TerminalError extends Error {\n\t/** Holds the machine-readable condition — see {@link TerminalErrorCode}. */\n\treadonly code: TerminalErrorCode\n\t/** Holds an optional context bag naming the offending values — see the class {@link TerminalError remarks}. */\n\treadonly context?: Readonly<Record<string, unknown>>\n\n\t/**\n\t * Builds one terminal refusal.\n\t *\n\t * @param code - The machine-readable {@link TerminalErrorCode} a caller branches on\n\t * @param message - The human-readable reason\n\t * @param context - The optional bag naming the offending values — see the class {@link TerminalError remarks}\n\t */\n\tconstructor(\n\t\tcode: TerminalErrorCode,\n\t\tmessage: string,\n\t\tcontext?: Readonly<Record<string, unknown>>,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'TerminalError'\n\t\tthis.code = code\n\t\tif (context !== undefined) this.context = context\n\t}\n}\n\n/**\n * Narrows an unknown caught value to a {@link TerminalError}, so a caller can branch on its `code`.\n *\n * @param value - The value to test (typically a `catch` binding or a rejected prompt call)\n * @returns True if `value` is a {@link TerminalError}; false otherwise\n *\n * @example\n * ```ts\n * try {\n * \tawait terminal.ask(form)\n * } catch (error) {\n * \tif (isTerminalError(error) && error.code === 'CANCEL') {\n * \t\t// the person aborted\n * \t}\n * }\n * ```\n */\nexport function isTerminalError(value: unknown): value is TerminalError {\n\treturn isInstance(value, TerminalError)\n}\n","import type { PendingForm, PendingFormStatus, TerminalSnapshot, WireEvent } from './types.js'\nimport type { Guard } from '@orkestrel/contract'\nimport {\n\tisNonEmptyString,\n\tisNumber,\n\tisRecord,\n\tisString,\n\tliteralOf,\n\trecordOf,\n} from '@orkestrel/contract'\n\n/**\n * Narrows an unknown value to a {@link PendingFormStatus}.\n *\n * @param value - The candidate ticket status\n * @returns True if the value is one of the declared ticket statuses; false otherwise\n */\nexport const isPendingFormStatus: Guard<PendingFormStatus> = literalOf(\n\t'pending',\n\t'answered',\n\t'expired',\n)\n\n/**\n * Narrows an unknown wire value to a {@link PendingForm} envelope — the envelope alone, because the\n * form package's `parseForm` owns the schema payload.\n *\n * @remarks\n * This guard checks the transport record and proves only that `schema` is a record. The Form\n * package's `parseForm` owns the schema payload and its semantic audit.\n *\n * @param value - The decoded wire value to inspect\n * @returns True if the value is a complete pending-form envelope; false otherwise\n */\nexport function isPendingForm(value: unknown): value is PendingForm {\n\treturn recordOf(\n\t\t{\n\t\t\tid: isNonEmptyString,\n\t\t\tschema: isRecord,\n\t\t\tstatus: isPendingFormStatus,\n\t\t\ttime: isNumber,\n\t\t\tfrom: isString,\n\t\t\tto: isString,\n\t\t},\n\t\t['from', 'to'],\n\t)(value)\n}\n\n/**\n * Narrows an unknown value to a transport-neutral {@link WireEvent} — the guard a consumer's own\n * transport applies to an inbound frame.\n *\n * @param value - The candidate wire event\n * @returns True if the value carries an event name, serialized data, and an optional id; false otherwise\n */\nexport const isWireEvent: Guard<WireEvent> = recordOf(\n\t{ event: isString, data: isString, id: isString },\n\t['id'],\n)\n\n/**\n * Narrows an unknown value to a {@link TerminalSnapshot} — a non-empty `id` and an optional numeric\n * `timeout`, the read boundary a store applies to an untrusted persisted row.\n *\n * @param value - The candidate snapshot read back from storage\n * @returns True if the value carries a non-empty `id` and an optional numeric `timeout`; false otherwise\n */\nexport const isTerminalSnapshot: Guard<TerminalSnapshot> = recordOf(\n\t{ id: isNonEmptyString, timeout: isNumber },\n\t['timeout'],\n)\n","import type {\n\tCheckboxState,\n\tConfirmState,\n\tEditorState,\n\tFetchInit,\n\tInputState,\n\tKeyEvent,\n\tPasswordState,\n\tPendingForm,\n\tPromptIcon,\n\tPromptRole,\n\tPromptStep,\n\tPromptTheme,\n\tPromptThemeOptions,\n\tSelectState,\n\tTimerCancelFunction,\n\tWireEvent,\n} from './types.js'\nimport type { Style, StylerInterface } from '@orkestrel/console'\nimport type {\n\tCheckboxField,\n\tConfirmField,\n\tEditorField,\n\tFormField,\n\tFormSchema,\n\tPasswordField,\n\tSelectField,\n\tTextField,\n} from '@orkestrel/form'\nimport {\n\tCONTROL_NAMES,\n\tDEFAULT_MASK,\n\tDEFAULT_PROMPT_THEME,\n\tPROMPT_ROLES,\n\tSEQUENCE_NAMES,\n} from './constants.js'\nimport { isError, isString } from '@orkestrel/contract'\nimport { createStyler, freezeStyle, strip, stripControls } from '@orkestrel/console'\n\n// The PURE prompt core implementation — all EXPORTED, all pure, all unit-tested:\n// the key decoder, schema sanitization, per-field view renderers, and the `create*State`\n// factories with their `reduce*` reducers. No `node:*`, no I/O, no events. Form owns validation and\n// settlement; these reducers only turn keys into candidate field values.\n\n// === Key decoding\n\n/**\n * Decodes one keypress's bytes into a {@link KeyEvent} — total, never throws. A `Uint8Array` is\n * read as UTF-8; the resulting string is matched against the known control bytes and the CRLF pair\n * ({@link CONTROL_NAMES}) and escape sequences ({@link SEQUENCE_NAMES}), falling back to a single\n * printable character. An unrecognized sequence carries no `name`, with the raw `sequence`\n * preserved.\n *\n * @remarks\n * - **Single control byte.** A one-character control input (`return` / `backspace` / `tab` /\n * `escape` / `space`, or a Ctrl combo `c` / `d` / `u` / `a` / `e`), or the two-byte `\\r\\n`\n * CRLF pair, is looked up in {@link CONTROL_NAMES}, carrying its `ctrl` flag.\n * - **Escape sequence.** A multi-byte ESC sequence (`up` / `down` / `left` / `right` in both the\n * `ESC[A` and `ESCOA` forms, plus `home` / `end` / `delete`) is looked up in\n * {@link SEQUENCE_NAMES} and flagged `meta`.\n * - **Printable character.** A single printable character becomes `name` = that character, with\n * `shift` set when it is an uppercase letter. A multi-code-point printable (an emoji, a pasted\n * run) keeps its first code point as the name and the whole input as `sequence`.\n * - **Unknown.** Anything else (an unrecognized escape, an empty input) yields an event with NO\n * `name` — absence, never an empty string — total, so the driver never crashes on a stray byte.\n *\n * @param input - The raw keypress bytes, as a string or `Uint8Array`\n * @returns The decoded {@link KeyEvent}\n *\n * @example\n * ```ts\n * parseKey('\\r') // { name: 'return', sequence: '\\r', ctrl: false, meta: false, shift: false }\n * parseKey('\\r\\n') // { name: 'return', sequence: '\\r\\n', ctrl: false, meta: false, shift: false }\n * parseKey('\\x1b[A') // { name: 'up', sequence: '\\x1b[A', ctrl: false, meta: true, shift: false }\n * parseKey('A') // { name: 'A', sequence: 'A', ctrl: false, meta: false, shift: true }\n * parseKey('\\x03') // { name: 'c', sequence: '\\x03', ctrl: true, meta: false, shift: false }\n * ```\n */\nexport function parseKey(input: string | Uint8Array): KeyEvent {\n\tconst sequence = isString(input) ? input : new TextDecoder().decode(input)\n\n\t// A known multi-byte escape sequence (arrows / home / end / delete) — flagged `meta`.\n\tconst sequenceName = SEQUENCE_NAMES[sequence]\n\tif (sequenceName !== undefined) {\n\t\treturn { name: sequenceName, sequence, ctrl: false, meta: true, shift: false }\n\t}\n\n\t// A known single control byte (return / backspace / tab / escape / space / a ctrl combo),\n\t// or the two-byte CRLF pair.\n\tconst control = CONTROL_NAMES[sequence]\n\tif (control !== undefined) {\n\t\treturn { name: control.name, sequence, ctrl: control.ctrl, meta: false, shift: false }\n\t}\n\n\t// A printable character — one or more code points, the first naming the key.\n\tconst points = [...sequence]\n\tconst first = points[0]\n\tif (first !== undefined && isPrintable(first)) {\n\t\treturn { name: first, sequence, ctrl: false, meta: false, shift: first !== first.toLowerCase() }\n\t}\n\n\t// Anything else (an unrecognized escape, an empty input) — total, never a throw. The name is\n\t// OMITTED rather than emptied, so a caller reads absence instead of a sentinel.\n\treturn { sequence, ctrl: false, meta: false, shift: false }\n}\n\n/**\n * Checks whether a single character is printable — the fallback test {@link parseKey} applies after\n * the control bytes and the escape sequences, so the C0 controls and DEL are excluded.\n *\n * @param character - The single character to test\n * @returns True if the character is at or above space and is not DEL; false otherwise\n */\nexport function isPrintable(character: string): boolean {\n\tif (character.length === 0) return false\n\tconst code = character.codePointAt(0)\n\tif (code === undefined) return false\n\t// Exclude the C0 controls (0–31) and DEL (127); everything at or above space is printable.\n\treturn code >= 32 && code !== 127\n}\n\n// === Prompt theme\n\n/**\n * Builds a complete {@link PromptTheme} by merging a partial one over\n * {@link DEFAULT_PROMPT_THEME}, leaf by leaf — each supplied icon replaces that glyph, each\n * supplied role replaces that {@link Style}, and everything else keeps its default. Each supplied\n * style is snapshotted through the console module's own\n * {@link import('@orkestrel/console').freezeStyle}, so the result is deeply frozen and a caller\n * mutating its own attribute list afterwards cannot reach into a built theme.\n *\n * @param options - The partial theme to merge, or `undefined` for the defaults\n * @returns The resolved, deeply frozen theme every prompt state carries\n *\n * @example\n * ```ts\n * createPromptTheme() // the defaults\n * createPromptTheme({\n * \ticons: { pointer: '=>' },\n * \troles: { message: { foreground: 'magenta', attributes: ['bold'] } },\n * })\n * ```\n */\nexport function createPromptTheme(options?: PromptThemeOptions): PromptTheme {\n\tconst icons: Record<PromptIcon, string> = { ...DEFAULT_PROMPT_THEME.icons, ...options?.icons }\n\tconst roles: Record<PromptRole, Style> = { ...DEFAULT_PROMPT_THEME.roles }\n\tfor (const role of PROMPT_ROLES) {\n\t\tconst style = options?.roles?.[role]\n\t\tif (style !== undefined) roles[role] = freezeStyle(style)\n\t}\n\treturn Object.freeze({ icons: Object.freeze(icons), roles: Object.freeze(roles) })\n}\n\n/**\n * Sanitizes text for one single-line display slot. Composes console's ANSI {@link strip} and C0\n * {@link stripControls} passes with removal of tab, line feed, and carriage return.\n *\n * @param text - The text to sanitize for a glyph or hint slot\n * @returns The text with ANSI sequences, every C0 control character, and DEL removed\n *\n * @example\n * ```ts\n * sanitizeDisplayText('Q\\rOVERWRITE\\nNEXT\\tX') // 'QOVERWRITENEXTX'\n * ```\n */\nexport function sanitizeDisplayText(text: string): string {\n\treturn stripControls(strip(text)).replaceAll('\\t', '').replaceAll('\\n', '').replaceAll('\\r', '')\n}\n\n/**\n * Sanitizes every terminal-readable string in a parsed form schema, keeping every identity and\n * answer string verbatim and dropping field metadata.\n *\n * @remarks\n * Display strings pass through {@link sanitizeDisplayText}: labels, help, placeholders, masks,\n * choice labels and help, file accept entries, and pattern sources. Identity and answer strings\n * stay verbatim: schema, group, and field names, group references, choice values, and defaults.\n * Rewriting those would sever the rendering copy from the authoritative form. Field metadata is\n * removed because terminal neither renders nor interprets it. Pattern sources are sanitized as\n * text only and are never compiled or executed here.\n *\n * @param schema - A schema already accepted by the Form package's `parseForm`\n * @returns A new schema with terminal-readable strings sanitized and field metadata omitted\n *\n * @example\n * ```ts\n * sanitizeSchema({ fields: [{ control: 'text', name: 'na\\u001bme', label: 'N\\u0000ame' }] })\n * // { fields: [{ control: 'text', name: 'na\\u001bme', label: 'Name' }] }\n * ```\n */\nexport function sanitizeSchema(schema: FormSchema): FormSchema {\n\tconst groups = schema.groups?.map((group) => ({\n\t\tname: group.name,\n\t\tlabel: sanitizeDisplayText(group.label),\n\t\t...(group.help !== undefined ? { help: sanitizeDisplayText(group.help) } : {}),\n\t}))\n\tconst fields: FormField[] = []\n\tfor (const source of schema.fields) {\n\t\tconst { meta: _meta, ...field } = source\n\t\tconst rule =\n\t\t\tfield.rule === undefined\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\t...field.rule,\n\t\t\t\t\t\t...(field.rule.pattern !== undefined\n\t\t\t\t\t\t\t? { pattern: sanitizeDisplayText(field.rule.pattern) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t}\n\t\tconst shared = {\n\t\t\tname: field.name,\n\t\t\t...(field.label !== undefined ? { label: sanitizeDisplayText(field.label) } : {}),\n\t\t\t...(field.help !== undefined ? { help: sanitizeDisplayText(field.help) } : {}),\n\t\t\t...(field.group !== undefined ? { group: field.group } : {}),\n\t\t\t...(rule !== undefined ? { rule } : {}),\n\t\t}\n\n\t\tswitch (field.control) {\n\t\t\tcase 'text':\n\t\t\tcase 'editor':\n\t\t\tcase 'number': {\n\t\t\t\tfields.push({\n\t\t\t\t\t...field,\n\t\t\t\t\t...shared,\n\t\t\t\t\t...(field.placeholder !== undefined\n\t\t\t\t\t\t? { placeholder: sanitizeDisplayText(field.placeholder) }\n\t\t\t\t\t\t: {}),\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'password': {\n\t\t\t\tfields.push({\n\t\t\t\t\t...field,\n\t\t\t\t\t...shared,\n\t\t\t\t\t...(field.mask !== undefined ? { mask: sanitizeDisplayText(field.mask) } : {}),\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'date':\n\t\t\tcase 'time':\n\t\t\tcase 'datetime':\n\t\t\tcase 'color':\n\t\t\tcase 'confirm': {\n\t\t\t\tfields.push({\n\t\t\t\t\t...field,\n\t\t\t\t\t...shared,\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'select':\n\t\t\tcase 'checkbox': {\n\t\t\t\tfields.push({\n\t\t\t\t\t...field,\n\t\t\t\t\t...shared,\n\t\t\t\t\tchoices: field.choices.map((choice) => ({\n\t\t\t\t\t\t...choice,\n\t\t\t\t\t\tvalue: choice.value,\n\t\t\t\t\t\tlabel: sanitizeDisplayText(choice.label),\n\t\t\t\t\t\t...(choice.help !== undefined ? { help: sanitizeDisplayText(choice.help) } : {}),\n\t\t\t\t\t})),\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'file': {\n\t\t\t\tfields.push({\n\t\t\t\t\t...field,\n\t\t\t\t\t...shared,\n\t\t\t\t\t...(field.accept !== undefined ? { accept: field.accept.map(sanitizeDisplayText) } : {}),\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\t...(schema.name !== undefined ? { name: schema.name } : {}),\n\t\t...(schema.label !== undefined ? { label: sanitizeDisplayText(schema.label) } : {}),\n\t\t...(schema.help !== undefined ? { help: sanitizeDisplayText(schema.help) } : {}),\n\t\t...(groups !== undefined ? { groups } : {}),\n\t\tfields,\n\t}\n}\n\n/**\n * Sanitizes every glyph a wire-supplied {@link PromptThemeOptions} carries for a single-line display\n * slot. Only the icons need it: a role is guard-narrowed to a console {@link Style}, whose colors\n * and attributes are fixed name sets, so no role can carry a byte a terminal would act on.\n *\n * @param theme - The narrowed theme options a remote prompt supplied\n * @returns The same theme with every supplied glyph sanitized for a single-line display slot\n */\nexport function sanitizeThemeIcons(theme: PromptThemeOptions): PromptThemeOptions {\n\tconst icons = theme.icons\n\tif (icons === undefined) return theme\n\tconst sanitized: Record<string, string> = {}\n\tfor (const [icon, glyph] of Object.entries(icons)) sanitized[icon] = sanitizeDisplayText(glyph)\n\treturn { ...theme, icons: sanitized }\n}\n\n// === Shared view helpers\n\n/**\n * Renders the styled question header (`? message`) — the leading line every active prompt view\n * shares, themed by the `question` + `message` roles.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param message - The prompt's question text\n * @returns The rendered question header\n */\nexport function renderPromptHeader(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tmessage: string,\n): string {\n\treturn `${styler.render(theme.roles.question, theme.icons.question)} ${styler.render(theme.roles.message, message)}`\n}\n\n/**\n * Renders a question header followed by a key hint painted with the `hint` role, or the header\n * alone when no hint is supplied.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param message - The prompt's question text\n * @param hint - The optional key hint to append\n * @returns The rendered header with the optional hint\n */\nexport function renderHintedHeader(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tmessage: string,\n\thint?: string,\n): string {\n\tconst head = renderPromptHeader(styler, theme, message)\n\treturn hint === undefined ? head : `${head} ${styler.render(theme.roles.hint, hint)}`\n}\n\n/**\n * Renders the styled submit line (`✔ message`) — the committed header an interactive prompt shows\n * after it resolves, themed by the `success` + `message` roles.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param message - The settled prompt's question text\n * @returns The rendered committed header\n */\nexport function renderSubmitHeader(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tmessage: string,\n): string {\n\treturn `${styler.render(theme.roles.success, theme.icons.success)} ${styler.render(theme.roles.message, message)}`\n}\n\n/**\n * Renders the styled failure line (`✖ message`) a form driver writes for each refused field before\n * it asks that field again.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param message - The failure text, normally the field's label and the reason\n * @returns The rendered failure line\n */\nexport function renderErrorLine(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tmessage: string,\n): string {\n\treturn `${styler.render(theme.roles.error, theme.icons.error)} ${styler.render(theme.roles.error, message)}`\n}\n\n// === Input prompt\n\n/**\n * Builds the initial text-field reducer state — the sanitized label, the declared default, the\n * styler, and the resolved theme.\n *\n * @param field - The text field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createInputState(\n\tfield: TextField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): InputState {\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tdefault: field.default ?? '',\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t\tvalue: '',\n\t}\n}\n\n/**\n * Renders a text-field reducer state as a styled view — the header, the pointer, and the typed\n * value, or the default shown as a hint while nothing is typed.\n *\n * @param state - The text field's current reducer state\n * @returns The rendered single-line view — header, pointer, and the typed value or the default\n */\nexport function renderInputView(state: InputState): string {\n\tconst content = state.value.length > 0 ? state.value : state.default\n\tconst role = state.value.length > 0 ? state.theme.roles.content : state.theme.roles.hint\n\tconst shown = state.styler.render(role, sanitizeDisplayText(content))\n\treturn `${renderPromptHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)} ${shown}`\n}\n\n/**\n * Advances an input prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`\n * reducer. Printable characters extend the value; backspace shrinks it; ctrl-u clears it; ctrl-c\n * cancels; return produces the candidate value, with an empty line falling back to the default.\n *\n * @param state - The text field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the new state, the rendered view, the status, and the value on submit\n */\nexport function reduceInput(state: InputState, key: KeyEvent): PromptStep<string, InputState> {\n\tif (key.ctrl && key.name === 'c') return { state, view: renderInputView(state), status: 'cancel' }\n\n\tif (key.name === 'return') {\n\t\tconst answer = state.value.length > 0 ? state.value : state.default\n\t\tconst next = { ...state, value: answer }\n\t\treturn {\n\t\t\tstate: next,\n\t\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, sanitizeDisplayText(answer))}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue: answer,\n\t\t}\n\t}\n\n\tconst value = editLine(state.value, key)\n\tif (value === undefined) return { state, view: renderInputView(state), status: 'active' }\n\tconst next = { ...state, value }\n\treturn { state: next, view: renderInputView(next), status: 'active' }\n}\n\n// === Password prompt\n\n/**\n * Builds the initial password-field reducer state — the text-field state, plus the mask glyph each\n * typed character renders as.\n *\n * @param field - The password field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createPasswordState(\n\tfield: PasswordField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): PasswordState {\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tmask: sanitizeDisplayText(field.mask ?? DEFAULT_MASK),\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t\tvalue: '',\n\t}\n}\n\n/**\n * Renders a password-field reducer state as a styled view, with the value replaced by the mask\n * repeated so the secret is never echoed.\n *\n * @param state - The password field's current reducer state\n * @returns The rendered view, with the mask repeated in place of the typed value\n */\nexport function renderPasswordView(state: PasswordState): string {\n\tconst masked = state.styler.render(\n\t\tstate.theme.roles.content,\n\t\tstate.mask.repeat(state.value.length),\n\t)\n\treturn `${renderPromptHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)} ${masked}`\n}\n\n/**\n * Advances a password prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`\n * reducer. Identical line-editing to {@link reduceInput} (printable extends, backspace shrinks,\n * ctrl-u clears, ctrl-c cancels) but the view masks the value. Return produces the candidate value.\n *\n * @param state - The password field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the new state, the masked view, the status, and the value on submit\n */\nexport function reducePassword(\n\tstate: PasswordState,\n\tkey: KeyEvent,\n): PromptStep<string, PasswordState> {\n\tif (key.ctrl && key.name === 'c')\n\t\treturn { state, view: renderPasswordView(state), status: 'cancel' }\n\n\tif (key.name === 'return') {\n\t\treturn {\n\t\t\tstate,\n\t\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, state.mask.repeat(state.value.length))}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue: state.value,\n\t\t}\n\t}\n\n\tconst value = editLine(state.value, key)\n\tif (value === undefined) return { state, view: renderPasswordView(state), status: 'active' }\n\tconst next = { ...state, value }\n\treturn { state: next, view: renderPasswordView(next), status: 'active' }\n}\n\n// === Confirm prompt\n\n/**\n * Builds the initial confirm-field reducer state — the sanitized label and the declared default\n * answer.\n *\n * @param field - The confirm field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createConfirmState(\n\tfield: ConfirmField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): ConfirmState {\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tdefault: field.default ?? false,\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t}\n}\n\n/**\n * Renders a confirm-field reducer state as a styled view — the header and the yes/no group, with\n * the default letter capitalized and painted by the `selected` role.\n *\n * @param state - The confirm field's current reducer state\n * @returns The rendered view — the header and the yes/no group with the default capitalized\n */\nexport function renderConfirmView(state: ConfirmState): string {\n\tconst head = renderPromptHeader(state.styler, state.theme, state.message)\n\tconst answer = state.default\n\t\t? `${state.styler.render(state.theme.roles.selected, 'Y')}${state.styler.render(state.theme.roles.hint, '/n')}`\n\t\t: `${state.styler.render(state.theme.roles.hint, 'y/')}${state.styler.render(state.theme.roles.selected, 'N')}`\n\treturn `${head} ${state.styler.render(state.theme.roles.hint, '(')}${answer}${state.styler.render(state.theme.roles.hint, ')')}`\n}\n\n/**\n * Advances a confirm prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<boolean>`\n * reducer. `y` / `Y` submits `true`, `n` / `N` submits `false`, return on an empty line submits\n * the `default`, ctrl-c cancels; any other key is ignored (stays active).\n *\n * @param state - The confirm field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the state, the rendered view, the status, and the answer on submit\n */\nexport function reduceConfirm(\n\tstate: ConfirmState,\n\tkey: KeyEvent,\n): PromptStep<boolean, ConfirmState> {\n\tif (key.ctrl && key.name === 'c')\n\t\treturn { state, view: renderConfirmView(state), status: 'cancel' }\n\n\tlet answer: boolean | undefined\n\tconst choice = key.name?.toLowerCase()\n\tif (key.name === 'return') answer = state.default\n\telse if (choice === 'y') answer = true\n\telse if (choice === 'n') answer = false\n\n\tif (answer === undefined) return { state, view: renderConfirmView(state), status: 'active' }\n\treturn {\n\t\tstate,\n\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, answer ? 'yes' : 'no')}`,\n\t\tstatus: 'submit',\n\t\tvalue: answer,\n\t}\n}\n\n// === Select prompt\n\n/**\n * Builds the initial select-field reducer state — the offered choices, with the focus pre-placed on\n * the declared default.\n *\n * @param field - The select field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createSelectState(\n\tfield: SelectField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): SelectState {\n\tconst choices = [...field.choices]\n\tconst index = choices.findIndex((choice) => choice.value === field.default)\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tchoices,\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t\tfocused: index >= 0 ? index : 0,\n\t}\n}\n\n/**\n * Renders a select-field reducer state as a multi-line styled view — one row per choice, with the\n * focused row marked and its help shown.\n *\n * @param state - The select field's current reducer state\n * @returns The rendered view — the header, then one row per choice with the focused row marked\n */\nexport function renderSelectView(state: SelectState): string {\n\tconst lines = state.choices.map((choice, index) => {\n\t\tconst active = index === state.focused\n\t\tconst pointer = active\n\t\t\t? state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)\n\t\t\t: ' '\n\t\tconst marker = active\n\t\t\t? state.styler.render(state.theme.roles.selected, state.theme.icons.selected)\n\t\t\t: state.styler.render(state.theme.roles.muted, state.theme.icons.dot)\n\t\tconst label = active\n\t\t\t? state.styler.render(state.theme.roles.focus, choice.label)\n\t\t\t: state.styler.render(state.theme.roles.content, choice.label)\n\t\tconst description =\n\t\t\tchoice.help === undefined\n\t\t\t\t? ''\n\t\t\t\t: ` ${state.styler.render(state.theme.roles.description, choice.help)}`\n\t\treturn `${pointer} ${marker} ${label}${description}`\n\t})\n\treturn [renderPromptHeader(state.styler, state.theme, state.message), ...lines].join('\\n')\n}\n\n/**\n * Advances a select prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`\n * reducer. `up` / `down` (and `k` / `j`) move the focus, wrapping at the ends; return submits the\n * focused choice's `value`; ctrl-c cancels. An empty choice list can never submit (a higher layer\n * guards against it); any other key is ignored.\n *\n * @param state - The select field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the state, the rendered view, the status, and the chosen value on submit\n */\nexport function reduceSelect(state: SelectState, key: KeyEvent): PromptStep<string, SelectState> {\n\tif (key.ctrl && key.name === 'c')\n\t\treturn { state, view: renderSelectView(state), status: 'cancel' }\n\n\tconst count = state.choices.length\n\tif (count === 0) return { state, view: renderSelectView(state), status: 'active' }\n\n\tif (key.name === 'up' || key.name === 'k') {\n\t\tconst next = { ...state, focused: (state.focused - 1 + count) % count }\n\t\treturn { state: next, view: renderSelectView(next), status: 'active' }\n\t}\n\tif (key.name === 'down' || key.name === 'j') {\n\t\tconst next = { ...state, focused: (state.focused + 1) % count }\n\t\treturn { state: next, view: renderSelectView(next), status: 'active' }\n\t}\n\tif (key.name === 'return') {\n\t\tconst choice = state.choices[state.focused]\n\t\tconst value = choice?.value ?? ''\n\t\treturn {\n\t\t\tstate,\n\t\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, choice?.label ?? '')}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue,\n\t\t}\n\t}\n\treturn { state, view: renderSelectView(state), status: 'active' }\n}\n\n// === Checkbox prompt\n\n/**\n * Builds the initial checkbox-field reducer state — the offered choices, with every value in the\n * field's `default` list pre-checked.\n *\n * @param field - The checkbox field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createCheckboxState(\n\tfield: CheckboxField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): CheckboxState {\n\tconst choices = [...field.choices]\n\tconst checked: readonly number[] = choices.reduce<number[]>((indices, choice, index) => {\n\t\tif (field.default?.includes(choice.value) === true) indices.push(index)\n\t\treturn indices\n\t}, [])\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tchoices,\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t\tfocused: 0,\n\t\tchecked,\n\t}\n}\n\n/**\n * Renders a checkbox-field reducer state as a multi-line styled view — one box per choice, and the\n * selected count beneath them.\n *\n * @param state - The checkbox field's current reducer state\n * @returns The rendered view — the header, one box per choice, and the selected count\n */\nexport function renderCheckboxView(state: CheckboxState): string {\n\tconst lines = state.choices.map((choice, index) => {\n\t\tconst active = index === state.focused\n\t\tconst ticked = state.checked.includes(index)\n\t\tconst pointer = active\n\t\t\t? state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)\n\t\t\t: ' '\n\t\tconst box = ticked\n\t\t\t? state.styler.render(state.theme.roles.selected, state.theme.icons.checked)\n\t\t\t: state.styler.render(state.theme.roles.muted, state.theme.icons.unchecked)\n\t\tconst label = active\n\t\t\t? state.styler.render(state.theme.roles.focus, choice.label)\n\t\t\t: state.styler.render(state.theme.roles.content, choice.label)\n\t\tconst description =\n\t\t\tchoice.help === undefined\n\t\t\t\t? ''\n\t\t\t\t: ` ${state.styler.render(state.theme.roles.description, choice.help)}`\n\t\treturn `${pointer} ${box} ${label}${description}`\n\t})\n\tconst summary = state.styler.render(state.theme.roles.hint, `${state.checked.length} selected`)\n\tconst body = [\n\t\trenderPromptHeader(state.styler, state.theme, state.message),\n\t\t...lines,\n\t\tsummary,\n\t].join('\\n')\n\treturn body\n}\n\n/**\n * Advances a checkbox prompt by one {@link KeyEvent} — the pure\n * `(state, key) → PromptStep<readonly string[]>` reducer. `up` / `down` (and `k` / `j`) move the\n * focus (wrapping); `space` toggles the focused index in the checked set; return submits the\n * checked values in choice order; ctrl-c cancels. The form applies selection-count rules.\n *\n * @param state - The checkbox field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the state, the rendered view, the status, and the ticked values on submit\n */\nexport function reduceCheckbox(\n\tstate: CheckboxState,\n\tkey: KeyEvent,\n): PromptStep<readonly string[], CheckboxState> {\n\tif (key.ctrl && key.name === 'c')\n\t\treturn { state, view: renderCheckboxView(state), status: 'cancel' }\n\n\tconst count = state.choices.length\n\n\tif ((key.name === 'up' || key.name === 'k') && count > 0) {\n\t\tconst next = {\n\t\t\t...state,\n\t\t\tfocused: (state.focused - 1 + count) % count,\n\t\t}\n\t\treturn { state: next, view: renderCheckboxView(next), status: 'active' }\n\t}\n\tif ((key.name === 'down' || key.name === 'j') && count > 0) {\n\t\tconst next = { ...state, focused: (state.focused + 1) % count }\n\t\treturn { state: next, view: renderCheckboxView(next), status: 'active' }\n\t}\n\tif (key.name === 'space' && count > 0) {\n\t\tconst checked = toggleIndex(state.checked, state.focused)\n\t\tconst next = { ...state, checked }\n\t\treturn { state: next, view: renderCheckboxView(next), status: 'active' }\n\t}\n\tif (key.name === 'return') {\n\t\tconst ordered = [...state.checked].sort((a, b) => a - b)\n\t\tconst values = ordered\n\t\t\t.map((index) => state.choices[index]?.value)\n\t\t\t.filter((value): value is string => value !== undefined)\n\t\tconst summary = ordered\n\t\t\t.map((index) => state.choices[index]?.label)\n\t\t\t.filter((name): name is string => name !== undefined)\n\t\t\t.join(', ')\n\t\treturn {\n\t\t\tstate,\n\t\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, summary)}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue: values,\n\t\t}\n\t}\n\treturn { state, view: renderCheckboxView(state), status: 'active' }\n}\n\n/**\n * Toggles `index` in a readonly index list — copy-on-write, returning the new sorted-by-insertion\n * list; the primitive {@link reduceCheckbox} calls.\n *\n * @param indices - The ticked indices, in tick order\n * @param index - The index to add when absent, or drop when present\n * @returns A new list carrying the toggled membership; the input is never mutated\n */\nexport function toggleIndex(indices: readonly number[], index: number): readonly number[] {\n\treturn indices.includes(index) ? indices.filter((i) => i !== index) : [...indices, index]\n}\n\n// === Editor prompt\n\n/**\n * Builds the initial editor-field reducer state — the committed lines empty, and the declared\n * default held for a finish with nothing typed.\n *\n * @param field - The editor field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createEditorState(\n\tfield: EditorField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): EditorState {\n\tconst lines: readonly string[] = []\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tdefault: field.default ?? '',\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t\tlines,\n\t\tcurrent: '',\n\t}\n}\n\n/**\n * Renders an editor-field reducer state as a multi-line styled view — the finish hint, the\n * committed lines, and the line in progress.\n *\n * @param state - The editor field's current reducer state\n * @returns The rendered view — the hinted header, the committed lines, and the line in progress\n */\nexport function renderEditorView(state: EditorState): string {\n\tconst head = renderHintedHeader(state.styler, state.theme, state.message, '(Ctrl+D to finish)')\n\tconst pointer = state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)\n\tconst committed = state.lines.map((line) => state.styler.render(state.theme.roles.content, line))\n\tconst body = [\n\t\t...committed,\n\t\t`${pointer} ${state.styler.render(state.theme.roles.content, state.current)}`,\n\t]\n\treturn [head, ...body].join('\\n')\n}\n\n/**\n * Advances an editor prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`\n * reducer. Printable characters extend the current line; backspace shrinks it; return commits the\n * current line and starts a fresh one; ctrl-d finishes, joining every line and falling back to the\n * default when empty; ctrl-c cancels. The form validates the candidate after the driver fills it.\n *\n * @param state - The editor field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the state, the rendered view, the status, and the joined text on submit\n */\nexport function reduceEditor(state: EditorState, key: KeyEvent): PromptStep<string, EditorState> {\n\tif (key.ctrl && key.name === 'c')\n\t\treturn { state, view: renderEditorView(state), status: 'cancel' }\n\n\tif (key.ctrl && key.name === 'd') {\n\t\tconst lines = state.current.length > 0 ? [...state.lines, state.current] : state.lines\n\t\tconst joined = lines.join('\\n')\n\t\tconst answer = joined.length > 0 ? joined : state.default\n\t\treturn {\n\t\t\tstate,\n\t\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, `${String(lines.length)} line${lines.length === 1 ? '' : 's'}`)}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue: answer,\n\t\t}\n\t}\n\n\tif (key.name === 'return') {\n\t\tconst next = {\n\t\t\t...state,\n\t\t\tlines: [...state.lines, state.current],\n\t\t\tcurrent: '',\n\t\t}\n\t\treturn { state: next, view: renderEditorView(next), status: 'active' }\n\t}\n\n\tconst current = editLine(state.current, key)\n\tif (current === undefined) return { state, view: renderEditorView(state), status: 'active' }\n\tconst next = { ...state, current }\n\treturn { state: next, view: renderEditorView(next), status: 'active' }\n}\n\n// === Shared reducer helpers\n\n/**\n * Applies a single line-editing {@link KeyEvent} to a text buffer — the editing shared by input,\n * password, and editor. A printable key appends its character; `backspace` drops the last\n * character; `space` appends a space; ctrl-u clears the line; a key that edits nothing returns\n * `undefined`.\n *\n * @param value - The buffer the field holds so far\n * @param key - The decoded keypress to apply\n * @returns The new buffer, or `undefined` when the key does not edit the line, so the caller can\n * leave the state untouched\n */\nexport function editLine(value: string, key: KeyEvent): string | undefined {\n\tif (key.ctrl && key.name === 'u') return ''\n\tif (key.name === 'backspace') return value.slice(0, -1)\n\tif (key.name === 'space') return `${value} `\n\t// A printable key that is not a control / navigation key — `name` is the literal character, and an\n\t// undecoded key carries none at all. Count CODE POINTS (not UTF-16 units) so an astral printable\n\t// (an emoji, a surrogate pair — `name.length` 2 but ONE code point) appends instead of being\n\t// dropped, while a multi-char control name (`up`, `return`) is still rejected.\n\tif (\n\t\t!key.ctrl &&\n\t\t!key.meta &&\n\t\tkey.name !== undefined &&\n\t\t[...key.name].length === 1 &&\n\t\tisPrintable(key.name)\n\t) {\n\t\treturn `${value}${key.sequence}`\n\t}\n\treturn undefined\n}\n\n// === Broker + bridge wiring helpers\n\n/**\n * Implements the default {@link import('./types.js').TimerHandler} — a thin host `setTimeout` / `clearTimeout`\n * wrapper that arms `callback` after `ms` and returns a {@link TimerCancelFunction}. The deadline seam\n * behind both the {@link import('./Prompt.js').Prompt} broker (its expiry) and the\n * {@link import('./PromptClient.js').PromptClient} (its reconnect backoff); a test injects a\n * deterministic timer instead, so neither entity touches real time.\n *\n * @param callback - The deadline callback to arm\n * @param ms - How long to wait before firing it, in milliseconds\n * @returns The {@link TimerCancelFunction} that clears the armed deadline\n */\nexport function defaultTimer(callback: () => void, ms: number): TimerCancelFunction {\n\tconst handle = setTimeout(callback, ms)\n\treturn () => clearTimeout(handle)\n}\n\n/**\n * Implements the default {@link import('./types.js').FetchHandler} — the global `fetch`, adapted to\n * the minimal injected shape the {@link import('./PromptClient.js').PromptClient} uses.\n *\n * @param input - The request URL\n * @param init - The request init the client sets — method, headers, body, and abort signal\n * @returns The host `fetch` promise for that request\n */\nexport function globalFetch(input: string, init?: FetchInit): Promise<Response> {\n\treturn fetch(input, init)\n}\n\n/**\n * Checks whether a caught value is an `AbortError` — the {@link import('./PromptClient.js').PromptClient}\n * distinguishes a deliberate `disconnect` / teardown (an aborted `fetch`) from a real fault, so it\n * exits its connect loop quietly instead of emitting `error` / reconnecting.\n *\n * @param error - The caught value to test\n * @returns True if the value is a host `Error` or `DOMException` named `AbortError`; false otherwise\n */\nexport function isAbortError(error: unknown): boolean {\n\treturn isError(error) && error.name === 'AbortError'\n}\n\n/**\n * Checks whether `url` is an insecure remote endpoint — a plain `http://` URL whose host is not a\n * loopback address. Pure string parsing (no `URL` global), so it stays total on malformed input;\n * the {@link import('./PromptClient.js').PromptClient} warns once when a `token` would cross such\n * an endpoint in cleartext.\n *\n * @remarks\n * A loopback host (`localhost`, `127.0.0.1`, `[::1]`) over `http://` is exempt (local\n * development has no network hop to eavesdrop on); every other `http://` host is insecure.\n * An `https://` URL (or any non-`http://` scheme) is never flagged.\n *\n * @param url - The candidate endpoint URL\n * @returns True if `url` is a non-loopback `http://` endpoint; false otherwise\n *\n * @example\n * ```ts\n * isInsecureRemote('http://example.com') // true\n * isInsecureRemote('http://localhost:3000') // false\n * isInsecureRemote('https://example.com') // false\n * ```\n */\nexport function isInsecureRemote(url: string): boolean {\n\tconst prefix = 'http://'\n\tif (!url.startsWith(prefix)) return false\n\tconst rest = url.slice(prefix.length)\n\tconst hostEnd = rest.search(/[/?#]/)\n\tconst authority = hostEnd === -1 ? rest : rest.slice(0, hostEnd)\n\tconst host = authority.includes('@') ? authority.slice(authority.indexOf('@') + 1) : authority\n\tconst hostname = host.startsWith('[')\n\t\t? host.slice(0, host.indexOf(']') + 1)\n\t\t: (host.split(':')[0] ?? '')\n\treturn hostname !== 'localhost' && hostname !== '127.0.0.1' && hostname !== '[::1]'\n}\n\n// === Terminal manager wire seams (transport-neutral, no http dependency)\n\n/**\n * Serializes a parked {@link PendingForm} into a `pending` {@link WireEvent}, whose frame `id` is\n * the form's own id.\n *\n * @param form - The parked form's wire-safe record\n * @returns The `pending` frame — the JSON-stringified record as `data`, and the form's own `id`\n */\nexport function serializePending(form: PendingForm): WireEvent {\n\treturn { event: 'pending', data: JSON.stringify(form), id: form.id }\n}\n\n/**\n * Serializes a parked form's expiry or release into an `expire` {@link WireEvent}, whose `data` is\n * the JSON `{ id }` payload.\n *\n * @param id - The id of the parked form that expired or was released\n * @returns The `expire` frame, carrying the JSON-stringified `{ id }` payload as `data`\n */\nexport function serializeExpire(id: string): WireEvent {\n\treturn { event: 'expire', data: JSON.stringify({ id }) }\n}\n\n/**\n * Serializes the `destroy` {@link WireEvent} a broker or manager sends when it is going away, which\n * carries no payload.\n *\n * @returns The `destroy` frame, whose `data` is empty because the signal carries no payload\n */\nexport function serializeDestroy(): WireEvent {\n\treturn { event: 'destroy', data: '' }\n}\n","import type {\n\tAnswerError,\n\tParkedForm,\n\tParkRequest,\n\tPendingForm,\n\tPromptEventMap,\n\tPromptInterface,\n\tPromptOptions,\n\tTimerHandler,\n} from './types.js'\nimport type { Result } from '@orkestrel/contract'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { FieldError, FormInterface, FormResult, FormValues } from '@orkestrel/form'\nimport { DEFAULT_PROMPT_TIMEOUT_MS } from './constants.js'\nimport { TerminalError } from './errors.js'\nimport { defaultTimer } from './helpers.js'\nimport { attempt, isArray, isString } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport { isFieldError, isFormError, serializeForm } from '@orkestrel/form'\n\n/**\n * Implements the headless form broker. It parks live forms, exposes their serialized schemas,\n * applies remote answers to the authoritative form, and abandons a parked form on timeout, release,\n * or teardown.\n *\n * @remarks\n * A parked record carries one call to `serializeForm`. A failed fill or submit leaves the record\n * parked for another answer. A successful submit settles the form once, emits `answer`, and removes\n * the record. Timeout, `stop`, and teardown abandon unsettled forms through their own `destroy`\n * method.\n *\n * @example\n * ```ts\n * const form = createForm({ fields: [{ control: 'text', name: 'name' }] })\n * const prompt = createPrompt()\n * const id = prompt.park(form)\n * prompt.answer(id, { name: 'Ada' })\n * await form.answer // { name: 'Ada' }\n * ```\n */\nexport class Prompt implements PromptInterface {\n\treadonly #timeout: number\n\treadonly #timer: TimerHandler\n\treadonly #cap: number | undefined\n\treadonly #parked = new Map<string, ParkedForm>()\n\treadonly #emitter: Emitter<PromptEventMap>\n\t#destroyed = false\n\n\tconstructor(options?: PromptOptions) {\n\t\tthis.#timeout = options?.timeout ?? DEFAULT_PROMPT_TIMEOUT_MS\n\t\tthis.#timer = options?.timer ?? defaultTimer\n\t\tthis.#cap = options?.cap\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t}\n\n\tget emitter(): EmitterInterface<PromptEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget count(): number {\n\t\treturn this.#parked.size\n\t}\n\n\tpending(): readonly PendingForm[]\n\tpending(id: string): PendingForm | undefined\n\tpending(id?: string): readonly PendingForm[] | PendingForm | undefined {\n\t\tif (id !== undefined) return this.#parked.get(id)?.pending\n\t\tconst forms: PendingForm[] = []\n\t\tfor (const parked of this.#parked.values()) forms.push(parked.pending)\n\t\treturn forms\n\t}\n\n\tpark(form: FormInterface, request?: ParkRequest): string {\n\t\tif (this.#destroyed) {\n\t\t\tform.destroy()\n\t\t\tthrow new TerminalError('EXPIRE', 'The broker has been destroyed')\n\t\t}\n\t\tif (this.#cap !== undefined && this.#parked.size >= this.#cap) {\n\t\t\tform.destroy()\n\t\t\tthrow new TerminalError('LIMIT', `The parked-form cap (${String(this.#cap)}) was reached`, {\n\t\t\t\tcap: this.#cap,\n\t\t\t})\n\t\t}\n\n\t\tconst id = crypto.randomUUID()\n\t\tconst pending: PendingForm = {\n\t\t\tid,\n\t\t\tschema: serializeForm(form.schema),\n\t\t\tstatus: 'pending',\n\t\t\ttime: Date.now(),\n\t\t\t...(request?.from !== undefined ? { from: request.from } : {}),\n\t\t\t...(request?.to !== undefined ? { to: request.to } : {}),\n\t\t}\n\t\tconst cancel = this.#timer(() => this.#expire(id), this.#timeout)\n\t\tthis.#parked.set(id, { form, pending, cancel })\n\t\tthis.#emitter.emit('pending', pending)\n\t\treturn id\n\t}\n\n\tanswer(id: string, values: FormValues): Result<FormValues, AnswerError> {\n\t\tconst outcome = attempt(() => this.#answer(id, values))\n\t\tif (outcome.success) return outcome.value\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\treason: 'rejected',\n\t\t\t\terrors: [{ field: 'form', message: 'The form rejected the answer' }],\n\t\t\t},\n\t\t}\n\t}\n\n\tstop(ids: readonly string[]): boolean\n\tstop(id: string): boolean\n\tstop(): void\n\tstop(ids?: string | readonly string[]): boolean | void {\n\t\tif (ids === undefined) {\n\t\t\tfor (const id of [...this.#parked.keys()]) this.#expire(id)\n\t\t\treturn\n\t\t}\n\t\tif (isArray(ids)) {\n\t\t\tlet stopped = true\n\t\t\tfor (const id of ids) {\n\t\t\t\tconst parked = this.#parked.get(id)\n\t\t\t\tif (parked === undefined || parked.pending.status !== 'pending') stopped = false\n\t\t\t}\n\t\t\tfor (const id of ids) this.#expire(id)\n\t\t\treturn stopped\n\t\t}\n\t\treturn this.#expire(ids)\n\t}\n\n\tdestroy(): void {\n\t\tif (this.#destroyed) return\n\t\tthis.#destroyed = true\n\t\tfor (const id of [...this.#parked.keys()]) this.#expire(id)\n\t\tthis.#emitter.destroy()\n\t}\n\n\t#answer(id: string, values: FormValues): Result<FormValues, AnswerError> {\n\t\tconst parked = this.#parked.get(id)\n\t\tif (parked === undefined || parked.pending.status !== 'pending') {\n\t\t\treturn { success: false, error: { reason: 'unknown' } }\n\t\t}\n\n\t\tconst outcome = attempt(() => this.#submit(parked.form, values))\n\t\tif (!outcome.success) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { reason: 'rejected', errors: this.#errors(outcome.error, parked.form) },\n\t\t\t}\n\t\t}\n\t\tif (!outcome.value.success) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { reason: 'rejected', errors: outcome.value.error },\n\t\t\t}\n\t\t}\n\n\t\tparked.cancel()\n\t\tconst answered: ParkedForm = {\n\t\t\t...parked,\n\t\t\tpending: { ...parked.pending, status: 'answered' },\n\t\t}\n\t\tthis.#parked.set(id, answered)\n\t\tthis.#emitter.emit('answer', id, outcome.value.value)\n\t\tthis.#parked.delete(id)\n\t\treturn outcome.value\n\t}\n\n\t#submit(form: FormInterface, values: FormValues): FormResult {\n\t\tfor (const [field, value] of Object.entries(values)) {\n\t\t\tconst outcome = attempt(() => form.fill(field, value))\n\t\t\tif (!outcome.success) {\n\t\t\t\treturn { success: false, error: this.#errors(outcome.error, form, field) }\n\t\t\t}\n\t\t}\n\t\treturn form.submit()\n\t}\n\n\t#errors(error: unknown, form: FormInterface, field?: string): readonly FieldError[] {\n\t\tif (isFormError(error)) {\n\t\t\tif (isFieldError(error.context)) return [error.context]\n\t\t\tconst named = error.context?.field\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tfield: isString(named) ? named : this.#field(form, field),\n\t\t\t\t\tmessage: error.message,\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\t\treturn [\n\t\t\t{\n\t\t\t\tfield: this.#field(form, field),\n\t\t\t\tmessage: 'The form rejected the answer',\n\t\t\t},\n\t\t]\n\t}\n\n\t#field(form: FormInterface, field?: string): string {\n\t\treturn field ?? form.schema.fields[0]?.name ?? form.schema.name ?? 'form'\n\t}\n\n\t#expire(id: string): boolean {\n\t\tconst parked = this.#parked.get(id)\n\t\tif (parked === undefined || parked.pending.status !== 'pending') return false\n\t\tparked.cancel()\n\t\tconst expired: ParkedForm = {\n\t\t\t...parked,\n\t\t\tpending: { ...parked.pending, status: 'expired' },\n\t\t}\n\t\tthis.#parked.set(id, expired)\n\t\tparked.form.destroy()\n\t\tthis.#emitter.emit('expire', id)\n\t\tthis.#parked.delete(id)\n\t\treturn true\n\t}\n}\n","import type {\n\tFetchHandler,\n\tPromptClientEventMap,\n\tPromptClientInterface,\n\tPromptClientOptions,\n\tTimerCancelFunction,\n\tTimerHandler,\n} from './types.js'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { FieldError, FormInterface, FormSchema, FormValues } from '@orkestrel/form'\nimport type { SSEEvent } from '@orkestrel/sse'\nimport {\n\tACCEPT_EVENT_STREAM,\n\tDEFAULT_RECONNECT_DELAY_MS,\n\tHEADER_TOKEN,\n\tSSE_BUFFER_LIMIT,\n\tSSE_EVENTS,\n} from './constants.js'\nimport {\n\tdefaultTimer,\n\tglobalFetch,\n\tisAbortError,\n\tisInsecureRemote,\n\tsanitizeDisplayText,\n\tsanitizeSchema,\n} from './helpers.js'\nimport { isPendingForm } from './validators.js'\nimport { arrayOf, isBoolean, isRecord, isString, parseJSON } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport { createForm, isFieldError, parseForm } from '@orkestrel/form'\nimport { createSSEParser } from '@orkestrel/sse'\n\n/**\n * Implements the SSE form bridge. It ingests serialized forms from a remote broker without waiting\n * on a render, drives one form at a time through a local terminal, posts each answer back, and asks\n * again when the authoritative form refuses one.\n *\n * @remarks\n * - **Connect + reconnect.** {@link connect} opens the SSE stream and reconnects after a transport\n * drop with the injected backoff unless reconnect is disabled, the client was destroyed, or\n * {@link disconnect} deliberately stopped it.\n * - **Ingest + render.** Each `pending` envelope passes through `isPendingForm`, Form's `parseForm`,\n * and terminal's `sanitizeSchema`, then enters a serial render queue. The SSE reader never awaits\n * that queue, so `expire` and `destroy` remain live while a person is answering.\n * - **Safe local form.** The rendering copy omits every wire `pattern`, because Form compiles a\n * pattern during local evaluation. The broker's parked form retains it and remains authoritative.\n * - **Refusal retry.** A structured `rejected` response seeds a new rendering form with the values\n * the refused attempt submitted, applies every {@link FieldError} through `invalidate`, and asks\n * again. No retry counter truncates the loop; acceptance, expiry, and the broker's own teardown\n * are its bounds.\n * - **Replay safety.** A replayed id is skipped while it is queued, rendering, or posting. Once an\n * attempt ends, a later delivery of that id may be rendered again.\n *\n * @example\n * ```ts\n * const client = createPromptClient({\n * \turl: 'http://localhost:3001/prompts',\n * \tterminal: createTerminal(),\n * })\n * await client.connect()\n * ```\n */\nexport class PromptClient implements PromptClientInterface {\n\treadonly url: string\n\treadonly #terminal: PromptClientOptions['terminal']\n\treadonly #token: string | undefined\n\treadonly #reconnect: boolean\n\treadonly #delay: number\n\treadonly #fetch: FetchHandler\n\treadonly #timer: TimerHandler\n\treadonly #emitter: Emitter<PromptClientEventMap>\n\t#controller: AbortController | undefined\n\t#backoff: TimerCancelFunction | undefined\n\t#wake: (() => void) | undefined\n\t#connecting = false\n\t#connected = false\n\t#destroyed = false\n\t#draining = false\n\t#warnedInsecureToken = false\n\treadonly #seen = new Set<string>()\n\treadonly #queue = new Map<string, FormSchema>()\n\t#active:\n\t\t| { readonly id: string; readonly form: FormInterface; readonly stopped: boolean }\n\t\t| undefined\n\n\tconstructor(options: PromptClientOptions) {\n\t\tthis.url = options.url\n\t\tthis.#terminal = options.terminal\n\t\tthis.#token = options.token\n\t\tthis.#reconnect = options.reconnect ?? true\n\t\tthis.#delay = options.delay ?? DEFAULT_RECONNECT_DELAY_MS\n\t\tthis.#fetch = options.fetch ?? globalFetch\n\t\tthis.#timer = options.timer ?? defaultTimer\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t}\n\n\tget emitter(): EmitterInterface<PromptClientEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget connected(): boolean {\n\t\treturn this.#connected\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.#destroyed || this.#connecting) return\n\t\tthis.#connecting = true\n\t\twhile (this.#connecting && !this.#destroyed) {\n\t\t\ttry {\n\t\t\t\tawait this.#stream()\n\t\t\t} catch (error) {\n\t\t\t\tthis.#markDisconnected()\n\t\t\t\tif (this.#destroyed || isAbortError(error)) return\n\t\t\t\tthis.#emitter.emit('error', error)\n\t\t\t}\n\t\t\tif (!this.#reconnect || !this.#connecting || this.#destroyed) return\n\t\t\tawait this.#wait(this.#delay)\n\t\t}\n\t}\n\n\tdisconnect(): void {\n\t\tthis.#connecting = false\n\t\tthis.#controller?.abort()\n\t\tthis.#controller = undefined\n\t\tthis.#backoff?.()\n\t\tthis.#backoff = undefined\n\t\tconst wake = this.#wake\n\t\tthis.#wake = undefined\n\t\twake?.()\n\t\tthis.#markDisconnected()\n\t}\n\n\tdestroy(): void {\n\t\tif (this.#destroyed) return\n\t\tthis.#destroyed = true\n\t\tthis.disconnect()\n\t\tthis.#interrupt()\n\t\tthis.#emitter.destroy()\n\t}\n\n\tasync #stream(): Promise<void> {\n\t\tif (this.#token !== undefined && isInsecureRemote(this.url) && !this.#warnedInsecureToken) {\n\t\t\tthis.#warnedInsecureToken = true\n\t\t\tthis.#emitter.emit(\n\t\t\t\t'error',\n\t\t\t\tnew Error('auth token sent as cleartext over insecure http; use https'),\n\t\t\t)\n\t\t}\n\t\tconst controller = new AbortController()\n\t\tthis.#controller = controller\n\t\tconst response = await this.#fetch(this.url, {\n\t\t\theaders: this.#headers({ Accept: ACCEPT_EVENT_STREAM }),\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\tif (!response.ok) throw new Error(`broker returned ${String(response.status)}`)\n\t\tconst body = response.body\n\t\tif (body === null) throw new Error('broker sent no stream')\n\n\t\tthis.#connected = true\n\t\tthis.#emitter.emit('connect')\n\n\t\tconst reader = body.getReader()\n\t\tconst decoder = new TextDecoder()\n\t\tconst parser = createSSEParser({ limit: SSE_BUFFER_LIMIT })\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst { done, value } = await reader.read()\n\t\t\t\tif (done) break\n\t\t\t\tfor (const event of parser.parse(decoder.decode(value, { stream: true }))) {\n\t\t\t\t\tthis.#handle(event)\n\t\t\t\t\tif (!this.#connecting) break\n\t\t\t\t}\n\t\t\t\tif (!this.#connecting) break\n\t\t\t}\n\t\t} finally {\n\t\t\treader.releaseLock()\n\t\t}\n\t\tthis.#markDisconnected()\n\t}\n\n\t#handle(event: SSEEvent): void {\n\t\tif (event.event === SSE_EVENTS.pending) {\n\t\t\tconst parsed = parseJSON(event.data)\n\t\t\tif (!isPendingForm(parsed) || this.#seen.has(parsed.id)) return\n\t\t\tconst schema = parseForm(parsed.schema)\n\t\t\tif (schema === undefined) {\n\t\t\t\tthis.#emitter.emit(\n\t\t\t\t\t'error',\n\t\t\t\t\tnew Error(`broker sent an invalid form schema for ${parsed.id}`),\n\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.#seen.add(parsed.id)\n\t\t\tthis.#queue.set(parsed.id, sanitizeSchema(schema))\n\t\t\tvoid this.#drain()\n\t\t\treturn\n\t\t}\n\t\tif (event.event === SSE_EVENTS.expire) {\n\t\t\tconst parsed = parseJSON(event.data)\n\t\t\tif (isRecord(parsed) && isString(parsed.id)) this.#expire(parsed.id)\n\t\t\treturn\n\t\t}\n\t\tif (event.event === SSE_EVENTS.destroy) {\n\t\t\tthis.disconnect()\n\t\t\tthis.#interrupt()\n\t\t}\n\t}\n\n\tasync #drain(): Promise<void> {\n\t\tif (this.#draining) return\n\t\tthis.#draining = true\n\t\ttry {\n\t\t\twhile (!this.#destroyed) {\n\t\t\t\tlet queued: readonly [string, FormSchema] | undefined\n\t\t\t\tfor (const entry of this.#queue) {\n\t\t\t\t\tqueued = entry\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif (queued === undefined) return\n\t\t\t\tconst [id, schema] = queued\n\t\t\t\tthis.#queue.delete(id)\n\t\t\t\ttry {\n\t\t\t\t\tawait this.#render(id, schema)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst active = this.#active\n\t\t\t\t\tif (active?.id !== id || !active.stopped) this.#emitter.emit('error', error)\n\t\t\t\t} finally {\n\t\t\t\t\tconst active = this.#active\n\t\t\t\t\tif (active?.id === id) {\n\t\t\t\t\t\tactive.form.destroy()\n\t\t\t\t\t\tthis.#active = undefined\n\t\t\t\t\t}\n\t\t\t\t\tif (!this.#queue.has(id)) this.#seen.delete(id)\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.#draining = false\n\t\t}\n\t}\n\n\tasync #render(id: string, schema: FormSchema): Promise<void> {\n\t\tlet values: FormValues | undefined\n\t\tlet errors: readonly FieldError[] = []\n\t\twhile (this.#seen.has(id) && !this.#destroyed) {\n\t\t\tconst form = this.#createRenderingForm(schema, values)\n\t\t\tthis.#active = { id, form, stopped: false }\n\t\t\tfor (const error of errors) form.invalidate(error.field, sanitizeDisplayText(error.message))\n\t\t\tconst submitted = await this.#terminal.ask(form)\n\t\t\tconst active = this.#active\n\t\t\tif (active?.id !== id || active.stopped) return\n\t\t\tconst rejected = await this.#post(id, submitted)\n\t\t\tconst posted = this.#active\n\t\t\tif (posted?.id !== id || posted.stopped || rejected === undefined) return\n\t\t\tvalues = submitted\n\t\t\terrors = rejected\n\t\t\tform.destroy()\n\t\t\tthis.#active = undefined\n\t\t}\n\t}\n\n\t#createRenderingForm(schema: FormSchema, values?: FormValues): FormInterface {\n\t\tconst fields = schema.fields.map((field) => {\n\t\t\tif (field.rule?.pattern === undefined) return field\n\t\t\tconst { pattern: _pattern, ...rule } = field.rule\n\t\t\treturn { ...field, rule }\n\t\t})\n\t\tconst form = createForm({ ...schema, fields }, values === undefined ? undefined : { values })\n\t\tvoid form.answer.catch(() => undefined)\n\t\treturn form\n\t}\n\n\tasync #post(id: string, values: FormValues): Promise<readonly FieldError[] | undefined> {\n\t\tconst response = await this.#fetch(this.url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: this.#headers({ 'Content-Type': 'application/json' }),\n\t\t\tbody: JSON.stringify({ id, values }),\n\t\t})\n\t\tif (!response.ok) this.#emitter.emit('error', new Error(`broker rejected answer ${id}`))\n\t\tconst parsed = parseJSON(await response.text())\n\t\tif (!isRecord(parsed) || !isBoolean(parsed.success)) {\n\t\t\tthis.#emitter.emit('error', new Error(`broker returned an invalid answer result for ${id}`))\n\t\t\treturn undefined\n\t\t}\n\t\tif (parsed.success) return undefined\n\t\tconst error = parsed.error\n\t\tif (!isRecord(error) || !isString(error.reason)) {\n\t\t\tthis.#emitter.emit('error', new Error(`broker returned an invalid answer error for ${id}`))\n\t\t\treturn undefined\n\t\t}\n\t\tif (error.reason === 'unknown') return undefined\n\t\tif (error.reason === 'rejected' && arrayOf(isFieldError)(error.errors)) return error.errors\n\t\tthis.#emitter.emit('error', new Error(`broker returned an invalid answer refusal for ${id}`))\n\t\treturn undefined\n\t}\n\n\t#expire(id: string): void {\n\t\tconst active = this.#active\n\t\tif (active?.id === id) {\n\t\t\tthis.#active = { ...active, stopped: true }\n\t\t\tthis.#seen.delete(id)\n\t\t\tactive.form.destroy()\n\t\t} else if (this.#queue.delete(id)) this.#seen.delete(id)\n\t\tthis.#emitter.emit('expire', id)\n\t}\n\n\t#interrupt(): void {\n\t\tthis.#queue.clear()\n\t\tthis.#seen.clear()\n\t\tconst active = this.#active\n\t\tif (active === undefined) return\n\t\tthis.#active = { ...active, stopped: true }\n\t\tactive.form.destroy()\n\t}\n\n\t#markDisconnected(): void {\n\t\tif (!this.#connected) return\n\t\tthis.#connected = false\n\t\tthis.#emitter.emit('disconnect')\n\t}\n\n\t#headers(base: Record<string, string>): Record<string, string> {\n\t\tif (this.#token !== undefined) return { ...base, [HEADER_TOKEN]: this.#token }\n\t\treturn { ...base }\n\t}\n\n\t#wait(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst settle = this.#createSettler(resolve)\n\t\t\tthis.#wake = settle\n\t\t\tthis.#backoff = this.#timer(settle, ms)\n\t\t})\n\t}\n\n\t#createSettler(resolve: () => void): () => void {\n\t\treturn () => {\n\t\t\tthis.#backoff = undefined\n\t\t\tthis.#wake = undefined\n\t\t\tresolve()\n\t\t}\n\t}\n}\n","import type {\n\tPendingForm,\n\tPromptInterface,\n\tPromptOptions,\n\tTerminalAnswerError,\n\tTerminalManagerEventMap,\n\tTerminalManagerInterface,\n\tTerminalManagerOptions,\n\tTerminalSnapshot,\n\tTerminalStoreInterface,\n\tTimerHandler,\n} from './types.js'\nimport type { Result } from '@orkestrel/contract'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { FormInterface, FormValues } from '@orkestrel/form'\nimport { TerminalError } from './errors.js'\nimport { createPrompt } from './factories.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { isArray } from '@orkestrel/contract'\n\n/**\n * Registers named {@link PromptInterface} brokers, one per endpoint, so several parties can `ask`\n * forms of each other by name with a `from` → `to` attribution edge on every parked form, and\n * refuses `DEADLOCK` on a transitive cycle across every in-flight ask.\n *\n * @remarks\n * - **Registry.** `add(name, options?)` mints (or, if `name` is already mounted, returns the\n * existing broker unchanged — idempotent, never clobbers a live/parked endpoint). Every mounted\n * broker's `pending` / `answer` / `expire` events are re-emitted on the manager, attributed by\n * `name`.\n * - **`ask`.** The target must already be mounted through {@link add} — `ask` never auto-adds it;\n * rejects `TARGET` for an unknown `to` (listing the known names). Rejects `DEADLOCK` when parking\n * `from → to` would close a cycle over the current in-flight edge set (walked transitively);\n * otherwise parks the caller's live form through the target's broker and returns that form's own\n * `answer` promise. Edge cleanup never alters the value or rejection the caller observes.\n * - **Durable open / save.** `open(name)` restores an EMPTY broker from the `store` (parked\n * Promises are process-bound and never resurrected); `save(name)` persists the endpoint's\n * configured `timeout`.\n * - **Removal.** `remove` drops one endpoint, a batch (the array overload declared first), or every\n * endpoint when called without an argument. It destroys each broker, which expires every form\n * still parked on it. `destroy` is idempotent.\n *\n * @example\n * ```ts\n * const form = createForm({ fields: [{ control: 'text', name: 'name' }] })\n * const manager = new TerminalManager()\n * manager.add('agent')\n * const answer = manager.ask('user', 'agent', form)\n * manager.answer('agent', manager.pending('agent')[0].id, { name: 'Ada' })\n * await answer // { name: 'Ada' }\n * ```\n */\nexport class TerminalManager implements TerminalManagerInterface {\n\treadonly #terminals = new Map<string, PromptInterface>()\n\treadonly #config = new Map<string, PromptOptions>()\n\t// The handlers subscribed on a mounted broker's emitter — kept so `remove` can `off` them\n\t// explicitly (on top of the broker's own `destroy`, which already renders its emitter inert).\n\treadonly #listeners = new Map<\n\t\tstring,\n\t\t{\n\t\t\treadonly pending: (form: PendingForm) => void\n\t\t\treadonly answer: (id: string, values: FormValues) => void\n\t\t\treadonly expire: (id: string) => void\n\t\t}\n\t>()\n\t// In-flight `ask` edges, keyed by the parked form's id — the deadlock graph. `from` asked\n\t// `to`; cleanup on settle (answer / expire / destroy / remove) removes EXACTLY the edge that\n\t// call created.\n\treadonly #edges = new Map<string, { readonly from: string; readonly to: string }>()\n\treadonly #store: TerminalStoreInterface | undefined\n\treadonly #timeout: number | undefined\n\treadonly #timer: TimerHandler | undefined\n\treadonly #cap: number | undefined\n\treadonly #emitter: Emitter<TerminalManagerEventMap>\n\t#destroyed = false\n\n\tconstructor(options?: TerminalManagerOptions) {\n\t\tthis.#store = options?.store\n\t\tthis.#timeout = options?.timeout\n\t\tthis.#timer = options?.timer\n\t\tthis.#cap = options?.cap\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t}\n\n\tget emitter(): EmitterInterface<TerminalManagerEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget count(): number {\n\t\treturn this.#terminals.size\n\t}\n\n\t// === Accessors\n\n\tterminal(name: string): PromptInterface | undefined {\n\t\treturn this.#terminals.get(name)\n\t}\n\n\tterminals(): readonly PromptInterface[] {\n\t\treturn [...this.#terminals.values()]\n\t}\n\n\t// === Registry\n\n\tadd(name: string, options?: PromptOptions): PromptInterface {\n\t\tif (this.#destroyed) throw new TerminalError('DESTROYED', 'manager destroyed')\n\t\tconst existing = this.#terminals.get(name)\n\t\tif (existing !== undefined) return existing\n\t\tconst timeout = options?.timeout ?? this.#timeout\n\t\tconst timer = options?.timer ?? this.#timer\n\t\tconst cap = options?.cap ?? this.#cap\n\t\tconst promptOptions: PromptOptions = {\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t\t...(timeout !== undefined ? { timeout } : {}),\n\t\t\t...(timer !== undefined ? { timer } : {}),\n\t\t\t...(cap !== undefined ? { cap } : {}),\n\t\t}\n\t\tconst broker = createPrompt(promptOptions)\n\t\tconst listeners = {\n\t\t\tpending: this.#createPendingListener(),\n\t\t\tanswer: this.#createAnswerListener(name),\n\t\t\texpire: this.#createExpireListener(name),\n\t\t}\n\t\tbroker.emitter.on('pending', listeners.pending)\n\t\tbroker.emitter.on('answer', listeners.answer)\n\t\tbroker.emitter.on('expire', listeners.expire)\n\t\tthis.#terminals.set(name, broker)\n\t\tthis.#config.set(name, { ...options })\n\t\tthis.#listeners.set(name, listeners)\n\t\treturn broker\n\t}\n\n\t// === Ask\n\n\task(from: string, to: string, form: FormInterface): Promise<FormValues> {\n\t\tconst broker = this.#terminals.get(to)\n\t\tif (broker === undefined) {\n\t\t\tconst known = [...this.#terminals.keys()]\n\t\t\treturn Promise.reject(\n\t\t\t\tnew TerminalError(\n\t\t\t\t\t'TARGET',\n\t\t\t\t\t`unknown terminal '${to}' (known: ${known.length > 0 ? known.join(', ') : 'none'})`,\n\t\t\t\t\t{ to, known },\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\t\tconst cycle = this.#findCycle(from, to)\n\t\tif (cycle !== undefined) {\n\t\t\treturn Promise.reject(\n\t\t\t\tnew TerminalError(\n\t\t\t\t\t'DEADLOCK',\n\t\t\t\t\t`ask ${from} -> ${to} would deadlock: ${cycle.join(' -> ')}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tfrom,\n\t\t\t\t\t\tto,\n\t\t\t\t\t\tpath: cycle,\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\t\tconst id = broker.park(form, { from, to })\n\t\tif (broker.pending(id) !== undefined) {\n\t\t\tthis.#edges.set(id, { from, to })\n\t\t\tform.answer.then(this.#createEdgeClear(id), this.#createEdgeClear(id))\n\t\t}\n\t\treturn form.answer\n\t}\n\n\t// === Pending accessors\n\n\tpending(): readonly PendingForm[]\n\tpending(to: string): readonly PendingForm[]\n\tpending(to?: string): readonly PendingForm[] {\n\t\tif (to !== undefined) {\n\t\t\tconst broker = this.#terminals.get(to)\n\t\t\treturn broker === undefined ? [] : broker.pending()\n\t\t}\n\t\tconst result: PendingForm[] = []\n\t\tfor (const broker of this.#terminals.values()) result.push(...broker.pending())\n\t\treturn result\n\t}\n\n\t// === Answer\n\n\tanswer(to: string, id: string, values: FormValues): Result<FormValues, TerminalAnswerError> {\n\t\tconst broker = this.#terminals.get(to)\n\t\tif (broker === undefined) return { success: false, error: { reason: 'target' } }\n\t\tconst result = broker.answer(id, values)\n\t\tif (result.success) this.#edges.delete(id)\n\t\treturn result\n\t}\n\n\t// === Durable open / save\n\n\tasync open(name: string): Promise<PromptInterface | undefined> {\n\t\tif (this.#destroyed) throw new TerminalError('DESTROYED', 'manager destroyed')\n\t\tconst existing = this.#terminals.get(name)\n\t\tif (existing !== undefined) return existing\n\t\tif (this.#store === undefined) return undefined\n\t\tconst snapshot = await this.#store.get(name)\n\t\tif (this.#destroyed) throw new TerminalError('DESTROYED', 'manager destroyed')\n\t\tif (snapshot === undefined) return undefined\n\t\treturn this.add(name, snapshot.timeout !== undefined ? { timeout: snapshot.timeout } : {})\n\t}\n\n\tasync save(name: string): Promise<boolean> {\n\t\tconst broker = this.#terminals.get(name)\n\t\tif (this.#store === undefined || broker === undefined) return false\n\t\tconst config = this.#config.get(name)\n\t\tconst snapshot: TerminalSnapshot = {\n\t\t\tid: name,\n\t\t\t...(config?.timeout !== undefined ? { timeout: config.timeout } : {}),\n\t\t}\n\t\tawait this.#store.set(snapshot)\n\t\treturn true\n\t}\n\n\t// === Removal (the array overload declared FIRST)\n\n\tremove(names: readonly string[]): boolean\n\tremove(name: string): boolean\n\tremove(): void\n\tremove(names?: string | readonly string[]): boolean | void {\n\t\tif (names === undefined) {\n\t\t\tfor (const name of [...this.#terminals.keys()]) this.#removeOne(name)\n\t\t\treturn\n\t\t}\n\t\tif (isArray(names)) {\n\t\t\tlet removed = true\n\t\t\tfor (const name of names) {\n\t\t\t\tif (!this.#removeOne(name)) removed = false\n\t\t\t}\n\t\t\treturn removed\n\t\t}\n\t\treturn this.#removeOne(names)\n\t}\n\n\tdestroy(): void {\n\t\tif (this.#destroyed) return\n\t\tthis.#destroyed = true\n\t\tthis.remove()\n\t\tthis.#edges.clear()\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// === Private helpers\n\n\t#createPendingListener(): (form: PendingForm) => void {\n\t\treturn (form) => this.#emitter.emit('pending', form)\n\t}\n\n\t#createAnswerListener(name: string): (id: string, values: FormValues) => void {\n\t\treturn (id, values) => {\n\t\t\tthis.#edges.delete(id)\n\t\t\tthis.#emitter.emit('answer', name, id, values)\n\t\t}\n\t}\n\n\t#createExpireListener(name: string): (id: string) => void {\n\t\treturn (id) => {\n\t\t\tthis.#edges.delete(id)\n\t\t\tthis.#emitter.emit('expire', name, id)\n\t\t}\n\t}\n\n\t#createEdgeClear(id: string): () => void {\n\t\treturn () => {\n\t\t\tthis.#edges.delete(id)\n\t\t}\n\t}\n\n\t// Drop one endpoint: destroy its broker FIRST (its expire loop re-emits `expire` for every\n\t// still-parked form through the manager's listeners — still attached at this point, so\n\t// each settles on the manager emitter too), THEN unsubscribe the manager's listeners and\n\t// remove it from every registry map. `false` when `name` was not mounted.\n\t#removeOne(name: string): boolean {\n\t\tconst broker = this.#terminals.get(name)\n\t\tif (broker === undefined) return false\n\t\tbroker.destroy()\n\t\tconst listeners = this.#listeners.get(name)\n\t\tif (listeners !== undefined) {\n\t\t\tbroker.emitter.off('pending', listeners.pending)\n\t\t\tbroker.emitter.off('answer', listeners.answer)\n\t\t\tbroker.emitter.off('expire', listeners.expire)\n\t\t}\n\t\tthis.#terminals.delete(name)\n\t\tthis.#config.delete(name)\n\t\tthis.#listeners.delete(name)\n\t\tthis.#clearEdges(name)\n\t\treturn true\n\t}\n\n\t#clearEdges(to: string): void {\n\t\tfor (const [id, edge] of this.#edges) {\n\t\t\tif (edge.to === to) this.#edges.delete(id)\n\t\t}\n\t}\n\n\t// Walk the in-flight edge graph forward from `to`, looking for `from` — a hit means parking\n\t// `from -> to` would close a cycle. Returns the closing cycle path (`from` first and last),\n\t// or `undefined` when no cycle would form.\n\t#findCycle(from: string, to: string): readonly string[] | undefined {\n\t\tif (from === to) return [from, to]\n\t\tconst visited = new Set<string>([to])\n\t\tconst queue: Array<readonly string[]> = [[to]]\n\t\twhile (queue.length > 0) {\n\t\t\tconst path = queue.shift()\n\t\t\tif (path === undefined) break\n\t\t\tconst last = path[path.length - 1]\n\t\t\tif (last === undefined) continue\n\t\t\tfor (const edge of this.#edges.values()) {\n\t\t\t\tif (edge.from !== last) continue\n\t\t\t\tif (edge.to === from) return [from, ...path, from]\n\t\t\t\tif (visited.has(edge.to)) continue\n\t\t\t\tvisited.add(edge.to)\n\t\t\t\tqueue.push([...path, edge.to])\n\t\t\t}\n\t\t}\n\t\treturn undefined\n\t}\n}\n","import type { TerminalSnapshot, TerminalStoreInterface } from '../types.js'\n\n/**\n * Implements the in-memory {@link TerminalStoreInterface} — a process-lifetime `Map` of\n * {@link TerminalSnapshot} records keyed by endpoint id, the default store\n * {@link import('../factories.js').createMemoryTerminalStore} builds and the exact twin of\n * {@link import('./DatabaseTerminalStore.js').DatabaseTerminalStore}. It carries no idle expiry and\n * no eviction.\n *\n * @remarks\n * A plain `Map<string, TerminalSnapshot>` — the snapshot is already pure, self-contained CONFIG-only\n * JSON, so the memory tier needs no encoding. There is NO idle-TTL and NO\n * eviction: a persisted config lives until an explicit `delete`. A durable backend (JSON / SQLite /\n * IndexedDB) swaps in through the SAME interface without touching the manager — its\n * driver-pluggable twin is {@link import('./DatabaseTerminalStore.js').DatabaseTerminalStore} (the\n * snapshot as one opaque JSON column).\n *\n * - **`get` resolves the persisted snapshot for an id**, or `undefined` if none is stored.\n * - **`set` inserts / replaces under the snapshot's OWN `id`** (no separate id param).\n * - **`delete` drops a snapshot by id**; an absent id is a no-op (no throw).\n *\n * The public surface is EXACTLY `get` / `set` / `delete` — no extra members, so the class and\n * {@link TerminalStoreInterface} carry the same methods. Hydration is a caller concern: `open` always\n * restores an EMPTY broker — parked Promises are process-bound and never resurrected.\n *\n * @example\n * ```ts\n * import { createMemoryTerminalStore } from '@orkestrel/terminal'\n *\n * const store = createMemoryTerminalStore()\n * await store.set({ id: 'shell', timeout: 5000 }) // persist a config\n * const snapshot = await store.get('shell')\n * await store.delete('shell') // drop it\n * ```\n */\nexport class MemoryTerminalStore implements TerminalStoreInterface {\n\treadonly #snapshots = new Map<string, TerminalSnapshot>()\n\n\t/**\n\t * Resolves the persisted snapshot for `id`.\n\t *\n\t * @param id - The endpoint name the snapshot is keyed by\n\t * @returns The stored snapshot, or `undefined` when none is held\n\t */\n\tget(id: string): Promise<TerminalSnapshot | undefined> {\n\t\treturn Promise.resolve(this.#snapshots.get(id))\n\t}\n\n\t/**\n\t * Inserts or replaces under the snapshot's OWN `id` (no separate id param).\n\t *\n\t * @param snapshot - The config snapshot to persist, carrying its own `id`\n\t * @returns A promise that settles once the snapshot is held\n\t */\n\tset(snapshot: TerminalSnapshot): Promise<void> {\n\t\tthis.#snapshots.set(snapshot.id, snapshot)\n\t\treturn Promise.resolve()\n\t}\n\n\t/**\n\t * Drops a snapshot by id; an absent id is a no-op (no throw).\n\t *\n\t * @param id - The endpoint name to drop\n\t * @returns A promise that settles once the snapshot is gone\n\t */\n\tdelete(id: string): Promise<void> {\n\t\tthis.#snapshots.delete(id)\n\t\treturn Promise.resolve()\n\t}\n}\n","import type { TerminalSnapshot, TerminalSnapshotRow, TerminalStoreInterface } from '../types.js'\nimport type { TableInterface } from '@orkestrel/database'\nimport { isTerminalSnapshot } from '../validators.js'\n\n/**\n * Implements a {@link TerminalStoreInterface} backed by one table of the `databases` layer — an\n * endpoint's durable config state is a row, so persistence reduces to keyed point-access (`get` /\n * `set` / `delete`) over a {@link TableInterface}, the driver-pluggable twin of the plain-`Map`\n * {@link import('./MemoryTerminalStore.js').MemoryTerminalStore}. A stored `snapshot` is narrowed\n * with {@link import('../validators.js').isTerminalSnapshot} on read.\n *\n * @remarks\n * The store is driver-agnostic: it holds a single {@link TableInterface} whose backend (memory,\n * JSON, SQLite, IndexedDB) is chosen by whoever builds it (the factories), so a JSON / SQLite /\n * IndexedDB backend swaps in WITHOUT touching the manager — the same seam as\n * {@link import('./MemoryTerminalStore.js').MemoryTerminalStore}. The driver defaults to memory\n * ({@link import('../factories.js').createDatabaseTerminalStore} passes `createMemoryDriver()`), so\n * it ALSO works in memory out of the box; you opt into the durable plumbing by passing a JSON /\n * SQLite / IndexedDB driver.\n *\n * The {@link TerminalSnapshot} is stored as ONE OPAQUE JSON COLUMN — the table is a row of\n * `{ id; snapshot }` ({@link TerminalSnapshotRow}). The snapshot is already a COMPLETE,\n * self-contained, pure-JSON CONFIG payload (no live broker state), so storing it whole is lossless\n * AND keeps the row type flat (`snapshot` reads back as `unknown`).\n *\n * - **`set(snapshot)` upserts under the snapshot's OWN `id`** (no separate id param) — it writes\n * the row `{ id: snapshot.id, snapshot }`.\n * - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to\n * a {@link TerminalSnapshot} ({@link import('../validators.js').isTerminalSnapshot} — the total\n * guard that narrows an untrusted storage read), or `undefined` if none is stored.\n * - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).\n *\n * There is NO idle-TTL / eviction — a persisted config lives until an explicit `delete`. The public\n * surface is EXACTLY `get` / `set` / `delete` — no extra members, so the class and\n * {@link TerminalStoreInterface} carry the same methods. Hydration stays a caller concern: `open` always restores an EMPTY\n * broker — parked Promises are process-bound and never resurrected.\n *\n * @example\n * ```ts\n * import { createDatabaseTerminalStore } from '@orkestrel/terminal'\n * import { createMemoryDriver } from '@orkestrel/database'\n *\n * const store = createDatabaseTerminalStore(createMemoryDriver()) // a durable driver swaps in here\n * await store.set({ id: 'shell', timeout: 5000 }) // persist the config (one JSON column)\n * const snapshot = await store.get('shell')\n * await store.delete('shell') // drop it\n * ```\n */\nexport class DatabaseTerminalStore implements TerminalStoreInterface {\n\treadonly #table: TableInterface<TerminalSnapshotRow>\n\n\t/**\n\t * Wraps a table as a terminal store.\n\t *\n\t * @param table - The {@link TableInterface} holding the snapshots — its row is the\n\t * {@link TerminalSnapshotRow} `{ id; snapshot }` shape (the snapshot one opaque JSON column)\n\t */\n\tconstructor(table: TableInterface<TerminalSnapshotRow>) {\n\t\tthis.#table = table\n\t}\n\n\t/**\n\t * Resolves the persisted snapshot for `id`, narrowing the opaque JSON column back to a\n\t * `TerminalSnapshot`.\n\t *\n\t * @param id - The endpoint name the row is keyed by\n\t * @returns The stored snapshot, or `undefined` when none is held or the column is off-shape\n\t */\n\tasync get(id: string): Promise<TerminalSnapshot | undefined> {\n\t\tconst row = await this.#table.get(id)\n\t\tif (row === undefined) return undefined\n\t\t// The snapshot crosses back as an untrusted storage read (a structured clone / a JSON row),\n\t\t// so narrow the opaque JSON column with the boundary guard rather than a cast;\n\t\t// a malformed blob resolves `undefined`, never a broken config.\n\t\treturn isTerminalSnapshot(row.snapshot) ? row.snapshot : undefined\n\t}\n\n\t/**\n\t * Inserts or replaces under the snapshot's OWN `id` (no separate id param) — the row is\n\t * `{ id, snapshot }`.\n\t *\n\t * @param snapshot - The config snapshot to persist, carrying its own `id`\n\t * @returns A promise that settles once the row is written\n\t */\n\tasync set(snapshot: TerminalSnapshot): Promise<void> {\n\t\tawait this.#table.set({ id: snapshot.id, snapshot })\n\t}\n\n\t/**\n\t * Drops a snapshot by id; an absent id is a no-op (no throw).\n\t *\n\t * @param id - The endpoint name to drop\n\t * @returns A promise that settles once the row is gone\n\t */\n\tasync delete(id: string): Promise<void> {\n\t\tawait this.#table.remove(id)\n\t}\n}\n","import type {\n\tPromptClientInterface,\n\tPromptClientOptions,\n\tPromptInterface,\n\tPromptOptions,\n\tTerminalManagerInterface,\n\tTerminalManagerOptions,\n\tTerminalSnapshotRow,\n\tTerminalStoreInterface,\n} from './types.js'\nimport type { DriverInterface, TableInterface } from '@orkestrel/database'\nimport { Prompt } from './Prompt.js'\nimport { PromptClient } from './PromptClient.js'\nimport { TerminalManager } from './TerminalManager.js'\nimport { MemoryTerminalStore } from './stores/MemoryTerminalStore.js'\nimport { DatabaseTerminalStore } from './stores/DatabaseTerminalStore.js'\nimport { createDatabase, createMemoryDriver } from '@orkestrel/database'\nimport { rawShape, stringShape } from '@orkestrel/contract'\n\n/**\n * Creates the headless {@link PromptInterface} broker. It parks live forms and applies remote\n * answers to the authoritative instances.\n *\n * @param options - See {@link PromptOptions}\n * @returns A {@link PromptInterface}\n *\n * @remarks\n * The caller awaits the parked form's own `answer`. Timeout, `stop`, or teardown destroys the form,\n * so that promise rejects with the Form package's `ABANDONED` error. Inject `options.timer` to\n * drive expiry without real time.\n *\n * @example\n * ```ts\n * import { createPrompt } from '@orkestrel/terminal'\n * import { createForm } from '@orkestrel/form'\n *\n * const prompt = createPrompt()\n * const form = createForm({ fields: [{ control: 'text', name: 'name' }] })\n * const id = prompt.park(form)\n * prompt.answer(id, { name: 'Ada' })\n * ```\n */\nexport function createPrompt(options?: PromptOptions): PromptInterface {\n\treturn new Prompt(options)\n}\n\n/**\n * Creates the SSE prompt {@link PromptClientInterface} bridge — it connects to a remote broker's\n * SSE endpoint, dispatches each received form to a local\n * {@link import('./types.js').TerminalInterface}, and POSTs the answer back. Universal — `fetch`\n * and SSE are web standards.\n *\n * @param options - See {@link PromptClientOptions} (`url` + `terminal` required)\n * @returns A {@link PromptClientInterface}\n *\n * @remarks\n * - **Connect + reconnect.** `await client.connect()` streams remote prompts until the stream\n * ends; it reconnects with the `delay` backoff unless `reconnect` is `false` / the client was\n * `destroy`ed. Inject `options.fetch` (a scripted `fetch`) and `options.timer` to drive it\n * deterministically in tests — no real network.\n * - **Wire narrowing.** Every decoded prompt is guard-narrowed before dispatch (never an `as`).\n *\n * @example\n * ```ts\n * import { createPromptClient } from '@orkestrel/terminal'\n *\n * const client = createPromptClient({ url: 'http://host/prompts', terminal })\n * await client.connect()\n * ```\n */\nexport function createPromptClient(options: PromptClientOptions): PromptClientInterface {\n\treturn new PromptClient(options)\n}\n\n/**\n * Creates the multi-endpoint {@link TerminalManager} — a named registry of {@link PromptInterface}\n * brokers so several parties can `ask` forms of each other by name, with a transitive cycle check\n * that refuses `DEADLOCK` across every in-flight ask.\n *\n * @param options - See {@link TerminalManagerOptions}\n * @returns A {@link TerminalManager}\n *\n * @example\n * ```ts\n * import { createTerminalManager } from '@orkestrel/terminal'\n *\n * const manager = createTerminalManager()\n * manager.add('agent')\n * ```\n */\nexport function createTerminalManager(options?: TerminalManagerOptions): TerminalManagerInterface {\n\treturn new TerminalManager(options)\n}\n\n/**\n * Creates the in-memory {@link TerminalStoreInterface} — a process-lifetime `Map` of endpoint\n * config snapshots, the default store backing a {@link TerminalManagerInterface}'s `open` / `save`.\n *\n * @returns A {@link TerminalStoreInterface}\n *\n * @example\n * ```ts\n * import { createMemoryTerminalStore } from '@orkestrel/terminal'\n *\n * const store = createMemoryTerminalStore()\n * ```\n */\nexport function createMemoryTerminalStore(): TerminalStoreInterface {\n\treturn new MemoryTerminalStore()\n}\n\n/**\n * Creates a {@link TerminalStoreInterface} backed by one table of the `databases` layer — the\n * driver-pluggable twin of {@link createMemoryTerminalStore}, storing each endpoint's config\n * snapshot as one opaque JSON column. The default driver is an in-memory `@orkestrel/database`\n * driver.\n *\n * @param driver - The {@link DriverInterface} backing the table (default an in-memory driver)\n * @returns A {@link TerminalStoreInterface}\n *\n * @example\n * ```ts\n * import { createDatabaseTerminalStore } from '@orkestrel/terminal'\n *\n * const store = createDatabaseTerminalStore() // in-memory by default\n * ```\n */\nexport function createDatabaseTerminalStore(\n\tdriver: DriverInterface = createMemoryDriver(),\n): TerminalStoreInterface {\n\t// The snapshot is stored as ONE OPAQUE JSON column (`rawShape`), so the row infers FLAT —\n\t// `{ id: string; snapshot: unknown }` = TerminalSnapshotRow.\n\tconst columns = { id: stringShape(), snapshot: rawShape({}) }\n\tconst database = createDatabase({ driver, tables: { terminals: columns } })\n\tconst table: TableInterface<TerminalSnapshotRow> = database.table('terminals')\n\treturn new DatabaseTerminalStore(table)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["ESC","CSI","STATUS_ICONS","freezeStyle","holds","isError","INTRINSICS","isObject","isFunction","literalOf","recordOf","isNonEmptyString","isRecord","isNumber","isString","isString","freezeStyle","stripControls","strip","createStyler","isError","Emitter","serializeForm","attempt","isArray","isFormError","isFieldError","isString","Emitter","createSSEParser","parseJSON","parseForm","isRecord","isString","createForm","isBoolean","arrayOf","isFieldError","Emitter","isArray","createMemoryDriver","stringShape","rawShape","createDatabase"],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/validators.ts","../../../src/core/helpers.ts","../../../src/core/Prompt.ts","../../../src/core/PromptAnswers.ts","../../../src/core/PromptClient.ts","../../../src/core/TerminalManager.ts","../../../src/core/stores/MemoryTerminalStore.ts","../../../src/core/stores/DatabaseTerminalStore.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { PromptRole, PromptTheme } from './types.js'\nimport { CSI, ESC, freezeStyle, STATUS_ICONS } from '@orkestrel/console'\n\n// The constant DATA the pure terminal core reads: key decoding, rendering, and transport defaults.\n// UPPER_SNAKE, `Object.freeze`d, every member exported. Control bytes are built with\n// `String.fromCharCode` so no raw control character appears in source, and the escape lead and the\n// CSI prefix come from `@orkestrel/console`, which publishes both.\n\n// === Control bytes (named, no raw control characters in source)\n\n/** Names the carriage return byte (`\\r`, U+000D) — Enter on most terminals. */\nexport const RETURN = String.fromCharCode(13)\n/** Names the line feed byte (`\\n`, U+000A) — Enter on some terminals / pasted input. */\nexport const NEWLINE = String.fromCharCode(10)\n/** Names the tab byte (`\\t`, U+0009). */\nexport const TAB = String.fromCharCode(9)\n/** Names the backspace byte (BS, U+0008) — Ctrl+H / some terminals' Backspace. */\nexport const BACKSPACE = String.fromCharCode(8)\n/** Names the delete byte (DEL, U+007F) — the usual Backspace byte on a Unix TTY. */\nexport const DELETE = String.fromCharCode(127)\n/** Names the space byte (U+0020). */\nexport const SPACE = ' '\n/** Names the Ctrl+C byte (ETX, U+0003) — interrupt / cancel. */\nexport const CTRL_C = String.fromCharCode(3)\n/** Names the Ctrl+D byte (EOT, U+0004) — end-of-transmission / finish (the editor's commit key). */\nexport const CTRL_D = String.fromCharCode(4)\n/** Names the Ctrl+U byte (NAK, U+0015) — clear the current line. */\nexport const CTRL_U = String.fromCharCode(21)\n/** Names the Ctrl+A byte (SOH, U+0001) — move to start of line. */\nexport const CTRL_A = String.fromCharCode(1)\n/** Names the Ctrl+E byte (ENQ, U+0005) — move to end of line. */\nexport const CTRL_E = String.fromCharCode(5)\n\n/**\n * Names the Single Shift Three lead (`ESCO`) — the alternate arrow-key prefix some terminals emit\n * (`ESC O A`). Built from the console module's own {@link import('@orkestrel/console').ESC}; the\n * navigation keys' CSI lead is that module's {@link import('@orkestrel/console').CSI}, which this\n * package reuses rather than redeclaring.\n */\nexport const KEY_SS3 = `${ESC}O`\n\n/**\n * Holds the exact escape sequence to canonical key name table\n * {@link import('./helpers.js').parseKey} consults for the navigation and editing keys. Covers the\n * CSI form (`ESC[A`…) and the SS3 form (`ESCOA`…) of the arrows, plus the `home` / `end` / `delete`\n * CSI sequences with their numeric-tilde variants. The source of truth for the multi-byte key\n * decode; frozen.\n *\n * @remarks\n * Terminals disagree on these: a cursor key is `ESC[A` (normal) or `ESCOA` (application mode),\n * and Home / End / Delete each have a letter form (`ESC[H` / `ESC[F`) and a numeric form\n * (`ESC[1~` / `ESC[4~` / `ESC[3~`). Every accepted spelling maps to one name so a reducer never\n * sees the wire encoding.\n */\nexport const SEQUENCE_NAMES: Readonly<Record<string, string>> = Object.freeze({\n\t[`${CSI}A`]: 'up',\n\t[`${CSI}B`]: 'down',\n\t[`${CSI}C`]: 'right',\n\t[`${CSI}D`]: 'left',\n\t[`${KEY_SS3}A`]: 'up',\n\t[`${KEY_SS3}B`]: 'down',\n\t[`${KEY_SS3}C`]: 'right',\n\t[`${KEY_SS3}D`]: 'left',\n\t[`${CSI}H`]: 'home',\n\t[`${CSI}F`]: 'end',\n\t[`${CSI}1~`]: 'home',\n\t[`${CSI}4~`]: 'end',\n\t[`${CSI}3~`]: 'delete',\n\t[`${CSI}7~`]: 'home',\n\t[`${CSI}8~`]: 'end',\n})\n\n/**\n * Holds the control byte (or CRLF pair) to key descriptor table\n * {@link import('./helpers.js').parseKey} consults for the one-byte keys and the two-byte CRLF\n * Enter chunk. Each entry carries the canonical `name` and whether it is a `ctrl` combination. The\n * source of truth for that decode; frozen.\n *\n * @remarks\n * `return` / `newline` / `return + newline` all map to `return` (one canonical Enter name) — a\n * terminal or a paste can deliver Enter as `\\r`, `\\n`, or the `\\r\\n` pair in one chunk;\n * `delete` / `backspace` both map to `backspace` (the Backspace bytes); the Ctrl combos\n * (`c` / `d` / `u` / `a` / `e`) carry `ctrl: true` so a reducer can match\n * `key.ctrl && key.name === 'c'`. `escape` / `tab` / `space` are plain named keys.\n */\nexport const CONTROL_NAMES: Readonly<\n\tRecord<string, { readonly name: string; readonly ctrl: boolean }>\n> = Object.freeze({\n\t[RETURN]: Object.freeze({ name: 'return', ctrl: false }),\n\t[NEWLINE]: Object.freeze({ name: 'return', ctrl: false }),\n\t[`${RETURN}${NEWLINE}`]: Object.freeze({ name: 'return', ctrl: false }),\n\t[TAB]: Object.freeze({ name: 'tab', ctrl: false }),\n\t[ESC]: Object.freeze({ name: 'escape', ctrl: false }),\n\t[BACKSPACE]: Object.freeze({ name: 'backspace', ctrl: false }),\n\t[DELETE]: Object.freeze({ name: 'backspace', ctrl: false }),\n\t[SPACE]: Object.freeze({ name: 'space', ctrl: false }),\n\t[CTRL_C]: Object.freeze({ name: 'c', ctrl: true }),\n\t[CTRL_D]: Object.freeze({ name: 'd', ctrl: true }),\n\t[CTRL_U]: Object.freeze({ name: 'u', ctrl: true }),\n\t[CTRL_A]: Object.freeze({ name: 'a', ctrl: true }),\n\t[CTRL_E]: Object.freeze({ name: 'e', ctrl: true }),\n})\n\n// === Prompt defaults\n\n/** Names the default mask glyph {@link import('./helpers.js').createPasswordState} uses — `*`. */\nexport const DEFAULT_MASK = '*'\n\n// === Prompt-view icons\n\n/**\n * Holds the terminal-owned glyphs {@link DEFAULT_PROMPT_THEME} assembles its `icons` from, beside\n * the console module's own success and error marks. Read only when the default theme is assembled;\n * a view reads its resolved theme and never this constant. Frozen.\n *\n * @remarks\n * - `question` — the leading mark on a prompt's message line.\n * - `pointer` — the cursor before the input / the focused choice row.\n * - `dot` / `selected` — an unfocused / focused row marker in a select list.\n * - `checked` / `unchecked` — a checked / unchecked box in a checkbox list.\n */\nexport const PROMPT_ICONS = Object.freeze({\n\tquestion: '?',\n\tpointer: '›',\n\tdot: '○',\n\tselected: '●',\n\tchecked: '☑',\n\tunchecked: '☐',\n})\n\n// === The default prompt theme\n\n/**\n * Holds every {@link import('./types.js').PromptRole}, in one frozen list — the role axis's source of\n * truth. {@link import('./helpers.js').createPromptTheme} walks it to merge a partial theme, and\n * a consumer building a complete role map reads it rather than retyping every name.\n */\nexport const PROMPT_ROLES: readonly PromptRole[] = Object.freeze([\n\t'question',\n\t'pointer',\n\t'message',\n\t'content',\n\t'success',\n\t'error',\n\t'selected',\n\t'focus',\n\t'hint',\n\t'muted',\n\t'description',\n])\n\n/**\n * Holds the {@link import('./types.js').PromptTheme} every prompt renders with unless its options supply\n * another — the glyph set assembled from {@link PROMPT_ICONS} plus the console\n * {@link import('@orkestrel/console').STATUS_ICONS} `success` / `error` marks, and the console\n * {@link import('@orkestrel/console').Style} each role is painted with. Deeply frozen through the\n * console module's own {@link import('@orkestrel/console').freezeStyle}; the baseline\n * {@link import('./helpers.js').createPromptTheme} merges a partial theme over.\n *\n * @remarks\n * The default roles reproduce the views' historical coloring exactly: `question` / `pointer` cyan,\n * `message` / `focus` bold, `success` / `selected` green, `error` red, `hint` / `muted` /\n * `description` dim, and `content` the EMPTY style — an empty style renders bare text, so primary\n * content keeps the bytes it had before it became themeable.\n * Two roles sharing a style today are still two roles — re-mapping one leaves the other alone.\n */\nexport const DEFAULT_PROMPT_THEME: PromptTheme = Object.freeze({\n\ticons: Object.freeze({\n\t\tquestion: PROMPT_ICONS.question,\n\t\tpointer: PROMPT_ICONS.pointer,\n\t\tdot: PROMPT_ICONS.dot,\n\t\tselected: PROMPT_ICONS.selected,\n\t\tchecked: PROMPT_ICONS.checked,\n\t\tunchecked: PROMPT_ICONS.unchecked,\n\t\tsuccess: STATUS_ICONS.success,\n\t\terror: STATUS_ICONS.error,\n\t}),\n\troles: Object.freeze({\n\t\tquestion: freezeStyle({ foreground: 'cyan', attributes: [] }),\n\t\tpointer: freezeStyle({ foreground: 'cyan', attributes: [] }),\n\t\tmessage: freezeStyle({ attributes: ['bold'] }),\n\t\tcontent: freezeStyle({ attributes: [] }),\n\t\tsuccess: freezeStyle({ foreground: 'green', attributes: [] }),\n\t\terror: freezeStyle({ foreground: 'red', attributes: [] }),\n\t\tselected: freezeStyle({ foreground: 'green', attributes: [] }),\n\t\tfocus: freezeStyle({ attributes: ['bold'] }),\n\t\thint: freezeStyle({ attributes: ['dim'] }),\n\t\tmuted: freezeStyle({ attributes: ['dim'] }),\n\t\tdescription: freezeStyle({ attributes: ['dim'] }),\n\t}),\n})\n\n// === Broker + SSE-bridge defaults\n\n/** Holds how long (ms) the {@link import('./types.js').PromptInterface} broker parks an unanswered form before it expires — 5 minutes. */\nexport const DEFAULT_PROMPT_TIMEOUT_MS = 300_000\n\n/** Holds how long (ms) the {@link import('./types.js').PromptClientInterface} waits before each reconnect attempt — 2 seconds. */\nexport const DEFAULT_RECONNECT_DELAY_MS = 2_000\n\n/**\n * Holds the SSE `event:` names the broker emits and the\n * {@link import('./types.js').PromptClientInterface} dispatches on — `pending`, `expire`, and\n * `destroy`. Frozen; the source of truth for the wire event vocabulary.\n *\n * @remarks\n * - `pending` — a serialized {@link import('./types.js').PendingForm} to dispatch and answer.\n * - `expire` — an `{ id }` payload: the broker expired or released a parked form (the client drops it).\n * - `destroy` — the broker is going away; the client disconnects (no auto-reconnect) but stays reusable.\n */\nexport const SSE_EVENTS = Object.freeze({\n\tpending: 'pending',\n\texpire: 'expire',\n\tdestroy: 'destroy',\n})\n\n/**\n * Names the auth-token request header the {@link import('./types.js').PromptClientInterface} sends\n * when a `token` is configured — `x-orkestrel-token`.\n */\nexport const HEADER_TOKEN = 'x-orkestrel-token'\n\n/** Names the `Accept` header value that opens the broker's SSE stream — `text/event-stream`. */\nexport const ACCEPT_EVENT_STREAM = 'text/event-stream'\n\n/**\n * Sets the maximum number of characters the {@link import('./types.js').PromptClientInterface} lets its\n * SSE parser buffer before treating the stream as hostile — 1 MiB, comfortably above any\n * legitimate prompt payload. Passed as the `limit` to `createSSEParser` so an unterminated\n * or oversized `data:` field cannot grow the buffer without bound (a memory-exhaustion guard).\n */\nexport const SSE_BUFFER_LIMIT = 1_048_576\n","import type { TerminalErrorCode } from './types.js'\nimport { holds, INTRINSICS, isError, isFunction, isObject } from '@orkestrel/contract'\n\n/**\n * Represents the error the terminal surfaces for its own refusals: parking on a destroyed or full broker, an\n * unusable driver stream, a manager routing fault, or a ctrl-c cancellation. A parked form's own\n * lifecycle failures reject through the form's `answer` with the form package's error, never with\n * this one.\n *\n * @remarks\n * Carries a {@link TerminalErrorCode} and an optional `context` bag naming the offending values:\n * `{ cap }` on `LIMIT`, `{ to, known }` on `TARGET`, and `{ from, to, path }` on `DEADLOCK`. Narrow\n * a caught value with {@link isTerminalError} and branch on `error.code`.\n */\nexport class TerminalError extends Error {\n\t/** Holds the machine-readable condition — see {@link TerminalErrorCode}. */\n\treadonly code: TerminalErrorCode\n\t/** Holds an optional context bag naming the offending values — see the class {@link TerminalError remarks}. */\n\treadonly context?: Readonly<Record<string, unknown>>\n\n\t/**\n\t * Builds one terminal refusal.\n\t *\n\t * @param code - The machine-readable {@link TerminalErrorCode} a caller branches on\n\t * @param message - The human-readable reason\n\t * @param context - The optional bag naming the offending values — see the class {@link TerminalError remarks}\n\t */\n\tconstructor(\n\t\tcode: TerminalErrorCode,\n\t\tmessage: string,\n\t\tcontext?: Readonly<Record<string, unknown>>,\n\t) {\n\t\tsuper(message)\n\t\tINTRINSICS.define(this, Symbol.for('@orkestrel/terminal.TerminalError'), { value: this })\n\t\tthis.name = 'TerminalError'\n\t\tthis.code = code\n\t\tif (context !== undefined) this.context = context\n\t}\n}\n\n/**\n * Narrows an unknown caught value to a {@link TerminalError}, so a caller can branch on its `code`.\n *\n * @remarks\n * Recognizes branded errors across package copies, including subclasses, and refuses transparent proxies.\n *\n * @param value - The value to test (typically a `catch` binding or a rejected prompt call)\n * @returns True if `value` is a {@link TerminalError}; false otherwise\n *\n * @example\n * ```ts\n * try {\n * \tawait terminal.ask(form)\n * } catch (error) {\n * \tif (isTerminalError(error) && error.code === 'CANCEL') {\n * \t\t// the person aborted\n * \t}\n * }\n * ```\n */\nexport function isTerminalError(value: unknown): value is TerminalError {\n\treturn holds(() => {\n\t\tif (!isError(value) || INTRINSICS.prototype(value) === Error.prototype) return false\n\t\tconst brand = INTRINSICS.describe(value, Symbol.for('@orkestrel/terminal.TerminalError'))\n\t\tif (brand === undefined || brand.value !== value) return false\n\t\tconst code: unknown = INTRINSICS.reflect.read(value, 'code')\n\t\tif (\n\t\t\tcode !== 'EXPIRE' &&\n\t\t\tcode !== 'CANCEL' &&\n\t\t\tcode !== 'DRIVER' &&\n\t\t\tcode !== 'DEADLOCK' &&\n\t\t\tcode !== 'TARGET' &&\n\t\t\tcode !== 'LIMIT' &&\n\t\t\tcode !== 'DESTROYED'\n\t\t)\n\t\t\treturn false\n\t\tconst context: unknown = INTRINSICS.reflect.read(value, 'context')\n\t\treturn context === undefined || isObject(context) || isFunction(context)\n\t})\n}\n","import type { PendingForm, PendingFormStatus, TerminalSnapshot, WireEvent } from './types.js'\nimport type { Guard } from '@orkestrel/contract'\nimport {\n\tisNonEmptyString,\n\tisNumber,\n\tisRecord,\n\tisString,\n\tliteralOf,\n\trecordOf,\n} from '@orkestrel/contract'\n\n/**\n * Narrows an unknown value to a {@link PendingFormStatus}.\n *\n * @param value - The candidate ticket status\n * @returns True if the value is one of the declared ticket statuses; false otherwise\n */\nexport const isPendingFormStatus: Guard<PendingFormStatus> = literalOf(\n\t'pending',\n\t'answered',\n\t'expired',\n)\n\n/**\n * Narrows an unknown wire value to a {@link PendingForm} envelope — the envelope alone, because the\n * form package's `parseForm` owns the schema payload.\n *\n * @remarks\n * This guard checks the transport record and proves only that `schema` is a record. The Form\n * package's `parseForm` owns the schema payload and its semantic audit.\n *\n * @param value - The decoded wire value to inspect\n * @returns True if the value is a complete pending-form envelope; false otherwise\n */\nexport function isPendingForm(value: unknown): value is PendingForm {\n\treturn recordOf(\n\t\t{\n\t\t\tid: isNonEmptyString,\n\t\t\tschema: isRecord,\n\t\t\tstatus: isPendingFormStatus,\n\t\t\ttime: isNumber,\n\t\t\tfrom: isString,\n\t\t\tto: isString,\n\t\t},\n\t\t['from', 'to'],\n\t)(value)\n}\n\n/**\n * Narrows an unknown value to a transport-neutral {@link WireEvent} — the guard a consumer's own\n * transport applies to an inbound frame.\n *\n * @param value - The candidate wire event\n * @returns True if the value carries an event name, serialized data, and an optional id; false otherwise\n */\nexport const isWireEvent: Guard<WireEvent> = recordOf(\n\t{ event: isString, data: isString, id: isString },\n\t['id'],\n)\n\n/**\n * Narrows an unknown value to a {@link TerminalSnapshot} — a non-empty `id` and an optional numeric\n * `timeout`, the read boundary a store applies to an untrusted persisted row.\n *\n * @param value - The candidate snapshot read back from storage\n * @returns True if the value carries a non-empty `id` and an optional numeric `timeout`; false otherwise\n */\nexport const isTerminalSnapshot: Guard<TerminalSnapshot> = recordOf(\n\t{ id: isNonEmptyString, timeout: isNumber },\n\t['timeout'],\n)\n","import type {\n\tCheckboxState,\n\tConfirmState,\n\tEditorState,\n\tFetchInit,\n\tInputState,\n\tKeyEvent,\n\tPasswordState,\n\tPendingForm,\n\tPromptIcon,\n\tPromptRole,\n\tPromptStep,\n\tPromptTheme,\n\tPromptThemeOptions,\n\tSelectState,\n\tTimerCancelFunction,\n\tWireEvent,\n} from './types.js'\nimport type { Style, StylerInterface } from '@orkestrel/console'\nimport type {\n\tCheckboxField,\n\tConfirmField,\n\tEditorField,\n\tFormField,\n\tFormSchema,\n\tPasswordField,\n\tSelectField,\n\tTextField,\n} from '@orkestrel/form'\nimport {\n\tCONTROL_NAMES,\n\tDEFAULT_MASK,\n\tDEFAULT_PROMPT_THEME,\n\tPROMPT_ROLES,\n\tSEQUENCE_NAMES,\n} from './constants.js'\nimport { isError, isString } from '@orkestrel/contract'\nimport { createStyler, freezeStyle, strip, stripControls } from '@orkestrel/console'\n\n// The PURE prompt core implementation — all EXPORTED, all pure, all unit-tested:\n// the key decoder, schema sanitization, per-field view renderers, and the `create*State`\n// factories with their `reduce*` reducers. No `node:*`, no I/O, no events. Form owns validation and\n// settlement; these reducers only turn keys into candidate field values.\n\n// === Key decoding\n\n/**\n * Decodes one keypress's bytes into a {@link KeyEvent} — total, never throws. A `Uint8Array` is\n * read as UTF-8; the resulting string is matched against the known control bytes and the CRLF pair\n * ({@link CONTROL_NAMES}) and escape sequences ({@link SEQUENCE_NAMES}), falling back to a single\n * printable character. An unrecognized sequence carries no `name`, with the raw `sequence`\n * preserved.\n *\n * @remarks\n * - **Single control byte.** A one-character control input (`return` / `backspace` / `tab` /\n * `escape` / `space`, or a Ctrl combo `c` / `d` / `u` / `a` / `e`), or the two-byte `\\r\\n`\n * CRLF pair, is looked up in {@link CONTROL_NAMES}, carrying its `ctrl` flag.\n * - **Escape sequence.** A multi-byte ESC sequence (`up` / `down` / `left` / `right` in both the\n * `ESC[A` and `ESCOA` forms, plus `home` / `end` / `delete`) is looked up in\n * {@link SEQUENCE_NAMES} and flagged `meta`.\n * - **Printable character.** A single printable character becomes `name` = that character, with\n * `shift` set when it is an uppercase letter. A multi-code-point printable (an emoji, a pasted\n * run) keeps its first code point as the name and the whole input as `sequence`.\n * - **Unknown.** Anything else (an unrecognized escape, an empty input) yields an event with NO\n * `name` — absence, never an empty string — total, so the driver never crashes on a stray byte.\n *\n * @param input - The raw keypress bytes, as a string or `Uint8Array`\n * @returns The decoded {@link KeyEvent}\n *\n * @example\n * ```ts\n * parseKey('\\r') // { name: 'return', sequence: '\\r', ctrl: false, meta: false, shift: false }\n * parseKey('\\r\\n') // { name: 'return', sequence: '\\r\\n', ctrl: false, meta: false, shift: false }\n * parseKey('\\x1b[A') // { name: 'up', sequence: '\\x1b[A', ctrl: false, meta: true, shift: false }\n * parseKey('A') // { name: 'A', sequence: 'A', ctrl: false, meta: false, shift: true }\n * parseKey('\\x03') // { name: 'c', sequence: '\\x03', ctrl: true, meta: false, shift: false }\n * ```\n */\nexport function parseKey(input: string | Uint8Array): KeyEvent {\n\tconst sequence = isString(input) ? input : new TextDecoder().decode(input)\n\n\t// A known multi-byte escape sequence (arrows / home / end / delete) — flagged `meta`.\n\tconst sequenceName = SEQUENCE_NAMES[sequence]\n\tif (sequenceName !== undefined) {\n\t\treturn { name: sequenceName, sequence, ctrl: false, meta: true, shift: false }\n\t}\n\n\t// A known single control byte (return / backspace / tab / escape / space / a ctrl combo),\n\t// or the two-byte CRLF pair.\n\tconst control = CONTROL_NAMES[sequence]\n\tif (control !== undefined) {\n\t\treturn { name: control.name, sequence, ctrl: control.ctrl, meta: false, shift: false }\n\t}\n\n\t// A printable character — one or more code points, the first naming the key.\n\tconst points = [...sequence]\n\tconst first = points[0]\n\tif (first !== undefined && isPrintable(first)) {\n\t\treturn { name: first, sequence, ctrl: false, meta: false, shift: first !== first.toLowerCase() }\n\t}\n\n\t// Anything else (an unrecognized escape, an empty input) — total, never a throw. The name is\n\t// OMITTED rather than emptied, so a caller reads absence instead of a sentinel.\n\treturn { sequence, ctrl: false, meta: false, shift: false }\n}\n\n/**\n * Checks whether a single character is printable — the fallback test {@link parseKey} applies after\n * the control bytes and the escape sequences, so the C0 controls and DEL are excluded.\n *\n * @param character - The single character to test\n * @returns True if the character is at or above space and is not DEL; false otherwise\n */\nexport function isPrintable(character: string): boolean {\n\tif (character.length === 0) return false\n\tconst code = character.codePointAt(0)\n\tif (code === undefined) return false\n\t// Exclude the C0 controls (0–31) and DEL (127); everything at or above space is printable.\n\treturn code >= 32 && code !== 127\n}\n\n// === Prompt theme\n\n/**\n * Builds a complete {@link PromptTheme} by merging a partial one over\n * {@link DEFAULT_PROMPT_THEME}, leaf by leaf — each supplied icon replaces that glyph, each\n * supplied role replaces that {@link Style}, and everything else keeps its default. Each supplied\n * style is snapshotted through the console module's own\n * {@link import('@orkestrel/console').freezeStyle}, so the result is deeply frozen and a caller\n * mutating its own attribute list afterwards cannot reach into a built theme.\n *\n * @param options - The partial theme to merge, or `undefined` for the defaults\n * @returns The resolved, deeply frozen theme every prompt state carries\n *\n * @example\n * ```ts\n * createPromptTheme() // the defaults\n * createPromptTheme({\n * \ticons: { pointer: '=>' },\n * \troles: { message: { foreground: 'magenta', attributes: ['bold'] } },\n * })\n * ```\n */\nexport function createPromptTheme(options?: PromptThemeOptions): PromptTheme {\n\tconst icons: Record<PromptIcon, string> = { ...DEFAULT_PROMPT_THEME.icons, ...options?.icons }\n\tconst roles: Record<PromptRole, Style> = { ...DEFAULT_PROMPT_THEME.roles }\n\tfor (const role of PROMPT_ROLES) {\n\t\tconst style = options?.roles?.[role]\n\t\tif (style !== undefined) roles[role] = freezeStyle(style)\n\t}\n\treturn Object.freeze({ icons: Object.freeze(icons), roles: Object.freeze(roles) })\n}\n\n/**\n * Sanitizes text for one single-line display slot. Composes console's ANSI {@link strip} and C0\n * {@link stripControls} passes with removal of tab, line feed, and carriage return.\n *\n * @param text - The text to sanitize for a glyph or hint slot\n * @returns The text with ANSI sequences, every C0 control character, and DEL removed\n *\n * @example\n * ```ts\n * sanitizeDisplayText('Q\\rOVERWRITE\\nNEXT\\tX') // 'QOVERWRITENEXTX'\n * ```\n */\nexport function sanitizeDisplayText(text: string): string {\n\treturn stripControls(strip(text)).replaceAll('\\t', '').replaceAll('\\n', '').replaceAll('\\r', '')\n}\n\n/**\n * Sanitizes every terminal-readable string in a parsed form schema, keeping every identity and\n * answer string verbatim and dropping field metadata.\n *\n * @remarks\n * Display strings pass through {@link sanitizeDisplayText}: labels, help, placeholders, masks,\n * choice labels and help, file accept entries, and pattern sources. Identity and answer strings\n * stay verbatim: schema, group, and field names, group references, choice values, and defaults.\n * Rewriting those would sever the rendering copy from the authoritative form. Field metadata is\n * removed because terminal neither renders nor interprets it. Pattern sources are sanitized as\n * text only and are never compiled or executed here.\n *\n * @param schema - A schema already accepted by the Form package's `parseForm`\n * @returns A new schema with terminal-readable strings sanitized and field metadata omitted\n *\n * @example\n * ```ts\n * sanitizeSchema({ fields: [{ control: 'text', name: 'na\\u001bme', label: 'N\\u0000ame' }] })\n * // { fields: [{ control: 'text', name: 'na\\u001bme', label: 'Name' }] }\n * ```\n */\nexport function sanitizeSchema(schema: FormSchema): FormSchema {\n\tconst groups = schema.groups?.map((group) => ({\n\t\tname: group.name,\n\t\tlabel: sanitizeDisplayText(group.label),\n\t\t...(group.help !== undefined ? { help: sanitizeDisplayText(group.help) } : {}),\n\t}))\n\tconst fields: FormField[] = []\n\tfor (const source of schema.fields) {\n\t\tconst { meta: _meta, ...field } = source\n\t\tconst rule =\n\t\t\tfield.rule === undefined\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\t...field.rule,\n\t\t\t\t\t\t...(field.rule.pattern !== undefined\n\t\t\t\t\t\t\t? { pattern: sanitizeDisplayText(field.rule.pattern) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t}\n\t\tconst shared = {\n\t\t\tname: field.name,\n\t\t\t...(field.label !== undefined ? { label: sanitizeDisplayText(field.label) } : {}),\n\t\t\t...(field.help !== undefined ? { help: sanitizeDisplayText(field.help) } : {}),\n\t\t\t...(field.group !== undefined ? { group: field.group } : {}),\n\t\t\t...(rule !== undefined ? { rule } : {}),\n\t\t}\n\n\t\tswitch (field.control) {\n\t\t\tcase 'text':\n\t\t\tcase 'editor':\n\t\t\tcase 'number': {\n\t\t\t\tfields.push({\n\t\t\t\t\t...field,\n\t\t\t\t\t...shared,\n\t\t\t\t\t...(field.placeholder !== undefined\n\t\t\t\t\t\t? { placeholder: sanitizeDisplayText(field.placeholder) }\n\t\t\t\t\t\t: {}),\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'password': {\n\t\t\t\tfields.push({\n\t\t\t\t\t...field,\n\t\t\t\t\t...shared,\n\t\t\t\t\t...(field.mask !== undefined ? { mask: sanitizeDisplayText(field.mask) } : {}),\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'date':\n\t\t\tcase 'time':\n\t\t\tcase 'datetime':\n\t\t\tcase 'color':\n\t\t\tcase 'confirm':\n\t\t\tcase 'list': {\n\t\t\t\tfields.push({\n\t\t\t\t\t...field,\n\t\t\t\t\t...shared,\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'select':\n\t\t\tcase 'checkbox': {\n\t\t\t\tfields.push({\n\t\t\t\t\t...field,\n\t\t\t\t\t...shared,\n\t\t\t\t\tchoices: field.choices.map((choice) => ({\n\t\t\t\t\t\t...choice,\n\t\t\t\t\t\tvalue: choice.value,\n\t\t\t\t\t\tlabel: sanitizeDisplayText(choice.label),\n\t\t\t\t\t\t...(choice.help !== undefined ? { help: sanitizeDisplayText(choice.help) } : {}),\n\t\t\t\t\t})),\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'file': {\n\t\t\t\tfields.push({\n\t\t\t\t\t...field,\n\t\t\t\t\t...shared,\n\t\t\t\t\t...(field.accept !== undefined ? { accept: field.accept.map(sanitizeDisplayText) } : {}),\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\t...(schema.name !== undefined ? { name: schema.name } : {}),\n\t\t...(schema.label !== undefined ? { label: sanitizeDisplayText(schema.label) } : {}),\n\t\t...(schema.help !== undefined ? { help: sanitizeDisplayText(schema.help) } : {}),\n\t\t...(groups !== undefined ? { groups } : {}),\n\t\tfields,\n\t}\n}\n\n/**\n * Sanitizes every glyph a wire-supplied {@link PromptThemeOptions} carries for a single-line display\n * slot. Only the icons need it: a role is guard-narrowed to a console {@link Style}, whose colors\n * and attributes are fixed name sets, so no role can carry a byte a terminal would act on.\n *\n * @param theme - The narrowed theme options a remote prompt supplied\n * @returns The same theme with every supplied glyph sanitized for a single-line display slot\n */\nexport function sanitizeThemeIcons(theme: PromptThemeOptions): PromptThemeOptions {\n\tconst icons = theme.icons\n\tif (icons === undefined) return theme\n\tconst sanitized: Record<string, string> = {}\n\tfor (const [icon, glyph] of Object.entries(icons)) sanitized[icon] = sanitizeDisplayText(glyph)\n\treturn { ...theme, icons: sanitized }\n}\n\n// === Shared view helpers\n\n/**\n * Renders the styled question header (`? message`) — the leading line every active prompt view\n * shares, themed by the `question` + `message` roles.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param message - The prompt's question text\n * @returns The rendered question header\n */\nexport function renderPromptHeader(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tmessage: string,\n): string {\n\treturn `${styler.render(theme.roles.question, theme.icons.question)} ${styler.render(theme.roles.message, message)}`\n}\n\n/**\n * Renders a question header followed by a key hint painted with the `hint` role, or the header\n * alone when no hint is supplied.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param message - The prompt's question text\n * @param hint - The optional key hint to append\n * @returns The rendered header with the optional hint\n */\nexport function renderHintedHeader(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tmessage: string,\n\thint?: string,\n): string {\n\tconst head = renderPromptHeader(styler, theme, message)\n\treturn hint === undefined ? head : `${head} ${styler.render(theme.roles.hint, hint)}`\n}\n\n/**\n * Renders the styled submit line (`✔ message`) — the committed header an interactive prompt shows\n * after it resolves, themed by the `success` + `message` roles.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param message - The settled prompt's question text\n * @returns The rendered committed header\n */\nexport function renderSubmitHeader(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tmessage: string,\n): string {\n\treturn `${styler.render(theme.roles.success, theme.icons.success)} ${styler.render(theme.roles.message, message)}`\n}\n\n/**\n * Renders the styled failure line (`✖ message`) a form driver writes for each refused field before\n * it asks that field again.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param message - The failure text, normally the field's label and the reason\n * @returns The rendered failure line\n */\nexport function renderErrorLine(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tmessage: string,\n): string {\n\treturn `${styler.render(theme.roles.error, theme.icons.error)} ${styler.render(theme.roles.error, message)}`\n}\n\n// === Input prompt\n\n/**\n * Builds the initial text-field reducer state — the sanitized label, the declared default, the\n * styler, and the resolved theme.\n *\n * @param field - The text field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createInputState(\n\tfield: TextField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): InputState {\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tdefault: field.default ?? '',\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t\tvalue: '',\n\t}\n}\n\n/**\n * Renders a text-field reducer state as a styled view — the header, the pointer, and the typed\n * value, or the default shown as a hint while nothing is typed.\n *\n * @param state - The text field's current reducer state\n * @returns The rendered single-line view — header, pointer, and the typed value or the default\n */\nexport function renderInputView(state: InputState): string {\n\tconst content = state.value.length > 0 ? state.value : state.default\n\tconst role = state.value.length > 0 ? state.theme.roles.content : state.theme.roles.hint\n\tconst shown = state.styler.render(role, sanitizeDisplayText(content))\n\treturn `${renderPromptHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)} ${shown}`\n}\n\n/**\n * Advances an input prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`\n * reducer. Printable characters extend the value; backspace shrinks it; ctrl-u clears it; ctrl-c\n * cancels; return produces the candidate value, with an empty line falling back to the default.\n *\n * @param state - The text field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the new state, the rendered view, the status, and the value on submit\n */\nexport function reduceInput(state: InputState, key: KeyEvent): PromptStep<string, InputState> {\n\tif (key.ctrl && key.name === 'c') return { state, view: renderInputView(state), status: 'cancel' }\n\n\tif (key.name === 'return') {\n\t\tconst answer = state.value.length > 0 ? state.value : state.default\n\t\tconst next = { ...state, value: answer }\n\t\treturn {\n\t\t\tstate: next,\n\t\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, sanitizeDisplayText(answer))}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue: answer,\n\t\t}\n\t}\n\n\tconst value = editLine(state.value, key)\n\tif (value === undefined) return { state, view: renderInputView(state), status: 'active' }\n\tconst next = { ...state, value }\n\treturn { state: next, view: renderInputView(next), status: 'active' }\n}\n\n// === Password prompt\n\n/**\n * Builds the initial password-field reducer state — the text-field state, plus the mask glyph each\n * typed character renders as.\n *\n * @param field - The password field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createPasswordState(\n\tfield: PasswordField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): PasswordState {\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tmask: sanitizeDisplayText(field.mask ?? DEFAULT_MASK),\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t\tvalue: '',\n\t}\n}\n\n/**\n * Renders a password-field reducer state as a styled view, with the value replaced by the mask\n * repeated so the secret is never echoed.\n *\n * @param state - The password field's current reducer state\n * @returns The rendered view, with the mask repeated in place of the typed value\n */\nexport function renderPasswordView(state: PasswordState): string {\n\tconst masked = state.styler.render(\n\t\tstate.theme.roles.content,\n\t\tstate.mask.repeat(state.value.length),\n\t)\n\treturn `${renderPromptHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)} ${masked}`\n}\n\n/**\n * Advances a password prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`\n * reducer. Identical line-editing to {@link reduceInput} (printable extends, backspace shrinks,\n * ctrl-u clears, ctrl-c cancels) but the view masks the value. Return produces the candidate value.\n *\n * @param state - The password field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the new state, the masked view, the status, and the value on submit\n */\nexport function reducePassword(\n\tstate: PasswordState,\n\tkey: KeyEvent,\n): PromptStep<string, PasswordState> {\n\tif (key.ctrl && key.name === 'c')\n\t\treturn { state, view: renderPasswordView(state), status: 'cancel' }\n\n\tif (key.name === 'return') {\n\t\treturn {\n\t\t\tstate,\n\t\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, state.mask.repeat(state.value.length))}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue: state.value,\n\t\t}\n\t}\n\n\tconst value = editLine(state.value, key)\n\tif (value === undefined) return { state, view: renderPasswordView(state), status: 'active' }\n\tconst next = { ...state, value }\n\treturn { state: next, view: renderPasswordView(next), status: 'active' }\n}\n\n// === Confirm prompt\n\n/**\n * Builds the initial confirm-field reducer state — the sanitized label and the declared default\n * answer.\n *\n * @param field - The confirm field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createConfirmState(\n\tfield: ConfirmField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): ConfirmState {\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tdefault: field.default ?? false,\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t}\n}\n\n/**\n * Renders a confirm-field reducer state as a styled view — the header and the yes/no group, with\n * the default letter capitalized and painted by the `selected` role.\n *\n * @param state - The confirm field's current reducer state\n * @returns The rendered view — the header and the yes/no group with the default capitalized\n */\nexport function renderConfirmView(state: ConfirmState): string {\n\tconst head = renderPromptHeader(state.styler, state.theme, state.message)\n\tconst answer = state.default\n\t\t? `${state.styler.render(state.theme.roles.selected, 'Y')}${state.styler.render(state.theme.roles.hint, '/n')}`\n\t\t: `${state.styler.render(state.theme.roles.hint, 'y/')}${state.styler.render(state.theme.roles.selected, 'N')}`\n\treturn `${head} ${state.styler.render(state.theme.roles.hint, '(')}${answer}${state.styler.render(state.theme.roles.hint, ')')}`\n}\n\n/**\n * Advances a confirm prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<boolean>`\n * reducer. `y` / `Y` submits `true`, `n` / `N` submits `false`, return on an empty line submits\n * the `default`, ctrl-c cancels; any other key is ignored (stays active).\n *\n * @param state - The confirm field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the state, the rendered view, the status, and the answer on submit\n */\nexport function reduceConfirm(\n\tstate: ConfirmState,\n\tkey: KeyEvent,\n): PromptStep<boolean, ConfirmState> {\n\tif (key.ctrl && key.name === 'c')\n\t\treturn { state, view: renderConfirmView(state), status: 'cancel' }\n\n\tconst choice = key.name?.toLowerCase()\n\tconst answer =\n\t\tkey.name === 'return'\n\t\t\t? state.default\n\t\t\t: choice === 'y'\n\t\t\t\t? true\n\t\t\t\t: choice === 'n'\n\t\t\t\t\t? false\n\t\t\t\t\t: undefined\n\n\tif (answer === undefined) return { state, view: renderConfirmView(state), status: 'active' }\n\treturn {\n\t\tstate,\n\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, answer ? 'yes' : 'no')}`,\n\t\tstatus: 'submit',\n\t\tvalue: answer,\n\t}\n}\n\n// === Select prompt\n\n/**\n * Builds the initial select-field reducer state — the offered choices, with the focus pre-placed on\n * the declared default.\n *\n * @param field - The select field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createSelectState(\n\tfield: SelectField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): SelectState {\n\tconst choices = [...field.choices]\n\tconst index = choices.findIndex((choice) => choice.value === field.default)\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tchoices,\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t\tfocused: index >= 0 ? index : 0,\n\t}\n}\n\n/**\n * Renders a select-field reducer state as a multi-line styled view — one row per choice, with the\n * focused row marked and its help shown.\n *\n * @param state - The select field's current reducer state\n * @returns The rendered view — the header, then one row per choice with the focused row marked\n */\nexport function renderSelectView(state: SelectState): string {\n\tconst lines = state.choices.map((choice, index) => {\n\t\tconst active = index === state.focused\n\t\tconst pointer = active\n\t\t\t? state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)\n\t\t\t: ' '\n\t\tconst marker = active\n\t\t\t? state.styler.render(state.theme.roles.selected, state.theme.icons.selected)\n\t\t\t: state.styler.render(state.theme.roles.muted, state.theme.icons.dot)\n\t\tconst label = active\n\t\t\t? state.styler.render(state.theme.roles.focus, choice.label)\n\t\t\t: state.styler.render(state.theme.roles.content, choice.label)\n\t\tconst description =\n\t\t\tchoice.help === undefined\n\t\t\t\t? ''\n\t\t\t\t: ` ${state.styler.render(state.theme.roles.description, choice.help)}`\n\t\treturn `${pointer} ${marker} ${label}${description}`\n\t})\n\treturn [renderPromptHeader(state.styler, state.theme, state.message), ...lines].join('\\n')\n}\n\n/**\n * Advances a select prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`\n * reducer. `up` / `down` (and `k` / `j`) move the focus, wrapping at the ends; return submits the\n * focused choice's `value`; ctrl-c cancels. An empty choice list can never submit (a higher layer\n * guards against it); any other key is ignored.\n *\n * @param state - The select field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the state, the rendered view, the status, and the chosen value on submit\n */\nexport function reduceSelect(state: SelectState, key: KeyEvent): PromptStep<string, SelectState> {\n\tif (key.ctrl && key.name === 'c')\n\t\treturn { state, view: renderSelectView(state), status: 'cancel' }\n\n\tconst count = state.choices.length\n\tif (count === 0) return { state, view: renderSelectView(state), status: 'active' }\n\n\tif (key.name === 'up' || key.name === 'k') {\n\t\tconst next = { ...state, focused: (state.focused - 1 + count) % count }\n\t\treturn { state: next, view: renderSelectView(next), status: 'active' }\n\t}\n\tif (key.name === 'down' || key.name === 'j') {\n\t\tconst next = { ...state, focused: (state.focused + 1) % count }\n\t\treturn { state: next, view: renderSelectView(next), status: 'active' }\n\t}\n\tif (key.name === 'return') {\n\t\tconst choice = state.choices[state.focused]\n\t\tconst value = choice?.value ?? ''\n\t\treturn {\n\t\t\tstate,\n\t\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, choice?.label ?? '')}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue,\n\t\t}\n\t}\n\treturn { state, view: renderSelectView(state), status: 'active' }\n}\n\n// === Checkbox prompt\n\n/**\n * Builds the initial checkbox-field reducer state — the offered choices, with every value in the\n * field's `default` list pre-checked.\n *\n * @param field - The checkbox field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createCheckboxState(\n\tfield: CheckboxField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): CheckboxState {\n\tconst choices = [...field.choices]\n\tconst checked: readonly number[] = choices.reduce<number[]>((indices, choice, index) => {\n\t\tif (field.default?.includes(choice.value) === true) indices.push(index)\n\t\treturn indices\n\t}, [])\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tchoices,\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t\tfocused: 0,\n\t\tchecked,\n\t}\n}\n\n/**\n * Renders a checkbox-field reducer state as a multi-line styled view — one box per choice, and the\n * selected count beneath them.\n *\n * @param state - The checkbox field's current reducer state\n * @returns The rendered view — the header, one box per choice, and the selected count\n */\nexport function renderCheckboxView(state: CheckboxState): string {\n\tconst lines = state.choices.map((choice, index) => {\n\t\tconst active = index === state.focused\n\t\tconst ticked = state.checked.includes(index)\n\t\tconst pointer = active\n\t\t\t? state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)\n\t\t\t: ' '\n\t\tconst box = ticked\n\t\t\t? state.styler.render(state.theme.roles.selected, state.theme.icons.checked)\n\t\t\t: state.styler.render(state.theme.roles.muted, state.theme.icons.unchecked)\n\t\tconst label = active\n\t\t\t? state.styler.render(state.theme.roles.focus, choice.label)\n\t\t\t: state.styler.render(state.theme.roles.content, choice.label)\n\t\tconst description =\n\t\t\tchoice.help === undefined\n\t\t\t\t? ''\n\t\t\t\t: ` ${state.styler.render(state.theme.roles.description, choice.help)}`\n\t\treturn `${pointer} ${box} ${label}${description}`\n\t})\n\tconst summary = state.styler.render(state.theme.roles.hint, `${state.checked.length} selected`)\n\tconst body = [\n\t\trenderPromptHeader(state.styler, state.theme, state.message),\n\t\t...lines,\n\t\tsummary,\n\t].join('\\n')\n\treturn body\n}\n\n/**\n * Advances a checkbox prompt by one {@link KeyEvent} — the pure\n * `(state, key) → PromptStep<readonly string[]>` reducer. `up` / `down` (and `k` / `j`) move the\n * focus (wrapping); `space` toggles the focused index in the checked set; return submits the\n * checked values in choice order; ctrl-c cancels. The form applies selection-count rules.\n *\n * @param state - The checkbox field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the state, the rendered view, the status, and the ticked values on submit\n */\nexport function reduceCheckbox(\n\tstate: CheckboxState,\n\tkey: KeyEvent,\n): PromptStep<readonly string[], CheckboxState> {\n\tif (key.ctrl && key.name === 'c')\n\t\treturn { state, view: renderCheckboxView(state), status: 'cancel' }\n\n\tconst count = state.choices.length\n\n\tif ((key.name === 'up' || key.name === 'k') && count > 0) {\n\t\tconst next = {\n\t\t\t...state,\n\t\t\tfocused: (state.focused - 1 + count) % count,\n\t\t}\n\t\treturn { state: next, view: renderCheckboxView(next), status: 'active' }\n\t}\n\tif ((key.name === 'down' || key.name === 'j') && count > 0) {\n\t\tconst next = { ...state, focused: (state.focused + 1) % count }\n\t\treturn { state: next, view: renderCheckboxView(next), status: 'active' }\n\t}\n\tif (key.name === 'space' && count > 0) {\n\t\tconst checked = toggleIndex(state.checked, state.focused)\n\t\tconst next = { ...state, checked }\n\t\treturn { state: next, view: renderCheckboxView(next), status: 'active' }\n\t}\n\tif (key.name === 'return') {\n\t\tconst ordered = [...state.checked].sort((a, b) => a - b)\n\t\tconst values = ordered\n\t\t\t.map((index) => state.choices[index]?.value)\n\t\t\t.filter((value): value is string => value !== undefined)\n\t\tconst summary = ordered\n\t\t\t.map((index) => state.choices[index]?.label)\n\t\t\t.filter((name): name is string => name !== undefined)\n\t\t\t.join(', ')\n\t\treturn {\n\t\t\tstate,\n\t\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, summary)}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue: values,\n\t\t}\n\t}\n\treturn { state, view: renderCheckboxView(state), status: 'active' }\n}\n\n/**\n * Toggles `index` in a readonly index list — copy-on-write, returning the new sorted-by-insertion\n * list; the primitive {@link reduceCheckbox} calls.\n *\n * @param indices - The ticked indices, in tick order\n * @param index - The index to add when absent, or drop when present\n * @returns A new list carrying the toggled membership; the input is never mutated\n */\nexport function toggleIndex(indices: readonly number[], index: number): readonly number[] {\n\treturn indices.includes(index) ? indices.filter((i) => i !== index) : [...indices, index]\n}\n\n// === Editor prompt\n\n/**\n * Builds the initial editor-field reducer state — the committed lines empty, and the declared\n * default held for a finish with nothing typed.\n *\n * @param field - The editor field to render\n * @param styler - The styler used to render the view\n * @param theme - The optional terminal theme\n * @returns The initial immutable key state\n */\nexport function createEditorState(\n\tfield: EditorField,\n\tstyler: StylerInterface = createStyler(),\n\ttheme?: PromptThemeOptions,\n): EditorState {\n\tconst lines: readonly string[] = []\n\treturn {\n\t\tmessage: sanitizeDisplayText(field.label ?? field.name),\n\t\tdefault: field.default ?? '',\n\t\tstyler,\n\t\ttheme: createPromptTheme(theme),\n\t\tlines,\n\t\tcurrent: '',\n\t}\n}\n\n/**\n * Renders an editor-field reducer state as a multi-line styled view — the finish hint, the\n * committed lines, and the line in progress.\n *\n * @param state - The editor field's current reducer state\n * @returns The rendered view — the hinted header, the committed lines, and the line in progress\n */\nexport function renderEditorView(state: EditorState): string {\n\tconst head = renderHintedHeader(state.styler, state.theme, state.message, '(Ctrl+D to finish)')\n\tconst pointer = state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)\n\tconst committed = state.lines.map((line) => state.styler.render(state.theme.roles.content, line))\n\tconst body = [\n\t\t...committed,\n\t\t`${pointer} ${state.styler.render(state.theme.roles.content, state.current)}`,\n\t]\n\treturn [head, ...body].join('\\n')\n}\n\n/**\n * Advances an editor prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`\n * reducer. Printable characters extend the current line; backspace shrinks it; return commits the\n * current line and starts a fresh one; ctrl-d finishes, joining every line and falling back to the\n * default when empty; ctrl-c cancels. The form validates the candidate after the driver fills it.\n *\n * @param state - The editor field's current reducer state\n * @param key - The decoded keypress to apply\n * @returns The next step — the state, the rendered view, the status, and the joined text on submit\n */\nexport function reduceEditor(state: EditorState, key: KeyEvent): PromptStep<string, EditorState> {\n\tif (key.ctrl && key.name === 'c')\n\t\treturn { state, view: renderEditorView(state), status: 'cancel' }\n\n\tif (key.ctrl && key.name === 'd') {\n\t\tconst lines = state.current.length > 0 ? [...state.lines, state.current] : state.lines\n\t\tconst joined = lines.join('\\n')\n\t\tconst answer = joined.length > 0 ? joined : state.default\n\t\treturn {\n\t\t\tstate,\n\t\t\tview: `${renderSubmitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, `${String(lines.length)} line${lines.length === 1 ? '' : 's'}`)}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue: answer,\n\t\t}\n\t}\n\n\tif (key.name === 'return') {\n\t\tconst next = {\n\t\t\t...state,\n\t\t\tlines: [...state.lines, state.current],\n\t\t\tcurrent: '',\n\t\t}\n\t\treturn { state: next, view: renderEditorView(next), status: 'active' }\n\t}\n\n\tconst current = editLine(state.current, key)\n\tif (current === undefined) return { state, view: renderEditorView(state), status: 'active' }\n\tconst next = { ...state, current }\n\treturn { state: next, view: renderEditorView(next), status: 'active' }\n}\n\n// === Shared reducer helpers\n\n/**\n * Applies a single line-editing {@link KeyEvent} to a text buffer — the editing shared by input,\n * password, and editor. A printable key appends its character; `backspace` drops the last\n * character; `space` appends a space; ctrl-u clears the line; a key that edits nothing returns\n * `undefined`.\n *\n * @param value - The buffer the field holds so far\n * @param key - The decoded keypress to apply\n * @returns The new buffer, or `undefined` when the key does not edit the line, so the caller can\n * leave the state untouched\n */\nexport function editLine(value: string, key: KeyEvent): string | undefined {\n\tif (key.ctrl && key.name === 'u') return ''\n\tif (key.name === 'backspace') return value.slice(0, -1)\n\tif (key.name === 'space') return `${value} `\n\t// A printable key that is not a control / navigation key — `name` is the literal character, and an\n\t// undecoded key carries none at all. Count CODE POINTS (not UTF-16 units) so an astral printable\n\t// (an emoji, a surrogate pair — `name.length` 2 but ONE code point) appends instead of being\n\t// dropped, while a multi-char control name (`up`, `return`) is still rejected.\n\tif (\n\t\t!key.ctrl &&\n\t\t!key.meta &&\n\t\tkey.name !== undefined &&\n\t\t[...key.name].length === 1 &&\n\t\tisPrintable(key.name)\n\t) {\n\t\treturn `${value}${key.sequence}`\n\t}\n\treturn undefined\n}\n\n// === Broker + bridge wiring helpers\n\n/**\n * Implements the default {@link import('./types.js').TimerHandler} — a thin host `setTimeout` / `clearTimeout`\n * wrapper that arms `callback` after `ms` and returns a {@link TimerCancelFunction}. The deadline seam\n * behind both the {@link import('./Prompt.js').Prompt} broker (its expiry) and the\n * {@link import('./PromptClient.js').PromptClient} (its reconnect backoff); a test injects a\n * deterministic timer instead, so neither entity touches real time.\n *\n * @param callback - The deadline callback to arm\n * @param ms - How long to wait before firing it, in milliseconds\n * @returns The {@link TimerCancelFunction} that clears the armed deadline\n */\nexport function defaultTimer(callback: () => void, ms: number): TimerCancelFunction {\n\tconst handle = setTimeout(callback, ms)\n\treturn () => clearTimeout(handle)\n}\n\n/**\n * Implements the default {@link import('./types.js').FetchHandler} — the global `fetch`, adapted to\n * the minimal injected shape the {@link import('./PromptClient.js').PromptClient} uses.\n *\n * @param input - The request URL\n * @param init - The request init the client sets — method, headers, body, and abort signal\n * @returns The host `fetch` promise for that request\n */\nexport function globalFetch(input: string, init?: FetchInit): Promise<Response> {\n\treturn fetch(input, init)\n}\n\n/**\n * Checks whether a caught value is an `AbortError` — the {@link import('./PromptClient.js').PromptClient}\n * distinguishes a deliberate `disconnect` / teardown (an aborted `fetch`) from a real fault, so it\n * exits its connect loop quietly instead of emitting `error` / reconnecting.\n *\n * @param error - The caught value to test\n * @returns True if the value is a host `Error` or `DOMException` named `AbortError`; false otherwise\n */\nexport function isAbortError(error: unknown): boolean {\n\treturn isError(error) && error.name === 'AbortError'\n}\n\n/**\n * Checks whether `url` is an insecure remote endpoint — a plain `http://` URL whose host is not a\n * loopback address. Pure string parsing (no `URL` global), so it stays total on malformed input;\n * the {@link import('./PromptClient.js').PromptClient} warns once when a `token` would cross such\n * an endpoint in cleartext.\n *\n * @remarks\n * A loopback host (`localhost`, `127.0.0.1`, `[::1]`) over `http://` is exempt (local\n * development has no network hop to eavesdrop on); every other `http://` host is insecure.\n * An `https://` URL (or any non-`http://` scheme) is never flagged.\n *\n * @param url - The candidate endpoint URL\n * @returns True if `url` is a non-loopback `http://` endpoint; false otherwise\n *\n * @example\n * ```ts\n * isInsecureRemote('http://example.com') // true\n * isInsecureRemote('http://localhost:3000') // false\n * isInsecureRemote('https://example.com') // false\n * ```\n */\nexport function isInsecureRemote(url: string): boolean {\n\tconst prefix = 'http://'\n\tif (!url.startsWith(prefix)) return false\n\tconst rest = url.slice(prefix.length)\n\tconst hostEnd = rest.search(/[/?#]/)\n\tconst authority = hostEnd === -1 ? rest : rest.slice(0, hostEnd)\n\tconst host = authority.includes('@') ? authority.slice(authority.indexOf('@') + 1) : authority\n\tconst hostname = host.startsWith('[')\n\t\t? host.slice(0, host.indexOf(']') + 1)\n\t\t: (host.split(':')[0] ?? '')\n\treturn hostname !== 'localhost' && hostname !== '127.0.0.1' && hostname !== '[::1]'\n}\n\n// === Terminal manager wire seams (transport-neutral, no http dependency)\n\n/**\n * Serializes a parked {@link PendingForm} into a `pending` {@link WireEvent}, whose frame `id` is\n * the form's own id.\n *\n * @param form - The parked form's wire-safe record\n * @returns The `pending` frame — the JSON-stringified record as `data`, and the form's own `id`\n */\nexport function serializePending(form: PendingForm): WireEvent {\n\treturn { event: 'pending', data: JSON.stringify(form), id: form.id }\n}\n\n/**\n * Serializes a parked form's expiry or release into an `expire` {@link WireEvent}, whose `data` is\n * the JSON `{ id }` payload.\n *\n * @param id - The id of the parked form that expired or was released\n * @returns The `expire` frame, carrying the JSON-stringified `{ id }` payload as `data`\n */\nexport function serializeExpire(id: string): WireEvent {\n\treturn { event: 'expire', data: JSON.stringify({ id }) }\n}\n\n/**\n * Serializes the `destroy` {@link WireEvent} a broker or manager sends when it is going away, which\n * carries no payload.\n *\n * @returns The `destroy` frame, whose `data` is empty because the signal carries no payload\n */\nexport function serializeDestroy(): WireEvent {\n\treturn { event: 'destroy', data: '' }\n}\n","import type {\n\tAnswerError,\n\tParkedForm,\n\tParkRequest,\n\tPendingForm,\n\tPromptEventMap,\n\tPromptInterface,\n\tPromptOptions,\n\tTimerHandler,\n} from './types.js'\nimport type { Result } from '@orkestrel/contract'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { FieldError, FormInterface, FormResult, FormValues } from '@orkestrel/form'\nimport { DEFAULT_PROMPT_TIMEOUT_MS } from './constants.js'\nimport { TerminalError } from './errors.js'\nimport { defaultTimer } from './helpers.js'\nimport { attempt, isArray, isString } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport { isFieldError, isFormError, serializeForm } from '@orkestrel/form'\n\n/**\n * Implements the headless form broker. It parks live forms, exposes their serialized schemas,\n * applies remote answers to the authoritative form, and abandons a parked form on timeout, release,\n * or teardown.\n *\n * @remarks\n * A parked record carries one call to `serializeForm`. A failed fill or submit leaves the record\n * parked for another answer. A successful submit settles the form once, emits `answer`, and removes\n * the record. Timeout, `stop`, and teardown abandon unsettled forms through their own `destroy`\n * method.\n *\n * @example\n * ```ts\n * const form = createForm({ fields: [{ control: 'text', name: 'name' }] })\n * const prompt = createPrompt()\n * const id = prompt.park(form)\n * prompt.answer(id, { name: 'Ada' })\n * await form.answer // { name: 'Ada' }\n * ```\n */\nexport class Prompt implements PromptInterface {\n\treadonly #timeout: number\n\treadonly #timer: TimerHandler\n\treadonly #cap: number | undefined\n\treadonly #parked = new Map<string, ParkedForm>()\n\treadonly #emitter: Emitter<PromptEventMap>\n\t#destroyed = false\n\n\tconstructor(options?: PromptOptions) {\n\t\tthis.#timeout = options?.timeout ?? DEFAULT_PROMPT_TIMEOUT_MS\n\t\tthis.#timer = options?.timer ?? defaultTimer\n\t\tthis.#cap = options?.cap\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t}\n\n\tget emitter(): EmitterInterface<PromptEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget count(): number {\n\t\treturn this.#parked.size\n\t}\n\n\tpending(): readonly PendingForm[]\n\tpending(id: string): PendingForm | undefined\n\tpending(id?: string): readonly PendingForm[] | PendingForm | undefined {\n\t\tif (id !== undefined) return this.#parked.get(id)?.pending\n\t\tconst forms: PendingForm[] = []\n\t\tfor (const parked of this.#parked.values()) forms.push(parked.pending)\n\t\treturn forms\n\t}\n\n\tpark(form: FormInterface, request?: ParkRequest): string {\n\t\tif (this.#destroyed) {\n\t\t\tform.destroy()\n\t\t\tthrow new TerminalError('EXPIRE', 'The broker has been destroyed')\n\t\t}\n\t\tif (this.#cap !== undefined && this.#parked.size >= this.#cap) {\n\t\t\tform.destroy()\n\t\t\tthrow new TerminalError('LIMIT', `The parked-form cap (${String(this.#cap)}) was reached`, {\n\t\t\t\tcap: this.#cap,\n\t\t\t})\n\t\t}\n\n\t\tconst id = crypto.randomUUID()\n\t\tconst pending: PendingForm = {\n\t\t\tid,\n\t\t\tschema: serializeForm(form.schema),\n\t\t\tstatus: 'pending',\n\t\t\ttime: Date.now(),\n\t\t\t...(request?.from !== undefined ? { from: request.from } : {}),\n\t\t\t...(request?.to !== undefined ? { to: request.to } : {}),\n\t\t}\n\t\tconst cancel = this.#timer(() => this.#expire(id), this.#timeout)\n\t\tthis.#parked.set(id, { form, pending, cancel })\n\t\tthis.#emitter.emit('pending', pending)\n\t\treturn id\n\t}\n\n\tanswer(id: string, values: FormValues): Result<FormValues, AnswerError> {\n\t\tconst outcome = attempt(() => this.#answer(id, values))\n\t\tif (outcome.success) return outcome.value\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\treason: 'rejected',\n\t\t\t\terrors: [{ field: 'form', message: 'The form rejected the answer' }],\n\t\t\t},\n\t\t}\n\t}\n\n\tstop(ids: readonly string[]): boolean\n\tstop(id: string): boolean\n\tstop(): void\n\tstop(ids?: string | readonly string[]): boolean | void {\n\t\tif (ids === undefined) {\n\t\t\tfor (const id of [...this.#parked.keys()]) this.#expire(id)\n\t\t\treturn\n\t\t}\n\t\tif (isArray(ids)) {\n\t\t\tconst stopped = Iterator.from(ids).reduce((result, id) => {\n\t\t\t\tconst parked = this.#parked.get(id)\n\t\t\t\treturn parked !== undefined && parked.pending.status === 'pending' && result\n\t\t\t}, true)\n\t\t\tfor (const id of ids) this.#expire(id)\n\t\t\treturn stopped\n\t\t}\n\t\treturn this.#expire(ids)\n\t}\n\n\tdestroy(): void {\n\t\tif (this.#destroyed) return\n\t\tthis.#destroyed = true\n\t\tfor (const id of [...this.#parked.keys()]) this.#expire(id)\n\t\tthis.#emitter.destroy()\n\t}\n\n\t#answer(id: string, values: FormValues): Result<FormValues, AnswerError> {\n\t\tconst parked = this.#parked.get(id)\n\t\tif (parked === undefined || parked.pending.status !== 'pending') {\n\t\t\treturn { success: false, error: { reason: 'unknown' } }\n\t\t}\n\n\t\tconst outcome = attempt(() => this.#submit(parked.form, values))\n\t\tif (!outcome.success) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { reason: 'rejected', errors: this.#errors(outcome.error, parked.form) },\n\t\t\t}\n\t\t}\n\t\tif (!outcome.value.success) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { reason: 'rejected', errors: outcome.value.error },\n\t\t\t}\n\t\t}\n\n\t\tparked.cancel()\n\t\tconst answered: ParkedForm = {\n\t\t\t...parked,\n\t\t\tpending: { ...parked.pending, status: 'answered' },\n\t\t}\n\t\tthis.#parked.set(id, answered)\n\t\tthis.#emitter.emit('answer', id, outcome.value.value)\n\t\tthis.#parked.delete(id)\n\t\treturn outcome.value\n\t}\n\n\t#submit(form: FormInterface, values: FormValues): FormResult {\n\t\tfor (const [field, value] of Object.entries(values)) {\n\t\t\tconst outcome = attempt(() => form.fill(field, value))\n\t\t\tif (!outcome.success) {\n\t\t\t\treturn { success: false, error: this.#errors(outcome.error, form, field) }\n\t\t\t}\n\t\t}\n\t\treturn form.submit()\n\t}\n\n\t#errors(error: unknown, form: FormInterface, field?: string): readonly FieldError[] {\n\t\tif (isFormError(error)) {\n\t\t\tif (isFieldError(error.context)) return [error.context]\n\t\t\tconst named = error.context?.field\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tfield: isString(named) ? named : this.#field(form, field),\n\t\t\t\t\tmessage: error.message,\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\t\treturn [\n\t\t\t{\n\t\t\t\tfield: this.#field(form, field),\n\t\t\t\tmessage: 'The form rejected the answer',\n\t\t\t},\n\t\t]\n\t}\n\n\t#field(form: FormInterface, field?: string): string {\n\t\treturn field ?? form.schema.fields[0]?.name ?? form.schema.name ?? 'form'\n\t}\n\n\t#expire(id: string): boolean {\n\t\tconst parked = this.#parked.get(id)\n\t\tif (parked === undefined || parked.pending.status !== 'pending') return false\n\t\tparked.cancel()\n\t\tconst expired: ParkedForm = {\n\t\t\t...parked,\n\t\t\tpending: { ...parked.pending, status: 'expired' },\n\t\t}\n\t\tthis.#parked.set(id, expired)\n\t\tparked.form.destroy()\n\t\tthis.#emitter.emit('expire', id)\n\t\tthis.#parked.delete(id)\n\t\treturn true\n\t}\n}\n","import type { FieldError, FormValues } from '@orkestrel/form'\n\n/** Holds the answer and refusal carried between attempts of one remote prompt. */\nexport class PromptAnswers {\n\t#values: FormValues | undefined\n\t#errors: readonly FieldError[] = []\n\n\tget values(): FormValues | undefined {\n\t\treturn this.#values\n\t}\n\n\tget errors(): readonly FieldError[] {\n\t\treturn this.#errors\n\t}\n\n\treplace(values: FormValues, errors: readonly FieldError[]): void {\n\t\tthis.#values = values\n\t\tthis.#errors = errors\n\t}\n}\n","import type {\n\tFetchHandler,\n\tPromptClientEventMap,\n\tPromptClientInterface,\n\tPromptClientOptions,\n\tTimerCancelFunction,\n\tTimerHandler,\n} from './types.js'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { FieldError, FormInterface, FormSchema, FormValues } from '@orkestrel/form'\nimport type { SSEEvent } from '@orkestrel/sse'\nimport {\n\tACCEPT_EVENT_STREAM,\n\tDEFAULT_RECONNECT_DELAY_MS,\n\tHEADER_TOKEN,\n\tSSE_BUFFER_LIMIT,\n\tSSE_EVENTS,\n} from './constants.js'\nimport {\n\tdefaultTimer,\n\tglobalFetch,\n\tisAbortError,\n\tisInsecureRemote,\n\tsanitizeDisplayText,\n\tsanitizeSchema,\n} from './helpers.js'\nimport { isPendingForm } from './validators.js'\nimport { PromptAnswers } from './PromptAnswers.js'\nimport { arrayOf, isBoolean, isRecord, isString, parseJSON } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport { createForm, isFieldError, parseForm } from '@orkestrel/form'\nimport { createSSEParser } from '@orkestrel/sse'\n\n/**\n * Implements the SSE form bridge. It ingests serialized forms from a remote broker without waiting\n * on a render, drives one form at a time through a local terminal, posts each answer back, and asks\n * again when the authoritative form refuses one.\n *\n * @remarks\n * - **Connect + reconnect.** {@link connect} opens the SSE stream and reconnects after a transport\n * drop with the injected backoff unless reconnect is disabled, the client was destroyed, or\n * {@link disconnect} deliberately stopped it.\n * - **Ingest + render.** Each `pending` envelope passes through `isPendingForm`, Form's `parseForm`,\n * and terminal's `sanitizeSchema`, then enters a serial render queue. The SSE reader never awaits\n * that queue, so `expire` and `destroy` remain live while a person is answering.\n * - **Safe local form.** The rendering copy omits every wire `pattern`, because Form compiles a\n * pattern during local evaluation. The broker's parked form retains it and remains authoritative.\n * - **Refusal retry.** A structured `rejected` response seeds a new rendering form with the values\n * the refused attempt submitted, applies every {@link FieldError} through `invalidate`, and asks\n * again. No retry counter truncates the loop; acceptance, expiry, and the broker's own teardown\n * are its bounds.\n * - **Replay safety.** A replayed id is skipped while it is queued, rendering, or posting. Once an\n * attempt ends, a later delivery of that id may be rendered again.\n *\n * @example\n * ```ts\n * const client = createPromptClient({\n * \turl: 'http://localhost:3001/prompts',\n * \tterminal: createTerminal(),\n * })\n * await client.connect()\n * ```\n */\nexport class PromptClient implements PromptClientInterface {\n\treadonly url: string\n\treadonly #terminal: PromptClientOptions['terminal']\n\treadonly #token: string | undefined\n\treadonly #reconnect: boolean\n\treadonly #delay: number\n\treadonly #fetch: FetchHandler\n\treadonly #timer: TimerHandler\n\treadonly #emitter: Emitter<PromptClientEventMap>\n\t#controller: AbortController | undefined\n\t#backoff: TimerCancelFunction | undefined\n\t#wake: (() => void) | undefined\n\t#connecting = false\n\t#connected = false\n\t#destroyed = false\n\t#draining = false\n\t#warnedInsecureToken = false\n\treadonly #seen = new Set<string>()\n\treadonly #queue = new Map<string, FormSchema>()\n\t#active:\n\t\t| { readonly id: string; readonly form: FormInterface; readonly stopped: boolean }\n\t\t| undefined\n\n\tconstructor(options: PromptClientOptions) {\n\t\tthis.url = options.url\n\t\tthis.#terminal = options.terminal\n\t\tthis.#token = options.token\n\t\tthis.#reconnect = options.reconnect ?? true\n\t\tthis.#delay = options.delay ?? DEFAULT_RECONNECT_DELAY_MS\n\t\tthis.#fetch = options.fetch ?? globalFetch\n\t\tthis.#timer = options.timer ?? defaultTimer\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t}\n\n\tget emitter(): EmitterInterface<PromptClientEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget connected(): boolean {\n\t\treturn this.#connected\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.#destroyed || this.#connecting) return\n\t\tthis.#connecting = true\n\t\twhile (this.#connecting && !this.#destroyed) {\n\t\t\ttry {\n\t\t\t\tawait this.#stream()\n\t\t\t} catch (error) {\n\t\t\t\tthis.#markDisconnected()\n\t\t\t\tif (this.#destroyed || isAbortError(error)) return\n\t\t\t\tthis.#emitter.emit('error', error)\n\t\t\t}\n\t\t\tif (!this.#reconnect || !this.#connecting || this.#destroyed) return\n\t\t\tawait this.#wait(this.#delay)\n\t\t}\n\t}\n\n\tdisconnect(): void {\n\t\tthis.#connecting = false\n\t\tthis.#controller?.abort()\n\t\tthis.#controller = undefined\n\t\tthis.#backoff?.()\n\t\tthis.#backoff = undefined\n\t\tconst wake = this.#wake\n\t\tthis.#wake = undefined\n\t\twake?.()\n\t\tthis.#markDisconnected()\n\t}\n\n\tdestroy(): void {\n\t\tif (this.#destroyed) return\n\t\tthis.#destroyed = true\n\t\tthis.disconnect()\n\t\tthis.#interrupt()\n\t\tthis.#emitter.destroy()\n\t}\n\n\tasync #stream(): Promise<void> {\n\t\tif (this.#token !== undefined && isInsecureRemote(this.url) && !this.#warnedInsecureToken) {\n\t\t\tthis.#warnedInsecureToken = true\n\t\t\tthis.#emitter.emit(\n\t\t\t\t'error',\n\t\t\t\tnew Error('auth token sent as cleartext over insecure http; use https'),\n\t\t\t)\n\t\t}\n\t\tconst controller = new AbortController()\n\t\tthis.#controller = controller\n\t\tconst response = await this.#fetch(this.url, {\n\t\t\theaders: this.#headers({ Accept: ACCEPT_EVENT_STREAM }),\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\tif (!response.ok) throw new Error(`broker returned ${String(response.status)}`)\n\t\tconst body = response.body\n\t\tif (body === null) throw new Error('broker sent no stream')\n\n\t\tthis.#connected = true\n\t\tthis.#emitter.emit('connect')\n\n\t\tconst reader = body.getReader()\n\t\tconst decoder = new TextDecoder()\n\t\tconst parser = createSSEParser({ limit: SSE_BUFFER_LIMIT })\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst { done, value } = await reader.read()\n\t\t\t\tif (done) break\n\t\t\t\tfor (const event of parser.parse(decoder.decode(value, { stream: true }))) {\n\t\t\t\t\tthis.#handle(event)\n\t\t\t\t\tif (!this.#connecting) break\n\t\t\t\t}\n\t\t\t\tif (!this.#connecting) break\n\t\t\t}\n\t\t} finally {\n\t\t\treader.releaseLock()\n\t\t}\n\t\tthis.#markDisconnected()\n\t}\n\n\t#handle(event: SSEEvent): void {\n\t\tif (event.event === SSE_EVENTS.pending) {\n\t\t\tconst parsed = parseJSON(event.data)\n\t\t\tif (!isPendingForm(parsed) || this.#seen.has(parsed.id)) return\n\t\t\tconst schema = parseForm(parsed.schema)\n\t\t\tif (schema === undefined) {\n\t\t\t\tthis.#emitter.emit(\n\t\t\t\t\t'error',\n\t\t\t\t\tnew Error(`broker sent an invalid form schema for ${parsed.id}`),\n\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.#seen.add(parsed.id)\n\t\t\tthis.#queue.set(parsed.id, sanitizeSchema(schema))\n\t\t\tvoid this.#drain()\n\t\t\treturn\n\t\t}\n\t\tif (event.event === SSE_EVENTS.expire) {\n\t\t\tconst parsed = parseJSON(event.data)\n\t\t\tif (isRecord(parsed) && isString(parsed.id)) this.#expire(parsed.id)\n\t\t\treturn\n\t\t}\n\t\tif (event.event === SSE_EVENTS.destroy) {\n\t\t\tthis.disconnect()\n\t\t\tthis.#interrupt()\n\t\t}\n\t}\n\n\tasync #drain(): Promise<void> {\n\t\tif (this.#draining) return\n\t\tthis.#draining = true\n\t\ttry {\n\t\t\twhile (!this.#destroyed) {\n\t\t\t\tconst queued = this.#next()\n\t\t\t\tif (queued === undefined) return\n\t\t\t\tconst [id, schema] = queued\n\t\t\t\tthis.#queue.delete(id)\n\t\t\t\ttry {\n\t\t\t\t\tawait this.#render(id, schema)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst active = this.#active\n\t\t\t\t\tif (active?.id !== id || !active.stopped) this.#emitter.emit('error', error)\n\t\t\t\t} finally {\n\t\t\t\t\tconst active = this.#active\n\t\t\t\t\tif (active?.id === id) {\n\t\t\t\t\t\tactive.form.destroy()\n\t\t\t\t\t\tthis.#active = undefined\n\t\t\t\t\t}\n\t\t\t\t\tif (!this.#queue.has(id)) this.#seen.delete(id)\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.#draining = false\n\t\t}\n\t}\n\n\tasync #render(id: string, schema: FormSchema): Promise<void> {\n\t\tconst answers = new PromptAnswers()\n\t\twhile (this.#seen.has(id) && !this.#destroyed) {\n\t\t\tconst form = this.#createRenderingForm(schema, answers.values)\n\t\t\tthis.#active = { id, form, stopped: false }\n\t\t\tfor (const error of answers.errors)\n\t\t\t\tform.invalidate(error.field, sanitizeDisplayText(error.message))\n\t\t\tconst submitted = await this.#terminal.ask(form)\n\t\t\tconst active = this.#active\n\t\t\tif (active?.id !== id || active.stopped) return\n\t\t\tconst rejected = await this.#post(id, submitted)\n\t\t\tconst posted = this.#active\n\t\t\tif (posted?.id !== id || posted.stopped || rejected === undefined) return\n\t\t\tanswers.replace(submitted, rejected)\n\t\t\tform.destroy()\n\t\t\tthis.#active = undefined\n\t\t}\n\t}\n\n\t#next(): readonly [string, FormSchema] | undefined {\n\t\tfor (const entry of this.#queue) return entry\n\t\treturn undefined\n\t}\n\n\t#createRenderingForm(schema: FormSchema, values?: FormValues): FormInterface {\n\t\tconst fields = schema.fields.map((field) => {\n\t\t\tif (field.rule?.pattern === undefined) return field\n\t\t\tconst { pattern: _pattern, ...rule } = field.rule\n\t\t\treturn { ...field, rule }\n\t\t})\n\t\tconst form = createForm({ ...schema, fields }, values === undefined ? undefined : { values })\n\t\tvoid form.answer.catch(() => undefined)\n\t\treturn form\n\t}\n\n\tasync #post(id: string, values: FormValues): Promise<readonly FieldError[] | undefined> {\n\t\tconst response = await this.#fetch(this.url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: this.#headers({ 'Content-Type': 'application/json' }),\n\t\t\tbody: JSON.stringify({ id, values }),\n\t\t})\n\t\tif (!response.ok) this.#emitter.emit('error', new Error(`broker rejected answer ${id}`))\n\t\tconst parsed = parseJSON(await response.text())\n\t\tif (!isRecord(parsed) || !isBoolean(parsed.success)) {\n\t\t\tthis.#emitter.emit('error', new Error(`broker returned an invalid answer result for ${id}`))\n\t\t\treturn undefined\n\t\t}\n\t\tif (parsed.success) return undefined\n\t\tconst error = parsed.error\n\t\tif (!isRecord(error) || !isString(error.reason)) {\n\t\t\tthis.#emitter.emit('error', new Error(`broker returned an invalid answer error for ${id}`))\n\t\t\treturn undefined\n\t\t}\n\t\tif (error.reason === 'unknown') return undefined\n\t\tif (error.reason === 'rejected' && arrayOf(isFieldError)(error.errors)) return error.errors\n\t\tthis.#emitter.emit('error', new Error(`broker returned an invalid answer refusal for ${id}`))\n\t\treturn undefined\n\t}\n\n\t#expire(id: string): void {\n\t\tconst active = this.#active\n\t\tif (active?.id === id) {\n\t\t\tthis.#active = { ...active, stopped: true }\n\t\t\tthis.#seen.delete(id)\n\t\t\tactive.form.destroy()\n\t\t} else if (this.#queue.delete(id)) this.#seen.delete(id)\n\t\tthis.#emitter.emit('expire', id)\n\t}\n\n\t#interrupt(): void {\n\t\tthis.#queue.clear()\n\t\tthis.#seen.clear()\n\t\tconst active = this.#active\n\t\tif (active === undefined) return\n\t\tthis.#active = { ...active, stopped: true }\n\t\tactive.form.destroy()\n\t}\n\n\t#markDisconnected(): void {\n\t\tif (!this.#connected) return\n\t\tthis.#connected = false\n\t\tthis.#emitter.emit('disconnect')\n\t}\n\n\t#headers(base: Record<string, string>): Record<string, string> {\n\t\tif (this.#token !== undefined) return { ...base, [HEADER_TOKEN]: this.#token }\n\t\treturn { ...base }\n\t}\n\n\t#wait(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst settle = this.#createSettler(resolve)\n\t\t\tthis.#wake = settle\n\t\t\tthis.#backoff = this.#timer(settle, ms)\n\t\t})\n\t}\n\n\t#createSettler(resolve: () => void): () => void {\n\t\treturn () => {\n\t\t\tthis.#backoff = undefined\n\t\t\tthis.#wake = undefined\n\t\t\tresolve()\n\t\t}\n\t}\n}\n","import type {\n\tPendingForm,\n\tPromptInterface,\n\tPromptOptions,\n\tTerminalAnswerError,\n\tTerminalManagerEventMap,\n\tTerminalManagerInterface,\n\tTerminalManagerOptions,\n\tTerminalSnapshot,\n\tTerminalStoreInterface,\n\tTimerHandler,\n} from './types.js'\nimport type { Result } from '@orkestrel/contract'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { FormInterface, FormValues } from '@orkestrel/form'\nimport { TerminalError } from './errors.js'\nimport { createPrompt } from './factories.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { isArray } from '@orkestrel/contract'\n\n/**\n * Registers named {@link PromptInterface} brokers, one per endpoint, so several parties can `ask`\n * forms of each other by name with a `from` → `to` attribution edge on every parked form, and\n * refuses `DEADLOCK` on a transitive cycle across every in-flight ask.\n *\n * @remarks\n * - **Registry.** `add(name, options?)` mints (or, if `name` is already mounted, returns the\n * existing broker unchanged — idempotent, never clobbers a live/parked endpoint). Every mounted\n * broker's `pending` / `answer` / `expire` events are re-emitted on the manager, attributed by\n * `name`.\n * - **`ask`.** The target must already be mounted through {@link add} — `ask` never auto-adds it;\n * rejects `TARGET` for an unknown `to` (listing the known names). Rejects `DEADLOCK` when parking\n * `from → to` would close a cycle over the current in-flight edge set (walked transitively);\n * otherwise parks the caller's live form through the target's broker and returns that form's own\n * `answer` promise. Edge cleanup never alters the value or rejection the caller observes.\n * - **Durable open / save.** `open(name)` restores an EMPTY broker from the `store` (parked\n * Promises are process-bound and never resurrected); `save(name)` persists the endpoint's\n * configured `timeout`.\n * - **Removal.** `remove` drops one endpoint, a batch (the array overload declared first), or every\n * endpoint when called without an argument. It destroys each broker, which expires every form\n * still parked on it. `destroy` is idempotent.\n *\n * @example\n * ```ts\n * const form = createForm({ fields: [{ control: 'text', name: 'name' }] })\n * const manager = new TerminalManager()\n * manager.add('agent')\n * const answer = manager.ask('user', 'agent', form)\n * manager.answer('agent', manager.pending('agent')[0].id, { name: 'Ada' })\n * await answer // { name: 'Ada' }\n * ```\n */\nexport class TerminalManager implements TerminalManagerInterface {\n\treadonly #terminals = new Map<string, PromptInterface>()\n\treadonly #config = new Map<string, PromptOptions>()\n\t// The handlers subscribed on a mounted broker's emitter — kept so `remove` can `off` them\n\t// explicitly (on top of the broker's own `destroy`, which already renders its emitter inert).\n\treadonly #listeners = new Map<\n\t\tstring,\n\t\t{\n\t\t\treadonly pending: (form: PendingForm) => void\n\t\t\treadonly answer: (id: string, values: FormValues) => void\n\t\t\treadonly expire: (id: string) => void\n\t\t}\n\t>()\n\t// In-flight `ask` edges, keyed by the parked form's id — the deadlock graph. `from` asked\n\t// `to`; cleanup on settle (answer / expire / destroy / remove) removes EXACTLY the edge that\n\t// call created.\n\treadonly #edges = new Map<string, { readonly from: string; readonly to: string }>()\n\treadonly #store: TerminalStoreInterface | undefined\n\treadonly #timeout: number | undefined\n\treadonly #timer: TimerHandler | undefined\n\treadonly #cap: number | undefined\n\treadonly #emitter: Emitter<TerminalManagerEventMap>\n\t#destroyed = false\n\n\tconstructor(options?: TerminalManagerOptions) {\n\t\tthis.#store = options?.store\n\t\tthis.#timeout = options?.timeout\n\t\tthis.#timer = options?.timer\n\t\tthis.#cap = options?.cap\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t}\n\n\tget emitter(): EmitterInterface<TerminalManagerEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget count(): number {\n\t\treturn this.#terminals.size\n\t}\n\n\t// === Accessors\n\n\tterminal(name: string): PromptInterface | undefined {\n\t\treturn this.#terminals.get(name)\n\t}\n\n\tterminals(): readonly PromptInterface[] {\n\t\treturn [...this.#terminals.values()]\n\t}\n\n\t// === Registry\n\n\tadd(name: string, options?: PromptOptions): PromptInterface {\n\t\tif (this.#destroyed) throw new TerminalError('DESTROYED', 'manager destroyed')\n\t\tconst existing = this.#terminals.get(name)\n\t\tif (existing !== undefined) return existing\n\t\tconst timeout = options?.timeout ?? this.#timeout\n\t\tconst timer = options?.timer ?? this.#timer\n\t\tconst cap = options?.cap ?? this.#cap\n\t\tconst promptOptions: PromptOptions = {\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t\t...(timeout !== undefined ? { timeout } : {}),\n\t\t\t...(timer !== undefined ? { timer } : {}),\n\t\t\t...(cap !== undefined ? { cap } : {}),\n\t\t}\n\t\tconst broker = createPrompt(promptOptions)\n\t\tconst listeners = {\n\t\t\tpending: this.#createPendingListener(),\n\t\t\tanswer: this.#createAnswerListener(name),\n\t\t\texpire: this.#createExpireListener(name),\n\t\t}\n\t\tbroker.emitter.on('pending', listeners.pending)\n\t\tbroker.emitter.on('answer', listeners.answer)\n\t\tbroker.emitter.on('expire', listeners.expire)\n\t\tthis.#terminals.set(name, broker)\n\t\tthis.#config.set(name, { ...options })\n\t\tthis.#listeners.set(name, listeners)\n\t\treturn broker\n\t}\n\n\t// === Ask\n\n\task(from: string, to: string, form: FormInterface): Promise<FormValues> {\n\t\tconst broker = this.#terminals.get(to)\n\t\tif (broker === undefined) {\n\t\t\tconst known = [...this.#terminals.keys()]\n\t\t\treturn Promise.reject(\n\t\t\t\tnew TerminalError(\n\t\t\t\t\t'TARGET',\n\t\t\t\t\t`unknown terminal '${to}' (known: ${known.length > 0 ? known.join(', ') : 'none'})`,\n\t\t\t\t\t{ to, known },\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\t\tconst cycle = this.#findCycle(from, to)\n\t\tif (cycle !== undefined) {\n\t\t\treturn Promise.reject(\n\t\t\t\tnew TerminalError(\n\t\t\t\t\t'DEADLOCK',\n\t\t\t\t\t`ask ${from} -> ${to} would deadlock: ${cycle.join(' -> ')}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tfrom,\n\t\t\t\t\t\tto,\n\t\t\t\t\t\tpath: cycle,\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\t\tconst id = broker.park(form, { from, to })\n\t\tif (broker.pending(id) !== undefined) {\n\t\t\tthis.#edges.set(id, { from, to })\n\t\t\tform.answer.then(this.#createEdgeClear(id), this.#createEdgeClear(id))\n\t\t}\n\t\treturn form.answer\n\t}\n\n\t// === Pending accessors\n\n\tpending(): readonly PendingForm[]\n\tpending(to: string): readonly PendingForm[]\n\tpending(to?: string): readonly PendingForm[] {\n\t\tif (to !== undefined) {\n\t\t\tconst broker = this.#terminals.get(to)\n\t\t\treturn broker === undefined ? [] : broker.pending()\n\t\t}\n\t\tconst result: PendingForm[] = []\n\t\tfor (const broker of this.#terminals.values()) result.push(...broker.pending())\n\t\treturn result\n\t}\n\n\t// === Answer\n\n\tanswer(to: string, id: string, values: FormValues): Result<FormValues, TerminalAnswerError> {\n\t\tconst broker = this.#terminals.get(to)\n\t\tif (broker === undefined) return { success: false, error: { reason: 'target' } }\n\t\tconst result = broker.answer(id, values)\n\t\tif (result.success) this.#edges.delete(id)\n\t\treturn result\n\t}\n\n\t// === Durable open / save\n\n\tasync open(name: string): Promise<PromptInterface | undefined> {\n\t\tif (this.#destroyed) throw new TerminalError('DESTROYED', 'manager destroyed')\n\t\tconst existing = this.#terminals.get(name)\n\t\tif (existing !== undefined) return existing\n\t\tif (this.#store === undefined) return undefined\n\t\tconst snapshot = await this.#store.get(name)\n\t\tif (this.#destroyed) throw new TerminalError('DESTROYED', 'manager destroyed')\n\t\tif (snapshot === undefined) return undefined\n\t\treturn this.add(name, snapshot.timeout !== undefined ? { timeout: snapshot.timeout } : {})\n\t}\n\n\tasync save(name: string): Promise<boolean> {\n\t\tconst broker = this.#terminals.get(name)\n\t\tif (this.#store === undefined || broker === undefined) return false\n\t\tconst config = this.#config.get(name)\n\t\tconst snapshot: TerminalSnapshot = {\n\t\t\tid: name,\n\t\t\t...(config?.timeout !== undefined ? { timeout: config.timeout } : {}),\n\t\t}\n\t\tawait this.#store.set(snapshot)\n\t\treturn true\n\t}\n\n\t// === Removal (the array overload declared FIRST)\n\n\tremove(names: readonly string[]): boolean\n\tremove(name: string): boolean\n\tremove(): void\n\tremove(names?: string | readonly string[]): boolean | void {\n\t\tif (names === undefined) {\n\t\t\tfor (const name of [...this.#terminals.keys()]) this.#removeOne(name)\n\t\t\treturn\n\t\t}\n\t\tif (isArray(names)) {\n\t\t\tconst removed = Iterator.from(names).reduce(\n\t\t\t\t(result, name) => this.#removeOne(name) && result,\n\t\t\t\ttrue,\n\t\t\t)\n\t\t\treturn removed\n\t\t}\n\t\treturn this.#removeOne(names)\n\t}\n\n\tdestroy(): void {\n\t\tif (this.#destroyed) return\n\t\tthis.#destroyed = true\n\t\tthis.remove()\n\t\tthis.#edges.clear()\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// === Private helpers\n\n\t#createPendingListener(): (form: PendingForm) => void {\n\t\treturn (form) => this.#emitter.emit('pending', form)\n\t}\n\n\t#createAnswerListener(name: string): (id: string, values: FormValues) => void {\n\t\treturn (id, values) => {\n\t\t\tthis.#edges.delete(id)\n\t\t\tthis.#emitter.emit('answer', name, id, values)\n\t\t}\n\t}\n\n\t#createExpireListener(name: string): (id: string) => void {\n\t\treturn (id) => {\n\t\t\tthis.#edges.delete(id)\n\t\t\tthis.#emitter.emit('expire', name, id)\n\t\t}\n\t}\n\n\t#createEdgeClear(id: string): () => void {\n\t\treturn () => {\n\t\t\tthis.#edges.delete(id)\n\t\t}\n\t}\n\n\t// Drop one endpoint: destroy its broker FIRST (its expire loop re-emits `expire` for every\n\t// still-parked form through the manager's listeners — still attached at this point, so\n\t// each settles on the manager emitter too), THEN unsubscribe the manager's listeners and\n\t// remove it from every registry map. `false` when `name` was not mounted.\n\t#removeOne(name: string): boolean {\n\t\tconst broker = this.#terminals.get(name)\n\t\tif (broker === undefined) return false\n\t\tbroker.destroy()\n\t\tconst listeners = this.#listeners.get(name)\n\t\tif (listeners !== undefined) {\n\t\t\tbroker.emitter.off('pending', listeners.pending)\n\t\t\tbroker.emitter.off('answer', listeners.answer)\n\t\t\tbroker.emitter.off('expire', listeners.expire)\n\t\t}\n\t\tthis.#terminals.delete(name)\n\t\tthis.#config.delete(name)\n\t\tthis.#listeners.delete(name)\n\t\tthis.#clearEdges(name)\n\t\treturn true\n\t}\n\n\t#clearEdges(to: string): void {\n\t\tfor (const [id, edge] of this.#edges) {\n\t\t\tif (edge.to === to) this.#edges.delete(id)\n\t\t}\n\t}\n\n\t// Walk the in-flight edge graph forward from `to`, looking for `from` — a hit means parking\n\t// `from -> to` would close a cycle. Returns the closing cycle path (`from` first and last),\n\t// or `undefined` when no cycle would form.\n\t#findCycle(from: string, to: string): readonly string[] | undefined {\n\t\tif (from === to) return [from, to]\n\t\tconst visited = new Set<string>([to])\n\t\tconst queue: Array<readonly string[]> = [[to]]\n\t\twhile (queue.length > 0) {\n\t\t\tconst path = queue.shift()\n\t\t\tif (path === undefined) break\n\t\t\tconst last = path[path.length - 1]\n\t\t\tif (last === undefined) continue\n\t\t\tfor (const edge of this.#edges.values()) {\n\t\t\t\tif (edge.from !== last) continue\n\t\t\t\tif (edge.to === from) return [from, ...path, from]\n\t\t\t\tif (visited.has(edge.to)) continue\n\t\t\t\tvisited.add(edge.to)\n\t\t\t\tqueue.push([...path, edge.to])\n\t\t\t}\n\t\t}\n\t\treturn undefined\n\t}\n}\n","import type { TerminalSnapshot, TerminalStoreInterface } from '../types.js'\n\n/**\n * Implements the in-memory {@link TerminalStoreInterface} — a process-lifetime `Map` of\n * {@link TerminalSnapshot} records keyed by endpoint id, the default store\n * {@link import('../factories.js').createMemoryTerminalStore} builds and the exact twin of\n * {@link import('./DatabaseTerminalStore.js').DatabaseTerminalStore}. It carries no idle expiry and\n * no eviction.\n *\n * @remarks\n * A plain `Map<string, TerminalSnapshot>` — the snapshot is already pure, self-contained CONFIG-only\n * JSON, so the memory tier needs no encoding. There is NO idle-TTL and NO\n * eviction: a persisted config lives until an explicit `delete`. A durable backend (JSON / SQLite /\n * IndexedDB) swaps in through the SAME interface without touching the manager — its\n * driver-pluggable twin is {@link import('./DatabaseTerminalStore.js').DatabaseTerminalStore} (the\n * snapshot as one opaque JSON column).\n *\n * - **`get` resolves the persisted snapshot for an id**, or `undefined` if none is stored.\n * - **`set` inserts / replaces under the snapshot's OWN `id`** (no separate id param).\n * - **`delete` drops a snapshot by id**; an absent id is a no-op (no throw).\n *\n * The public surface is EXACTLY `get` / `set` / `delete` — no extra members, so the class and\n * {@link TerminalStoreInterface} carry the same methods. Hydration is a caller concern: `open` always\n * restores an EMPTY broker — parked Promises are process-bound and never resurrected.\n *\n * @example\n * ```ts\n * import { createMemoryTerminalStore } from '@orkestrel/terminal'\n *\n * const store = createMemoryTerminalStore()\n * await store.set({ id: 'shell', timeout: 5000 }) // persist a config\n * const snapshot = await store.get('shell')\n * await store.delete('shell') // drop it\n * ```\n */\nexport class MemoryTerminalStore implements TerminalStoreInterface {\n\treadonly #snapshots = new Map<string, TerminalSnapshot>()\n\n\t/**\n\t * Resolves the persisted snapshot for `id`.\n\t *\n\t * @param id - The endpoint name the snapshot is keyed by\n\t * @returns The stored snapshot, or `undefined` when none is held\n\t */\n\tget(id: string): Promise<TerminalSnapshot | undefined> {\n\t\treturn Promise.resolve(this.#snapshots.get(id))\n\t}\n\n\t/**\n\t * Inserts or replaces under the snapshot's OWN `id` (no separate id param).\n\t *\n\t * @param snapshot - The config snapshot to persist, carrying its own `id`\n\t * @returns A promise that settles once the snapshot is held\n\t */\n\tset(snapshot: TerminalSnapshot): Promise<void> {\n\t\tthis.#snapshots.set(snapshot.id, snapshot)\n\t\treturn Promise.resolve()\n\t}\n\n\t/**\n\t * Drops a snapshot by id; an absent id is a no-op (no throw).\n\t *\n\t * @param id - The endpoint name to drop\n\t * @returns A promise that settles once the snapshot is gone\n\t */\n\tdelete(id: string): Promise<void> {\n\t\tthis.#snapshots.delete(id)\n\t\treturn Promise.resolve()\n\t}\n}\n","import type { TerminalSnapshot, TerminalSnapshotRow, TerminalStoreInterface } from '../types.js'\nimport type { TableInterface } from '@orkestrel/database'\nimport { isTerminalSnapshot } from '../validators.js'\n\n/**\n * Implements a {@link TerminalStoreInterface} backed by one table of the `databases` layer — an\n * endpoint's durable config state is a row, so persistence reduces to keyed point-access (`get` /\n * `set` / `delete`) over a {@link TableInterface}, the driver-pluggable twin of the plain-`Map`\n * {@link import('./MemoryTerminalStore.js').MemoryTerminalStore}. A stored `snapshot` is narrowed\n * with {@link import('../validators.js').isTerminalSnapshot} on read.\n *\n * @remarks\n * The store is driver-agnostic: it holds a single {@link TableInterface} whose backend (memory,\n * JSON, SQLite, IndexedDB) is chosen by whoever builds it (the factories), so a JSON / SQLite /\n * IndexedDB backend swaps in WITHOUT touching the manager — the same seam as\n * {@link import('./MemoryTerminalStore.js').MemoryTerminalStore}. The driver defaults to memory\n * ({@link import('../factories.js').createDatabaseTerminalStore} passes `createMemoryDriver()`), so\n * it ALSO works in memory out of the box; you opt into the durable plumbing by passing a JSON /\n * SQLite / IndexedDB driver.\n *\n * The {@link TerminalSnapshot} is stored as ONE OPAQUE JSON COLUMN — the table is a row of\n * `{ id; snapshot }` ({@link TerminalSnapshotRow}). The snapshot is already a COMPLETE,\n * self-contained, pure-JSON CONFIG payload (no live broker state), so storing it whole is lossless\n * AND keeps the row type flat (`snapshot` reads back as `unknown`).\n *\n * - **`set(snapshot)` upserts under the snapshot's OWN `id`** (no separate id param) — it writes\n * the row `{ id: snapshot.id, snapshot }`.\n * - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to\n * a {@link TerminalSnapshot} ({@link import('../validators.js').isTerminalSnapshot} — the total\n * guard that narrows an untrusted storage read), or `undefined` if none is stored.\n * - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).\n *\n * There is NO idle-TTL / eviction — a persisted config lives until an explicit `delete`. The public\n * surface is EXACTLY `get` / `set` / `delete` — no extra members, so the class and\n * {@link TerminalStoreInterface} carry the same methods. Hydration stays a caller concern: `open` always restores an EMPTY\n * broker — parked Promises are process-bound and never resurrected.\n *\n * @example\n * ```ts\n * import { createDatabaseTerminalStore } from '@orkestrel/terminal'\n * import { createMemoryDriver } from '@orkestrel/database'\n *\n * const store = createDatabaseTerminalStore(createMemoryDriver()) // a durable driver swaps in here\n * await store.set({ id: 'shell', timeout: 5000 }) // persist the config (one JSON column)\n * const snapshot = await store.get('shell')\n * await store.delete('shell') // drop it\n * ```\n */\nexport class DatabaseTerminalStore implements TerminalStoreInterface {\n\treadonly #table: TableInterface<TerminalSnapshotRow>\n\n\t/**\n\t * Wraps a table as a terminal store.\n\t *\n\t * @param table - The {@link TableInterface} holding the snapshots — its row is the\n\t * {@link TerminalSnapshotRow} `{ id; snapshot }` shape (the snapshot one opaque JSON column)\n\t */\n\tconstructor(table: TableInterface<TerminalSnapshotRow>) {\n\t\tthis.#table = table\n\t}\n\n\t/**\n\t * Resolves the persisted snapshot for `id`, narrowing the opaque JSON column back to a\n\t * `TerminalSnapshot`.\n\t *\n\t * @param id - The endpoint name the row is keyed by\n\t * @returns The stored snapshot, or `undefined` when none is held or the column is off-shape\n\t */\n\tasync get(id: string): Promise<TerminalSnapshot | undefined> {\n\t\tconst row = await this.#table.get(id)\n\t\tif (row === undefined) return undefined\n\t\t// The snapshot crosses back as an untrusted storage read (a structured clone / a JSON row),\n\t\t// so narrow the opaque JSON column with the boundary guard rather than a cast;\n\t\t// a malformed blob resolves `undefined`, never a broken config.\n\t\treturn isTerminalSnapshot(row.snapshot) ? row.snapshot : undefined\n\t}\n\n\t/**\n\t * Inserts or replaces under the snapshot's OWN `id` (no separate id param) — the row is\n\t * `{ id, snapshot }`.\n\t *\n\t * @param snapshot - The config snapshot to persist, carrying its own `id`\n\t * @returns A promise that settles once the row is written\n\t */\n\tasync set(snapshot: TerminalSnapshot): Promise<void> {\n\t\tawait this.#table.set({ id: snapshot.id, snapshot })\n\t}\n\n\t/**\n\t * Drops a snapshot by id; an absent id is a no-op (no throw).\n\t *\n\t * @param id - The endpoint name to drop\n\t * @returns A promise that settles once the row is gone\n\t */\n\tasync delete(id: string): Promise<void> {\n\t\tawait this.#table.remove(id)\n\t}\n}\n","import type {\n\tPromptClientInterface,\n\tPromptClientOptions,\n\tPromptInterface,\n\tPromptOptions,\n\tTerminalManagerInterface,\n\tTerminalManagerOptions,\n\tTerminalSnapshotRow,\n\tTerminalStoreInterface,\n} from './types.js'\nimport type { DriverInterface, TableInterface } from '@orkestrel/database'\nimport { Prompt } from './Prompt.js'\nimport { PromptClient } from './PromptClient.js'\nimport { TerminalManager } from './TerminalManager.js'\nimport { MemoryTerminalStore } from './stores/MemoryTerminalStore.js'\nimport { DatabaseTerminalStore } from './stores/DatabaseTerminalStore.js'\nimport { createDatabase, createMemoryDriver } from '@orkestrel/database'\nimport { rawShape, stringShape } from '@orkestrel/contract'\n\n/**\n * Creates the headless {@link PromptInterface} broker. It parks live forms and applies remote\n * answers to the authoritative instances.\n *\n * @param options - See {@link PromptOptions}\n * @returns A {@link PromptInterface}\n *\n * @remarks\n * The caller awaits the parked form's own `answer`. Timeout, `stop`, or teardown destroys the form,\n * so that promise rejects with the Form package's `ABANDONED` error. Inject `options.timer` to\n * drive expiry without real time.\n *\n * @example\n * ```ts\n * import { createPrompt } from '@orkestrel/terminal'\n * import { createForm } from '@orkestrel/form'\n *\n * const prompt = createPrompt()\n * const form = createForm({ fields: [{ control: 'text', name: 'name' }] })\n * const id = prompt.park(form)\n * prompt.answer(id, { name: 'Ada' })\n * ```\n */\nexport function createPrompt(options?: PromptOptions): PromptInterface {\n\treturn new Prompt(options)\n}\n\n/**\n * Creates the SSE prompt {@link PromptClientInterface} bridge — it connects to a remote broker's\n * SSE endpoint, dispatches each received form to a local\n * {@link import('./types.js').TerminalInterface}, and POSTs the answer back. Universal — `fetch`\n * and SSE are web standards.\n *\n * @param options - See {@link PromptClientOptions} (`url` + `terminal` required)\n * @returns A {@link PromptClientInterface}\n *\n * @remarks\n * - **Connect + reconnect.** `await client.connect()` streams remote prompts until the stream\n * ends; it reconnects with the `delay` backoff unless `reconnect` is `false` / the client was\n * `destroy`ed. Inject `options.fetch` (a scripted `fetch`) and `options.timer` to drive it\n * deterministically in tests — no real network.\n * - **Wire narrowing.** Every decoded prompt is guard-narrowed before dispatch (never an `as`).\n *\n * @example\n * ```ts\n * import { createPromptClient } from '@orkestrel/terminal'\n *\n * const client = createPromptClient({ url: 'http://host/prompts', terminal })\n * await client.connect()\n * ```\n */\nexport function createPromptClient(options: PromptClientOptions): PromptClientInterface {\n\treturn new PromptClient(options)\n}\n\n/**\n * Creates the multi-endpoint {@link TerminalManager} — a named registry of {@link PromptInterface}\n * brokers so several parties can `ask` forms of each other by name, with a transitive cycle check\n * that refuses `DEADLOCK` across every in-flight ask.\n *\n * @param options - See {@link TerminalManagerOptions}\n * @returns A {@link TerminalManager}\n *\n * @example\n * ```ts\n * import { createTerminalManager } from '@orkestrel/terminal'\n *\n * const manager = createTerminalManager()\n * manager.add('agent')\n * ```\n */\nexport function createTerminalManager(options?: TerminalManagerOptions): TerminalManagerInterface {\n\treturn new TerminalManager(options)\n}\n\n/**\n * Creates the in-memory {@link TerminalStoreInterface} — a process-lifetime `Map` of endpoint\n * config snapshots, the default store backing a {@link TerminalManagerInterface}'s `open` / `save`.\n *\n * @returns A {@link TerminalStoreInterface}\n *\n * @example\n * ```ts\n * import { createMemoryTerminalStore } from '@orkestrel/terminal'\n *\n * const store = createMemoryTerminalStore()\n * ```\n */\nexport function createMemoryTerminalStore(): TerminalStoreInterface {\n\treturn new MemoryTerminalStore()\n}\n\n/**\n * Creates a {@link TerminalStoreInterface} backed by one table of the `databases` layer — the\n * driver-pluggable twin of {@link createMemoryTerminalStore}, storing each endpoint's config\n * snapshot as one opaque JSON column. The default driver is an in-memory `@orkestrel/database`\n * driver.\n *\n * @param driver - The {@link DriverInterface} backing the table (default an in-memory driver)\n * @returns A {@link TerminalStoreInterface}\n *\n * @example\n * ```ts\n * import { createDatabaseTerminalStore } from '@orkestrel/terminal'\n *\n * const store = createDatabaseTerminalStore() // in-memory by default\n * ```\n */\nexport function createDatabaseTerminalStore(\n\tdriver: DriverInterface = createMemoryDriver(),\n): TerminalStoreInterface {\n\t// The snapshot is stored as ONE OPAQUE JSON column (`rawShape`), so the row infers FLAT —\n\t// `{ id: string; snapshot: unknown }` = TerminalSnapshotRow.\n\tconst columns = { id: stringShape(), snapshot: rawShape({}) }\n\tconst database = createDatabase({ driver, tables: { terminals: columns } })\n\tconst table: TableInterface<TerminalSnapshotRow> = database.table('terminals')\n\treturn new DatabaseTerminalStore(table)\n}\n"],"mappings":"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"}