@orkestrel/terminal 0.0.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["#timeout","#timer","#parked","#emitter","#park","#destroyed","#expire","#terminal","#token","#reconnect","#delay","#fetch","#timer","#emitter","#connected","#destroyed","#connecting","#stream","#markDisconnected","#wait","#controller","#backoff","#wake","#warnedInsecureToken","#headers","#handle","#dispatch","#post"],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/helpers.ts","../../../src/core/Prompt.ts","../../../src/core/PromptClient.ts","../../../src/core/factories.ts"],"sourcesContent":["// The constant DATA the pure prompt core reads — the control-byte → key-name decode table\n// {@link parseKey} consults, the default mask, the validation regex patterns the rule engine\n// tests against, the prompt-view icon glyphs, and the default rule error messages. UPPER_SNAKE,\n// `Object.freeze`d, every member exported (AGENTS §5). Control bytes are built with\n// `String.fromCharCode` so no raw control character appears in source (the console-module idiom).\n\n// === Control bytes (named, no raw control characters in source)\n\n/** Carriage return (`\\r`, U+000D) — Enter on most terminals. */\nexport const RETURN = String.fromCharCode(13)\n/** Line feed (`\\n`, U+000A) — Enter on some terminals / pasted input. */\nexport const NEWLINE = String.fromCharCode(10)\n/** Tab (`\\t`, U+0009). */\nexport const TAB = String.fromCharCode(9)\n/** Escape (ESC, U+001B) — the lone byte, and the lead byte of every CSI / SS3 sequence. */\nexport const ESCAPE = String.fromCharCode(27)\n/** Backspace (BS, U+0008) — Ctrl+H / some terminals' Backspace. */\nexport const BACKSPACE = String.fromCharCode(8)\n/** Delete (DEL, U+007F) — the usual Backspace byte on a Unix TTY. */\nexport const DELETE = String.fromCharCode(127)\n/** Space (U+0020). */\nexport const SPACE = ' '\n/** Ctrl+C (ETX, U+0003) — interrupt / cancel. */\nexport const CTRL_C = String.fromCharCode(3)\n/** Ctrl+D (EOT, U+0004) — end-of-transmission / finish (the editor's commit key). */\nexport const CTRL_D = String.fromCharCode(4)\n/** Ctrl+U (NAK, U+0015) — clear the current line. */\nexport const CTRL_U = String.fromCharCode(21)\n/** Ctrl+A (SOH, U+0001) — move to start of line. */\nexport const CTRL_A = String.fromCharCode(1)\n/** Ctrl+E (ENQ, U+0005) — move to end of line. */\nexport const CTRL_E = String.fromCharCode(5)\n\n/**\n * The Control Sequence Introducer lead (`ESC[`) for the navigation keys — the prefix of the\n * arrow / home / end / delete sequences {@link SEQUENCE_NAMES} is keyed by. Named `KEY_CSI`\n * (not `CSI`) so it never collides with the console module's SGR `CSI` (both barrel through\n * `@src/core`).\n */\nexport const KEY_CSI = `${ESCAPE}[`\n/** The Single Shift Three lead (`ESCO`) — the alternate arrow-key prefix some terminals emit (`ESC O A`). */\nexport const KEY_SS3 = `${ESCAPE}O`\n\n/**\n * The exact escape SEQUENCE → canonical key NAME table {@link import('./helpers.js').parseKey}\n * consults for the navigation / editing keys. Covers BOTH the CSI form (`ESC[A`…) and the SS3\n * form (`ESCOA`…) of the four arrows, plus the `home` / `end` / `delete` CSI sequences (with\n * their numeric-tilde variants). The source of truth for the multi-byte key 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[`${KEY_CSI}A`]: 'up',\n\t[`${KEY_CSI}B`]: 'down',\n\t[`${KEY_CSI}C`]: 'right',\n\t[`${KEY_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[`${KEY_CSI}H`]: 'home',\n\t[`${KEY_CSI}F`]: 'end',\n\t[`${KEY_CSI}1~`]: 'home',\n\t[`${KEY_CSI}4~`]: 'end',\n\t[`${KEY_CSI}3~`]: 'delete',\n\t[`${KEY_CSI}7~`]: 'home',\n\t[`${KEY_CSI}8~`]: 'end',\n})\n\n/**\n * The single control BYTE → key descriptor table {@link import('./helpers.js').parseKey}\n * consults for the one-byte keys. Each entry carries the canonical `name` and whether it is a\n * `ctrl` combination. The source of truth for the single-byte key decode; frozen.\n *\n * @remarks\n * `return` / `newline` map to `return` (one canonical Enter name); `delete` / `backspace` both\n * map to `backspace` (the two Backspace bytes); the Ctrl combos (`c` / `d` / `u` / `a` / `e`)\n * carry `ctrl: true` so a reducer can match `key.ctrl && key.name === 'c'`. `escape` / `tab` /\n * `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[TAB]: Object.freeze({ name: 'tab', ctrl: false }),\n\t[ESCAPE]: 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/** The default mask glyph a {@link import('./types.js').PasswordState} renders each input character as — `*`. */\nexport const DEFAULT_MASK = '*'\n\n// === Validation patterns\n\n/** Matches an email address — a non-trivial `local@domain.tld` shape. The `email` rule tests against this. */\nexport const EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\n/** Matches an HTTP(S) URL. The `url` rule tests against this. */\nexport const URL_PATTERN = /^https?:\\/\\/.+/\n\n/** Matches a numeric value (integer or decimal, optional sign). The `numeric` rule tests against this. */\nexport const NUMERIC_PATTERN = /^-?\\d+(\\.\\d+)?$/\n\n/** Matches an integer (optional sign). The `integer` rule tests against this. */\nexport const INTEGER_PATTERN = /^-?\\d+$/\n\n/** Matches an alphanumeric string (letters and digits only). The `alphanumeric` rule tests against this. */\nexport const ALPHANUMERIC_PATTERN = /^[a-zA-Z0-9]+$/\n\n// === Default rule error messages\n\n/**\n * Each built-in validation rule's default error message — what the composed {@link\n * import('./types.js').Validator} returns when that rule fails (the `minimum` / `maximum`\n * messages are interpolated with the configured length at build time). Frozen; the source of\n * truth for the rule-failure copy.\n */\nexport const RULE_MESSAGES = Object.freeze({\n\trequired: 'This field is required',\n\tminimum: 'Must be at least {count} characters',\n\tmaximum: 'Must be at most {count} characters',\n\tpattern: 'Must match pattern: {pattern}',\n\temail: 'Must be a valid email address',\n\turl: 'Must be a valid URL',\n\tnumeric: 'Must be a numeric value',\n\tinteger: 'Must be an integer',\n\talphanumeric: 'Must contain only letters and digits',\n\tinvalid: 'Invalid input',\n})\n\n// === Prompt-view icons (glyphs only — the styler colors them at render time)\n\n/**\n * The prompt-view icon glyphs the reducers render the prompt line and choice rows with. PLAIN\n * glyphs — color is applied by the {@link import('./types.js').PromptState}'s\n * {@link import('@orkestrel/console').StylerInterface} at render time, never baked into the\n * constant (AGENTS — styling orthogonal to data; the rework fixes the terminal's ANSI-in-the-icon).\n * 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// === Broker + SSE-bridge defaults (T-b)\n\n/** How long (ms) the {@link import('./types.js').PromptInterface} broker parks an unanswered prompt before it expires — 5 minutes. */\nexport const DEFAULT_PROMPT_TIMEOUT_MS = 300_000\n\n/** 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 * The SSE `event:` names the broker emits and the {@link import('./types.js').PromptClient}\n * dispatches on. Frozen; the source of truth for the wire event vocabulary.\n *\n * @remarks\n * - `pending` — a serialized {@link import('./types.js').PendingPrompt} to dispatch + answer.\n * - `expire` — an `{ id }` payload: the broker expired a parked prompt (the client drops it).\n * - `shutdown` — 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\tshutdown: 'shutdown',\n})\n\n/** The auth-token request header the {@link import('./types.js').PromptClient} sends when a `token` is configured. */\nexport const HEADER_TOKEN = 'x-orkestrel-token'\n\n/** The `Accept` header value that opens the broker's SSE stream. */\nexport const ACCEPT_EVENT_STREAM = 'text/event-stream'\n\n/**\n * The maximum number of characters the {@link import('./types.js').PromptClient} 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'\n\n// AGENTS §12: a real error type, not a sentinel. A parked broker prompt that is never\n// answered (its `timeout` elapsed, or the broker was `destroy`ed while it was still pending)\n// REJECTS its Promise with a `TerminalError` carrying a machine-readable `code`, so an\n// `await prompt.input(...)` caller branches on `error.code` rather than parsing the message.\n// The optional `context` bag names the offending prompt id. The guard narrows with `instanceof`,\n// mirroring the agents-module errors.\n\n/**\n * An error a {@link import('./Prompt.js').Prompt} broker rejects a parked prompt's Promise with.\n *\n * @remarks\n * Carries a {@link TerminalErrorCode} and an optional `context` bag (the prompt `id`). Thrown —\n * as a Promise rejection on the awaited prompt call — when a parked prompt is not answered before\n * its `timeout`, or when the broker is `destroy`ed while the prompt is still `pending` (both\n * `EXPIRE`); or when the user aborts an interactive server-`Terminal` prompt with ctrl-c\n * (`CANCEL`). Narrow a caught value with {@link isTerminalError} and branch on `error.code`.\n */\nexport class TerminalError extends Error {\n\t/** The machine-readable condition — see {@link TerminalErrorCode}. */\n\treadonly code: TerminalErrorCode\n\t/** An optional context bag naming the offending prompt id. */\n\treadonly context?: Readonly<Record<string, unknown>>\n\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\tthis.context = context\n\t}\n}\n\n/**\n * Narrow an unknown caught value to a {@link TerminalError}.\n *\n * @param value - The value to test (typically a `catch` binding or a rejected prompt call)\n * @returns `true` when `value` is a {@link TerminalError}\n *\n * @example\n * ```ts\n * try {\n * \tconst name = await prompt.input({ message: 'Your name' })\n * } catch (error) {\n * \tif (isTerminalError(error) && error.code === 'EXPIRE') retryLater()\n * }\n * ```\n */\nexport function isTerminalError(value: unknown): value is TerminalError {\n\treturn value instanceof TerminalError\n}\n","import type {\n\tCheckboxChoice,\n\tCheckboxOptions,\n\tCheckboxState,\n\tConfirmOptions,\n\tConfirmState,\n\tEditorOptions,\n\tEditorState,\n\tFetchInit,\n\tInputOptions,\n\tInputState,\n\tKeyEvent,\n\tPasswordOptions,\n\tPasswordState,\n\tPendingPrompt,\n\tPendingPromptStatus,\n\tPromptChoice,\n\tPromptFormInterface,\n\tPromptStep,\n\tPromptType,\n\tSelectOptions,\n\tSelectState,\n\tTimerCancel,\n\tValidationRules,\n\tValidator,\n} from './types.js'\nimport type { Guard } from '@orkestrel/contract'\nimport type { StylerInterface } from '@orkestrel/console'\nimport {\n\tALPHANUMERIC_PATTERN,\n\tCONTROL_NAMES,\n\tDEFAULT_MASK,\n\tEMAIL_PATTERN,\n\tINTEGER_PATTERN,\n\tNUMERIC_PATTERN,\n\tPROMPT_ICONS,\n\tRULE_MESSAGES,\n\tSEQUENCE_NAMES,\n\tURL_PATTERN,\n} from './constants.js'\nimport {\n\tisBoolean,\n\tisNonEmptyString,\n\tisNumber,\n\tisRecord,\n\tisString,\n\tliteralOf,\n\trecordOf,\n} from '@orkestrel/contract'\nimport { createStyler, STATUS_ICONS, stripControls } from '@orkestrel/console'\n\n// The PURE prompt core implementation — all EXPORTED, all pure, all unit-tested (AGENTS §5):\n// the key decoder, the validation rule engine, the choice normalizers, the per-prompt view\n// renderers, and the six `create*State` factories + `*Reduce` reducers. No `node:*`, no I/O,\n// no events. A reducer is a total `(state, key) → PromptStep`; the view is rendered through the\n// state's console {@link StylerInterface} (the ONE style engine), so the impure server driver\n// (T-c) only feeds bytes in and writes the rendered view out.\n\n// === Key decoding\n\n/**\n * Decode 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\n * ({@link CONTROL_NAMES}) and escape sequences ({@link SEQUENCE_NAMES}), falling back to a\n * single printable character. An unrecognized sequence yields `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`) is looked up in\n * {@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 `name: ''` —\n * 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('\\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\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.\n\treturn { name: '', sequence, ctrl: false, meta: false, shift: false }\n}\n\n/** Whether a single character is a printable (non-control) character — used by {@link parseKey}'s char fallback. */\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// === Validation engine\n\n/**\n * Evaluate ONE built-in validation rule against `input`, returning its error message when the\n * rule fails or `undefined` when it passes. The atomic check {@link buildRuleValidator} wraps\n * into a {@link Validator}. Pure.\n *\n * @remarks\n * A function `check` is the custom-override path: it is called and its `true` ⇒ pass, a string\n * ⇒ that message, anything else ⇒ the generic {@link RULE_MESSAGES.invalid}. A primitive `check`\n * runs the named built-in: `required` (non-empty trimmed), `minimum` / `maximum` (length\n * bounds, the message interpolated with the count), `pattern` (a regex source), and the\n * `email` / `url` / `numeric` / `integer` / `alphanumeric` pattern tests.\n *\n * @param rule - The rule name (`'required'`, `'minimum'`, …)\n * @param check - The configured value (a primitive toggle / bound / pattern, or a custom {@link Validator})\n * @param input - The input string to test\n * @returns The error message when the rule fails, else `undefined`\n */\nexport function evaluateRule(\n\trule: string,\n\tcheck: boolean | number | string | Validator,\n\tinput: string,\n): string | undefined {\n\t// `typeof` (not the broad `isFunction` guard) so the union narrows to the precise `Validator`.\n\tif (typeof check === 'function') {\n\t\tconst result = check(input)\n\t\tif (result === true) return undefined\n\t\treturn isString(result) ? result : RULE_MESSAGES.invalid\n\t}\n\n\tswitch (rule) {\n\t\tcase 'required':\n\t\t\tif (check === true && input.trim().length === 0) return RULE_MESSAGES.required\n\t\t\tbreak\n\t\tcase 'minimum':\n\t\t\tif (isNumber(check) && [...input].length < check)\n\t\t\t\treturn RULE_MESSAGES.minimum.replace('{count}', String(check))\n\t\t\tbreak\n\t\tcase 'maximum':\n\t\t\tif (isNumber(check) && [...input].length > check)\n\t\t\t\treturn RULE_MESSAGES.maximum.replace('{count}', String(check))\n\t\t\tbreak\n\t\tcase 'pattern':\n\t\t\tif (isString(check)) {\n\t\t\t\tlet compiled: RegExp | undefined\n\t\t\t\ttry {\n\t\t\t\t\tcompiled = new RegExp(check)\n\t\t\t\t} catch {\n\t\t\t\t\treturn RULE_MESSAGES.pattern.replace('{pattern}', check)\n\t\t\t\t}\n\t\t\t\tif (!compiled.test(input)) return RULE_MESSAGES.pattern.replace('{pattern}', check)\n\t\t\t}\n\t\t\tbreak\n\t\tcase 'email':\n\t\t\tif (check === true && !EMAIL_PATTERN.test(input)) return RULE_MESSAGES.email\n\t\t\tbreak\n\t\tcase 'url':\n\t\t\tif (check === true && !URL_PATTERN.test(input)) return RULE_MESSAGES.url\n\t\t\tbreak\n\t\tcase 'numeric':\n\t\t\tif (check === true && !NUMERIC_PATTERN.test(input)) return RULE_MESSAGES.numeric\n\t\t\tbreak\n\t\tcase 'integer':\n\t\t\tif (check === true && !INTEGER_PATTERN.test(input)) return RULE_MESSAGES.integer\n\t\t\tbreak\n\t\tcase 'alphanumeric':\n\t\t\tif (check === true && !ALPHANUMERIC_PATTERN.test(input)) return RULE_MESSAGES.alphanumeric\n\t\t\tbreak\n\t}\n\n\treturn undefined\n}\n\n/** Wrap a named rule + its primitive check into a {@link Validator} (returns `true` or the rule's message). */\nexport function buildRuleValidator(rule: string, check: boolean | number | string): Validator {\n\treturn (input: string) => evaluateRule(rule, check, input) ?? true\n}\n\n/**\n * Append a rule-backed {@link Validator} to `validators` when the rule is enabled — a `false` /\n * `undefined` `check` is skipped, a function `check` is added verbatim (the custom override), and\n * a primitive `check` is wrapped via {@link buildRuleValidator}. Mutates `validators` in place.\n */\nexport function appendRule(\n\tvalidators: Validator[],\n\trule: string,\n\tcheck: boolean | number | string | Validator | undefined,\n): void {\n\tif (check === undefined || check === false) return\n\tif (typeof check === 'function') {\n\t\tvalidators.push(check)\n\t\treturn\n\t}\n\tvalidators.push(buildRuleValidator(rule, check))\n}\n\n/**\n * Compose several {@link Validator}s into ONE short-circuiting validator — it runs them in order\n * and returns the FIRST error message, or `true` when all pass. The empty composition always\n * passes.\n */\nexport function composeValidators(...validators: Validator[]): Validator {\n\treturn (input: string) => {\n\t\tfor (const validator of validators) {\n\t\t\tconst result = validator(input)\n\t\t\tif (result !== true) return result\n\t\t}\n\t\treturn true\n\t}\n}\n\n/**\n * Compile a {@link Validator} or declarative {@link ValidationRules} (or nothing) into ONE\n * composed {@link Validator}. A bare validator passes through; rules are appended in the fixed\n * order (required → minimum → maximum → pattern → email → url → numeric → integer → alphanumeric\n * → custom) and composed; absent / empty input yields an always-passing validator. Pure.\n *\n * @remarks\n * Unlike a prior variant (which returned `Validator | undefined`), this ALWAYS returns a\n * `Validator` — an absent or empty rule set yields a validator that returns `true` for every\n * input. That keeps a prompt's state unconditional (it always holds a real validator to apply on\n * submit), with no `undefined` branch at the call site.\n *\n * @param validate - A custom {@link Validator}, a {@link ValidationRules} bag, or `undefined`\n * @returns The composed {@link Validator} (always-passing when nothing was supplied)\n *\n * @example\n * ```ts\n * const v = resolveValidation({ required: true, minimum: 3 })\n * v('') // 'This field is required'\n * v('ab') // 'Must be at least 3 characters'\n * v('abc') // true\n * ```\n */\nexport function resolveValidation(validate?: Validator | ValidationRules): Validator {\n\tif (validate === undefined) return passing\n\t// `typeof` (not the broad `isFunction` guard) so the union narrows to the precise `Validator`.\n\tif (typeof validate === 'function') return validate\n\n\tconst validators: Validator[] = []\n\tappendRule(validators, 'required', validate.required)\n\tappendRule(validators, 'minimum', validate.minimum)\n\tappendRule(validators, 'maximum', validate.maximum)\n\tappendRule(validators, 'pattern', validate.pattern)\n\tappendRule(validators, 'email', validate.email)\n\tappendRule(validators, 'url', validate.url)\n\tappendRule(validators, 'numeric', validate.numeric)\n\tappendRule(validators, 'integer', validate.integer)\n\tappendRule(validators, 'alphanumeric', validate.alphanumeric)\n\tif (typeof validate.custom === 'function') validators.push(validate.custom)\n\n\tif (validators.length === 0) return passing\n\treturn composeValidators(...validators)\n}\n\n/** The always-passing {@link Validator} — the resolved validator when no rules were supplied. */\nexport function passing(_input: string): true {\n\treturn true\n}\n\n// === Choice normalization\n\n/** Normalize a select choice input into a full {@link PromptChoice} (a bare string becomes both name and value). */\nexport function normalizeChoice(choice: string | PromptChoice): PromptChoice {\n\treturn isString(choice) ? { name: choice, value: choice } : choice\n}\n\n/** Normalize a checkbox choice input into a full {@link CheckboxChoice} (a bare string becomes both name and value). */\nexport function normalizeCheckboxChoice(choice: string | CheckboxChoice): CheckboxChoice {\n\treturn isString(choice) ? { name: choice, value: choice } : choice\n}\n\n// === Shared view helpers\n\n/** The styled prompt-message header (`? message`) — the leading line every active prompt view shares. */\nexport function promptHeader(styler: StylerInterface, message: string): string {\n\treturn `${styler.cyan(PROMPT_ICONS.question)} ${styler.bold(message)}`\n}\n\n/** The styled submit line (`✔ message`) — the committed header an interactive prompt shows once resolved. */\nexport function submitHeader(styler: StylerInterface, message: string): string {\n\treturn `${styler.green(STATUS_ICONS.success)} ${styler.bold(message)}`\n}\n\n/** The styled error line (`✖ message`) — appended beneath a prompt view when the last submit failed validation. */\nexport function errorLine(styler: StylerInterface, message: string): string {\n\treturn `${styler.red(STATUS_ICONS.error)} ${styler.red(message)}`\n}\n\n// === Input prompt\n\n/** Build the initial {@link InputState} from {@link InputOptions} — resolving the validator + styler, seeding an empty value. */\nexport function createInputState(options: InputOptions): InputState {\n\treturn {\n\t\tmessage: options.message,\n\t\tdefault: options.default ?? '',\n\t\tvalidator: resolveValidation(options.validate),\n\t\tstyler: options.styler ?? createStyler(),\n\t\tvalue: '',\n\t}\n}\n\n/** Render an {@link InputState} as a styled view — the header, the typed value (or dimmed default hint), and any error. */\nexport function inputView(state: InputState): string {\n\tconst shown = state.value.length > 0 ? state.value : state.styler.dim(state.default)\n\tconst head = `${promptHeader(state.styler, state.message)} ${state.styler.cyan(PROMPT_ICONS.pointer)} ${shown}`\n\treturn state.error === undefined ? head : `${head}\\n${errorLine(state.styler, state.error)}`\n}\n\n/**\n * Advance 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 submits (the empty line falls back to the default) through the validator — an\n * invalid submit stays active with the error in the view.\n */\nexport function inputReduce(state: InputState, key: KeyEvent): PromptStep<string, InputState> {\n\tif (key.ctrl && key.name === 'c') return { state, view: inputView(state), status: 'cancel' }\n\n\tif (key.name === 'return') {\n\t\tconst answer = state.value.length > 0 ? state.value : state.default\n\t\tconst result = state.validator(answer)\n\t\tif (result !== true) {\n\t\t\tconst next: InputState = { ...state, error: result }\n\t\t\treturn { state: next, view: inputView(next), status: 'active' }\n\t\t}\n\t\tconst next: InputState = { ...state, value: answer, error: undefined }\n\t\treturn {\n\t\t\tstate: next,\n\t\t\tview: `${submitHeader(state.styler, state.message)} ${state.styler.dim(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: inputView(state), status: 'active' }\n\tconst next: InputState = { ...state, value, error: undefined }\n\treturn { state: next, view: inputView(next), status: 'active' }\n}\n\n// === Password prompt\n\n/** Build the initial {@link PasswordState} from {@link PasswordOptions} — resolving the validator + styler + mask. */\nexport function createPasswordState(options: PasswordOptions): PasswordState {\n\treturn {\n\t\tmessage: options.message,\n\t\tmask: options.mask ?? DEFAULT_MASK,\n\t\tvalidator: resolveValidation(options.validate),\n\t\tstyler: options.styler ?? createStyler(),\n\t\tvalue: '',\n\t}\n}\n\n/** Render a {@link PasswordState} as a styled view — the header, the value masked to `mask` repeated, and any error. */\nexport function passwordView(state: PasswordState): string {\n\tconst masked = state.mask.repeat(state.value.length)\n\tconst head = `${promptHeader(state.styler, state.message)} ${state.styler.cyan(PROMPT_ICONS.pointer)} ${masked}`\n\treturn state.error === undefined ? head : `${head}\\n${errorLine(state.styler, state.error)}`\n}\n\n/**\n * Advance a password prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`\n * reducer. Identical line-editing to {@link inputReduce} (printable extends, backspace shrinks,\n * ctrl-u clears, ctrl-c cancels) but the view masks the value; return submits through the\n * validator (no default fallback — a password has no echoed default).\n */\nexport function passwordReduce(\n\tstate: PasswordState,\n\tkey: KeyEvent,\n): PromptStep<string, PasswordState> {\n\tif (key.ctrl && key.name === 'c') return { state, view: passwordView(state), status: 'cancel' }\n\n\tif (key.name === 'return') {\n\t\tconst result = state.validator(state.value)\n\t\tif (result !== true) {\n\t\t\tconst next: PasswordState = { ...state, error: result }\n\t\t\treturn { state: next, view: passwordView(next), status: 'active' }\n\t\t}\n\t\treturn {\n\t\t\tstate: { ...state, error: undefined },\n\t\t\tview: `${submitHeader(state.styler, state.message)} ${state.styler.dim(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: passwordView(state), status: 'active' }\n\tconst next: PasswordState = { ...state, value, error: undefined }\n\treturn { state: next, view: passwordView(next), status: 'active' }\n}\n\n// === Confirm prompt\n\n/** Build the initial {@link ConfirmState} from {@link ConfirmOptions} — defaulting the answer to `false`. */\nexport function createConfirmState(options: ConfirmOptions): ConfirmState {\n\treturn {\n\t\tmessage: options.message,\n\t\tdefault: options.default ?? false,\n\t\tstyler: options.styler ?? createStyler(),\n\t}\n}\n\n/** Render a {@link ConfirmState} as a styled view — the header plus a `(Y/n)` hint with the default letter emphasized. */\nexport function confirmView(state: ConfirmState): string {\n\tconst hint = state.default\n\t\t? `${state.styler.green('Y')}${state.styler.dim('/n')}`\n\t\t: `${state.styler.dim('y/')}${state.styler.green('N')}`\n\treturn `${promptHeader(state.styler, state.message)} ${state.styler.dim('(')}${hint}${state.styler.dim(')')}`\n}\n\n/**\n * Advance 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 */\nexport function confirmReduce(\n\tstate: ConfirmState,\n\tkey: KeyEvent,\n): PromptStep<boolean, ConfirmState> {\n\tif (key.ctrl && key.name === 'c') return { state, view: confirmView(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: confirmView(state), status: 'active' }\n\treturn {\n\t\tstate,\n\t\tview: `${submitHeader(state.styler, state.message)} ${state.styler.dim(answer ? 'yes' : 'no')}`,\n\t\tstatus: 'submit',\n\t\tvalue: answer,\n\t}\n}\n\n// === Select prompt\n\n/** Build the initial {@link SelectState} from {@link SelectOptions} — normalizing choices and pre-focusing the default. */\nexport function createSelectState(options: SelectOptions): SelectState {\n\tconst choices = options.choices.map(normalizeChoice)\n\tconst index = choices.findIndex((choice) => choice.value === options.default)\n\treturn {\n\t\tmessage: options.message,\n\t\tchoices,\n\t\tstyler: options.styler ?? createStyler(),\n\t\tfocused: index >= 0 ? index : 0,\n\t}\n}\n\n/** Render a {@link SelectState} as a MULTI-LINE styled view — the header followed by one row per choice, the focused row marked. */\nexport function selectView(state: SelectState): string {\n\tconst lines = state.choices.map((choice, index) => {\n\t\tconst active = index === state.focused\n\t\tconst pointer = active ? state.styler.cyan(PROMPT_ICONS.pointer) : ' '\n\t\tconst marker = active\n\t\t\t? state.styler.green(PROMPT_ICONS.selected)\n\t\t\t: state.styler.dim(PROMPT_ICONS.dot)\n\t\tconst label = active ? state.styler.bold(choice.name) : choice.name\n\t\tconst description =\n\t\t\tchoice.description === undefined ? '' : ` ${state.styler.dim(choice.description)}`\n\t\treturn `${pointer} ${marker} ${label}${description}`\n\t})\n\treturn [promptHeader(state.styler, state.message), ...lines].join('\\n')\n}\n\n/**\n * Advance 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 */\nexport function selectReduce(state: SelectState, key: KeyEvent): PromptStep<string, SelectState> {\n\tif (key.ctrl && key.name === 'c') return { state, view: selectView(state), status: 'cancel' }\n\n\tconst count = state.choices.length\n\tif (count === 0) return { state, view: selectView(state), status: 'active' }\n\n\tif (key.name === 'up' || key.name === 'k') {\n\t\tconst next: SelectState = { ...state, focused: (state.focused - 1 + count) % count }\n\t\treturn { state: next, view: selectView(next), status: 'active' }\n\t}\n\tif (key.name === 'down' || key.name === 'j') {\n\t\tconst next: SelectState = { ...state, focused: (state.focused + 1) % count }\n\t\treturn { state: next, view: selectView(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: `${submitHeader(state.styler, state.message)} ${state.styler.dim(choice?.name ?? '')}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue,\n\t\t}\n\t}\n\treturn { state, view: selectView(state), status: 'active' }\n}\n\n// === Checkbox prompt\n\n/** Build the initial {@link CheckboxState} from {@link CheckboxOptions} — normalizing choices, seeding the checked set, carrying min/max. */\nexport function createCheckboxState(options: CheckboxOptions): CheckboxState {\n\tconst choices = options.choices.map(normalizeCheckboxChoice)\n\tconst checked = choices.reduce<number[]>((indices, choice, index) => {\n\t\tif (choice.checked === true) indices.push(index)\n\t\treturn indices\n\t}, [])\n\treturn {\n\t\tmessage: options.message,\n\t\tchoices,\n\t\tstyler: options.styler ?? createStyler(),\n\t\tfocused: 0,\n\t\tchecked,\n\t\tmin: options.min,\n\t\tmax: options.max,\n\t}\n}\n\n/** Render a {@link CheckboxState} as a MULTI-LINE styled view — the header, one box per choice (focused + checked marked), a count, and any error. */\nexport function checkboxView(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 ? state.styler.cyan(PROMPT_ICONS.pointer) : ' '\n\t\tconst box = ticked\n\t\t\t? state.styler.green(PROMPT_ICONS.checked)\n\t\t\t: state.styler.dim(PROMPT_ICONS.unchecked)\n\t\tconst label = active ? state.styler.bold(choice.name) : choice.name\n\t\tconst description =\n\t\t\tchoice.description === undefined ? '' : ` ${state.styler.dim(choice.description)}`\n\t\treturn `${pointer} ${box} ${label}${description}`\n\t})\n\tconst summary = state.styler.dim(`${state.checked.length} selected`)\n\tconst body = [promptHeader(state.styler, state.message), ...lines, summary].join('\\n')\n\treturn state.error === undefined ? body : `${body}\\n${errorLine(state.styler, state.error)}`\n}\n\n/**\n * Advance 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 — gated by `min` / `max` (an out-of-range count stays active with\n * the reason in the view); ctrl-c cancels.\n */\nexport function checkboxReduce(\n\tstate: CheckboxState,\n\tkey: KeyEvent,\n): PromptStep<readonly string[], CheckboxState> {\n\tif (key.ctrl && key.name === 'c') return { state, view: checkboxView(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: CheckboxState = {\n\t\t\t...state,\n\t\t\tfocused: (state.focused - 1 + count) % count,\n\t\t\terror: undefined,\n\t\t}\n\t\treturn { state: next, view: checkboxView(next), status: 'active' }\n\t}\n\tif ((key.name === 'down' || key.name === 'j') && count > 0) {\n\t\tconst next: CheckboxState = { ...state, focused: (state.focused + 1) % count, error: undefined }\n\t\treturn { state: next, view: checkboxView(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: CheckboxState = { ...state, checked, error: undefined }\n\t\treturn { state: next, view: checkboxView(next), status: 'active' }\n\t}\n\tif (key.name === 'return') {\n\t\tconst error = gateSelection(state.checked.length, state.min, state.max)\n\t\tif (error !== undefined) {\n\t\t\tconst next: CheckboxState = { ...state, error }\n\t\t\treturn { state: next, view: checkboxView(next), status: 'active' }\n\t\t}\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]?.name)\n\t\t\t.filter((name): name is string => name !== undefined)\n\t\t\t.join(', ')\n\t\treturn {\n\t\t\tstate: { ...state, error: undefined },\n\t\t\tview: `${submitHeader(state.styler, state.message)} ${state.styler.dim(summary)}`,\n\t\t\tstatus: 'submit',\n\t\t\tvalue: values,\n\t\t}\n\t}\n\treturn { state, view: checkboxView(state), status: 'active' }\n}\n\n/** Toggle `index` in a readonly index list — copy-on-write, returning the new sorted-by-insertion list. */\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/** The min/max gate for a checkbox submit — the rejection message when `count` is out of range, else `undefined`. */\nexport function gateSelection(count: number, min?: number, max?: number): string | undefined {\n\tif (min !== undefined && count < min)\n\t\treturn `Select at least ${String(min)} option${min === 1 ? '' : 's'}`\n\tif (max !== undefined && count > max)\n\t\treturn `Select no more than ${String(max)} option${max === 1 ? '' : 's'}`\n\treturn undefined\n}\n\n// === Editor prompt\n\n/** Build the initial {@link EditorState} from {@link EditorOptions} — resolving the validator + styler, seeding empty lines. */\nexport function createEditorState(options: EditorOptions): EditorState {\n\treturn {\n\t\tmessage: options.message,\n\t\tdefault: options.default ?? '',\n\t\tvalidator: resolveValidation(options.validate),\n\t\tstyler: options.styler ?? createStyler(),\n\t\tlines: [],\n\t\tcurrent: '',\n\t}\n}\n\n/** Render an {@link EditorState} as a MULTI-LINE styled view — the header (with a Ctrl+D hint), the committed lines, the in-progress line, and any error. */\nexport function editorView(state: EditorState): string {\n\tconst head = `${promptHeader(state.styler, state.message)} ${state.styler.dim('(Ctrl+D to finish)')}`\n\tconst body = [...state.lines, `${state.styler.cyan(PROMPT_ICONS.pointer)} ${state.current}`]\n\tconst view = [head, ...body].join('\\n')\n\treturn state.error === undefined ? view : `${view}\\n${errorLine(state.styler, state.error)}`\n}\n\n/**\n * Advance 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 all lines, falling back to the\n * default when empty) through the validator; ctrl-c cancels. An invalid finish stays active with\n * the error.\n */\nexport function editorReduce(state: EditorState, key: KeyEvent): PromptStep<string, EditorState> {\n\tif (key.ctrl && key.name === 'c') return { state, view: editorView(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\tconst result = state.validator(answer)\n\t\tif (result !== true) {\n\t\t\tconst next: EditorState = { ...state, error: result }\n\t\t\treturn { state: next, view: editorView(next), status: 'active' }\n\t\t}\n\t\treturn {\n\t\t\tstate: { ...state, error: undefined },\n\t\t\tview: `${submitHeader(state.styler, state.message)} ${state.styler.dim(`${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: EditorState = {\n\t\t\t...state,\n\t\t\tlines: [...state.lines, state.current],\n\t\t\tcurrent: '',\n\t\t\terror: undefined,\n\t\t}\n\t\treturn { state: next, view: editorView(next), status: 'active' }\n\t}\n\n\tconst current = editLine(state.current, key)\n\tif (current === undefined) return { state, view: editorView(state), status: 'active' }\n\tconst next: EditorState = { ...state, current, error: undefined }\n\treturn { state: next, view: editorView(next), status: 'active' }\n}\n\n// === Shared reducer helpers\n\n/**\n * Apply a single line-editing {@link KeyEvent} to a text buffer — the editing shared by input /\n * password / editor. A printable key appends its character; `backspace` drops the last character;\n * `space` appends a space; ctrl-u clears the line. Returns the new buffer, or `undefined` when the\n * key does not edit the line (so the caller can 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. Count\n\t// CODE POINTS (not UTF-16 units) so an astral printable (an emoji, a surrogate pair — `name.length`\n\t// 2 but ONE code point) appends instead of being dropped, while a multi-char control name (`up`,\n\t// `return`) is still rejected.\n\tif (!key.ctrl && !key.meta && [...key.name].length === 1 && isPrintable(key.name)) {\n\t\treturn `${value}${key.sequence}`\n\t}\n\treturn undefined\n}\n\n// === Wire serialization (T-b)\n\n/**\n * Produce the WIRE-SAFE form of a prompt's options — the {@link PendingPrompt.options} a broker\n * serializes over SSE. Drops everything that cannot cross the wire (a `styler`, and any\n * function-valued `validate` rule), while KEEPING the declarative data a remote client needs to\n * reconstruct the prompt: the {@link ValidationRules} as data, plus `message` / `choices` /\n * `default` / `mask` / `min` / `max`. This is WHY T-a's validation is rules-as-data: a `Validator`\n * FUNCTION can't be serialized, but its declarative rules can — the client rebuilds the validator\n * from them via {@link resolveValidation}.\n *\n * @remarks\n * - **Functions are dropped.** A top-level function value (e.g. a bare-`Validator` `validate`) is\n * omitted entirely; the `styler` (a fluent function-bearing object) is dropped by key.\n * - **`validate` rules are flattened.** A {@link ValidationRules} bag is copied with each\n * function rule replaced by `true` (the rule's INTENT survives as the built-in check; its\n * custom function does not). A bare-function `validate` is dropped (no declarative form to keep).\n * - **`choices` are function-stripped.** Each choice keeps its plain fields (`name` / `value` /\n * `description` / `checked`); a bare string passes through.\n *\n * @param options - The raw prompt options bag (may hold functions / a styler)\n * @returns A JSON-safe options record — only serializable, declarative data\n */\nexport function serializePromptOptions(options: object): Readonly<Record<string, unknown>> {\n\tconst result: Record<string, unknown> = {}\n\tfor (const [key, value] of Object.entries(options)) {\n\t\t// Drop the non-serializable styler (a fluent function-bearing object) and any bare function.\n\t\tif (key === 'styler' || typeof value === 'function') continue\n\t\tif (key === 'validate') {\n\t\t\tconst rules = serializeValidationRules(value)\n\t\t\tif (rules !== undefined) result[key] = rules\n\t\t\tcontinue\n\t\t}\n\t\tif (key === 'choices') {\n\t\t\tresult[key] = serializeChoices(value)\n\t\t\tcontinue\n\t\t}\n\t\tresult[key] = value\n\t}\n\treturn result\n}\n\n/**\n * Flatten a `validate` option to its wire-safe {@link ValidationRules} DATA — a function rule\n * becomes `true` (its built-in check survives; its body cannot cross the wire). A bare-function\n * `validate` (no rules object) has no declarative form, so it yields `undefined` (dropped).\n */\nexport function serializeValidationRules(\n\tvalidate: unknown,\n): Readonly<Record<string, unknown>> | undefined {\n\tif (!isRecord(validate)) return undefined\n\tconst rules: Record<string, unknown> = {}\n\tfor (const [rule, value] of Object.entries(validate)) {\n\t\trules[rule] = typeof value === 'function' ? true : value\n\t}\n\treturn rules\n}\n\n/** Strip functions from a `choices` option — each choice keeps its plain fields; a bare string passes through. */\nexport function serializeChoices(choices: unknown): readonly unknown[] {\n\tif (!Array.isArray(choices)) return []\n\treturn choices.map((choice: unknown) => {\n\t\tif (isString(choice)) return choice\n\t\tif (!isRecord(choice)) return choice\n\t\tconst normalized: Record<string, unknown> = {}\n\t\tfor (const [key, value] of Object.entries(choice)) {\n\t\t\tif (typeof value !== 'function') normalized[key] = value\n\t\t}\n\t\treturn normalized\n\t})\n}\n\n// === Wire guards (§14 — narrow every wire-decoded value)\n\n/** Narrow an unknown value to a {@link PromptType} — one of the six prompt forms. */\nexport const isPromptType: Guard<PromptType> = literalOf(\n\t'input',\n\t'password',\n\t'confirm',\n\t'select',\n\t'checkbox',\n\t'editor',\n)\n\n/** Narrow an unknown value to a {@link PendingPromptStatus}. */\nexport const isPendingPromptStatus: Guard<PendingPromptStatus> = literalOf(\n\t'pending',\n\t'answered',\n\t'expired',\n)\n\n/**\n * Narrow an unknown wire value to a {@link PendingPrompt} — the §14 guard a {@link PromptClient}\n * applies to each decoded SSE `pending` payload before dispatching it (never an `as`).\n */\nexport const isPendingPrompt: Guard<PendingPrompt> = recordOf({\n\tid: isNonEmptyString,\n\tform: isPromptType,\n\tmessage: isString,\n\toptions: isRecord,\n\tstatus: isPendingPromptStatus,\n\ttime: isNumber,\n})\n\n// === Remote prompt dispatch (T-b)\n\n/**\n * Rebuild a wire-decoded `validate` payload into a {@link ValidationRules} bag — the inverse of\n * {@link serializeValidationRules}. Keeps only the primitive rule values (`boolean` / `number` /\n * `string`) a serialized prompt could carry; an empty / non-record / all-dropped payload yields\n * `undefined` (no rules to apply). The client feeds the result back through {@link resolveValidation}.\n */\nexport function reconstructValidationRules(value: unknown): ValidationRules | undefined {\n\tif (!isRecord(value)) return undefined\n\tconst rules: Record<string, boolean | number | string> = {}\n\tlet count = 0\n\tfor (const [rule, item] of Object.entries(value)) {\n\t\t// `pattern` is dropped here: it is the only string-valued rule, and copying an untrusted\n\t\t// wire-supplied regex source into a client-side `RegExp` risks ReDoS. The broker still\n\t\t// re-validates authoritatively via its own answer() gate, so dropping it here is safe.\n\t\tif (rule === 'pattern') continue\n\t\tif (isBoolean(item) || isNumber(item) || isString(item)) {\n\t\t\trules[rule] = item\n\t\t\tcount += 1\n\t\t}\n\t}\n\tif (count === 0) return undefined\n\treturn rules\n}\n\n/** Read one option by key, narrowed by `guard` — `undefined` when absent or off-shape (§14, never an `as`). */\nexport function resolveOption<T>(\n\toptions: Readonly<Record<string, unknown>>,\n\tkey: string,\n\tguard: Guard<T>,\n): T | undefined {\n\tconst value = options[key]\n\treturn guard(value) ? value : undefined\n}\n\n/** Narrow an unknown value to a {@link PromptChoice} — the `recordOf` shape inlined so no non-exported member lingers (§5). */\nexport function isPromptChoice(value: unknown): value is PromptChoice {\n\treturn recordOf({ name: isString, value: isString, description: isString }, ['description'])(\n\t\tvalue,\n\t)\n}\n\n/** Narrow an unknown value to a {@link CheckboxChoice} — the `recordOf` shape inlined so no non-exported member lingers (§5). */\nexport function isCheckboxChoice(value: unknown): value is CheckboxChoice {\n\treturn recordOf({ name: isString, value: isString, description: isString, checked: isBoolean }, [\n\t\t'description',\n\t\t'checked',\n\t])(value)\n}\n\n/** Read a `choices` option as a list of bare strings / full choices — each element narrowed by `guard`, off-shape elements stringified. */\nexport function resolveChoices<TChoice extends PromptChoice | CheckboxChoice>(\n\toptions: Readonly<Record<string, unknown>>,\n\tguard: Guard<TChoice>,\n): readonly (string | TChoice)[] {\n\tconst choices = options.choices\n\tif (!Array.isArray(choices)) return []\n\treturn choices.map((choice: unknown) => {\n\t\tif (isString(choice)) return choice\n\t\tif (guard(choice)) return choice\n\t\treturn String(choice)\n\t})\n}\n\n/**\n * Sanitize a list of resolved choices' human-readable labels (`name` + `description`) with\n * {@link stripControls} — shared by the `select` and `checkbox` branches of\n * {@link dispatchPendingPrompt} so a remote-supplied choice can never inject raw control bytes\n * into the local terminal's rendered view.\n *\n * @param choices - The resolved choices (bare strings or full {@link PromptChoice} /\n * {@link CheckboxChoice} objects) as returned by {@link resolveChoices}\n * @returns The same choices with every `name` / `description` control-stripped\n */\nexport function sanitizeChoiceLabels<TChoice extends PromptChoice | CheckboxChoice>(\n\tchoices: readonly (string | TChoice)[],\n): readonly (string | TChoice)[] {\n\treturn choices.map((choice) => {\n\t\tif (isString(choice)) return stripControls(choice)\n\t\tconst description =\n\t\t\tchoice.description === undefined ? undefined : stripControls(choice.description)\n\t\treturn { ...choice, name: stripControls(choice.name), description }\n\t})\n}\n\n/**\n * Dispatch a {@link PendingPrompt} to the matching {@link PromptFormInterface} method — the bridge\n * step a {@link PromptClient} runs to drive a LOCAL terminal with a prompt issued elsewhere.\n * Reconstructs typed options from the wire-safe {@link PendingPrompt.options} (every field\n * §14-narrowed, never an `as`; the validator rebuilt from rules via {@link reconstructValidationRules}),\n * then calls the matching prompt form and returns its resolved value.\n *\n * @param terminal - The local {@link PromptFormInterface} to drive\n * @param pending - The decoded pending prompt to dispatch\n * @returns The prompt's resolved value (a `string` / `boolean` / `readonly string[]` per form)\n */\nexport function dispatchPendingPrompt(\n\tterminal: PromptFormInterface,\n\tpending: PendingPrompt,\n): Promise<string | boolean | readonly string[]> {\n\tconst options = pending.options\n\tconst validate = reconstructValidationRules(options.validate)\n\tconst message = stripControls(pending.message)\n\tswitch (pending.form) {\n\t\tcase 'input': {\n\t\t\tconst value = resolveOption(options, 'default', isString)\n\t\t\treturn terminal.input({\n\t\t\t\tmessage,\n\t\t\t\tdefault: value === undefined ? undefined : stripControls(value),\n\t\t\t\tvalidate,\n\t\t\t})\n\t\t}\n\t\tcase 'password': {\n\t\t\tconst value = resolveOption(options, 'mask', isString)\n\t\t\treturn terminal.password({\n\t\t\t\tmessage,\n\t\t\t\tmask: value === undefined ? undefined : stripControls(value),\n\t\t\t\tvalidate,\n\t\t\t})\n\t\t}\n\t\tcase 'confirm':\n\t\t\treturn terminal.confirm({\n\t\t\t\tmessage,\n\t\t\t\tdefault: resolveOption(options, 'default', isBoolean),\n\t\t\t})\n\t\tcase 'select': {\n\t\t\tconst value = resolveOption(options, 'default', isString)\n\t\t\treturn terminal.select({\n\t\t\t\tmessage,\n\t\t\t\tchoices: sanitizeChoiceLabels(resolveChoices(options, isPromptChoice)),\n\t\t\t\tdefault: value === undefined ? undefined : stripControls(value),\n\t\t\t})\n\t\t}\n\t\tcase 'checkbox':\n\t\t\treturn terminal.checkbox({\n\t\t\t\tmessage,\n\t\t\t\tchoices: sanitizeChoiceLabels(resolveChoices(options, isCheckboxChoice)),\n\t\t\t\tmin: resolveOption(options, 'min', isNumber),\n\t\t\t\tmax: resolveOption(options, 'max', isNumber),\n\t\t\t})\n\t\tcase 'editor': {\n\t\t\tconst value = resolveOption(options, 'default', isString)\n\t\t\treturn terminal.editor({\n\t\t\t\tmessage,\n\t\t\t\tdefault: value === undefined ? undefined : stripControls(value),\n\t\t\t\tvalidate,\n\t\t\t})\n\t\t}\n\t}\n}\n\n// === Broker + bridge wiring helpers (T-b)\n\n/**\n * The default {@link import('./types.js').TimerHandler} — a thin host `setTimeout` / `clearTimeout`\n * wrapper that arms `callback` after `ms` and returns a {@link TimerCancel}. 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 */\nexport function defaultTimer(callback: () => void, ms: number): TimerCancel {\n\tconst handle = setTimeout(callback, ms)\n\treturn () => clearTimeout(handle)\n}\n\n/** The default {@link import('./types.js').FetchHandler} — the global `fetch`, adapted to the minimal injected shape the {@link import('./PromptClient.js').PromptClient} uses. */\nexport function globalFetch(input: string, init?: FetchInit): Promise<Response> {\n\treturn fetch(input, init)\n}\n\n/**\n * 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 */\nexport function isAbortError(error: unknown): boolean {\n\treturn (error instanceof DOMException || error instanceof Error) && error.name === 'AbortError'\n}\n\n/**\n * Parse a JSON wire string TOTAL — a malformed / empty payload yields `undefined` (the caller's\n * guard then rejects it), never a throw. The {@link import('./PromptClient.js').PromptClient}\n * decodes every SSE `data` field through this before §14-narrowing it.\n */\nexport function parseWireJSON(text: string): unknown {\n\tif (text.length === 0) return undefined\n\ttry {\n\t\treturn JSON.parse(text)\n\t} catch {\n\t\treturn undefined\n\t}\n}\n\n/**\n * 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 *\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` when `url` is a non-loopback `http://` endpoint\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","import type {\n\tCheckboxOptions,\n\tConfirmOptions,\n\tEditorOptions,\n\tInputOptions,\n\tParked,\n\tPasswordOptions,\n\tPendingPrompt,\n\tPromptEventMap,\n\tPromptInterface,\n\tPromptOptions,\n\tPromptType,\n\tSelectOptions,\n\tTimerHandler,\n} from './types.js'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport { DEFAULT_PROMPT_TIMEOUT_MS } from './constants.js'\nimport { TerminalError } from './errors.js'\nimport {\n\tdefaultTimer,\n\tnormalizeCheckboxChoice,\n\tnormalizeChoice,\n\tresolveValidation,\n\tserializePromptOptions,\n} from './helpers.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { isArray, isBoolean, isString } from '@orkestrel/contract'\n\n/**\n * The headless prompt BROKER (observable §13) — parks each {@link PromptInterface} call as a\n * pending prompt and returns a Promise that resolves when the prompt is {@link answer}ed (or\n * rejects on timeout / teardown). The tri-surface's headless arm: there is no terminal here, so a\n * transport forwards each `pending` event to whoever can answer, and {@link answer} resolves the\n * parked Promise — for environments where direct user access is unavailable (a headless server on\n * stdio, a browser with no TTY, a prompt issued on one machine answered on another).\n *\n * @remarks\n * - **Park-as-Promise.** Each `input` / `password` / `confirm` / `select` / `checkbox` / `editor`\n * mints an id (`crypto.randomUUID()`), parks a wire-safe {@link PendingPrompt}, emits `pending`,\n * and returns an unresolved Promise. The prompt's options are serialized\n * ({@link serializePromptOptions}) so a transport can forward them as-is.\n * - **Answer validates + type-checks.** {@link answer} runs the prompt's per-form gate: it\n * type-checks `value` to the form (string / boolean / string[]) AND, for the text forms, runs\n * the validator resolved from the original `validate` rules. A rejected answer returns `false`\n * and the prompt stays `pending`; an accepted answer resolves the Promise, emits `answer`, and\n * removes the prompt.\n * - **Timeout → expire → reject.** An unanswered prompt expires after `timeout` ms (via the\n * INJECTED timer): `expire` fires and the parked Promise rejects with a {@link TerminalError}\n * (`code: 'EXPIRE'`). {@link destroy} expires every still-pending prompt the same way.\n * - **Deterministic.** The timer is injectable ({@link import('./types.js').TimerHandler}); a test\n * supplies one that fires on demand, so expiry is driven without real time.\n *\n * @example\n * ```ts\n * const prompt = createPrompt({ timeout: 60_000 })\n * prompt.emitter.on('pending', (pending) => broadcast(pending)) // forward to a client\n *\n * const name = await prompt.input({ message: 'Your name' }) // parks; resolves on answer()\n * // ...elsewhere, a client POSTs the answer back:\n * prompt.answer(id, 'Ada') // resolves the awaited input() above\n * ```\n */\nexport class Prompt implements PromptInterface {\n\treadonly #timeout: number\n\treadonly #timer: TimerHandler\n\treadonly #parked = new Map<string, Parked>()\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.#emitter = new Emitter({ on: options?.on, error: options?.error })\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\t// === Pending accessors (§9.1)\n\n\tpending(): readonly PendingPrompt[]\n\tpending(id: string): PendingPrompt | undefined\n\tpending(id?: string): readonly PendingPrompt[] | PendingPrompt | undefined {\n\t\tif (id !== undefined) return this.#parked.get(id)?.prompt\n\t\tconst result: PendingPrompt[] = []\n\t\tfor (const parked of this.#parked.values()) result.push(parked.prompt)\n\t\treturn result\n\t}\n\n\t// === Answer\n\n\tanswer(id: string, value: unknown): boolean {\n\t\tconst parked = this.#parked.get(id)\n\t\tif (parked === undefined) return false\n\t\t// The per-form gate validates + type-checks, and on accept resolves the Promise (it owns the\n\t\t// typed `resolve`). It returns the accepted value, or `undefined` to reject the answer.\n\t\tconst accepted = parked.respond(value)\n\t\tif (accepted === undefined) return false\n\t\tparked.cancel()\n\t\tthis.#emitter.emit('answer', id, accepted)\n\t\tthis.#parked.delete(id)\n\t\treturn true\n\t}\n\n\t// === PromptFormInterface — each call parks a prompt and awaits its answer\n\n\tinput(options: InputOptions): Promise<string> {\n\t\tconst validator = resolveValidation(options.validate)\n\t\treturn this.#park('input', options.message, options, (value) =>\n\t\t\tisString(value) && validator(value) === true ? value : undefined,\n\t\t)\n\t}\n\n\tpassword(options: PasswordOptions): Promise<string> {\n\t\tconst validator = resolveValidation(options.validate)\n\t\treturn this.#park('password', options.message, options, (value) =>\n\t\t\tisString(value) && validator(value) === true ? value : undefined,\n\t\t)\n\t}\n\n\tconfirm(options: ConfirmOptions): Promise<boolean> {\n\t\treturn this.#park('confirm', options.message, options, (value) =>\n\t\t\tisBoolean(value) ? value : undefined,\n\t\t)\n\t}\n\n\tselect(options: SelectOptions): Promise<string> {\n\t\tconst values = new Set(options.choices.map(normalizeChoice).map((choice) => choice.value))\n\t\treturn this.#park('select', options.message, options, (value) =>\n\t\t\tisString(value) && values.has(value) ? value : undefined,\n\t\t)\n\t}\n\n\tcheckbox(options: CheckboxOptions): Promise<readonly string[]> {\n\t\tconst values = new Set(\n\t\t\toptions.choices.map(normalizeCheckboxChoice).map((choice) => choice.value),\n\t\t)\n\t\tconst { min, max } = options\n\t\treturn this.#park('checkbox', options.message, options, (value) => {\n\t\t\tif (!isArray(value) || !value.every(isString)) return undefined\n\t\t\tif (!value.every((item) => values.has(item))) return undefined\n\t\t\tif (min !== undefined && value.length < min) return undefined\n\t\t\tif (max !== undefined && value.length > max) return undefined\n\t\t\treturn value\n\t\t})\n\t}\n\n\teditor(options: EditorOptions): Promise<string> {\n\t\tconst validator = resolveValidation(options.validate)\n\t\treturn this.#park('editor', options.message, options, (value) =>\n\t\t\tisString(value) && validator(value) === true ? value : undefined,\n\t\t)\n\t}\n\n\t// === Lifecycle\n\n\tdestroy(): void {\n\t\tif (this.#destroyed) return\n\t\tthis.#destroyed = true\n\t\t// Expire every still-pending prompt so no awaiting caller hangs — the full path (cancel +\n\t\t// emit `expire` + reject), same as a timeout. Snapshot the ids first (the map mutates).\n\t\tfor (const id of [...this.#parked.keys()]) this.#expire(id)\n\t\tthis.#parked.clear()\n\t\tthis.#emitter.destroy()\n\t}\n\n\t// === Private helpers\n\n\t// Park one prompt: build the wire record, arm the injected expiry timer, store the gate-and-resolve\n\t// closure, emit `pending`, and return the Promise the form method awaits. `gate` is typed to the\n\t// form's value `T` — it validates + type-checks an answer and returns the coerced `T` (or\n\t// `undefined` to reject) — so the Promise resolves with the precise type, no assertion anywhere.\n\t#park<T>(\n\t\tform: PromptType,\n\t\tmessage: string,\n\t\toptions: object,\n\t\tgate: (value: unknown) => T | undefined,\n\t): Promise<T> {\n\t\tif (this.#destroyed) return Promise.reject(new TerminalError('EXPIRE', 'broker destroyed'))\n\t\tconst id = crypto.randomUUID()\n\t\tconst prompt: PendingPrompt = {\n\t\t\tid,\n\t\t\tform,\n\t\t\tmessage,\n\t\t\toptions: serializePromptOptions(options),\n\t\t\tstatus: 'pending',\n\t\t\ttime: Date.now(),\n\t\t}\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst cancel = this.#timer(() => this.#expire(id), this.#timeout)\n\t\t\t// The gate-and-resolve closure: re-mark the record `answered`, resolve with the typed value.\n\t\t\tconst respond = (value: unknown): T | undefined => {\n\t\t\t\tconst accepted = gate(value)\n\t\t\t\tif (accepted === undefined) return undefined\n\t\t\t\tconst current = this.#parked.get(id)\n\t\t\t\tif (current !== undefined) {\n\t\t\t\t\tthis.#parked.set(id, { ...current, prompt: { ...current.prompt, status: 'answered' } })\n\t\t\t\t}\n\t\t\t\tresolve(accepted)\n\t\t\t\treturn accepted\n\t\t\t}\n\t\t\tconst expire = (): void => {\n\t\t\t\treject(new TerminalError('EXPIRE', `prompt ${id} expired`, { id }))\n\t\t\t}\n\t\t\tthis.#parked.set(id, { prompt, respond, expire, cancel })\n\t\t\tthis.#emitter.emit('pending', prompt)\n\t\t})\n\t}\n\n\t// Expire one parked prompt: cancel its timer, mark it `expired`, emit `expire`, reject its Promise,\n\t// and drop it. A no-op when the id is already gone (answered / already expired).\n\t#expire(id: string): void {\n\t\tconst parked = this.#parked.get(id)\n\t\tif (parked === undefined) return\n\t\tparked.cancel()\n\t\tthis.#parked.set(id, { ...parked, prompt: { ...parked.prompt, status: 'expired' } })\n\t\tthis.#emitter.emit('expire', id)\n\t\tthis.#parked.delete(id)\n\t\tparked.expire()\n\t}\n}\n","import type {\n\tFetchHandler,\n\tPendingPrompt,\n\tPromptClientEventMap,\n\tPromptClientInterface,\n\tPromptClientOptions,\n\tPromptFormInterface,\n\tTimerCancel,\n\tTimerHandler,\n} from './types.js'\nimport type { EmitterInterface } from '@orkestrel/emitter'\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\tdispatchPendingPrompt,\n\tglobalFetch,\n\tisAbortError,\n\tisInsecureRemote,\n\tisPendingPrompt,\n\tparseWireJSON,\n} from './helpers.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { createSSEParser } from '@orkestrel/sse'\nimport { isRecord, isString } from '@orkestrel/contract'\n\n/**\n * The SSE prompt BRIDGE (observable §13) — the client-side counterpart to\n * {@link import('./Prompt.js').Prompt}. Connects to a remote broker's SSE endpoint, receives\n * serialized pending prompts, dispatches EACH to a LOCAL {@link PromptFormInterface} terminal (so\n * a human at THIS machine answers a prompt parked elsewhere), and POSTs the answer back.\n * Universal — `fetch` + SSE are web-standard, so it runs in a browser or on a server; the\n * injected `fetch` / timer make it fully deterministic in tests.\n *\n * @remarks\n * - **Connect + reconnect.** {@link connect} opens the SSE stream (via the injected `fetch` + the\n * core `SSEParser`) and loops, reconnecting after the stream drops with the `delay` backoff\n * (driven by the injected timer) — unless `reconnect` is `false`, the client was\n * {@link destroy}ed, or the drop was a deliberate {@link disconnect} (an abort).\n * - **Dispatch + answer.** Each decoded `pending` event is narrowed to a `PendingPrompt` (§14 —\n * never an `as`), dispatched to `terminal`, and its resolved value POSTed back to `url`.\n * Dispatch is strictly SERIAL: the read loop drives the terminal for ONE prompt at a time and\n * only reads/dispatches the next event after the current prompt fully settles (its answer\n * POSTed). A prompt id redelivered by the broker AFTER its prior dispatch has settled is\n * dispatched again — the client does not dedupe across completion.\n * - **Server signals.** An `expire` event (the broker dropped a parked prompt) emits `expire`; a\n * `shutdown` event calls {@link disconnect} (not {@link destroy}) — the client stops streaming\n * without auto-reconnect but stays reusable; a later {@link connect} recovers it.\n * - **Lean events (§13).** `connect` / `disconnect` / `expire` / `error` — errors are `unknown`.\n * `disconnect` fires exactly once per connected-to-disconnected transition, whether triggered by\n * the server ending the stream cleanly or by a deliberate {@link disconnect} / {@link destroy}.\n *\n * @example\n * ```ts\n * const client = createPromptClient({\n * \turl: 'http://localhost:3001/prompts',\n * \tterminal: createTerminal(), // a local PromptFormInterface (T-c)\n * \ton: { connect: () => log('connected') },\n * })\n * await client.connect() // streams remote prompts to the local terminal, POSTs answers back\n * ```\n */\nexport class PromptClient implements PromptClientInterface {\n\treadonly url: string\n\treadonly #terminal: PromptFormInterface\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: TimerCancel | undefined\n\t#wake: (() => void) | undefined\n\t#connecting = false\n\t#connected = false\n\t#destroyed = false\n\t#warnedInsecureToken = false\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({ on: options.on, error: options.error })\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\t// === Connection lifecycle\n\n\tasync connect(): Promise<void> {\n\t\tif (this.#destroyed) return\n\t\t// Re-entrancy guard: a connect already in progress owns `#controller` / the backoff fields —\n\t\t// a second concurrent call must not race them, so it returns immediately.\n\t\tif (this.#connecting) return\n\t\t// Arm the \"should be connected\" flag — `disconnect()` clears it to stop the reconnect loop\n\t\t// (a deliberate disconnect, not a transport drop); re-arming here lets a later connect restart.\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\t// Stop after a clean end / error unless reconnect is on and the client is still connecting.\n\t\t\tif (!this.#reconnect || !this.#connecting || this.#destroyed) return\n\t\t\t// Park on the backoff. `disconnect()` wakes this early and clears `#connecting`, so the loop\n\t\t\t// re-checks the flag above and EXITS instead of reconnecting.\n\t\t\tawait this.#wait(this.#delay)\n\t\t}\n\t}\n\n\tdisconnect(): void {\n\t\t// Stop the CURRENT connection AND prevent reconnect — the user explicitly disconnected. Clearing\n\t\t// `#connecting` makes the connect loop exit the next time it re-checks (a later `connect()` may\n\t\t// restart it). Abort an in-flight stream; and if the loop is parked on the backoff, cancel that\n\t\t// timer and wake the parked `#wait` so the loop re-checks `#connecting` immediately and exits.\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.#emitter.destroy()\n\t}\n\n\t// === Private helpers\n\n\t// Open the SSE stream once and pump it to completion: GET the endpoint, read the body stream,\n\t// decode bytes, feed the core SSEParser, and handle each dispatched event. Throws on a non-OK\n\t// response / missing body / abort — `connect` catches and (maybe) reconnects.\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\t// Bound the parser's internal buffer — an OVERFLOW throws out of `parser.parse`, propagates\n\t\t// through this loop, `connect`'s catch (as an `error` event), and into the backoff reconnect\n\t\t// (which opens a fresh parser); this propagate-and-reconnect policy is intentional.\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\tawait this.#handle(event)\n\t\t\t\t}\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// Route one decoded SSE event by its `event:` name (§14-narrow every payload).\n\tasync #handle(event: SSEEvent): Promise<void> {\n\t\tif (event.event === SSE_EVENTS.pending) {\n\t\t\tconst parsed = parseWireJSON(event.data)\n\t\t\tif (isPendingPrompt(parsed)) await this.#dispatch(parsed.id, parsed)\n\t\t\treturn\n\t\t}\n\t\tif (event.event === SSE_EVENTS.expire) {\n\t\t\tconst parsed = parseWireJSON(event.data)\n\t\t\tif (isRecord(parsed) && isString(parsed.id)) {\n\t\t\t\tthis.#emitter.emit('expire', parsed.id)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tif (event.event === SSE_EVENTS.shutdown) this.disconnect()\n\t}\n\n\t// Dispatch one pending prompt to the local terminal and POST its answer back. Dispatch is\n\t// strictly serial — see the class docstring — so this always runs to completion (or errors)\n\t// before the read loop reads and dispatches the next event.\n\tasync #dispatch(id: string, pending: PendingPrompt): Promise<void> {\n\t\ttry {\n\t\t\tconst value = await dispatchPendingPrompt(this.#terminal, pending)\n\t\t\tawait this.#post(id, value)\n\t\t} catch (error) {\n\t\t\tthis.#emitter.emit('error', error)\n\t\t}\n\t}\n\n\t// POST one answer back to the broker; surface a non-OK / failed POST as an `error` event.\n\tasync #post(id: string, value: unknown): Promise<void> {\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, value }),\n\t\t})\n\t\tif (!response.ok) this.#emitter.emit('error', new Error(`broker rejected answer ${id}`))\n\t}\n\n\t// Emit `disconnect` exactly once per connected→disconnected transition — the single choke point\n\t// for both the clean server-end tail of `#stream` and the deliberate `disconnect()`/`destroy()`\n\t// teardown, so neither path can double-emit or miss the event.\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// Merge the base headers with the auth token header when a token is configured.\n\t#headers(base: Record<string, string>): Record<string, string> {\n\t\tif (this.#token !== undefined) base[HEADER_TOKEN] = this.#token\n\t\treturn base\n\t}\n\n\t// Park `ms` on the INJECTED timer (deterministic in tests) — the reconnect backoff. The timer's\n\t// cancel and the resolver are held on `#backoff` / `#wake` so `disconnect()` can wake the loop\n\t// early (cancel the timer + resolve now); both clear on settle so they never fire twice.\n\t#wait(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst settle = (): void => {\n\t\t\t\tthis.#backoff = undefined\n\t\t\t\tthis.#wake = undefined\n\t\t\t\tresolve()\n\t\t\t}\n\t\t\tthis.#wake = settle\n\t\t\tthis.#backoff = this.#timer(() => {\n\t\t\t\tsettle()\n\t\t\t}, ms)\n\t\t})\n\t}\n}\n","import type {\n\tPromptClientInterface,\n\tPromptClientOptions,\n\tPromptInterface,\n\tPromptOptions,\n} from './types.js'\nimport { Prompt } from './Prompt.js'\nimport { PromptClient } from './PromptClient.js'\n\n/**\n * Create the headless prompt {@link PromptInterface} BROKER — it parks each prompt call as a\n * pending prompt and resolves it when {@link PromptInterface.answer} arrives (or rejects on\n * timeout). The tri-surface's headless arm: subscribe `emitter.on('pending', …)` to forward each\n * prompt to whoever can answer (an SSE transport, a remote terminal), then route the answer back\n * through `answer(id, value)`.\n *\n * @param options - See {@link PromptOptions}\n * @returns A {@link PromptInterface}\n *\n * @remarks\n * - **Park-as-Promise.** `await prompt.input({ message })` blocks until `answer(id, value)` accepts\n * a matching value; the value is validated (text forms) and type-checked to the form first.\n * - **Timeout → expire → reject (deterministic).** An unanswered prompt expires after\n * `options.timeout` (default {@link import('./constants.js').DEFAULT_PROMPT_TIMEOUT_MS}) and its\n * Promise rejects with a {@link import('./errors.js').TerminalError}; inject `options.timer` to\n * drive expiry without real time.\n *\n * @example\n * ```ts\n * import { createPrompt } from '@src/core'\n *\n * const prompt = createPrompt()\n * prompt.emitter.on('pending', (pending) => send(pending)) // forward to a remote client\n * const name = await prompt.input({ message: 'Your name', validate: { required: true } })\n * ```\n */\nexport function createPrompt(options?: PromptOptions): PromptInterface {\n\treturn new Prompt(options)\n}\n\n/**\n * Create the SSE prompt {@link PromptClientInterface} BRIDGE — it connects to a remote broker's SSE\n * endpoint, dispatches each received prompt to a LOCAL {@link import('./types.js').PromptFormInterface}\n * terminal (so a human at this machine answers a prompt parked elsewhere), and POSTs the answer\n * back. Universal — `fetch` / SSE are web-standard.\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 * - **§14 wire narrowing.** Every decoded prompt is guard-narrowed before dispatch (never an `as`).\n *\n * @example\n * ```ts\n * import { createPromptClient } from '@src/core'\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"],"mappings":"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"}