@dolusoft/command-console-core 1.0.1 → 1.1.0

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":"command-console-core.js","names":["lookupOf","controllable","clear","write","write","feature","lookupOf","feature","lookupOf"],"sources":["../src/shared/registry.ts","../src/shared/hooks.ts","../src/shared/effects.ts","../src/shared/keys.ts","../src/shared/lifecycle.ts","../src/core/console/console.utils.ts","../src/store/action.ts","../src/core/dispatch/dispatch.utils.ts","../src/core/console/consoleFeature.ts","../src/core/dispatch/sensitivity.ts","../src/core/entries/entries.utils.ts","../src/core/entries/entriesFeature.ts","../src/core/input/inputFeature.ts","../src/core/dispatch/dispatchFeature.ts","../src/helpers/coreFeatures.ts","../src/store/createStore.ts","../src/core/console/constructConsole.ts","../src/helpers/consoleFeatures.ts","../src/features/context/context.utils.ts","../src/features/context/contextFeature.ts","../src/features/recall/recall.utils.ts","../src/features/recall/recallFeature.ts","../src/features/completion/completion.utils.ts","../src/features/completion/completionFeature.ts"],"sourcesContent":["// The per-console record of shared/ (ADR 0002): everything the\n// features have in common. It is keyed by the console instance in a WeakMap\n// and dropped on dispose, so it never keeps a disposed console alive and a\n// late call (a settling promise, an event after unmount) finds nothing.\nimport type { Hooks } from './hooks'\nimport type {\n AnyConsoleOptions,\n ConsoleState,\n ControlledSlice\n} from '../core/console/console.types'\nimport type { Store } from '../store/createStore'\n\n/** The store of a console. */\nexport type ConsoleStore = Store<ConsoleState, ControlledSlice>\n\n/** What every feature of one console shares. */\nexport interface SharedRecord {\n store: ConsoleStore\n /** The options with the features' defaults merged; replaced by `setOptions`. */\n options: AnyConsoleOptions & { prompt: string }\n hooks: Hooks\n}\n\nconst createHooks = (): Hooks => ({\n lineSubmitted: [],\n lineCleared: [],\n inputChanged: [],\n key: [],\n controlledChanged: [],\n contextChanged: [],\n reset: [],\n disposers: [],\n prompt: null,\n context: null,\n commandLookup: null,\n inputWriter: null,\n effects: {},\n keyActions: {}\n})\n\nconst records = new WeakMap<object, SharedRecord>()\nconst disposed = new WeakSet<object>()\n\n/** Creates the record of `console` (the engine, on construction). */\nexport const createRecord = (\n console: object,\n store: ConsoleStore,\n options: SharedRecord['options']\n): SharedRecord => {\n const record: SharedRecord = { store, options, hooks: createHooks() }\n records.set(console, record)\n return record\n}\n\n/** The record of `console`; `null` once it is disposed. */\nexport const recordOf = (console: object): SharedRecord | null =>\n records.get(console) ?? null\n\n/**\n * The record of a live console. For code that only runs while the console\n * lives (a method behind `assignMethods`, a registered hook).\n */\nexport const liveRecord = (console: object): SharedRecord => {\n const record = records.get(console)\n if (!record) {\n throw new Error('The console is disposed.')\n }\n return record\n}\n\n/** Drops the record of `console` for good and returns it, once. */\nexport const takeRecord = (console: object): SharedRecord | null => {\n const record = records.get(console) ?? null\n records.delete(console)\n disposed.add(console)\n return record\n}\n\n/** Whether `dispose()` ran for `console`. */\nexport const isDisposed = (console: object): boolean => disposed.has(console)\n","// The hooks features talk through (ADR 0002). An optional feature\n// never imports another feature or a core feature folder at run time: what\n// one needs from another is registered here by the feature that has it and\n// called by the one that needs it. Every function takes the console instance\n// and does nothing once it is disposed.\n//\n// Hooks run inside the action that calls them; a hook that changes state\n// does it through the store of the record (`liveRecord(console).store`),\n// so its changes join that action.\nimport type { ConsoleEffect, ContextFrame } from '@dolusoft/command-protocol'\n\nimport type { KeyActionName, KeyInput } from './keys'\nimport { liveRecord, recordOf } from './registry'\nimport type {\n ControllableState,\n ControlledSlice,\n FeatureName\n} from '../core/console/console.types'\nimport type { CommandDefinition } from '../core/dispatch/dispatch.types'\n\n/**\n * Who wrote the input: a feature, or `null` for `setInput` (the adapter on a\n * user edit or caret move, or the consumer).\n */\nexport type InputOrigin = FeatureName | null\n\n/** One change of the live input, as `onInputChange` hooks see it. */\nexport interface InputChange {\n value: string\n caret: number\n previousValue: string\n previousCaret: number\n origin: InputOrigin\n}\n\n/** A controlled slice the consumer replaced through `setOptions`. */\nexport type ControlledChange = {\n [K in ControlledSlice]: {\n slice: K\n previous: ControllableState[K]\n next: ControllableState[K]\n }\n}[ControlledSlice]\n\n/** The context stack as dispatch and completion read it. */\nexport interface ContextProvider {\n /** The frames now, bottom → top (a copy the caller may keep). */\n snapshot(): ContextFrame[]\n /**\n * A number that changes on every context change (by id sequence, core\n * README: Controlled slices). A run keeps the value it started with.\n */\n revision(): number\n}\n\n/** The commands as completion (and recall) see them. */\nexport interface CommandLookup {\n /** The command a name or alias runs, matched exactly (case-sensitive). */\n find(name: string): CommandDefinition | undefined\n /** The commands that are not `hidden`, in registration order. */\n visible(): CommandDefinition[]\n /**\n * The first argument position that is secret: `0` for `sensitive: true`,\n * `fromArg` for `{ fromArg }`, `null` for a command that is not sensitive.\n */\n sensitiveFrom(command: CommandDefinition): number | null\n /**\n * Whether `options.isSensitive` marks `line` (a throwing predicate counts\n * as a match). A match makes every argument position unsafe.\n */\n matchesPredicate(line: string): boolean\n /** Whether `line` is sensitive (README: Sensitive lines). */\n isSensitive(line: string): boolean\n}\n\n/** Writes the live input on behalf of a feature (registered by input). */\nexport type InputWriter = (\n value: string,\n caret: number,\n origin: InputOrigin\n) => void\n\n/** An effect handler; runs inside the action of the run's end. */\nexport type EffectHandler<T extends ConsoleEffect['type']> = (\n effect: Extract<ConsoleEffect, { type: T }>\n) => void\n\n/** The hooks of one console. Read through the functions below. */\nexport interface Hooks {\n lineSubmitted: ((line: string) => void)[]\n lineCleared: (() => void)[]\n inputChanged: ((change: InputChange) => void)[]\n key: ((input: KeyInput) => void)[]\n controlledChanged: ((change: ControlledChange) => void)[]\n contextChanged: (() => void)[]\n reset: (() => void)[]\n disposers: (() => void)[]\n prompt: (() => string | null) | null\n context: ContextProvider | null\n commandLookup: CommandLookup | null\n inputWriter: InputWriter | null\n effects: { [T in ConsoleEffect['type']]?: EffectHandler<T> }\n keyActions: { [N in KeyActionName]?: () => boolean }\n}\n\nconst call = <A extends unknown[]>(\n list: ((...args: A) => void)[] | undefined,\n ...args: A\n) => {\n for (const hook of list ?? []) {\n hook(...args)\n }\n}\n\nconst provide = <\n K extends 'prompt' | 'context' | 'commandLookup' | 'inputWriter'\n>(\n console: object,\n key: K,\n value: NonNullable<Hooks[K]>\n) => {\n const hooks = liveRecord(console).hooks\n if (hooks[key] !== null) {\n throw new Error(`The ${key} hook is already provided.`)\n }\n hooks[key] = value\n}\n\n// --- Line ends --------------------------------------------------------------\n\n/**\n * Registered by recall: `line` (trimmed) was submitted and is not sensitive.\n * Called by dispatch after the line-end cleanup and before tokenizing, so\n * unknown commands and lines with an unterminated quote are recorded too. Never\n * called for an empty, cancelled or sensitive line (README: Running a line,\n * Recall).\n */\nexport const onLineSubmitted = (\n console: object,\n hook: (line: string) => void\n): void => {\n liveRecord(console).hooks.lineSubmitted.push(hook)\n}\n\n/** Called by dispatch; see `onLineSubmitted`. */\nexport const lineSubmitted = (console: object, line: string): void =>\n call(recordOf(console)?.hooks.lineSubmitted, line)\n\n/**\n * Registered by recall (drop the cursor and the draft) and completion (drop\n * the session). Called on every end of a line (submit, cancel, `run(line)`)\n * after the input was cleared, and by `reset()`. The input is empty when it\n * runs; a hook must not write it.\n */\nexport const onLineCleared = (console: object, hook: () => void): void => {\n liveRecord(console).hooks.lineCleared.push(hook)\n}\n\n/** Called by dispatch and `reset()`; see `onLineCleared`. */\nexport const lineCleared = (console: object): void =>\n call(recordOf(console)?.hooks.lineCleared)\n\n// --- The live input ---------------------------------------------------------\n\n/**\n * Registered by recall (an edit ends browsing) and completion (an edit or a\n * caret move the session did not make closes it). Called after every change\n * of the input's value or caret, with the writer's `origin`: `setInput` has\n * origin `null`, `writeInput` the feature that wrote. Not called by the\n * line-end cleanup (that is `onLineCleared`) or by `reset()`.\n */\nexport const onInputChange = (\n console: object,\n hook: (change: InputChange) => void\n): void => {\n liveRecord(console).hooks.inputChanged.push(hook)\n}\n\n/** Called by the input feature; see `onInputChange`. */\nexport const inputChanged = (console: object, change: InputChange): void =>\n call(recordOf(console)?.hooks.inputChanged, change)\n\n/** Registered by the input feature. */\nexport const provideInputWriter = (console: object, writer: InputWriter) =>\n provide(console, 'inputWriter', writer)\n\n/**\n * Writes the live input for a feature (recall shows a line, completion\n * writes a candidate). The caret is clamped to the value. `onInputChange`\n * hooks see the change with `origin`, so a feature can tell its own writes\n * from the user's. Does nothing while a command runs (the input is\n * read-only).\n */\nexport const writeInput = (\n console: object,\n value: string,\n caret: number,\n origin: FeatureName\n): void => recordOf(console)?.hooks.inputWriter?.(value, caret, origin)\n\n// --- Keys -------------------------------------------------------------------\n\n/**\n * Registered by a feature that must see every key `handleKey` receives\n * before the key map runs (completion: a session with no candidates closes\n * on the next key). Not called for a key with `isComposing`.\n */\nexport const onKey = (console: object, hook: (input: KeyInput) => void) => {\n liveRecord(console).hooks.key.push(hook)\n}\n\n/** Called by `handleKey`; see `onKey`. */\nexport const keyPressed = (console: object, input: KeyInput): void =>\n call(recordOf(console)?.hooks.key, input)\n\n// --- Controlled slices ------------------------------------------------------\n\n/**\n * Registered by recall (an external `recall` ends browsing) and context (an\n * external `context` with another id sequence is a context change, core\n * README: Controlled slices). Called by `setOptions`, inside its action, for\n * each controlled slice whose value the consumer replaced (a different\n * array).\n */\nexport const onControlledChange = (\n console: object,\n hook: (change: ControlledChange) => void\n): void => {\n liveRecord(console).hooks.controlledChanged.push(hook)\n}\n\n/** Called by `setOptions`; see `onControlledChange`. */\nexport const controlledChanged = (\n console: object,\n change: ControlledChange\n): void => call(recordOf(console)?.hooks.controlledChanged, change)\n\n// --- Context ----------------------------------------------------------------\n\n/**\n * Registered by context: the prompt of the next input entry, or `null` at\n * the root (dispatch then uses `options.prompt`). Read by dispatch when an\n * input entry is appended and by `getPrompt()`.\n */\nexport const providePrompt = (\n console: object,\n prompt: () => string | null\n): void => provide(console, 'prompt', prompt)\n\n/** The prompt of the context feature; `null` at the root or without it. */\nexport const promptOf = (console: object): string | null =>\n recordOf(console)?.hooks.prompt?.() ?? null\n\n/**\n * Registered by context: the frames and the revision. Read by dispatch (the\n * snapshot for `CommandRequest` and `RunInfo`, the revision a run starts\n * with) and completion (`CompletionRequest.context`).\n */\nexport const provideContext = (\n console: object,\n provider: ContextProvider\n): void => provide(console, 'context', provider)\n\n/** The context provider; `null` without the context feature. */\nexport const contextOf = (console: object): ContextProvider | null =>\n recordOf(console)?.hooks.context ?? null\n\n/**\n * Registered by dispatch: the context changed by any means other than a\n * run's own effects (a context method, an external `context`). Called by\n * context inside the action that changed it; dispatch aborts the current\n * run's signal (the run goes on, and its context effects are dropped when it\n * ends, README: Context).\n */\nexport const onContextChange = (console: object, hook: () => void): void => {\n liveRecord(console).hooks.contextChanged.push(hook)\n}\n\n/** Called by context; see `onContextChange`. */\nexport const contextChanged = (console: object): void =>\n call(recordOf(console)?.hooks.contextChanged)\n\n// --- Commands ---------------------------------------------------------------\n\n/** Registered by dispatch. */\nexport const provideCommandLookup = (\n console: object,\n lookup: CommandLookup\n): void => provide(console, 'commandLookup', lookup)\n\n/**\n * The commands of the console (completion: names, `complete`, safe\n * positions; recall: whether the live input is sensitive). Always present\n * while the console lives.\n */\nexport const lookupOf = (console: object): CommandLookup =>\n liveRecord(console).hooks.commandLookup!\n","// Effects (protocol README; README: Running a line). Each effect type is\n// applied by the feature that owns it: `clear` (entries), `close` (console),\n// `push-context`, `pop-context`, `reset-context` (context), `clear-recall`\n// (recall). Dispatch applies a run's effects in order, before the run's\n// output, inside the action of the run's end; an effect whose feature is\n// absent is ignored.\n// Context effects of a run whose context changed by someone else are dropped\n// by dispatch before they reach the handler (README: Context).\nimport type { ConsoleEffect } from '@dolusoft/command-protocol'\n\nimport type { EffectHandler } from './hooks'\nimport { liveRecord, recordOf } from './registry'\n\n/** The effect types that change the context stack. */\nexport const contextEffects: ReadonlySet<ConsoleEffect['type']> = new Set([\n 'push-context',\n 'pop-context',\n 'reset-context'\n])\n\n/** Registers the handler of effect `type` (one feature per type). */\nexport const handleEffect = <T extends ConsoleEffect['type']>(\n console: object,\n type: T,\n handler: EffectHandler<T>\n): void => {\n const effects = liveRecord(console).hooks.effects\n if (effects[type]) {\n throw new Error(`The ${type} effect already has a handler.`)\n }\n ;(effects as Record<string, unknown>)[type] = handler\n}\n\n/** Applies one effect; `false` when no feature handles its type. */\nexport const applyEffect = (\n console: object,\n effect: ConsoleEffect\n): boolean => {\n const handler = recordOf(console)?.hooks.effects[effect.type] as\n ((effect: ConsoleEffect) => void) | undefined\n if (!handler) {\n return false\n }\n handler(effect)\n return true\n}\n","// The fixed key map (README: Keyboard, C-53). `handleKey` matches a chord and\n// tries the chord's actions in order; an action returns `true` when its\n// condition held and it acted, so the next one is not tried and the key counts\n// as handled. An action that is not registered (its feature is absent) is\n// skipped. A key no action handles is left to the browser.\nimport { liveRecord, recordOf } from './registry'\n\n/** A key press as the adapter reports it; core never sees a DOM event. */\nexport interface KeyInput {\n key: string\n ctrlKey: boolean\n shiftKey: boolean\n altKey: boolean\n metaKey: boolean\n /** A key during IME composition is never handled. */\n isComposing: boolean\n /** Whether text is selected in the input or in the console's document. */\n selection: 'none' | 'input' | 'document'\n}\n\n/**\n * The actions of the key map:\n *\n * - `submit`, `cancel` (dispatch);\n * - `recallPrevious`, `recallNext` (recall);\n * - `acceptCompletion`, `completeNext`, `completePrevious`, `selectNext`,\n * `selectPrevious`, `closeCompletion` (completion).\n */\nexport type KeyActionName =\n | 'submit'\n | 'cancel'\n | 'recallPrevious'\n | 'recallNext'\n | 'acceptCompletion'\n | 'completeNext'\n | 'completePrevious'\n | 'selectNext'\n | 'selectPrevious'\n | 'closeCompletion'\n\ninterface Chord {\n key: string\n ctrl?: true\n shift?: true\n}\n\n/**\n * Chord → actions, tried in order. Modifiers match exactly; letters compare\n * case-insensitively. The \"when\" of each action (README: Keyboard) is the\n * action's own check:\n *\n * - Enter: `acceptCompletion` when a candidate is selected, else `submit`.\n * - Ctrl+C: `cancel`, only without a selection (`handleKey` checks it).\n * - ArrowUp / ArrowDown: `selectPrevious` / `selectNext` while a session is\n * open, else `recallPrevious` / `recallNext`.\n * - Tab: `completeNext` on a non-empty input or with a session open.\n * - Shift+Tab: `completePrevious` with a session open.\n * - Escape: `closeCompletion` with a session open.\n *\n * While a command runs only Ctrl+C is handled (README: Cancelling and errors).\n */\nconst keyMap: readonly (readonly [Chord, readonly KeyActionName[]])[] = [\n [{ key: 'enter' }, ['acceptCompletion', 'submit']],\n [{ key: 'c', ctrl: true }, ['cancel']],\n [{ key: 'arrowup' }, ['selectPrevious', 'recallPrevious']],\n [{ key: 'arrowdown' }, ['selectNext', 'recallNext']],\n [{ key: 'tab' }, ['completeNext']],\n [{ key: 'tab', shift: true }, ['completePrevious']],\n [{ key: 'escape' }, ['closeCompletion']]\n]\n\nconst matches = (chord: Chord, input: KeyInput) =>\n input.key.toLowerCase() === chord.key &&\n input.ctrlKey === (chord.ctrl ?? false) &&\n input.shiftKey === (chord.shift ?? false) &&\n !input.altKey &&\n !input.metaKey\n\n/** The actions `input` maps to, in order; empty when it maps to none. */\nexport const actionsFor = (input: KeyInput): readonly KeyActionName[] =>\n keyMap.find(([chord]) => matches(chord, input))?.[1] ?? []\n\n/**\n * Registers the action `name` (one feature per action). It runs inside the\n * `handleKey` action and returns whether it acted.\n */\nexport const registerKeyAction = (\n console: object,\n name: KeyActionName,\n action: () => boolean\n): void => {\n const actions = liveRecord(console).hooks.keyActions\n if (actions[name]) {\n throw new Error(`The key action ${name} is already registered.`)\n }\n actions[name] = action\n}\n\n/** Runs the action `name`; `false` when it is not registered or did not act. */\nexport const runKeyAction = (console: object, name: KeyActionName): boolean =>\n recordOf(console)?.hooks.keyActions[name]?.() ?? false\n","// Methods, reset and dispose (core README: Lifecycle). Every method a feature\n// puts on the instance goes through `assignMethods`, which refuses to overwrite\n// another feature's method and turns every call after `dispose()` into a no-op.\nimport { isDisposed, liveRecord, recordOf, takeRecord } from './registry'\n\ntype Method = (...args: never[]) => unknown\n\n/**\n * Assigns `methods` onto `console`. A name already present throws (no\n * feature overwrites another's method). After `dispose()` each method returns\n * its entry in `fallbacks` (default `undefined`) without running.\n */\nexport const assignMethods = <M extends Record<string, Method>>(\n console: object,\n methods: M,\n fallbacks: { [K in keyof M]?: ReturnType<M[K]> } = {}\n): void => {\n const target = console as Record<string, unknown>\n for (const [name, method] of Object.entries(methods)) {\n if (name in target) {\n throw new Error(`The console method ${name} is already defined.`)\n }\n target[name] = (...args: never[]) =>\n isDisposed(console) ? fallbacks[name] : method(...args)\n }\n}\n\n/**\n * Registered by a feature that keeps private state of its own (context: its\n * revision) or must act first (dispatch: end the run as cancelled, without an\n * `interrupted` entry). Called by `reset()` inside its action, in feature\n * order, before the line-cleared hooks and before every slice returns to its\n * initial value.\n */\nexport const onReset = (console: object, hook: () => void): void => {\n liveRecord(console).hooks.reset.push(hook)\n}\n\n/** Called by `reset()`; see `onReset`. */\nexport const resetHooks = (console: object): void => {\n for (const hook of recordOf(console)?.hooks.reset ?? []) {\n hook()\n }\n}\n\n/**\n * Registers a cleanup that `dispose()` runs once, in feature order (dispatch\n * first ends the run). No action is open when it runs; it must not change\n * state.\n */\nexport const onDispose = (console: object, cleanup: () => void): void => {\n liveRecord(console).hooks.disposers.push(cleanup)\n}\n\n/**\n * Drops the record of `console` and runs every cleanup once; a throwing\n * cleanup does not stop the others (its error goes to `onError`). Returns\n * `false` when the console was already disposed.\n */\nexport const disposeShared = (\n console: object,\n onError: (error: unknown) => void\n): boolean => {\n const record = takeRecord(console)\n if (!record) {\n return false\n }\n for (const cleanup of record.hooks.disposers) {\n try {\n cleanup()\n } catch (error) {\n onError(error)\n }\n }\n return true\n}\n","import type { AnyConsoleOptions } from './console.types'\nimport { liveRecord, promptOf, recordOf } from '../../shared'\nimport type { RunInfo } from '../dispatch/dispatch.types'\n\n/** The prompt of the next input entry: the top frame's, else the root's. */\nexport const currentPrompt = (console: object): string =>\n promptOf(console) ?? liveRecord(console).options.prompt\n\n/** Rethrows `error` outside the action, as an unhandled rejection. */\nconst rethrowAsync = (error: unknown): void => {\n void Promise.resolve().then(() => {\n throw error\n })\n}\n\n/**\n * Reports an error through `onError` (core README: Actions and\n * notification): a command's error with its `RunInfo`, a callback's error\n * with `null`. An error `onError` itself throws\n * is rethrown asynchronously; so is a callback's error without `onError`.\n */\nexport const reportError = (\n onError: AnyConsoleOptions['onError'],\n error: unknown,\n info: RunInfo | null\n): void => {\n if (!onError) {\n if (info === null) {\n rethrowAsync(error)\n }\n return\n }\n try {\n onError(error, info)\n } catch (thrown) {\n rethrowAsync(thrown)\n }\n}\n\n/** The callback-error reporter of the store. */\nexport const reportCallbackError = (console: object, error: unknown): void =>\n reportError(recordOf(console)?.options.onError, error, null)\n","// Updaters (core README: Controlled slices). A controlled slice is reported as\n// one updater per action that replays every change of the action, in order,\n// onto the value it is given.\n\n/** A new value, or a function from the old value to the new one. */\nexport type Updater<T> = T | ((old: T) => T)\n\n/** A change of one slice: a function from the old value to the new one. */\nexport type Step<T> = (old: T) => T\n\n/** The value `updater` gives when applied to `old`. */\nexport const resolveUpdater = <T>(updater: Updater<T>, old: T): T =>\n typeof updater === 'function' ? (updater as Step<T>)(old) : updater\n\n/** One step that applies `steps` in order. */\nexport const composeSteps =\n <T>(steps: readonly Step<T>[]): Step<T> =>\n old =>\n steps.reduce((value, step) => step(value), old)\n","import type {\n CommandResponse,\n CommandSpec,\n OutputBlock\n} from '@dolusoft/command-protocol'\n\nimport type { CommandDefinition, CommandReturn } from './dispatch.types'\n\nconst forbidden = /[\\s'\"]/\n\nconst checkName = (name: unknown, where: string) => {\n if (typeof name !== 'string' || name === '' || forbidden.test(name)) {\n throw new Error(\n `${where}: a command name must be a non-empty string without whitespace or quotes (got ${JSON.stringify(name)}).`\n )\n }\n}\n\n/**\n * Validates the commands (core README: Options, C-56): names and aliases are\n * non-empty, without whitespace or quotes, unique across every name and alias;\n * `fromArg` is a non-negative integer; `run` is a function. Throws on the\n * first violation.\n */\nexport const validateCommands = (commands: unknown): void => {\n if (!Array.isArray(commands)) {\n throw new Error('commands must be an array of command definitions.')\n }\n const seen = new Set<string>()\n for (const command of commands as CommandDefinition[]) {\n const names = [command?.name, ...(command?.aliases ?? [])]\n for (const name of names) {\n checkName(name, `command ${JSON.stringify(command?.name)}`)\n if (seen.has(name)) {\n throw new Error(`The command name ${name} is used twice.`)\n }\n seen.add(name)\n }\n const { sensitive } = command\n if (\n sensitive !== undefined &&\n typeof sensitive !== 'boolean' &&\n !(\n typeof sensitive === 'object' &&\n sensitive !== null &&\n Number.isInteger(sensitive.fromArg) &&\n sensitive.fromArg >= 0\n )\n ) {\n throw new Error(\n `command ${command.name}: sensitive must be a boolean or { fromArg } with a non-negative integer.`\n )\n }\n if (typeof command.run !== 'function') {\n throw new Error(`command ${command.name}: run must be a function.`)\n }\n }\n}\n\n/** The JSON spec of a command, without its functions (`getCommands`). */\nexport const specOf = (command: CommandDefinition): CommandSpec => {\n const spec: CommandSpec = {\n name: command.name,\n aliases: [...(command.aliases ?? [])]\n }\n if (command.summary !== undefined) {\n spec.summary = command.summary\n }\n if (command.usage !== undefined) {\n spec.usage = command.usage\n }\n if (command.sensitive !== undefined) {\n spec.sensitive =\n typeof command.sensitive === 'object'\n ? { fromArg: command.sensitive.fromArg }\n : command.sensitive\n }\n return spec\n}\n\n/** A command's return as a response (README: Running a line, End action). */\nexport const normalizeReturn = (value: CommandReturn): CommandResponse => {\n if (typeof value === 'string' || Array.isArray(value)) {\n return { output: value }\n }\n if (typeof value === 'object' && value !== null) {\n return value\n }\n return {}\n}\n\n/** The blocks of a response's output; a string is one text block. */\nexport const blocksOf = (\n output: string | OutputBlock[] | undefined\n): OutputBlock[] => {\n if (typeof output === 'string') {\n return [{ type: 'text', text: output }]\n }\n return output ?? []\n}\n\n/** Whether `value` is a promise or another thenable. */\nexport const isThenable = (value: unknown): value is PromiseLike<unknown> =>\n (typeof value === 'object' || typeof value === 'function') &&\n value !== null &&\n typeof (value as { then?: unknown }).then === 'function'\n","// The console feature (ADR 0002; core README: Actions and notification,\n// Lifecycle; README: Keyboard): state access, options, the key map, reset and\n// dispose, and the `close` effect.\nimport type { ConsoleEntry, ContextFrame } from '@dolusoft/command-protocol'\n\nimport type {\n AnyConsole,\n AnyConsoleOptions,\n ConsoleFeature,\n ConsoleState,\n ControlledSlice\n} from './console.types'\nimport { currentPrompt, reportError } from './console.utils'\nimport {\n actionsFor,\n assignMethods,\n controlledChanged,\n disposeShared,\n handleEffect,\n isDisposed,\n keyPressed,\n lineCleared,\n liveRecord,\n recordOf,\n resetHooks,\n runKeyAction,\n type ControlledChange,\n type KeyInput\n} from '../../shared'\nimport { resolveUpdater, type Updater } from '../../store/action'\nimport { validateCommands } from '../dispatch/dispatch.utils'\n\nconst controllable: readonly ControlledSlice[] = [\n 'entries',\n 'recall',\n 'context'\n]\n\n/** The state a console starts from before `initialState` and the features. */\nexport const emptyState = (): ConsoleState => ({\n entries: [],\n input: { value: '', caret: 0, revision: 0 },\n running: null,\n recall: [],\n recallCursor: null,\n recallDraft: null,\n completion: null,\n context: []\n})\n\n/**\n * The options as the features read them: the features' defaults, then every\n * option the consumer gave that is not `undefined`.\n */\nexport const mergeOptions = (\n defaults: Partial<AnyConsoleOptions>,\n options: AnyConsoleOptions\n): AnyConsoleOptions & { prompt: string } => {\n const merged: Record<string, unknown> = { ...defaults }\n for (const [key, value] of Object.entries(options)) {\n if (value !== undefined) {\n merged[key] = value\n }\n }\n return merged as unknown as AnyConsoleOptions & { prompt: string }\n}\n\nconst sameFeatures = (a: object | undefined, b: object | undefined) => {\n const left = Object.entries(a ?? {})\n const right = b ?? {}\n return (\n left.length === Object.keys(right).length &&\n left.every(\n ([key, value]) => (right as Record<string, unknown>)[key] === value\n )\n )\n}\n\n/** The initial values `reset()` returns the controllable slices to. */\nconst initialSlices = new WeakMap<\n object,\n { entries: ConsoleEntry[]; recall: string[]; context: ContextFrame[] }\n>()\nconst featureDefaults = new WeakMap<object, Partial<AnyConsoleOptions>>()\n\n/** Remembers what `setOptions` and `reset()` need from construction. */\nexport const rememberConstruction = (\n console: object,\n defaults: Partial<AnyConsoleOptions>,\n initial: ConsoleState\n): void => {\n featureDefaults.set(console, defaults)\n initialSlices.set(console, {\n entries: initial.entries,\n recall: initial.recall,\n context: initial.context\n })\n}\n\nexport const consoleFeature: ConsoleFeature = {\n name: 'console',\n\n getDefaultOptions: () => ({ prompt: '>' }),\n\n constructConsoleAPIs(console: AnyConsole) {\n const { store } = liveRecord(console)\n assignMethods(\n console,\n {\n subscribe: (listener: (state: ConsoleState) => void) =>\n store.subscribe(listener),\n\n setOptions(updater: Updater<AnyConsoleOptions>) {\n const record = liveRecord(console)\n const previous = record.options\n const given = resolveUpdater(updater, previous)\n if (!sameFeatures(previous.features, given.features)) {\n throw new Error('setOptions cannot change the feature set.')\n }\n validateCommands(given.commands)\n store.action(() => {\n const before = { ...store.read() }\n record.options = mergeOptions(featureDefaults.get(console)!, given)\n store.deliver(\n controllable.filter(\n slice =>\n record.options.state?.[slice] !== undefined ||\n previous.state?.[slice] !== undefined\n )\n )\n const after = store.read()\n for (const slice of controllable) {\n if (before[slice] !== after[slice]) {\n controlledChanged(console, {\n slice,\n previous: before[slice],\n next: after[slice]\n } as ControlledChange)\n }\n }\n })\n },\n\n reset() {\n store.action(() => {\n resetHooks(console)\n // The input is empty when the line-cleared hooks run.\n store.update('input', input =>\n input.value === ''\n ? { ...input, caret: 0 }\n : { value: '', caret: 0, revision: input.revision + 1 }\n )\n lineCleared(console)\n const initial = initialSlices.get(console)!\n const empty = emptyState()\n store.update('entries', () => [...initial.entries])\n store.update('recall', () => [...initial.recall])\n store.update('context', () => [...initial.context])\n store.update('recallCursor', () => empty.recallCursor)\n store.update('recallDraft', () => empty.recallDraft)\n store.update('completion', () => empty.completion)\n store.update('running', () => empty.running)\n })\n },\n\n dispose() {\n const record = recordOf(console)\n if (!record) {\n return\n }\n const { onError } = record.options\n disposeShared(console, error => reportError(onError, error, null))\n record.store.clear(emptyState())\n },\n\n getPrompt: () => currentPrompt(console),\n\n handleKey(input: KeyInput) {\n if (input.isComposing) {\n return false\n }\n return store.action(() => {\n keyPressed(console, input)\n const actions = actionsFor(input)\n if (actions[0] === 'cancel' && input.selection !== 'none') {\n return false\n }\n if (store.read().running !== null && actions[0] !== 'cancel') {\n return false\n }\n return actions.some(name => runKeyAction(console, name))\n })\n }\n },\n { handleKey: false, getPrompt: '', subscribe: () => () => {} }\n )\n // Readable after dispose: the cleared state.\n ;(console as { getState?: () => ConsoleState }).getState = () =>\n store.getState()\n },\n\n init(console: AnyConsole) {\n handleEffect(console, 'close', () => {\n liveRecord(console).store.afterCommit(() => {\n if (!isDisposed(console)) {\n recordOf(console)?.options.onClose?.()\n }\n })\n })\n }\n}\n","// Sensitivity (README: Sensitive lines, ADR 0006). Computed once when a line\n// ends, from the tolerant tokens, before anything else sees the line.\nimport { tokenize } from '@dolusoft/command-protocol'\n\nimport type { CommandDefinition } from './dispatch.types'\n\n/**\n * The first secret argument position of `command`: `0` for\n * `sensitive: true`, `fromArg` for `{ fromArg }`, `null` when not sensitive.\n */\nexport const sensitiveFrom = (command: CommandDefinition): number | null => {\n const { sensitive } = command\n if (sensitive === true) {\n return 0\n }\n return typeof sensitive === 'object' ? sensitive.fromArg : null\n}\n\n/**\n * The names and aliases of the sensitive commands, lowercased: the first\n * token is compared case-insensitively, so `Set Password x` is redacted and\n * then reported as unknown (S-04).\n */\nexport const sensitiveNames = (\n commands: readonly CommandDefinition[]\n): ReadonlySet<string> =>\n new Set(\n commands\n .filter(command => sensitiveFrom(command) !== null)\n .flatMap(command => [command.name, ...(command.aliases ?? [])])\n .map(name => name.toLowerCase())\n )\n\n/** Whether the predicate marks `line`; a throwing predicate marks it. */\nexport const matchesPredicate = (\n predicate: ((line: string) => boolean) | undefined,\n line: string\n): boolean => {\n if (!predicate) {\n return false\n }\n try {\n return predicate(line) === true\n } catch {\n return true\n }\n}\n\n/**\n * Whether `line` is sensitive: its first token (quotes removed) names a\n * sensitive command or alias, compared case-insensitively, or the predicate\n * marks it (README: Sensitive lines).\n */\nexport const isLineSensitive = (\n line: string,\n names: ReadonlySet<string>,\n predicate: ((line: string) => boolean) | undefined\n): boolean => {\n const first = tokenize(line).tokens[0]\n if (first && names.has(first.value.toLowerCase())) {\n return true\n }\n return matchesPredicate(predicate, line)\n}\n","import type { ConsoleEntry } from '@dolusoft/command-protocol'\n\nimport type { ConsoleStore } from '../../shared'\n\n/** Keeps the newest `max` entries (C-55); `undefined` keeps all. */\nexport const trimEntries = (\n entries: ConsoleEntry[],\n max: number | undefined\n): ConsoleEntry[] => {\n if (max === undefined || entries.length <= max) {\n return entries\n }\n return entries.slice(entries.length - Math.max(0, Math.floor(max)))\n}\n\n/** The default `createId`: `c1`, `c2`, … skipping ids already in `entries`. */\nexport const counterIds = (store: ConsoleStore): (() => string) => {\n let next = 0\n return () => {\n const present = new Set(store.read().entries.map(entry => entry.id))\n let id: string\n do {\n next += 1\n id = `c${next}`\n } while (present.has(id))\n return id\n }\n}\n\n/** The ids of `entries` that are already in `present` or repeat. */\nexport const duplicateIds = (\n present: readonly ConsoleEntry[],\n entries: readonly ConsoleEntry[]\n): string[] => {\n const seen = new Set(present.map(entry => entry.id))\n const duplicates: string[] = []\n for (const entry of entries) {\n if (seen.has(entry.id)) {\n duplicates.push(entry.id)\n }\n seen.add(entry.id)\n }\n return duplicates\n}\n","// The entries feature (C-55): the scrollback, its ids, `maxEntries` and\n// the `clear` effect.\nimport type { ConsoleEntry } from '@dolusoft/command-protocol'\n\nimport { counterIds, duplicateIds, trimEntries } from './entries.utils'\nimport {\n assignMethods,\n handleEffect,\n liveRecord,\n type ConsoleStore\n} from '../../shared'\nimport type { AnyConsole, ConsoleFeature } from '../console/console.types'\n\nconst defaultIds = new WeakMap<object, () => string>()\n\n/**\n * A new id: from `options.createId`, else the console's counter. An id that\n * is already in `entries` throws (a `createId` that repeats itself).\n */\nexport const newId = (console: object): string => {\n const record = liveRecord(console)\n const create = record.options.createId ?? defaultIds.get(console)!\n const id = create()\n if (record.store.read().entries.some(entry => entry.id === id)) {\n throw new Error(`createId returned ${id}, an id already in entries.`)\n }\n return id\n}\n\n/** Appends `entries` in the open action and applies `maxEntries`. */\nconst append = (\n store: ConsoleStore,\n entries: readonly ConsoleEntry[],\n max: number | undefined\n) => store.update('entries', old => trimEntries([...old, ...entries], max))\n\n/**\n * Appends one entry made by the console, with a new id, in the open action.\n * Returns the id.\n */\nexport const addEntry = (\n console: object,\n entry: ConsoleEntry extends infer E\n ? E extends ConsoleEntry\n ? Omit<E, 'id'>\n : never\n : never\n): string => {\n const record = liveRecord(console)\n const id = newId(console)\n append(record.store, [{ id, ...entry }], record.options.maxEntries)\n return id\n}\n\nconst clear = (store: ConsoleStore) =>\n store.update('entries', old => (old.length === 0 ? old : []))\n\nexport const entriesFeature: ConsoleFeature = {\n name: 'entries',\n\n constructConsoleAPIs(console: AnyConsole) {\n defaultIds.set(console, counterIds(liveRecord(console).store))\n assignMethods(console, {\n appendEntries(entries: ConsoleEntry[]) {\n const { store, options } = liveRecord(console)\n store.action(() => {\n const duplicates = duplicateIds(store.read().entries, entries)\n if (duplicates.length > 0) {\n throw new Error(\n `appendEntries: ids already present: ${duplicates.join(', ')}.`\n )\n }\n append(store, entries, options.maxEntries)\n })\n },\n clearEntries() {\n const { store } = liveRecord(console)\n store.action(() => clear(store))\n }\n })\n },\n\n init(console: AnyConsole) {\n handleEffect(console, 'clear', () => clear(liveRecord(console).store))\n }\n}\n","// The input feature (core README: State; README: Running a line, Sensitive\n// lines): the live line, its caret and the revision the adapter keys the\n// input element by.\nimport {\n assignMethods,\n inputChanged,\n lineCleared,\n liveRecord,\n provideInputWriter,\n type InputOrigin\n} from '../../shared'\nimport type { AnyConsole, ConsoleFeature } from '../console/console.types'\n\nconst clamp = (caret: number, value: string) =>\n Number.isFinite(caret)\n ? Math.min(Math.max(0, Math.floor(caret)), value.length)\n : value.length\n\n/**\n * Writes the input in the open action and tells the `onInputChange` hooks.\n * A programmatic clear of a non-empty input increments the revision; a user\n * edit (`programmatic: false`) never does (README: Sensitive lines, C-54).\n */\nconst write = (\n console: object,\n value: string,\n caret: number,\n origin: InputOrigin,\n programmatic: boolean\n): void => {\n const { store } = liveRecord(console)\n const previous = store.read().input\n const next = {\n value,\n caret: clamp(caret, value),\n revision:\n programmatic && value === '' && previous.value !== ''\n ? previous.revision + 1\n : previous.revision\n }\n if (next.value === previous.value && next.caret === previous.caret) {\n return\n }\n store.update('input', () => next)\n inputChanged(console, {\n value: next.value,\n caret: next.caret,\n previousValue: previous.value,\n previousCaret: previous.caret,\n origin\n })\n}\n\n/**\n * The line-end cleanup (README: Running a line), the same on every path that\n * ends a line: clears the input, increments the revision when the line was\n * sensitive, and calls the `onLineCleared` hooks. Runs in the open action.\n */\nexport const endLine = (console: object, sensitive: boolean): void => {\n const { store } = liveRecord(console)\n store.update('input', input => ({\n value: '',\n caret: 0,\n revision: sensitive ? input.revision + 1 : input.revision\n }))\n lineCleared(console)\n}\n\n/**\n * Replaces the live input with `line` for `run(line)`: a non-empty input is\n * a programmatic clear first (revision + 1), then `line` is written.\n */\nexport const replaceInput = (console: object, line: string): void => {\n const { store } = liveRecord(console)\n store.update('input', input => ({\n value: line,\n caret: line.length,\n revision: input.value === '' ? input.revision : input.revision + 1\n }))\n}\n\nexport const inputFeature: ConsoleFeature = {\n name: 'input',\n\n constructConsoleAPIs(console: AnyConsole) {\n const set = (value: string, caret: number, programmatic: boolean) => {\n const { store } = liveRecord(console)\n store.action(() => {\n if (store.read().running === null) {\n write(console, value, caret, null, programmatic)\n }\n })\n }\n assignMethods(console, {\n setInput(value: string, caret?: number) {\n set(value, caret ?? value.length, true)\n },\n editInput(value: string, caret: number) {\n set(value, caret, false)\n }\n })\n },\n\n init(console: AnyConsole) {\n provideInputWriter(console, (value, caret, origin) => {\n const { store } = liveRecord(console)\n store.action(() => {\n if (store.read().running === null) {\n // A feature's write is programmatic (recall restoring an empty\n // draft replaces the element like any programmatic clear).\n write(console, value, caret, origin, true)\n }\n })\n })\n }\n}\n","// The dispatch feature (README: Running a line, Cancelling and errors,\n// Sensitive lines): ends lines, looks the command up, runs it and appends what\n// it returns. A run is several actions: its start, each asynchronous `write()`,\n// and its end. Every end is guarded by the run: a run that is no longer current\n// changes nothing and calls nothing (C-17).\nimport {\n type CommandResponse,\n type ContextFrame,\n type MessageBlock,\n type OutputEntry,\n tokenize\n} from '@dolusoft/command-protocol'\n\nimport type {\n CommandDefinition,\n CommandRequest,\n CommandReturn,\n RunContext,\n RunInfo\n} from './dispatch.types'\nimport { blocksOf, isThenable, normalizeReturn, specOf } from './dispatch.utils'\nimport {\n isLineSensitive,\n matchesPredicate,\n sensitiveFrom,\n sensitiveNames\n} from './sensitivity'\nimport {\n applyEffect,\n assignMethods,\n contextEffects,\n contextOf,\n isDisposed,\n lineSubmitted,\n liveRecord,\n onContextChange,\n onDispose,\n onReset,\n provideCommandLookup,\n recordOf,\n registerKeyAction,\n type CommandLookup\n} from '../../shared'\nimport type { AnyConsole, ConsoleFeature } from '../console/console.types'\nimport { currentPrompt, reportError } from '../console/console.utils'\nimport { addEntry, newId } from '../entries/entriesFeature'\nimport { endLine, replaceInput } from '../input/inputFeature'\n\ninterface Run {\n readonly id: string\n readonly inputId: string\n readonly info: RunInfo\n readonly request: CommandRequest\n readonly command: CommandDefinition\n readonly controller: AbortController\n /** The context revision when the run started; `null` without context. */\n readonly contextRevision: number | null\n /** False once the run ended or was invalidated. */\n current: boolean\n /** True once the run's cleanup ran (once, C-57). */\n cleaned: boolean\n resolve(result: boolean): void\n}\n\ninterface DispatchState {\n run: Run | null\n lookup: { commands: CommandDefinition[]; value: CommandLookup } | null\n}\n\nconst states = new WeakMap<object, DispatchState>()\n\nconst stateOf = (console: object): DispatchState => states.get(console)!\n\n/** The lookup of the current commands, rebuilt when `commands` changes. */\nconst lookupOf = (console: object): CommandLookup => {\n const state = stateOf(console)\n const record = liveRecord(console)\n const { commands } = record.options\n if (state.lookup?.commands !== commands) {\n const byName = new Map<string, CommandDefinition>()\n for (const command of commands) {\n for (const name of [command.name, ...(command.aliases ?? [])]) {\n byName.set(name, command)\n }\n }\n const names = sensitiveNames(commands)\n const value: CommandLookup = {\n find: name => byName.get(name),\n visible: () => commands.filter(command => command.hidden !== true),\n sensitiveFrom,\n matchesPredicate: line =>\n matchesPredicate(liveRecord(console).options.isSensitive, line),\n isSensitive: line =>\n isLineSensitive(line, names, liveRecord(console).options.isSensitive)\n }\n state.lookup = { commands, value }\n }\n return state.lookup.value\n}\n\nconst message = (\n code: MessageBlock['code'],\n params?: MessageBlock['params']\n): MessageBlock =>\n params === undefined\n ? { type: 'message', code }\n : { type: 'message', code, params }\n\nconst output = (\n tone: OutputEntry['tone'],\n blocks: OutputEntry['blocks'],\n inputId: string,\n quiet?: boolean\n): Omit<OutputEntry, 'id'> =>\n quiet === true\n ? { kind: 'output', tone, blocks, inputId, quiet: true }\n : { kind: 'output', tone, blocks, inputId }\n\n// --- The end of a run ---------------------------------------------------------\n\n/** Clears `running` when it still names `run` and resolves its promise. */\nconst cleanup = (console: object, run: Run) => {\n if (run.cleaned) {\n return\n }\n run.cleaned = true\n const state = stateOf(console)\n if (state.run === run) {\n state.run = null\n }\n recordOf(console)?.store.update('running', running =>\n running?.runId === run.id ? null : running\n )\n run.resolve(true)\n}\n\n/** Effects in order, then the output (README: Running a line, B-29). */\nconst apply = (\n console: object,\n run: Run,\n response: CommandResponse,\n defaultTone: OutputEntry['tone']\n) => {\n const changed =\n run.contextRevision !== (contextOf(console)?.revision() ?? null)\n for (const effect of response.effects ?? []) {\n if (!(changed && contextEffects.has(effect.type))) {\n applyEffect(console, effect)\n }\n }\n const blocks = blocksOf(response.output)\n if (blocks.length > 0) {\n addEntry(\n console,\n output(response.tone ?? defaultTone, blocks, run.inputId, response.quiet)\n )\n }\n}\n\nconst fulfil = (console: object, run: Run, value: CommandReturn) => {\n run.current = false\n try {\n apply(console, run, normalizeReturn(value), 'default')\n } finally {\n cleanup(console, run)\n }\n}\n\nconst fail = (console: object, run: Run, error: unknown) => {\n run.current = false\n try {\n const { store, options } = liveRecord(console)\n store.afterCommit(() =>\n reportError(recordOf(console)?.options.onError, error, run.info)\n )\n let response: CommandResponse | undefined\n if (options.formatError) {\n try {\n response = normalizeReturn(options.formatError(error, run.info))\n } catch {\n response = undefined\n }\n }\n if (response) {\n apply(console, run, response, 'error')\n } else {\n addEntry(\n console,\n output('error', [message('command-failed')], run.inputId)\n )\n }\n } finally {\n cleanup(console, run)\n }\n}\n\n/** Ends `run` without output and without an entry (`false`, reset, dispose). */\nconst stop = (console: object, run: Run, abort: boolean) => {\n run.current = false\n if (abort) {\n run.controller.abort()\n }\n cleanup(console, run)\n}\n\n/** Runs `fn` as its own action if `run` is still current (a settle). */\nconst settle = (console: object, run: Run, fn: () => void) => {\n if (!run.current || isDisposed(console)) {\n return\n }\n const { store } = liveRecord(console)\n store.action(() => {\n if (run.current) {\n fn()\n }\n })\n}\n\n/** Handles a return that may be a promise: now, or in its own action. */\nconst whenSettled = <T>(\n console: object,\n run: Run,\n value: T | PromiseLike<T>,\n onValue: (value: T) => void\n) => {\n if (isThenable(value)) {\n Promise.resolve(value).then(\n result => settle(console, run, () => onValue(result)),\n (error: unknown) => settle(console, run, () => fail(console, run, error))\n )\n } else {\n onValue(value)\n }\n}\n\n// --- The start of a run -------------------------------------------------------\n\nconst go = (console: object, run: Run) => {\n liveRecord(console).store.update('running', running =>\n running?.runId === run.id ? { ...running, phase: 'running' } : running\n )\n const context: RunContext = {\n runId: run.id,\n inputId: run.inputId,\n signal: run.controller.signal,\n write: (out, tone) => write(console, run, out, tone)\n }\n let result: CommandReturn | Promise<CommandReturn>\n try {\n result = run.command.run(run.request, context)\n } catch (error) {\n fail(console, run, error)\n return\n }\n whenSettled(console, run, result, value => fulfil(console, run, value))\n}\n\nconst write = (\n console: object,\n run: Run,\n out: Parameters<RunContext['write']>[0],\n tone: OutputEntry['tone'] | undefined\n) => {\n settle(console, run, () => {\n const blocks = blocksOf(out)\n if (blocks.length > 0) {\n addEntry(console, output(tone ?? 'default', blocks, run.inputId))\n }\n })\n}\n\nconst start = (\n console: object,\n command: CommandDefinition,\n request: Omit<CommandRequest, 'context'>,\n inputId: string,\n sensitive: boolean\n): Promise<boolean> => {\n const { store, options } = liveRecord(console)\n const provider = contextOf(console)\n const frames: ContextFrame[] = provider?.snapshot() ?? []\n const id = newId(console)\n let resolve!: (result: boolean) => void\n const done = new Promise<boolean>(r => {\n resolve = r\n })\n const run: Run = {\n id,\n inputId,\n info: {\n runId: id,\n inputId,\n name: sensitive ? null : request.name,\n command: command.name,\n sensitive,\n context: [...frames]\n },\n request: { ...request, context: [...frames] },\n command,\n controller: new AbortController(),\n contextRevision: provider?.revision() ?? null,\n current: true,\n cleaned: false,\n resolve\n }\n stateOf(console).run = run\n const { beforeRun } = options\n store.update('running', () => ({\n runId: id,\n command: command.name,\n inputId,\n phase: beforeRun ? 'authorizing' : 'running'\n }))\n if (!beforeRun) {\n go(console, run)\n return done\n }\n let answer: ReturnType<typeof beforeRun>\n try {\n answer = beforeRun(run.info, run.controller.signal)\n } catch (error) {\n fail(console, run, error)\n return done\n }\n whenSettled(console, run, answer, value => {\n if (value === undefined) {\n go(console, run)\n } else if (value === false) {\n stop(console, run, false)\n } else {\n fulfil(console, run, value)\n }\n })\n return done\n}\n\n// --- Ending a line ------------------------------------------------------------\n\n/**\n * Ends the live input as Enter does (README: Running a line, start action).\n * Runs in the open action; resolves after the run's end, or at once when\n * nothing runs.\n */\nconst submitLine = (console: object): Promise<boolean> => {\n const { store } = liveRecord(console)\n const line = store.read().input.value\n const trimmed = line.trim()\n const prompt = currentPrompt(console)\n if (trimmed === '') {\n addEntry(console, {\n kind: 'input',\n prompt,\n text: '',\n redacted: false,\n status: 'submitted'\n })\n endLine(console, false)\n return Promise.resolve(true)\n }\n const lookup = lookupOf(console)\n const sensitive = lookup.isSensitive(line)\n const inputId = addEntry(console, {\n kind: 'input',\n prompt,\n text: sensitive ? null : trimmed,\n redacted: sensitive,\n status: 'submitted'\n })\n endLine(console, sensitive)\n if (!sensitive) {\n lineSubmitted(console, trimmed)\n }\n const parsed = tokenize(trimmed)\n if (!parsed.ok) {\n const index = sensitive ? null : parsed.error.index\n addEntry(\n console,\n output('error', [message('unterminated-quote', { index })], inputId)\n )\n return Promise.resolve(true)\n }\n const [first, second] = parsed.tokens\n const command = lookup.find(first.value)\n if (!command) {\n const name = sensitive ? null : first.value\n addEntry(\n console,\n output('error', [message('command-not-found', { name })], inputId)\n )\n return Promise.resolve(true)\n }\n return start(\n console,\n command,\n {\n name: first.value,\n command: command.name,\n args: parsed.tokens.slice(1).map(token => token.value),\n rest: second ? trimmed.slice(second.start) : '',\n line: trimmed\n },\n inputId,\n sensitive\n )\n}\n\n/**\n * Ctrl+C without a run: the line ends as cancelled (README: Cancelling and\n * errors, B-10).\n */\nconst cancelLine = (console: object) => {\n const { store } = liveRecord(console)\n const trimmed = store.read().input.value.trim()\n const sensitive = trimmed !== '' && lookupOf(console).isSensitive(trimmed)\n addEntry(console, {\n kind: 'input',\n prompt: currentPrompt(console),\n text: sensitive ? null : trimmed,\n redacted: sensitive,\n status: 'cancelled'\n })\n endLine(console, sensitive)\n}\n\n/** Ctrl+C or `cancel()` during a run: invalidate, abort, `interrupted`. */\nconst interrupt = (console: object, run: Run) => {\n run.current = false\n run.controller.abort()\n addEntry(console, output('notice', [message('interrupted')], run.inputId))\n cleanup(console, run)\n}\n\nconst cancel = (console: object) => {\n const run = stateOf(console).run\n if (run) {\n interrupt(console, run)\n } else {\n cancelLine(console)\n }\n}\n\nexport const dispatchFeature: ConsoleFeature = {\n name: 'dispatch',\n\n constructConsoleAPIs(console: AnyConsole) {\n states.set(console, { run: null, lookup: null })\n const locked = <T>(fn: () => Promise<T>, otherwise: T): Promise<T> => {\n const { store } = liveRecord(console)\n return store.action(() =>\n store.read().running === null ? fn() : Promise.resolve(otherwise)\n )\n }\n assignMethods(\n console,\n {\n submit: () => locked(() => submitLine(console), false),\n run: (line: string) =>\n locked(() => {\n replaceInput(console, line)\n return submitLine(console)\n }, false),\n cancel() {\n liveRecord(console).store.action(() => cancel(console))\n },\n isSensitive: (line: string) => lookupOf(console).isSensitive(line),\n getCommands: () => lookupOf(console).visible().map(specOf)\n },\n {\n submit: Promise.resolve(false),\n run: Promise.resolve(false),\n isSensitive: false,\n getCommands: []\n }\n )\n },\n\n init(console: AnyConsole) {\n provideCommandLookup(console, {\n find: name => lookupOf(console).find(name),\n visible: () => lookupOf(console).visible(),\n sensitiveFrom,\n matchesPredicate: line => lookupOf(console).matchesPredicate(line),\n isSensitive: line => lookupOf(console).isSensitive(line)\n })\n registerKeyAction(console, 'submit', () => {\n void submitLine(console)\n return true\n })\n registerKeyAction(console, 'cancel', () => {\n cancel(console)\n return true\n })\n onContextChange(console, () => {\n const run = stateOf(console).run\n if (run?.current && !run.controller.signal.aborted) {\n run.controller.abort()\n }\n })\n onReset(console, () => {\n const run = stateOf(console).run\n if (run) {\n stop(console, run, true)\n }\n })\n onDispose(console, () => {\n const state = stateOf(console)\n const run = state.run\n state.run = null\n if (run) {\n stop(console, run, true)\n }\n })\n }\n}\n","import type { ConsoleFeature } from '../core/console/console.types'\nimport { consoleFeature } from '../core/console/consoleFeature'\nimport { dispatchFeature } from '../core/dispatch/dispatchFeature'\nimport { entriesFeature } from '../core/entries/entriesFeature'\nimport { inputFeature } from '../core/input/inputFeature'\n\n/** The features every console has, in construction order (ADR 0002). */\nexport const coreFeatures: readonly ConsoleFeature[] = [\n consoleFeature,\n entriesFeature,\n inputFeature,\n dispatchFeature\n]\n","// The store and the action boundary (core README: Actions and notification,\n// Controlled slices; ADR 0001, ADR 0003).\n//\n// An action is one synchronous step. Inside it every change goes to a working\n// copy of the state; a call made while an action is open joins it. When the\n// outermost action ends:\n//\n// 1. each controlled slice that changed is reported once, through an updater\n// that replays the action's changes of that slice in order;\n// 2. the other slices are committed;\n// 3. the callbacks queued by the action run;\n// 4. subscribers are notified once.\n//\n// The base of a controlled slice is the value last reported, until the\n// consumer delivers one (`deliver`) or the microtask after the report runs;\n// then it is the consumer's value again. The store knows no console type: it\n// is generic over the state and the names of the controllable slices.\nimport { composeSteps, type Step } from './action'\n\nexport interface StoreConfig<S extends object, C extends keyof S> {\n /** The state on creation, controllable slices included. */\n initial: S\n /** The slices the consumer may control. */\n controllable: readonly C[]\n /** The consumer's value of slice `key`, `undefined` when not controlled. */\n external(key: C): S[C] | undefined\n /** Reports the changes of a controlled slice to the consumer. */\n report(key: C, step: Step<S[C]>): void\n /** A callback, report or subscriber threw. */\n onCallbackError(error: unknown): void\n}\n\nexport interface Store<S extends object, C extends keyof S> {\n /**\n * The committed state; controlled slices read from the consumer. The same\n * object until the next commit or delivery.\n */\n getState(): S\n /** Calls `listener` after every action that changed something. */\n subscribe(listener: (state: S) => void): () => void\n /** Runs `fn` as an action, or as part of the open one. */\n action<R>(fn: () => R): R\n /** Whether an action is open. */\n inAction(): boolean\n /** The state as the open action sees it; the committed state outside one. */\n read(): S\n /** Changes one slice inside the open action. */\n update<K extends keyof S>(key: K, step: Step<S[K]>): void\n /** Queues `callback` to run after the open action's commit. */\n afterCommit(callback: () => void): void\n /**\n * The consumer delivered new options: `keys` are the controlled slices\n * whose value it passed. Their last reported value stops being the base.\n * Must run inside an action, which then notifies.\n */\n deliver(keys: readonly C[]): void\n /** Whether slice `key` is controlled now. */\n isControlled(key: C): boolean\n /** Drops every listener and pending base and sets `state` (dispose). */\n clear(state: S): void\n}\n\ninterface OpenAction<S, C extends keyof S> {\n working: S\n steps: Map<C, Step<S[C]>[]>\n callbacks: (() => void)[]\n changed: boolean\n}\n\nexport function createStore<S extends object, C extends keyof S>(\n config: StoreConfig<S, C>\n): Store<S, C> {\n let committed: S = { ...config.initial }\n let snapshot: S | null = null\n let open: OpenAction<S, C> | null = null\n const pending = new Map<C, S[C]>()\n const listeners = new Set<(state: S) => void>()\n\n const isControlled = (key: C) => config.external(key) !== undefined\n const isControllable = (key: keyof S): key is C =>\n (config.controllable as readonly (keyof S)[]).includes(key)\n\n /** Where an action starts for a controlled slice. */\n const base = (key: C): S[C] =>\n pending.has(key) ? (pending.get(key) as S[C]) : config.external(key)!\n\n const getState = (): S => {\n if (snapshot === null) {\n const state = { ...committed }\n for (const key of config.controllable) {\n if (isControlled(key)) {\n state[key] = config.external(key)!\n }\n }\n snapshot = state\n }\n return snapshot\n }\n\n const guarded = (fn: () => void) => {\n try {\n fn()\n } catch (error) {\n config.onCallbackError(error)\n }\n }\n\n const commit = (action: OpenAction<S, C>) => {\n const reports: [C, Step<S[C]>][] = []\n for (const [key, steps] of action.steps) {\n if (isControlled(key)) {\n reports.push([key, composeSteps(steps)])\n pending.set(key, action.working[key])\n }\n }\n committed = action.working\n if (action.changed) {\n snapshot = null\n }\n for (const [key, step] of reports) {\n guarded(() => config.report(key, step))\n const reported = action.working[key]\n // The only scheduling the core does (core README: Actions and\n // notification): after this tick the consumer's own value is the base\n // again.\n void Promise.resolve().then(() => {\n if (pending.get(key) === reported) {\n pending.delete(key)\n }\n })\n }\n for (const callback of action.callbacks) {\n guarded(callback)\n }\n if (action.changed) {\n const state = getState()\n for (const listener of [...listeners]) {\n guarded(() => listener(state))\n }\n }\n }\n\n const requireOpen = (): OpenAction<S, C> => {\n if (open === null) {\n throw new Error('A state change must run inside an action.')\n }\n return open\n }\n\n return {\n getState,\n subscribe(listener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n action(fn) {\n if (open !== null) {\n return fn()\n }\n const working = { ...committed }\n for (const key of config.controllable) {\n if (isControlled(key)) {\n working[key] = base(key)\n }\n }\n const action: OpenAction<S, C> = {\n working,\n steps: new Map(),\n callbacks: [],\n changed: false\n }\n open = action\n try {\n return fn()\n } finally {\n open = null\n commit(action)\n }\n },\n inAction: () => open !== null,\n read: () => (open === null ? getState() : open.working),\n update(key, step) {\n const action = requireOpen()\n const old = action.working[key]\n const next = step(old)\n if (Object.is(old, next)) {\n return\n }\n action.working[key] = next\n action.changed = true\n if (isControllable(key) && isControlled(key)) {\n const steps = action.steps.get(key) ?? []\n steps.push(step as unknown as Step<S[C]>)\n action.steps.set(key, steps)\n }\n },\n afterCommit(callback) {\n requireOpen().callbacks.push(callback)\n },\n deliver(keys) {\n const action = requireOpen()\n snapshot = null\n action.changed = true\n for (const key of keys) {\n pending.delete(key)\n if (isControlled(key)) {\n // The action's own changes so far, replayed on the delivered value.\n action.working[key] = composeSteps(action.steps.get(key) ?? [])(\n base(key)\n )\n }\n }\n },\n isControlled,\n clear(state) {\n committed = { ...state }\n snapshot = null\n pending.clear()\n listeners.clear()\n }\n }\n}\n","// Builds a console from its features (ADR 0002, TanStack v9 shape): the\n// options merge the features' defaults, the initial state takes\n// `initialState` and each feature's adjustment, then every feature assigns\n// its methods and, once all methods exist, registers its hooks.\nimport type {\n AnyConsole,\n AnyConsoleOptions,\n ConsoleFeature,\n ControlledSlice,\n OptionalFeatures\n} from './console.types'\nimport { reportCallbackError } from './console.utils'\nimport {\n emptyState,\n mergeOptions,\n rememberConstruction\n} from './consoleFeature'\nimport { createRecord, type SharedRecord } from '../../shared'\nimport { createStore } from '../../store/createStore'\nimport { validateCommands } from '../dispatch/dispatch.utils'\n\n/** The keys of `options.features`, in construction order. */\nconst optionalFeatureKeys: readonly (keyof OptionalFeatures)[] = [\n 'recallFeature',\n 'completionFeature',\n 'contextFeature'\n]\n\nconst controllable: readonly ControlledSlice[] = [\n 'entries',\n 'recall',\n 'context'\n]\n\nconst reporters = {\n entries: 'onEntriesChange',\n recall: 'onRecallChange',\n context: 'onContextChange'\n} as const\n\n/**\n * Builds a console from `core` (the always-present features, in order) and\n * the optional features in `options.features`. Throws on an unknown feature\n * key or an invalid command set; calls nothing of the consumer's.\n */\nexport function constructConsole(\n options: AnyConsoleOptions,\n core: readonly ConsoleFeature[]\n): AnyConsole {\n const given = (options.features ?? {}) as Record<string, unknown>\n for (const key of Object.keys(given)) {\n if (!(optionalFeatureKeys as readonly string[]).includes(key)) {\n throw new Error(\n `Unknown feature ${key}; the features are ${optionalFeatureKeys.join(', ')}.`\n )\n }\n }\n const features = [\n ...core,\n ...optionalFeatureKeys\n .filter(key => given[key] !== undefined)\n .map(key => given[key] as ConsoleFeature)\n ]\n\n const defaults: Partial<AnyConsoleOptions> = Object.assign(\n {},\n ...features.map(feature => feature.getDefaultOptions?.() ?? {})\n ) as Partial<AnyConsoleOptions>\n const merged = mergeOptions(defaults, options)\n validateCommands(merged.commands)\n\n let initial = emptyState()\n for (const slice of controllable) {\n const value = merged.initialState?.[slice]\n if (value !== undefined) {\n initial = { ...initial, [slice]: value }\n }\n }\n for (const feature of features) {\n initial = feature.getInitialState?.(initial) ?? initial\n }\n\n const console = {} as AnyConsole\n const optionsNow = (): SharedRecord['options'] | undefined => record?.options\n let record: SharedRecord | undefined = undefined\n const store = createStore({\n initial,\n controllable,\n external: slice => optionsNow()?.state?.[slice],\n report: (slice, step) => {\n const callback = optionsNow()?.[reporters[slice]] as\n ((updater: typeof step) => void) | undefined\n callback?.(step)\n },\n onCallbackError: error => reportCallbackError(console, error)\n })\n record = createRecord(console, store, merged)\n rememberConstruction(console, defaults, initial)\n\n for (const feature of features) {\n feature.constructConsoleAPIs?.(console)\n }\n for (const feature of features) {\n feature.init?.(console)\n }\n return console\n}\n","import { coreFeatures } from './coreFeatures'\nimport type {\n Console,\n ConsoleOptions,\n OptionalFeatures\n} from '../core/console/console.types'\nimport { constructConsole } from '../core/console/constructConsole'\n\n/**\n * Keeps the type of a features object, so it can be declared once, outside\n * a component, and passed to `createConsole` (ADR 0002).\n *\n * @example\n * ```ts\n * const features = consoleFeatures({ recallFeature, contextFeature })\n * const console = createConsole({ features, commands })\n * ```\n */\nexport function consoleFeatures<T extends Partial<OptionalFeatures>>(\n features: T\n): T {\n return features\n}\n\n/**\n * Creates a console with the core features and the optional ones in\n * `options.features`. Nothing runs and nothing is called on creation.\n * Throws when a command name is invalid or repeats (C-56).\n */\n// `{}` and not its constraint: without `features` the console has no\n// optional method (ADR 0002, C-01).\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport function createConsole<T extends Partial<OptionalFeatures> = {}>(\n options: ConsoleOptions<T>\n): Console<T> {\n return constructConsole(options, coreFeatures) as unknown as Console<T>\n}\n","import type { ContextFrame } from '@dolusoft/command-protocol'\n\n/**\n * The id sequence of `frames`, as one comparable string. Two stacks with the\n * same ids in the same order are the same context (core README: Controlled\n * slices).\n */\nexport const idsOf = (frames: readonly ContextFrame[]): string =>\n JSON.stringify(frames.map(frame => frame.id))\n\n/** `frames` with `frame` on top. */\nexport const pushFrame = (\n frames: ContextFrame[],\n frame: ContextFrame\n): ContextFrame[] => [...frames, frame]\n\n/**\n * `frames` without its top `count` frames; stops at the root. `count` is\n * rounded down; a count below 1 (or `NaN`) pops nothing, and nothing popped\n * gives `frames` back unchanged.\n */\nexport const popFrames = (\n frames: ContextFrame[],\n count: number\n): ContextFrame[] => {\n const n = Number.isNaN(count) ? 0 : Math.floor(count)\n if (n < 1 || frames.length === 0) {\n return frames\n }\n return frames.slice(0, Math.max(0, frames.length - n))\n}\n\n/** The root: no frame. `frames` itself when it is already empty. */\nexport const resetFrames = (frames: ContextFrame[]): ContextFrame[] =>\n frames.length === 0 ? frames : []\n","// The context feature (README: Context; core README: Controlled slices): a\n// stack of frames, bottom → top, with an implicit root. The top frame sets the\n// prompt of the next input entry. A run takes a snapshot of the frames and the\n// revision at its start; dispatch drops the context effects of a run whose\n// context changed by someone else, and this feature tells it when that happens.\nimport type { ContextFrame } from '@dolusoft/command-protocol'\n\nimport { idsOf, popFrames, pushFrame, resetFrames } from './context.utils'\nimport type {\n AnyConsole,\n ConsoleFeature,\n ContextFeature\n} from '../../core/console/console.types'\nimport {\n assignMethods,\n contextChanged,\n handleEffect,\n liveRecord,\n onControlledChange,\n provideContext,\n providePrompt\n} from '../../shared'\n\n/** What the feature keeps per console: the revision and the ids it counts. */\ninterface Revision {\n value: number\n /** The id sequence the value was counted for. */\n ids: string\n}\n\nconst revisions = new WeakMap<object, Revision>()\n\nconst framesOf = (console: object): ContextFrame[] =>\n liveRecord(console).store.read().context\n\n/**\n * The revision now. It changes whenever the id sequence differs from the one\n * it was last counted for, so a change nobody announced (a controlled value\n * the consumer did not hand back) still counts.\n */\nconst revisionOf = (console: object): number => {\n const revision = revisions.get(console)!\n const ids = idsOf(framesOf(console))\n if (ids !== revision.ids) {\n revision.ids = ids\n revision.value++\n }\n return revision.value\n}\n\n/** A known change: always a new revision, even if the ids come back. */\nconst markChanged = (console: object) => {\n const revision = revisions.get(console)!\n revision.ids = idsOf(framesOf(console))\n revision.value++\n}\n\n/**\n * Changes the stack in the open action. `byOther`: the change does not come\n * from a run's effects, so a running command's context is stale (C-62).\n */\nconst change = (\n console: object,\n step: (frames: ContextFrame[]) => ContextFrame[],\n byOther: boolean\n) => {\n const { store } = liveRecord(console)\n const before = store.read().context\n store.update('context', step)\n if (store.read().context === before) {\n return\n }\n markChanged(console)\n if (byOther) {\n contextChanged(console)\n }\n}\n\nconst feature = {\n name: 'context',\n\n constructConsoleAPIs(console: AnyConsole) {\n const act = (step: (frames: ContextFrame[]) => ContextFrame[]): void => {\n liveRecord(console).store.action(() => change(console, step, true))\n }\n assignMethods(console, {\n pushContext: (frame: ContextFrame) =>\n act(frames => pushFrame(frames, frame)),\n popContext: (count = 1) => act(frames => popFrames(frames, count)),\n resetContext: () => act(resetFrames)\n })\n },\n\n init(console: AnyConsole) {\n revisions.set(console, { value: 0, ids: idsOf(framesOf(console)) })\n providePrompt(console, () => framesOf(console).at(-1)?.prompt ?? null)\n provideContext(console, {\n snapshot: () => [...framesOf(console)],\n revision: () => revisionOf(console)\n })\n handleEffect(console, 'push-context', effect =>\n change(console, frames => pushFrame(frames, effect.frame), false)\n )\n handleEffect(console, 'pop-context', effect =>\n change(console, frames => popFrames(frames, effect.count ?? 1), false)\n )\n handleEffect(console, 'reset-context', () =>\n change(console, resetFrames, false)\n )\n // An external `context` with another id sequence is a context change; a\n // new array with the same ids is not (core README: Controlled slices).\n onControlledChange(console, controlled => {\n if (\n controlled.slice === 'context' &&\n idsOf(controlled.previous) !== idsOf(controlled.next)\n ) {\n markChanged(console)\n contextChanged(console)\n }\n })\n }\n} satisfies ConsoleFeature\n\n/**\n * The context feature: a stack of frames whose top sets the prompt. Adds\n * `pushContext`, `popContext` and `resetContext`, and applies the\n * `push-context`, `pop-context` and `reset-context` effects.\n *\n * @example\n * ```ts\n * const console = createConsole({ features: { contextFeature }, commands })\n * console.pushContext({ id: 'db', prompt: 'db>' })\n * ```\n */\nexport const contextFeature: ContextFeature = feature\n","// Pure helpers of the recall feature (README: Recall).\n\n/** The default of `options.recallLimit`. */\nexport const defaultRecallLimit = 100\n\n/**\n * The most lines recall keeps: a non-negative integer, `Infinity` allowed.\n * Anything else falls back to the default.\n */\nexport const limitOf = (limit: number | undefined): number => {\n if (limit === undefined || Number.isNaN(limit)) {\n return defaultRecallLimit\n }\n return limit === Infinity ? limit : Math.max(0, Math.floor(limit))\n}\n\n/**\n * `recall` with `line` recorded: an equal line already present moves to the\n * newest position, and the oldest lines beyond `limit` are dropped. Returns\n * `recall` itself when nothing changes; never mutates it.\n */\nexport const recordLine = (\n recall: readonly string[],\n line: string,\n limit: number\n): string[] => {\n if (recall.length > 0 && recall[recall.length - 1] === line) {\n return recall.length > limit\n ? recall.slice(recall.length - limit)\n : (recall as string[])\n }\n const next = [...recall.filter(old => old !== line), line]\n return next.length > limit ? next.slice(next.length - limit) : next\n}\n","// The recall feature (README: Recall, Keyboard): the submitted lines, oldest →\n// newest, browsed with ArrowUp / ArrowDown. The list is a controllable slice\n// (`recall`); the cursor and the draft are internal and die with the line.\n//\n// A sensitive line never reaches the list (dispatch does not call\n// `onLineSubmitted` for it) and never becomes the draft: browsing away from a\n// sensitive input keeps an empty draft and replaces the input element (C-31).\nimport { limitOf, recordLine, defaultRecallLimit } from './recall.utils'\nimport type {\n AnyConsole,\n ConsoleFeature,\n RecallFeature\n} from '../../core/console/console.types'\nimport {\n assignMethods,\n handleEffect,\n liveRecord,\n lookupOf,\n onControlledChange,\n onInputChange,\n onLineCleared,\n onLineSubmitted,\n registerKeyAction,\n writeInput\n} from '../../shared'\n\n/** Ends browsing: drops the cursor and the draft, keeps the input. */\nconst endBrowsing = (console: object): void => {\n const { store } = liveRecord(console)\n store.update('recallCursor', () => null)\n store.update('recallDraft', () => null)\n}\n\n/** Shows `line` in the input, the caret at its end. */\nconst show = (console: object, line: string): void =>\n writeInput(console, line, line.length, 'recall')\n\n/** ArrowUp: keeps the draft on the first press, then goes older. */\nconst previous = (console: object): boolean => {\n const { store } = liveRecord(console)\n return store.action(() => {\n const { running, recall, recallCursor, input } = store.read()\n if (running !== null || recall.length === 0) {\n return false\n }\n let next: number\n if (recallCursor === null) {\n const sensitive =\n input.value.trim() !== '' && lookupOf(console).isSensitive(input.value)\n if (sensitive) {\n // A programmatic clear replaces the element that held the line\n // (README: Sensitive lines), so its undo history goes with it.\n writeInput(console, '', 0, 'recall')\n }\n store.update('recallDraft', () => (sensitive ? '' : input.value))\n next = recall.length - 1\n } else {\n next = Math.min(recallCursor, recall.length) - 1\n if (next < 0) {\n return false\n }\n }\n store.update('recallCursor', () => next)\n show(console, recall[next])\n return true\n })\n}\n\n/** ArrowDown: goes newer; past the newest restores the draft. */\nconst following = (console: object): boolean => {\n const { store } = liveRecord(console)\n return store.action(() => {\n const { running, recall, recallCursor, recallDraft } = store.read()\n if (running !== null || recallCursor === null) {\n return false\n }\n const next = recallCursor + 1\n if (next >= recall.length) {\n endBrowsing(console)\n show(console, recallDraft ?? '')\n return true\n }\n store.update('recallCursor', () => next)\n show(console, recall[next])\n return true\n })\n}\n\n/** Empties the list and ends browsing (README: Recall, C-23). */\nconst clear = (console: object): void => {\n const { store } = liveRecord(console)\n store.update('recall', old => (old.length === 0 ? old : []))\n endBrowsing(console)\n}\n\n/**\n * Records a submitted line. `shouldRecord` runs first; a throwing\n * `shouldRecord` records nothing and its error goes to `onError` after the\n * action, like any callback's.\n */\nconst record = (console: object, line: string): void => {\n const { store, options } = liveRecord(console)\n let keep: boolean\n try {\n keep = options.shouldRecord?.(line) ?? true\n } catch (error) {\n keep = false\n store.afterCommit(() => {\n throw error\n })\n }\n if (!keep) {\n return\n }\n const limit = limitOf(options.recallLimit)\n store.update('recall', old => recordLine(old, line, limit))\n}\n\nconst feature: ConsoleFeature & RecallFeature = {\n name: 'recall',\n\n getDefaultOptions: () => ({ recallLimit: defaultRecallLimit }),\n\n constructConsoleAPIs(console: AnyConsole) {\n assignMethods(\n console,\n {\n recallPrevious: () => previous(console),\n recallNext: () => following(console),\n clearRecall() {\n const { store } = liveRecord(console)\n store.action(() => clear(console))\n }\n },\n { recallPrevious: false, recallNext: false }\n )\n },\n\n init(console: AnyConsole) {\n registerKeyAction(console, 'recallPrevious', () => previous(console))\n registerKeyAction(console, 'recallNext', () => following(console))\n handleEffect(console, 'clear-recall', () => clear(console))\n onLineSubmitted(console, line => record(console, line))\n onLineCleared(console, () => endBrowsing(console))\n onInputChange(console, change => {\n // Any edit that is not recall's own ends browsing; a caret move does\n // not, and the edited text stays.\n if (change.origin !== 'recall' && change.value !== change.previousValue) {\n endBrowsing(console)\n }\n })\n onControlledChange(console, change => {\n if (change.slice === 'recall') {\n endBrowsing(console)\n }\n })\n }\n}\n\n/**\n * The recall feature: ArrowUp / ArrowDown browse the submitted lines\n * (`recallPrevious`, `recallNext`, `clearRecall`). Options: `recallLimit`\n * (default 100), `shouldRecord`.\n *\n * @example\n * ```ts\n * const console = createConsole({ features: { recallFeature }, commands })\n * ```\n */\nexport const recallFeature: RecallFeature = feature\n","// Pure helpers of the completion feature (README: Completion): the token at the\n// caret, the filter, the longest common prefix and the quoting of written text.\nimport { quoteArgument, tokenize, type Token } from '@dolusoft/command-protocol'\n\nimport type { Quote, Target } from './completion.types'\n\n/** The opening quote of a token's raw text; `null` for a bare token. */\nexport const quoteOf = (raw: string): Quote | null => {\n const token = tokenize(raw).tokens[0] as Token | undefined\n if (!token || !(token.quoted || token.open)) {\n return null\n }\n return /['\"]/.exec(raw)![0] as Quote\n}\n\n/**\n * The token completion works on (README: Completion): the tolerant token whose\n * raw span contains the caret (its end included), else an empty token at the\n * caret.\n */\nexport const targetAt = (line: string, caret: number): Target => {\n const { tokens } = tokenize(line)\n const at = tokens.findIndex(\n token => token.start <= caret && caret <= token.end\n )\n if (at !== -1) {\n const token = tokens[at]\n const raw = line.slice(token.start, token.end)\n return {\n position: at,\n start: token.start,\n end: token.end,\n raw,\n prefix: token.value,\n quote: quoteOf(raw),\n before: tokens.slice(0, at).map(t => t.value)\n }\n }\n const before = tokens.filter(token => token.end <= caret).map(t => t.value)\n return {\n position: before.length,\n start: caret,\n end: caret,\n raw: '',\n prefix: '',\n quote: null,\n before\n }\n}\n\n/** Whether only whitespace follows `end` in `line`. */\nexport const isLast = (line: string, end: number): boolean =>\n line.slice(end).trim() === ''\n\n/**\n * Keeps the candidates whose lowercase starts with the lowercase `prefix`,\n * in their order, without duplicates and without empty strings or\n * non-strings (README: Completion). Returns a new array.\n */\nexport const filterCandidates = (\n candidates: readonly unknown[],\n prefix: string\n): string[] => {\n const lower = prefix.toLowerCase()\n const kept = new Set<string>()\n for (const candidate of candidates) {\n if (\n typeof candidate === 'string' &&\n candidate !== '' &&\n candidate.toLowerCase().startsWith(lower)\n ) {\n kept.add(candidate)\n }\n }\n return [...kept]\n}\n\n/**\n * The longest prefix every candidate shares, compared case-insensitively,\n * in the case of the first candidate.\n */\nexport const commonPrefix = (candidates: readonly string[]): string => {\n const [first, ...others] = candidates\n let length = first.length\n for (const other of others) {\n let i = 0\n while (\n i < length &&\n i < other.length &&\n first[i].toLowerCase() === other[i].toLowerCase()\n ) {\n i++\n }\n length = i\n }\n return first.slice(0, length)\n}\n\n/**\n * `text` as it is written into a token's span (C-40). A quoted or open\n * token keeps its quote character, escaped for it (a `'` token whose text\n * holds a `'` switches to `\"`, the only quote that can carry it). A bare\n * token opens a quote only when the text needs one: `'`, or `\"` when the\n * text holds a `'`. `close` writes the closing quote.\n */\nexport const encode = (\n text: string,\n quote: Quote | null,\n close: boolean\n): string => {\n let q = quote\n if (q === null) {\n if (quoteArgument(text) === text) {\n return text\n }\n q = text.includes(\"'\") ? '\"' : \"'\"\n }\n if (q === \"'\" && text.includes(\"'\")) {\n q = '\"'\n }\n const body = q === '\"' ? text.replace(/[\\\\\"]/g, char => `\\\\${char}`) : text\n return `${q}${body}${close ? q : ''}`\n}\n\n/** `line` with `[start, end)` replaced by `text`. */\nexport const splice = (\n line: string,\n start: number,\n end: number,\n text: string\n): string => line.slice(0, start) + text + line.slice(end)\n","// The completion feature (README: Completion, Keyboard, ADR 0006): Tab\n// completes the token at the caret from the visible command names or the\n// command's `complete`. The candidate list is session state, never an\n// entry. Argument positions at or after a command's `fromArg` (all of them\n// for `sensitive: true` or a predicate match) call no provider and open no\n// session (P16, C-35).\nimport type { Found, Target } from './completion.types'\nimport {\n commonPrefix,\n encode,\n filterCandidates,\n isLast,\n quoteOf,\n splice,\n targetAt\n} from './completion.utils'\nimport type {\n AnyConsole,\n CompletionFeature,\n CompletionSession,\n ConsoleFeature\n} from '../../core/console/console.types'\nimport type { CompletionResult } from '../../core/dispatch/dispatch.types'\nimport {\n assignMethods,\n contextOf,\n liveRecord,\n lookupOf,\n onInputChange,\n onKey,\n onLineCleared,\n registerKeyAction,\n writeInput\n} from '../../shared'\n\nconst none: Found = { candidates: [], final: true }\n\nconst read = (console: object) => liveRecord(console).store.read()\n\nconst setSession = (console: object, session: CompletionSession | null) =>\n liveRecord(console).store.update('completion', () => session)\n\nconst write = (console: object, value: string, caret: number) =>\n writeInput(console, value, caret, 'completion')\n\n/** A provider's result as candidates; anything else gives none. */\nconst resultOf = (result: CompletionResult, prefix: string): Found => {\n if (Array.isArray(result)) {\n return { candidates: filterCandidates(result, prefix), final: true }\n }\n if (\n typeof result === 'object' &&\n result !== null &&\n Array.isArray(result.candidates)\n ) {\n return {\n candidates: filterCandidates(result.candidates, prefix),\n final: result.final !== false\n }\n }\n return none\n}\n\n/**\n * The candidates of `target` (C-37, C-38), or `null` when its position is\n * not safe: then no provider is called and no session opens.\n * A line the predicate marks is unsafe everywhere, its name included; an\n * unknown first token that names a sensitive command case-insensitively is\n * unsafe at every argument position.\n */\nconst candidatesOf = (\n console: object,\n line: string,\n target: Target\n): Found | null => {\n const lookup = lookupOf(console)\n if (lookup.matchesPredicate(line)) {\n return null\n }\n if (target.position === 0) {\n const names = lookup\n .visible()\n .flatMap(command => [command.name, ...(command.aliases ?? [])])\n return { candidates: filterCandidates(names, target.prefix), final: true }\n }\n const command = lookup.find(target.before[0])\n if (!command) {\n return lookup.isSensitive(line) ? null : none\n }\n const index = target.position - 1\n const from = lookup.sensitiveFrom(command)\n if (from !== null && index >= from) {\n return null\n }\n if (typeof command.complete !== 'function') {\n return none\n }\n try {\n return resultOf(\n command.complete({\n command: command.name,\n args: target.before.slice(1),\n prefix: target.prefix,\n index,\n context: contextOf(console)?.snapshot() ?? []\n }),\n target.prefix\n )\n } catch {\n return none\n }\n}\n\n/**\n * Writes a completed candidate into `[start, end)` (closed), then the space\n * of step 5 when `space` holds: a whitespace already after the span is\n * stepped over instead of doubled.\n */\nconst writeCompleted = (\n console: object,\n start: number,\n end: number,\n text: string,\n space: boolean\n) => {\n const value = splice(read(console).input.value, start, end, text)\n const after = start + text.length\n if (!space) {\n write(console, value, after)\n } else if (/\\s/.test(value.charAt(after))) {\n write(console, value, after + 1)\n } else {\n write(console, splice(value, after, after, ' '), after + 1)\n }\n}\n\n/** Tab with no session (C-37 to C-41); `false` when nothing was done. */\nconst complete = (console: object): boolean => {\n const { input, running } = read(console)\n if (running !== null || input.value === '') {\n return false\n }\n setSession(console, null)\n const target = targetAt(input.value, input.caret)\n const found = candidatesOf(console, input.value, target)\n if (found === null) {\n return false\n }\n const { candidates, final } = found\n const { start, end, raw, quote } = target\n if (candidates.length === 0) {\n setSession(console, {\n status: 'none',\n candidates: [],\n final,\n active: -1,\n span: { start, end },\n original: raw\n })\n return true\n }\n if (candidates.length === 1) {\n writeCompleted(\n console,\n start,\n end,\n encode(candidates[0], quote, true),\n final && isLast(input.value, end)\n )\n return true\n }\n let spanEnd = end\n const shared = commonPrefix(candidates)\n if (shared.length > target.prefix.length) {\n const text = encode(shared, quote, false)\n spanEnd = start + text.length\n write(console, splice(input.value, start, end, text), spanEnd)\n }\n setSession(console, {\n status: 'open',\n candidates,\n final,\n active: -1,\n span: { start, end: spanEnd },\n original: raw\n })\n return true\n}\n\nconst openSession = (console: object): CompletionSession | null => {\n const session = read(console).completion\n return session?.status === 'open' ? session : null\n}\n\n/** Selects the next (`1`) or previous (`-1`) candidate, with wrap (step 8). */\nconst select = (console: object, step: 1 | -1): boolean => {\n const session = openSession(console)\n if (!session) {\n return false\n }\n const count = session.candidates.length\n const active =\n session.active === -1\n ? step === 1\n ? 0\n : count - 1\n : (session.active + step + count) % count\n const text = encode(\n session.candidates[active],\n quoteOf(session.original),\n true\n )\n const { start, end } = session.span\n write(\n console,\n splice(read(console).input.value, start, end, text),\n start + text.length\n )\n setSession(console, {\n ...session,\n active,\n span: { start, end: start + text.length }\n })\n return true\n}\n\n/** Enter on a selected candidate: the space of step 5, session closed. */\nconst accept = (console: object): boolean => {\n const session = openSession(console)\n if (!session || session.active === -1) {\n return false\n }\n const value = read(console).input.value\n const { start, end } = session.span\n setSession(console, null)\n writeCompleted(\n console,\n start,\n end,\n value.slice(start, end),\n session.final && isLast(value, end)\n )\n return true\n}\n\n/** Escape: the original token back, session closed. */\nconst close = (console: object): boolean => {\n const session = read(console).completion\n if (!session) {\n return false\n }\n setSession(console, null)\n if (session.status === 'open') {\n const { start, end } = session.span\n write(\n console,\n splice(read(console).input.value, start, end, session.original),\n start + session.original.length\n )\n }\n return true\n}\n\nconst feature = {\n name: 'completion',\n\n constructConsoleAPIs(console: AnyConsole) {\n const action = (fn: () => boolean) => () =>\n liveRecord(console).store.action(() =>\n read(console).running === null ? fn() : false\n )\n assignMethods(\n console,\n {\n complete: action(() => complete(console)),\n completeNext: action(() => select(console, 1) || complete(console)),\n completePrevious: action(() => select(console, -1)),\n acceptCompletion: action(() => accept(console)),\n closeCompletion: action(() => close(console))\n },\n {\n complete: false,\n completeNext: false,\n completePrevious: false,\n acceptCompletion: false,\n closeCompletion: false\n }\n )\n },\n\n init(console: AnyConsole) {\n registerKeyAction(console, 'completeNext', () => {\n if (select(console, 1)) {\n return true\n }\n // Tab on a non-empty input is always taken, even when nothing can be\n // completed; on an empty input it moves focus (README: Keyboard, C-59).\n complete(console)\n return read(console).input.value !== ''\n })\n registerKeyAction(console, 'completePrevious', () => select(console, -1))\n registerKeyAction(console, 'selectNext', () => select(console, 1))\n registerKeyAction(console, 'selectPrevious', () => select(console, -1))\n registerKeyAction(console, 'acceptCompletion', () => accept(console))\n registerKeyAction(console, 'closeCompletion', () =>\n openSession(console) ? close(console) : false\n )\n // A session with no candidates closes on the next key (step 4).\n onKey(console, () => {\n if (read(console).completion?.status === 'none') {\n setSession(console, null)\n }\n })\n // Any edit or caret move the session did not make closes it (step 8).\n onInputChange(console, change => {\n if (change.origin !== 'completion' && read(console).completion) {\n setSession(console, null)\n }\n })\n onLineCleared(console, () => setSession(console, null))\n }\n} satisfies ConsoleFeature & CompletionFeature\n\n/**\n * The completion feature: Tab completes command names and, through a\n * command's `complete`, its safe arguments (README: Completion).\n *\n * @example\n * ```ts\n * const console = createConsole({ commands, features: { completionFeature } })\n * ```\n */\nexport const completionFeature: CompletionFeature = feature\n"],"mappings":"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"}
1
+ {"version":3,"file":"command-console-core.js","names":["lookupOf","controllable","clear","write","close","write","feature","lookupOf","feature","lookupOf"],"sources":["../src/shared/registry.ts","../src/shared/hooks.ts","../src/shared/effects.ts","../src/shared/keys.ts","../src/shared/lifecycle.ts","../src/core/console/console.utils.ts","../src/store/action.ts","../src/core/dispatch/dispatch.utils.ts","../src/core/dispatch/operation.ts","../src/core/console/consoleFeature.ts","../src/core/dispatch/commandError.ts","../src/core/dispatch/sensitivity.ts","../src/core/entries/entries.utils.ts","../src/core/entries/entriesFeature.ts","../src/core/input/inputFeature.ts","../src/core/dispatch/dispatchFeature.ts","../src/helpers/coreFeatures.ts","../src/store/createStore.ts","../src/core/console/constructConsole.ts","../src/helpers/consoleFeatures.ts","../src/helpers/agentTools.ts","../src/features/context/context.utils.ts","../src/features/context/contextFeature.ts","../src/features/recall/recall.utils.ts","../src/features/recall/recallFeature.ts","../src/features/completion/completion.utils.ts","../src/features/completion/completionFeature.ts"],"sourcesContent":["// The per-console record of shared/ (ADR 0002): everything the\n// features have in common. It is keyed by the console instance in a WeakMap\n// and dropped on dispose, so it never keeps a disposed console alive and a\n// late call (a settling promise, an event after unmount) finds nothing.\nimport type { Hooks } from './hooks'\nimport type {\n AnyConsoleOptions,\n ConsoleState,\n ControlledSlice\n} from '../core/console/console.types'\nimport type { Store } from '../store/createStore'\n\n/** The store of a console. */\nexport type ConsoleStore = Store<ConsoleState, ControlledSlice>\n\n/** What every feature of one console shares. */\nexport interface SharedRecord {\n store: ConsoleStore\n /** The options with the features' defaults merged; replaced by `setOptions`. */\n options: AnyConsoleOptions & { prompt: string }\n hooks: Hooks\n}\n\nconst createHooks = (): Hooks => ({\n lineSubmitted: [],\n lineCleared: [],\n inputChanged: [],\n key: [],\n controlledChanged: [],\n contextChanged: [],\n reset: [],\n disposers: [],\n prompt: null,\n context: null,\n commandLookup: null,\n inputWriter: null,\n effects: {},\n keyActions: {}\n})\n\nconst records = new WeakMap<object, SharedRecord>()\nconst disposed = new WeakSet<object>()\n\n/** Creates the record of `console` (the engine, on construction). */\nexport const createRecord = (\n console: object,\n store: ConsoleStore,\n options: SharedRecord['options']\n): SharedRecord => {\n const record: SharedRecord = { store, options, hooks: createHooks() }\n records.set(console, record)\n return record\n}\n\n/** The record of `console`; `null` once it is disposed. */\nexport const recordOf = (console: object): SharedRecord | null =>\n records.get(console) ?? null\n\n/**\n * The record of a live console. For code that only runs while the console\n * lives (a method behind `assignMethods`, a registered hook).\n */\nexport const liveRecord = (console: object): SharedRecord => {\n const record = records.get(console)\n if (!record) {\n throw new Error('The console is disposed.')\n }\n return record\n}\n\n/** Drops the record of `console` for good and returns it, once. */\nexport const takeRecord = (console: object): SharedRecord | null => {\n const record = records.get(console) ?? null\n records.delete(console)\n disposed.add(console)\n return record\n}\n\n/** Whether `dispose()` ran for `console`. */\nexport const isDisposed = (console: object): boolean => disposed.has(console)\n","// The hooks features talk through (ADR 0002). An optional feature\n// never imports another feature or a core feature folder at run time: what\n// one needs from another is registered here by the feature that has it and\n// called by the one that needs it. Every function takes the console instance\n// and does nothing once it is disposed.\n//\n// Hooks run inside the action that calls them; a hook that changes state\n// does it through the store of the record (`liveRecord(console).store`),\n// so its changes join that action.\nimport type { ConsoleEffect, ContextFrame } from '@dolusoft/command-protocol'\n\nimport type { KeyActionName, KeyInput } from './keys'\nimport { liveRecord, recordOf } from './registry'\nimport type {\n ControllableState,\n ControlledSlice,\n FeatureName\n} from '../core/console/console.types'\nimport type { CommandDefinition } from '../core/dispatch/dispatch.types'\n\n/**\n * Who wrote the input: a feature, or `null` for `setInput` (the adapter on a\n * user edit or caret move, or the consumer).\n */\nexport type InputOrigin = FeatureName | null\n\n/** One change of the live input, as `onInputChange` hooks see it. */\nexport interface InputChange {\n value: string\n caret: number\n previousValue: string\n previousCaret: number\n origin: InputOrigin\n}\n\n/** A controlled slice the consumer replaced through `setOptions`. */\nexport type ControlledChange = {\n [K in ControlledSlice]: {\n slice: K\n previous: ControllableState[K]\n next: ControllableState[K]\n }\n}[ControlledSlice]\n\n/** The context stack as dispatch and completion read it. */\nexport interface ContextProvider {\n /** The frames now, bottom → top (a copy the caller may keep). */\n snapshot(): ContextFrame[]\n /**\n * A number that changes on every context change (by id sequence, core\n * README: Controlled slices). A run keeps the value it started with.\n */\n revision(): number\n}\n\n/** The commands as completion (and recall) see them. */\nexport interface CommandLookup {\n /** The command a name or alias runs, matched exactly (case-sensitive). */\n find(name: string): CommandDefinition | undefined\n /** The commands that are not `hidden`, in registration order. */\n visible(): CommandDefinition[]\n /**\n * The first argument position that is secret: `0` for `sensitive: true`,\n * `fromArg` for `{ fromArg }`, `null` for a command that is not sensitive.\n */\n sensitiveFrom(command: CommandDefinition): number | null\n /**\n * Whether `options.isSensitive` marks `line` (a throwing predicate counts\n * as a match). A match makes every argument position unsafe.\n */\n matchesPredicate(line: string): boolean\n /** Whether `line` is sensitive (README: Sensitive lines). */\n isSensitive(line: string): boolean\n}\n\n/** Writes the live input on behalf of a feature (registered by input). */\nexport type InputWriter = (\n value: string,\n caret: number,\n origin: InputOrigin\n) => void\n\n/** An effect handler; runs inside the action of the run's end. */\nexport type EffectHandler<T extends ConsoleEffect['type']> = (\n effect: Extract<ConsoleEffect, { type: T }>\n) => void\n\n/** The hooks of one console. Read through the functions below. */\nexport interface Hooks {\n lineSubmitted: ((line: string) => void)[]\n lineCleared: (() => void)[]\n inputChanged: ((change: InputChange) => void)[]\n key: ((input: KeyInput) => void)[]\n controlledChanged: ((change: ControlledChange) => void)[]\n contextChanged: (() => void)[]\n reset: (() => void)[]\n disposers: (() => void)[]\n prompt: (() => string | null) | null\n context: ContextProvider | null\n commandLookup: CommandLookup | null\n inputWriter: InputWriter | null\n effects: { [T in ConsoleEffect['type']]?: EffectHandler<T> }\n keyActions: { [N in KeyActionName]?: () => boolean }\n}\n\nconst call = <A extends unknown[]>(\n list: ((...args: A) => void)[] | undefined,\n ...args: A\n) => {\n for (const hook of list ?? []) {\n hook(...args)\n }\n}\n\nconst provide = <\n K extends 'prompt' | 'context' | 'commandLookup' | 'inputWriter'\n>(\n console: object,\n key: K,\n value: NonNullable<Hooks[K]>\n) => {\n const hooks = liveRecord(console).hooks\n if (hooks[key] !== null) {\n throw new Error(`The ${key} hook is already provided.`)\n }\n hooks[key] = value\n}\n\n// --- Line ends --------------------------------------------------------------\n\n/**\n * Registered by recall: `line` (trimmed) was submitted and is not sensitive.\n * Called by dispatch after the line-end cleanup and before tokenizing, so\n * unknown commands and lines with an unterminated quote are recorded too. Never\n * called for an empty, cancelled or sensitive line (README: Running a line,\n * Recall).\n */\nexport const onLineSubmitted = (\n console: object,\n hook: (line: string) => void\n): void => {\n liveRecord(console).hooks.lineSubmitted.push(hook)\n}\n\n/** Called by dispatch; see `onLineSubmitted`. */\nexport const lineSubmitted = (console: object, line: string): void =>\n call(recordOf(console)?.hooks.lineSubmitted, line)\n\n/**\n * Registered by recall (drop the cursor and the draft) and completion (drop\n * the session). Called on every end of a line (submit, cancel, `run(line)`)\n * after the input was cleared, and by `reset()`. The input is empty when it\n * runs; a hook must not write it.\n */\nexport const onLineCleared = (console: object, hook: () => void): void => {\n liveRecord(console).hooks.lineCleared.push(hook)\n}\n\n/** Called by dispatch and `reset()`; see `onLineCleared`. */\nexport const lineCleared = (console: object): void =>\n call(recordOf(console)?.hooks.lineCleared)\n\n// --- The live input ---------------------------------------------------------\n\n/**\n * Registered by recall (an edit ends browsing) and completion (an edit or a\n * caret move the session did not make closes it). Called after every change\n * of the input's value or caret, with the writer's `origin`: `setInput` has\n * origin `null`, `writeInput` the feature that wrote. Not called by the\n * line-end cleanup (that is `onLineCleared`) or by `reset()`.\n */\nexport const onInputChange = (\n console: object,\n hook: (change: InputChange) => void\n): void => {\n liveRecord(console).hooks.inputChanged.push(hook)\n}\n\n/** Called by the input feature; see `onInputChange`. */\nexport const inputChanged = (console: object, change: InputChange): void =>\n call(recordOf(console)?.hooks.inputChanged, change)\n\n/** Registered by the input feature. */\nexport const provideInputWriter = (console: object, writer: InputWriter) =>\n provide(console, 'inputWriter', writer)\n\n/**\n * Writes the live input for a feature (recall shows a line, completion\n * writes a candidate). The caret is clamped to the value. `onInputChange`\n * hooks see the change with `origin`, so a feature can tell its own writes\n * from the user's. Does nothing while a command runs (the input is\n * read-only).\n */\nexport const writeInput = (\n console: object,\n value: string,\n caret: number,\n origin: FeatureName\n): void => recordOf(console)?.hooks.inputWriter?.(value, caret, origin)\n\n// --- Keys -------------------------------------------------------------------\n\n/**\n * Registered by a feature that must see every key `handleKey` receives\n * before the key map runs (completion: a session with no candidates closes\n * on the next key). Not called for a key with `isComposing`.\n */\nexport const onKey = (console: object, hook: (input: KeyInput) => void) => {\n liveRecord(console).hooks.key.push(hook)\n}\n\n/** Called by `handleKey`; see `onKey`. */\nexport const keyPressed = (console: object, input: KeyInput): void =>\n call(recordOf(console)?.hooks.key, input)\n\n// --- Controlled slices ------------------------------------------------------\n\n/**\n * Registered by recall (an external `recall` ends browsing) and context (an\n * external `context` with another id sequence is a context change, core\n * README: Controlled slices). Called by `setOptions`, inside its action, for\n * each controlled slice whose value the consumer replaced (a different\n * array).\n */\nexport const onControlledChange = (\n console: object,\n hook: (change: ControlledChange) => void\n): void => {\n liveRecord(console).hooks.controlledChanged.push(hook)\n}\n\n/** Called by `setOptions`; see `onControlledChange`. */\nexport const controlledChanged = (\n console: object,\n change: ControlledChange\n): void => call(recordOf(console)?.hooks.controlledChanged, change)\n\n// --- Context ----------------------------------------------------------------\n\n/**\n * Registered by context: the prompt of the next input entry, or `null` at\n * the root (dispatch then uses `options.prompt`). Read by dispatch when an\n * input entry is appended and by `getPrompt()`.\n */\nexport const providePrompt = (\n console: object,\n prompt: () => string | null\n): void => provide(console, 'prompt', prompt)\n\n/** The prompt of the context feature; `null` at the root or without it. */\nexport const promptOf = (console: object): string | null =>\n recordOf(console)?.hooks.prompt?.() ?? null\n\n/**\n * Registered by context: the frames and the revision. Read by dispatch (the\n * snapshot for `CommandRequest` and `RunInfo`, the revision a run starts\n * with) and completion (`CompletionRequest.context`).\n */\nexport const provideContext = (\n console: object,\n provider: ContextProvider\n): void => provide(console, 'context', provider)\n\n/** The context provider; `null` without the context feature. */\nexport const contextOf = (console: object): ContextProvider | null =>\n recordOf(console)?.hooks.context ?? null\n\n/**\n * Registered by dispatch: the context changed by any means other than a\n * run's own effects (a context method, an external `context`). Called by\n * context inside the action that changed it; dispatch aborts the current\n * run's signal (the run goes on, and its context effects are dropped when it\n * ends, README: Context).\n */\nexport const onContextChange = (console: object, hook: () => void): void => {\n liveRecord(console).hooks.contextChanged.push(hook)\n}\n\n/** Called by context; see `onContextChange`. */\nexport const contextChanged = (console: object): void =>\n call(recordOf(console)?.hooks.contextChanged)\n\n// --- Commands ---------------------------------------------------------------\n\n/** Registered by dispatch. */\nexport const provideCommandLookup = (\n console: object,\n lookup: CommandLookup\n): void => provide(console, 'commandLookup', lookup)\n\n/**\n * The commands of the console (completion: names, `complete`, safe\n * positions; recall: whether the live input is sensitive). Always present\n * while the console lives.\n */\nexport const lookupOf = (console: object): CommandLookup =>\n liveRecord(console).hooks.commandLookup!\n","// Effects (protocol README; README: Running a line). Each effect type is\n// applied by the feature that owns it: `clear` (entries), `close` (console),\n// `push-context`, `pop-context`, `reset-context` (context), `clear-recall`\n// (recall). Dispatch applies a run's effects in order, before the run's\n// output, inside the action of the run's end; an effect whose feature is\n// absent is ignored.\n// Context effects of a run whose context changed by someone else are dropped\n// by dispatch before they reach the handler (README: Context).\nimport type { ConsoleEffect } from '@dolusoft/command-protocol'\n\nimport type { EffectHandler } from './hooks'\nimport { liveRecord, recordOf } from './registry'\n\n/** The effect types that change the context stack. */\nexport const contextEffects: ReadonlySet<ConsoleEffect['type']> = new Set([\n 'push-context',\n 'pop-context',\n 'reset-context'\n])\n\n/** Registers the handler of effect `type` (one feature per type). */\nexport const handleEffect = <T extends ConsoleEffect['type']>(\n console: object,\n type: T,\n handler: EffectHandler<T>\n): void => {\n const effects = liveRecord(console).hooks.effects\n if (effects[type]) {\n throw new Error(`The ${type} effect already has a handler.`)\n }\n ;(effects as Record<string, unknown>)[type] = handler\n}\n\n/** Applies one effect; `false` when no feature handles its type. */\nexport const applyEffect = (\n console: object,\n effect: ConsoleEffect\n): boolean => {\n const handler = recordOf(console)?.hooks.effects[effect.type] as\n ((effect: ConsoleEffect) => void) | undefined\n if (!handler) {\n return false\n }\n handler(effect)\n return true\n}\n","// The fixed key map (README: Keyboard, C-53). `handleKey` matches a chord and\n// tries the chord's actions in order; an action returns `true` when its\n// condition held and it acted, so the next one is not tried and the key counts\n// as handled. An action that is not registered (its feature is absent) is\n// skipped. A key no action handles is left to the browser.\nimport { liveRecord, recordOf } from './registry'\n\n/** A key press as the adapter reports it; core never sees a DOM event. */\nexport interface KeyInput {\n key: string\n ctrlKey: boolean\n shiftKey: boolean\n altKey: boolean\n metaKey: boolean\n /** A key during IME composition is never handled. */\n isComposing: boolean\n /** Whether text is selected in the input or in the console's document. */\n selection: 'none' | 'input' | 'document'\n}\n\n/**\n * The actions of the key map:\n *\n * - `submit`, `cancel` (dispatch);\n * - `recallPrevious`, `recallNext` (recall);\n * - `acceptCompletion`, `completeNext`, `completePrevious`, `selectNext`,\n * `selectPrevious`, `closeCompletion` (completion).\n */\nexport type KeyActionName =\n | 'submit'\n | 'cancel'\n | 'recallPrevious'\n | 'recallNext'\n | 'acceptCompletion'\n | 'completeNext'\n | 'completePrevious'\n | 'selectNext'\n | 'selectPrevious'\n | 'closeCompletion'\n\ninterface Chord {\n key: string\n ctrl?: true\n shift?: true\n}\n\n/**\n * Chord → actions, tried in order. Modifiers match exactly; letters compare\n * case-insensitively. The \"when\" of each action (README: Keyboard) is the\n * action's own check:\n *\n * - Enter: `acceptCompletion` when a candidate is selected, else `submit`.\n * - Ctrl+C: `cancel`, only without a selection (`handleKey` checks it).\n * - ArrowUp / ArrowDown: `selectPrevious` / `selectNext` while a session is\n * open, else `recallPrevious` / `recallNext`.\n * - Tab: `completeNext` on a non-empty input or with a session open.\n * - Shift+Tab: `completePrevious` with a session open.\n * - Escape: `closeCompletion` with a session open.\n *\n * While a command runs only Ctrl+C is handled (README: Cancelling and errors).\n */\nconst keyMap: readonly (readonly [Chord, readonly KeyActionName[]])[] = [\n [{ key: 'enter' }, ['acceptCompletion', 'submit']],\n [{ key: 'c', ctrl: true }, ['cancel']],\n [{ key: 'arrowup' }, ['selectPrevious', 'recallPrevious']],\n [{ key: 'arrowdown' }, ['selectNext', 'recallNext']],\n [{ key: 'tab' }, ['completeNext']],\n [{ key: 'tab', shift: true }, ['completePrevious']],\n [{ key: 'escape' }, ['closeCompletion']]\n]\n\nconst matches = (chord: Chord, input: KeyInput) =>\n input.key.toLowerCase() === chord.key &&\n input.ctrlKey === (chord.ctrl ?? false) &&\n input.shiftKey === (chord.shift ?? false) &&\n !input.altKey &&\n !input.metaKey\n\n/** The actions `input` maps to, in order; empty when it maps to none. */\nexport const actionsFor = (input: KeyInput): readonly KeyActionName[] =>\n keyMap.find(([chord]) => matches(chord, input))?.[1] ?? []\n\n/**\n * Registers the action `name` (one feature per action). It runs inside the\n * `handleKey` action and returns whether it acted.\n */\nexport const registerKeyAction = (\n console: object,\n name: KeyActionName,\n action: () => boolean\n): void => {\n const actions = liveRecord(console).hooks.keyActions\n if (actions[name]) {\n throw new Error(`The key action ${name} is already registered.`)\n }\n actions[name] = action\n}\n\n/** Runs the action `name`; `false` when it is not registered or did not act. */\nexport const runKeyAction = (console: object, name: KeyActionName): boolean =>\n recordOf(console)?.hooks.keyActions[name]?.() ?? false\n","// Methods, reset and dispose (core README: Lifecycle). Every method a feature\n// puts on the instance goes through `assignMethods`, which refuses to overwrite\n// another feature's method and turns every call after `dispose()` into a no-op.\nimport { isDisposed, liveRecord, recordOf, takeRecord } from './registry'\n\ntype Method = (...args: never[]) => unknown\n\n/**\n * Assigns `methods` onto `console`. A name already present throws (no\n * feature overwrites another's method). After `dispose()` each method returns\n * its entry in `fallbacks` (default `undefined`) without running.\n */\nexport const assignMethods = <M extends Record<string, Method>>(\n console: object,\n methods: M,\n fallbacks: { [K in keyof M]?: ReturnType<M[K]> } = {}\n): void => {\n const target = console as Record<string, unknown>\n for (const [name, method] of Object.entries(methods)) {\n if (name in target) {\n throw new Error(`The console method ${name} is already defined.`)\n }\n target[name] = (...args: never[]) =>\n isDisposed(console) ? fallbacks[name] : method(...args)\n }\n}\n\n/**\n * Registered by a feature that keeps private state of its own (context: its\n * revision) or must act first (dispatch: end the run as cancelled, without an\n * `interrupted` entry). Called by `reset()` inside its action, in feature\n * order, before the line-cleared hooks and before every slice returns to its\n * initial value.\n */\nexport const onReset = (console: object, hook: () => void): void => {\n liveRecord(console).hooks.reset.push(hook)\n}\n\n/** Called by `reset()`; see `onReset`. */\nexport const resetHooks = (console: object): void => {\n for (const hook of recordOf(console)?.hooks.reset ?? []) {\n hook()\n }\n}\n\n/**\n * Registers a cleanup that `dispose()` runs once, in feature order (dispatch\n * first ends the run). No action is open when it runs; it must not change\n * state.\n */\nexport const onDispose = (console: object, cleanup: () => void): void => {\n liveRecord(console).hooks.disposers.push(cleanup)\n}\n\n/**\n * Drops the record of `console` and runs every cleanup once; a throwing\n * cleanup does not stop the others (its error goes to `onError`). Returns\n * `false` when the console was already disposed.\n */\nexport const disposeShared = (\n console: object,\n onError: (error: unknown) => void\n): boolean => {\n const record = takeRecord(console)\n if (!record) {\n return false\n }\n for (const cleanup of record.hooks.disposers) {\n try {\n cleanup()\n } catch (error) {\n onError(error)\n }\n }\n return true\n}\n","import type { AnyConsoleOptions } from './console.types'\nimport { liveRecord, promptOf, recordOf } from '../../shared'\nimport type { RunInfo } from '../dispatch/dispatch.types'\n\n/** The prompt of the next input entry: the top frame's, else the root's. */\nexport const currentPrompt = (console: object): string =>\n promptOf(console) ?? liveRecord(console).options.prompt\n\n/** Rethrows `error` outside the action, as an unhandled rejection. */\nconst rethrowAsync = (error: unknown): void => {\n void Promise.resolve().then(() => {\n throw error\n })\n}\n\n/**\n * Reports an error through `onError` (core README: Actions and\n * notification): a command's error with its `RunInfo`, a callback's error\n * with `null`. An error `onError` itself throws\n * is rethrown asynchronously; so is a callback's error without `onError`.\n */\nexport const reportError = (\n onError: AnyConsoleOptions['onError'],\n error: unknown,\n info: RunInfo | null\n): void => {\n if (!onError) {\n if (info === null) {\n rethrowAsync(error)\n }\n return\n }\n try {\n onError(error, info)\n } catch (thrown) {\n rethrowAsync(thrown)\n }\n}\n\n/** The callback-error reporter of the store. */\nexport const reportCallbackError = (console: object, error: unknown): void =>\n reportError(recordOf(console)?.options.onError, error, null)\n","// Updaters (core README: Controlled slices). A controlled slice is reported as\n// one updater per action that replays every change of the action, in order,\n// onto the value it is given.\n\n/** A new value, or a function from the old value to the new one. */\nexport type Updater<T> = T | ((old: T) => T)\n\n/** A change of one slice: a function from the old value to the new one. */\nexport type Step<T> = (old: T) => T\n\n/** The value `updater` gives when applied to `old`. */\nexport const resolveUpdater = <T>(updater: Updater<T>, old: T): T =>\n typeof updater === 'function' ? (updater as Step<T>)(old) : updater\n\n/** One step that applies `steps` in order. */\nexport const composeSteps =\n <T>(steps: readonly Step<T>[]): Step<T> =>\n old =>\n steps.reduce((value, step) => step(value), old)\n","import {\n checkInputSchema,\n type CommandResponse,\n type CommandSpec,\n type InputSchema,\n type OutputBlock\n} from '@dolusoft/command-protocol'\n\nimport type { CommandDefinition, CommandReturn } from './dispatch.types'\n\nconst forbidden = /[\\s'\"]/\n\nconst checkName = (name: unknown, where: string) => {\n if (typeof name !== 'string' || name === '' || forbidden.test(name)) {\n throw new Error(\n `${where}: a command name must be a non-empty string without whitespace or quotes (got ${JSON.stringify(name)}).`\n )\n }\n}\n\n/**\n * Validates the commands (core README: Options, C-56): names and aliases are\n * non-empty, without whitespace or quotes, unique across every name and alias;\n * `fromArg` is a non-negative integer; `run` is a function; `input` is an\n * input schema, `danger` a known value and `normalize` a function (C-76).\n * Throws on the first violation.\n */\nexport const validateCommands = (commands: unknown): void => {\n if (!Array.isArray(commands)) {\n throw new Error('commands must be an array of command definitions.')\n }\n const seen = new Set<string>()\n for (const command of commands as CommandDefinition[]) {\n const names = [command?.name, ...(command?.aliases ?? [])]\n for (const name of names) {\n checkName(name, `command ${JSON.stringify(command?.name)}`)\n if (seen.has(name)) {\n throw new Error(`The command name ${name} is used twice.`)\n }\n seen.add(name)\n }\n const { sensitive } = command\n if (\n sensitive !== undefined &&\n typeof sensitive !== 'boolean' &&\n !(\n typeof sensitive === 'object' &&\n sensitive !== null &&\n Number.isInteger(sensitive.fromArg) &&\n sensitive.fromArg >= 0\n )\n ) {\n throw new Error(\n `command ${command.name}: sensitive must be a boolean or { fromArg } with a non-negative integer.`\n )\n }\n if (typeof command.run !== 'function') {\n throw new Error(`command ${command.name}: run must be a function.`)\n }\n checkDescription(command)\n }\n}\n\nconst dangers: readonly unknown[] = ['read', 'change', 'irreversible']\n\n/** The checks of C-76: `input`, `danger` and `normalize`. */\nconst checkDescription = (command: CommandDefinition) => {\n if (command.input !== undefined) {\n try {\n checkInputSchema(command.input)\n } catch (error) {\n throw new TypeError(\n `command ${command.name}: ${(error as Error).message}`,\n { cause: error }\n )\n }\n }\n if (command.danger !== undefined && !dangers.includes(command.danger)) {\n throw new Error(\n `command ${command.name}: danger must be 'read', 'change' or 'irreversible'.`\n )\n }\n if (\n command.normalize !== undefined &&\n typeof command.normalize !== 'function'\n ) {\n throw new Error(`command ${command.name}: normalize must be a function.`)\n }\n}\n\n/** The JSON spec of a command, without its functions (`getCommands`). */\nexport const specOf = (command: CommandDefinition): CommandSpec => {\n const spec: CommandSpec = {\n name: command.name,\n aliases: [...(command.aliases ?? [])]\n }\n if (command.summary !== undefined) {\n spec.summary = command.summary\n }\n if (command.usage !== undefined) {\n spec.usage = command.usage\n }\n if (command.sensitive !== undefined) {\n spec.sensitive =\n typeof command.sensitive === 'object'\n ? { fromArg: command.sensitive.fromArg }\n : command.sensitive\n }\n if (command.input !== undefined) {\n spec.input = JSON.parse(JSON.stringify(command.input)) as InputSchema\n }\n if (command.danger !== undefined) {\n spec.danger = command.danger\n }\n return spec\n}\n\n/** A command's return as a response (README: Running a line, End action). */\nexport const normalizeReturn = (value: CommandReturn): CommandResponse => {\n if (typeof value === 'string' || Array.isArray(value)) {\n return { output: value }\n }\n if (typeof value === 'object' && value !== null) {\n return value\n }\n return {}\n}\n\n/** The blocks of a response's output; a string is one text block. */\nexport const blocksOf = (\n output: string | OutputBlock[] | undefined\n): OutputBlock[] => {\n if (typeof output === 'string') {\n return [{ type: 'text', text: output }]\n }\n return output ?? []\n}\n\n/** Whether `value` is a promise or another thenable. */\nexport const isThenable = (value: unknown): value is PromiseLike<unknown> =>\n (typeof value === 'object' || typeof value === 'function') &&\n value !== null &&\n typeof (value as { then?: unknown }).then === 'function'\n","// The pure parts of an operation that goes through the gate (ADR 0012): the\n// echo comparison, the closed ids, the summary cut and the default envelope id.\nimport type { CommandDefinition } from './dispatch.types'\nimport type { AnyConsoleOptions } from '../console/console.types'\n\n/** How many closed envelope ids a console remembers (C-81). */\nconst closedLimit = 500\n\n/** The longest `summary` an outcome carries, in code points (C-82). */\nconst summaryLimit = 200\n\n/** Whether two JSON values are equal, objects compared by their keys. */\nexport const sameJson = (a: unknown, b: unknown): boolean => {\n if (a === b) {\n return true\n }\n if (\n typeof a !== 'object' ||\n typeof b !== 'object' ||\n a === null ||\n b === null ||\n Array.isArray(a) !== Array.isArray(b)\n ) {\n return false\n }\n const left = Object.keys(a)\n const right = b as Record<string, unknown>\n return (\n left.length === Object.keys(right).length &&\n left.every(\n key =>\n Object.hasOwn(right, key) &&\n sameJson((a as Record<string, unknown>)[key], right[key])\n )\n )\n}\n\n/** Remembers `id` among the newest `closedLimit` closed ids. */\nexport const rememberClosed = (closed: Set<string>, id: string): void => {\n closed.delete(id)\n closed.add(id)\n if (closed.size > closedLimit) {\n closed.delete(closed.values().next().value!)\n }\n}\n\n/** `summary` cut to `summaryLimit` code points; `undefined` unless a string. */\nexport const cutSummary = (summary: unknown): string | undefined =>\n typeof summary === 'string'\n ? Array.from(summary).slice(0, summaryLimit).join('')\n : undefined\n\ninterface Crypto {\n randomUUID?: () => string\n getRandomValues?: (bytes: Uint8Array) => Uint8Array\n}\n\n/** An RFC 4122 version 4 UUID from 16 random bytes. */\nconst uuidV4 = (bytes: Uint8Array): string => {\n bytes[6] = (bytes[6] & 0x0f) | 0x40\n bytes[8] = (bytes[8] & 0x3f) | 0x80\n const hex = Array.from(bytes, byte => byte.toString(16).padStart(2, '0'))\n return [\n hex.slice(0, 4),\n hex.slice(4, 6),\n hex.slice(6, 8),\n hex.slice(8, 10),\n hex.slice(10, 16)\n ]\n .map(part => part.join(''))\n .join('-')\n}\n\n/**\n * The page's UUID function: `crypto.randomUUID`, else a v4 UUID from\n * `crypto.getRandomValues` (a page on an insecure origin has only the\n * latter), else none.\n */\nconst randomUUID = (): (() => string) | undefined => {\n const crypto = (globalThis as { crypto?: Crypto }).crypto\n if (typeof crypto?.randomUUID === 'function') {\n return () => crypto.randomUUID!()\n }\n if (typeof crypto?.getRandomValues === 'function') {\n return () => uuidV4(crypto.getRandomValues!(new Uint8Array(16)))\n }\n return undefined\n}\n\n/**\n * What makes envelope ids: `createEnvelopeId`, else the page's UUID function.\n * Throws when a gate is given and neither exists (C-78).\n */\nexport const envelopeIds = (\n options: Pick<AnyConsoleOptions, 'gate' | 'createEnvelopeId'>\n): (() => string) | undefined => {\n const create = options.createEnvelopeId ?? randomUUID()\n if (options.gate !== undefined && create === undefined) {\n throw new Error(\n 'A console with a gate needs crypto.randomUUID, crypto.getRandomValues or a createEnvelopeId option.'\n )\n }\n return create\n}\n\n/**\n * Checks the gate options at creation and on every `setOptions` (C-78):\n * envelope ids can be made, and `echoTimeoutMs` is a finite number above 0.\n */\nexport const checkGateOptions = (\n options: Pick<\n AnyConsoleOptions,\n 'gate' | 'createEnvelopeId' | 'echoTimeoutMs'\n >\n): void => {\n envelopeIds(options)\n const ms: unknown = options.echoTimeoutMs\n if (\n ms !== undefined &&\n !(typeof ms === 'number' && Number.isFinite(ms) && ms > 0)\n ) {\n throw new TypeError(\n `echoTimeoutMs must be a finite number above 0 (got ${typeof ms === 'number' ? ms : typeof ms}).`\n )\n }\n}\n\n/**\n * Whether a command can travel in an envelope: it has `input` and `danger`\n * and no `sensitive` (C-79).\n */\nexport const describedCommand = (command: CommandDefinition): boolean =>\n command.input !== undefined &&\n command.danger !== undefined &&\n (command.sensitive === undefined || command.sensitive === false)\n","// The console feature (ADR 0002; core README: Actions and notification,\n// Lifecycle; README: Keyboard): state access, options, the key map, reset and\n// dispose, and the `close` effect.\nimport type { ConsoleEntry, ContextFrame } from '@dolusoft/command-protocol'\n\nimport type {\n AnyConsole,\n AnyConsoleOptions,\n ConsoleFeature,\n ConsoleState,\n ControlledSlice\n} from './console.types'\nimport { currentPrompt, reportError } from './console.utils'\nimport {\n actionsFor,\n assignMethods,\n controlledChanged,\n disposeShared,\n handleEffect,\n isDisposed,\n keyPressed,\n lineCleared,\n liveRecord,\n recordOf,\n resetHooks,\n runKeyAction,\n type ControlledChange,\n type KeyInput\n} from '../../shared'\nimport { resolveUpdater, type Updater } from '../../store/action'\nimport { validateCommands } from '../dispatch/dispatch.utils'\nimport { checkGateOptions } from '../dispatch/operation'\n\nconst controllable: readonly ControlledSlice[] = [\n 'entries',\n 'recall',\n 'context'\n]\n\n/** The state a console starts from before `initialState` and the features. */\nexport const emptyState = (): ConsoleState => ({\n entries: [],\n input: { value: '', caret: 0, revision: 0 },\n running: null,\n recall: [],\n recallCursor: null,\n recallDraft: null,\n completion: null,\n context: []\n})\n\n/**\n * The options as the features read them: the features' defaults, then every\n * option the consumer gave that is not `undefined`.\n */\nexport const mergeOptions = (\n defaults: Partial<AnyConsoleOptions>,\n options: AnyConsoleOptions\n): AnyConsoleOptions & { prompt: string } => {\n const merged: Record<string, unknown> = { ...defaults }\n for (const [key, value] of Object.entries(options)) {\n if (value !== undefined) {\n merged[key] = value\n }\n }\n return merged as unknown as AnyConsoleOptions & { prompt: string }\n}\n\nconst sameFeatures = (a: object | undefined, b: object | undefined) => {\n const left = Object.entries(a ?? {})\n const right = b ?? {}\n return (\n left.length === Object.keys(right).length &&\n left.every(\n ([key, value]) => (right as Record<string, unknown>)[key] === value\n )\n )\n}\n\n/** The initial values `reset()` returns the controllable slices to. */\nconst initialSlices = new WeakMap<\n object,\n { entries: ConsoleEntry[]; recall: string[]; context: ContextFrame[] }\n>()\nconst featureDefaults = new WeakMap<object, Partial<AnyConsoleOptions>>()\n\n/** Remembers what `setOptions` and `reset()` need from construction. */\nexport const rememberConstruction = (\n console: object,\n defaults: Partial<AnyConsoleOptions>,\n initial: ConsoleState\n): void => {\n featureDefaults.set(console, defaults)\n initialSlices.set(console, {\n entries: initial.entries,\n recall: initial.recall,\n context: initial.context\n })\n}\n\nexport const consoleFeature: ConsoleFeature = {\n name: 'console',\n\n getDefaultOptions: () => ({ prompt: '>' }),\n\n constructConsoleAPIs(console: AnyConsole) {\n const { store } = liveRecord(console)\n assignMethods(\n console,\n {\n subscribe: (listener: (state: ConsoleState) => void) =>\n store.subscribe(listener),\n\n setOptions(updater: Updater<AnyConsoleOptions>) {\n const record = liveRecord(console)\n const previous = record.options\n const given = resolveUpdater(updater, previous)\n if (!sameFeatures(previous.features, given.features)) {\n throw new Error('setOptions cannot change the feature set.')\n }\n if (given.gate !== previous.gate) {\n throw new Error('setOptions cannot change the gate.')\n }\n validateCommands(given.commands)\n checkGateOptions(given)\n store.action(() => {\n const before = { ...store.read() }\n record.options = mergeOptions(featureDefaults.get(console)!, given)\n store.deliver(\n controllable.filter(\n slice =>\n record.options.state?.[slice] !== undefined ||\n previous.state?.[slice] !== undefined\n )\n )\n const after = store.read()\n for (const slice of controllable) {\n if (before[slice] !== after[slice]) {\n controlledChanged(console, {\n slice,\n previous: before[slice],\n next: after[slice]\n } as ControlledChange)\n }\n }\n })\n },\n\n reset() {\n store.action(() => {\n resetHooks(console)\n // The input is empty when the line-cleared hooks run.\n store.update('input', input =>\n input.value === ''\n ? { ...input, caret: 0 }\n : { value: '', caret: 0, revision: input.revision + 1 }\n )\n lineCleared(console)\n const initial = initialSlices.get(console)!\n const empty = emptyState()\n store.update('entries', () => [...initial.entries])\n store.update('recall', () => [...initial.recall])\n store.update('context', () => [...initial.context])\n store.update('recallCursor', () => empty.recallCursor)\n store.update('recallDraft', () => empty.recallDraft)\n store.update('completion', () => empty.completion)\n store.update('running', () => empty.running)\n })\n },\n\n dispose() {\n const record = recordOf(console)\n if (!record) {\n return\n }\n const { onError } = record.options\n disposeShared(console, error => reportError(onError, error, null))\n record.store.clear(emptyState())\n },\n\n getPrompt: () => currentPrompt(console),\n\n handleKey(input: KeyInput) {\n if (input.isComposing) {\n return false\n }\n return store.action(() => {\n keyPressed(console, input)\n const actions = actionsFor(input)\n if (actions[0] === 'cancel' && input.selection !== 'none') {\n return false\n }\n if (store.read().running !== null && actions[0] !== 'cancel') {\n return false\n }\n return actions.some(name => runKeyAction(console, name))\n })\n }\n },\n { handleKey: false, getPrompt: '', subscribe: () => () => {} }\n )\n // Readable after dispose: the cleared state.\n ;(console as { getState?: () => ConsoleState }).getState = () =>\n store.getState()\n },\n\n init(console: AnyConsole) {\n handleEffect(console, 'close', () => {\n liveRecord(console).store.afterCommit(() => {\n if (!isDisposed(console)) {\n recordOf(console)?.options.onClose?.()\n }\n })\n })\n }\n}\n","// The error a command throws to end its run with a code of its own (C-86,\n// ADR 0012 addendum).\nimport type { ErrorCode } from '@dolusoft/command-protocol'\n\n/**\n * The codes a command's `run` may end with through a `CommandError`. The\n * other codes belong to the core (`busy`, `timeout`, `id-conflict`, …); a\n * `CommandError` that carries one gives `failed`.\n */\nexport type CommandErrorCode = Extract<\n ErrorCode,\n 'target-not-found' | 'invalid-args' | 'failed'\n>\n\nconst commandCodes: readonly unknown[] = [\n 'target-not-found',\n 'invalid-args',\n 'failed'\n] satisfies CommandErrorCode[]\n\n/**\n * Thrown (or rejected) by a command's `run` to end the run with `code`: the\n * run fails as with any error (`onError`, the error entry), and the outcome a\n * `request()` resolves is `{ status: 'error', code }`.\n */\nexport class CommandError extends Error {\n /** The code the run's outcome carries. */\n readonly code: CommandErrorCode\n\n constructor(\n code: CommandErrorCode,\n message?: string,\n options?: ErrorOptions\n ) {\n super(message ?? code, options)\n this.name = 'CommandError'\n this.code = code\n }\n}\n\n/**\n * The outcome code of an error a command's `run` threw: a `CommandError`'s\n * code when a command may give it, else `failed` (C-86). The error is known\n * by its `name`, not by `instanceof`: a command built against a second copy\n * of the core throws a `CommandError` of another class.\n */\nexport const commandErrorCode = (error: unknown): CommandErrorCode => {\n if (!(error instanceof Error) || error.name !== 'CommandError') {\n return 'failed'\n }\n const { code } = error as Error & { code?: unknown }\n return commandCodes.includes(code) ? (code as CommandErrorCode) : 'failed'\n}\n","// Sensitivity (README: Sensitive lines, ADR 0006). Computed once when a line\n// ends, from the tolerant tokens, before anything else sees the line.\nimport { tokenize } from '@dolusoft/command-protocol'\n\nimport type { CommandDefinition } from './dispatch.types'\n\n/**\n * The first secret argument position of `command`: `0` for\n * `sensitive: true`, `fromArg` for `{ fromArg }`, `null` when not sensitive.\n */\nexport const sensitiveFrom = (command: CommandDefinition): number | null => {\n const { sensitive } = command\n if (sensitive === true) {\n return 0\n }\n return typeof sensitive === 'object' ? sensitive.fromArg : null\n}\n\n/**\n * The names and aliases of the sensitive commands, lowercased: the first\n * token is compared case-insensitively, so `Set Password x` is redacted and\n * then reported as unknown (S-04).\n */\nexport const sensitiveNames = (\n commands: readonly CommandDefinition[]\n): ReadonlySet<string> =>\n new Set(\n commands\n .filter(command => sensitiveFrom(command) !== null)\n .flatMap(command => [command.name, ...(command.aliases ?? [])])\n .map(name => name.toLowerCase())\n )\n\n/** Whether the predicate marks `line`; a throwing predicate marks it. */\nexport const matchesPredicate = (\n predicate: ((line: string) => boolean) | undefined,\n line: string\n): boolean => {\n if (!predicate) {\n return false\n }\n try {\n return predicate(line) === true\n } catch {\n return true\n }\n}\n\n/**\n * Whether `line` is sensitive: its first token (quotes removed) names a\n * sensitive command or alias, compared case-insensitively, or the predicate\n * marks it (README: Sensitive lines).\n */\nexport const isLineSensitive = (\n line: string,\n names: ReadonlySet<string>,\n predicate: ((line: string) => boolean) | undefined\n): boolean => {\n const first = tokenize(line).tokens[0]\n if (first && names.has(first.value.toLowerCase())) {\n return true\n }\n return matchesPredicate(predicate, line)\n}\n","import type { ConsoleEntry } from '@dolusoft/command-protocol'\n\nimport type { ConsoleStore } from '../../shared'\n\n/** Keeps the newest `max` entries (C-55); `undefined` keeps all. */\nexport const trimEntries = (\n entries: ConsoleEntry[],\n max: number | undefined\n): ConsoleEntry[] => {\n if (max === undefined || entries.length <= max) {\n return entries\n }\n return entries.slice(entries.length - Math.max(0, Math.floor(max)))\n}\n\n/** The default `createId`: `c1`, `c2`, … skipping ids already in `entries`. */\nexport const counterIds = (store: ConsoleStore): (() => string) => {\n let next = 0\n return () => {\n const present = new Set(store.read().entries.map(entry => entry.id))\n let id: string\n do {\n next += 1\n id = `c${next}`\n } while (present.has(id))\n return id\n }\n}\n\n/** The ids of `entries` that are already in `present` or repeat. */\nexport const duplicateIds = (\n present: readonly ConsoleEntry[],\n entries: readonly ConsoleEntry[]\n): string[] => {\n const seen = new Set(present.map(entry => entry.id))\n const duplicates: string[] = []\n for (const entry of entries) {\n if (seen.has(entry.id)) {\n duplicates.push(entry.id)\n }\n seen.add(entry.id)\n }\n return duplicates\n}\n","// The entries feature (C-55): the scrollback, its ids, `maxEntries` and\n// the `clear` effect.\nimport type { ConsoleEntry } from '@dolusoft/command-protocol'\n\nimport { counterIds, duplicateIds, trimEntries } from './entries.utils'\nimport {\n assignMethods,\n handleEffect,\n liveRecord,\n type ConsoleStore\n} from '../../shared'\nimport type { AnyConsole, ConsoleFeature } from '../console/console.types'\n\nconst defaultIds = new WeakMap<object, () => string>()\n\n/**\n * A new id: from `options.createId`, else the console's counter. An id that\n * is already in `entries` throws (a `createId` that repeats itself).\n */\nexport const newId = (console: object): string => {\n const record = liveRecord(console)\n const create = record.options.createId ?? defaultIds.get(console)!\n const id = create()\n if (record.store.read().entries.some(entry => entry.id === id)) {\n throw new Error(`createId returned ${id}, an id already in entries.`)\n }\n return id\n}\n\n/** Appends `entries` in the open action and applies `maxEntries`. */\nconst append = (\n store: ConsoleStore,\n entries: readonly ConsoleEntry[],\n max: number | undefined\n) => store.update('entries', old => trimEntries([...old, ...entries], max))\n\n/**\n * Appends one entry made by the console, with a new id, in the open action.\n * Returns the id.\n */\nexport const addEntry = (\n console: object,\n entry: ConsoleEntry extends infer E\n ? E extends ConsoleEntry\n ? Omit<E, 'id'>\n : never\n : never\n): string => {\n const record = liveRecord(console)\n const id = newId(console)\n append(record.store, [{ id, ...entry }], record.options.maxEntries)\n return id\n}\n\nconst clear = (store: ConsoleStore) =>\n store.update('entries', old => (old.length === 0 ? old : []))\n\nexport const entriesFeature: ConsoleFeature = {\n name: 'entries',\n\n constructConsoleAPIs(console: AnyConsole) {\n defaultIds.set(console, counterIds(liveRecord(console).store))\n assignMethods(console, {\n appendEntries(entries: ConsoleEntry[]) {\n const { store, options } = liveRecord(console)\n store.action(() => {\n const duplicates = duplicateIds(store.read().entries, entries)\n if (duplicates.length > 0) {\n throw new Error(\n `appendEntries: ids already present: ${duplicates.join(', ')}.`\n )\n }\n append(store, entries, options.maxEntries)\n })\n },\n clearEntries() {\n const { store } = liveRecord(console)\n store.action(() => clear(store))\n }\n })\n },\n\n init(console: AnyConsole) {\n handleEffect(console, 'clear', () => clear(liveRecord(console).store))\n }\n}\n","// The input feature (core README: State; README: Running a line, Sensitive\n// lines): the live line, its caret and the revision the adapter keys the\n// input element by.\nimport {\n assignMethods,\n inputChanged,\n lineCleared,\n liveRecord,\n provideInputWriter,\n type InputOrigin\n} from '../../shared'\nimport type { AnyConsole, ConsoleFeature } from '../console/console.types'\n\nconst clamp = (caret: number, value: string) =>\n Number.isFinite(caret)\n ? Math.min(Math.max(0, Math.floor(caret)), value.length)\n : value.length\n\n/**\n * Writes the input in the open action and tells the `onInputChange` hooks.\n * A programmatic clear of a non-empty input increments the revision; a user\n * edit (`programmatic: false`) never does (README: Sensitive lines, C-54).\n */\nconst write = (\n console: object,\n value: string,\n caret: number,\n origin: InputOrigin,\n programmatic: boolean\n): void => {\n const { store } = liveRecord(console)\n const previous = store.read().input\n const next = {\n value,\n caret: clamp(caret, value),\n revision:\n programmatic && value === '' && previous.value !== ''\n ? previous.revision + 1\n : previous.revision\n }\n if (next.value === previous.value && next.caret === previous.caret) {\n return\n }\n store.update('input', () => next)\n inputChanged(console, {\n value: next.value,\n caret: next.caret,\n previousValue: previous.value,\n previousCaret: previous.caret,\n origin\n })\n}\n\n/**\n * The line-end cleanup (README: Running a line), the same on every path that\n * ends a line: clears the input, increments the revision when the line was\n * sensitive, and calls the `onLineCleared` hooks. Runs in the open action.\n */\nexport const endLine = (console: object, sensitive: boolean): void => {\n const { store } = liveRecord(console)\n store.update('input', input => ({\n value: '',\n caret: 0,\n revision: sensitive ? input.revision + 1 : input.revision\n }))\n lineCleared(console)\n}\n\n/**\n * Replaces the live input with `line` for `run(line)`: a non-empty input is\n * a programmatic clear first (revision + 1), then `line` is written.\n */\nexport const replaceInput = (console: object, line: string): void => {\n const { store } = liveRecord(console)\n store.update('input', input => ({\n value: line,\n caret: line.length,\n revision: input.value === '' ? input.revision : input.revision + 1\n }))\n}\n\nexport const inputFeature: ConsoleFeature = {\n name: 'input',\n\n constructConsoleAPIs(console: AnyConsole) {\n const set = (value: string, caret: number, programmatic: boolean) => {\n const { store } = liveRecord(console)\n store.action(() => {\n if (store.read().running === null) {\n write(console, value, caret, null, programmatic)\n }\n })\n }\n assignMethods(console, {\n setInput(value: string, caret?: number) {\n set(value, caret ?? value.length, true)\n },\n editInput(value: string, caret: number) {\n set(value, caret, false)\n }\n })\n },\n\n init(console: AnyConsole) {\n provideInputWriter(console, (value, caret, origin) => {\n const { store } = liveRecord(console)\n store.action(() => {\n if (store.read().running === null) {\n // A feature's write is programmatic (recall restoring an empty\n // draft replaces the element like any programmatic clear).\n write(console, value, caret, origin, true)\n }\n })\n })\n }\n}\n","// The dispatch feature (README: Running a line, Cancelling and errors,\n// Sensitive lines; core README: The gate): ends lines, looks the command up,\n// runs it and appends what it returns. A run is several actions: its start,\n// each asynchronous `write()`, the echo of its envelope, and its end. Every\n// end is guarded by the run: a run that is no longer current changes nothing\n// and calls nothing (C-17).\nimport {\n type Actor,\n type CommandOutcome,\n type CommandResponse,\n type ContextFrame,\n type Envelope,\n type ErrorCode,\n type JsonValue,\n type MessageBlock,\n type OutputEntry,\n envelopeBytes,\n envelopeMaxBytes,\n formatCommandLine,\n parseEnvelope,\n parseOptions,\n tokenize,\n validateInput\n} from '@dolusoft/command-protocol'\n\nimport { commandErrorCode } from './commandError'\nimport type {\n CommandDefinition,\n CommandRequest,\n CommandReturn,\n RunContext,\n RunInfo\n} from './dispatch.types'\nimport { blocksOf, isThenable, normalizeReturn, specOf } from './dispatch.utils'\nimport {\n cutSummary,\n describedCommand,\n envelopeIds,\n rememberClosed,\n sameJson\n} from './operation'\nimport {\n isLineSensitive,\n matchesPredicate,\n sensitiveFrom,\n sensitiveNames\n} from './sensitivity'\nimport {\n applyEffect,\n assignMethods,\n contextEffects,\n contextOf,\n isDisposed,\n lineSubmitted,\n liveRecord,\n onContextChange,\n onDispose,\n onReset,\n provideCommandLookup,\n recordOf,\n registerKeyAction,\n type CommandLookup\n} from '../../shared'\nimport type {\n AnyConsole,\n ConsoleFeature,\n RequestInput\n} from '../console/console.types'\nimport {\n currentPrompt,\n reportCallbackError,\n reportError\n} from '../console/console.utils'\nimport { addEntry, newId } from '../entries/entriesFeature'\nimport { endLine, replaceInput } from '../input/inputFeature'\n\ntype Input = Record<string, JsonValue>\n\n/** How a line of a command with `input` goes on (C-77). */\ninterface Plan {\n /** The validated input, before `normalize`. */\n value: Input\n /** The view the line targets; called when the run starts. */\n view: () => string | undefined\n actor: Actor\n}\n\ninterface Run {\n readonly id: string\n readonly inputId: string\n readonly info: RunInfo\n /** Completed with the canonical line once the plan is applied (C-77). */\n request: CommandRequest\n readonly command: CommandDefinition\n readonly controller: AbortController\n /** The context revision when the run started; `null` without context. */\n readonly contextRevision: number | null\n /** Whether the run goes through the gate (C-79). */\n readonly gated: boolean\n readonly actor: Actor\n /** False once the run ended or was invalidated. */\n current: boolean\n /** True once the run's cleanup ran (once, C-57). */\n cleaned: boolean\n /** The local record of the operation, once it is sent. */\n envelope: Envelope | null\n /** True while the envelope waits for its echo. */\n waiting: boolean\n cancelTimer: (() => void) | null\n /** How the run ended, for `request()`. */\n outcome: CommandOutcome\n resolve(result: boolean): void\n onOutcome?: (outcome: CommandOutcome) => void\n}\n\ninterface DispatchState {\n run: Run | null\n lookup: { commands: CommandDefinition[]; value: CommandLookup } | null\n /** The gate's unsubscribe, once the console listens (C-78). */\n unsubscribe: (() => void) | null\n /** The newest closed envelope ids, oldest first (C-81). */\n closed: Set<string>\n}\n\nconst states = new WeakMap<object, DispatchState>()\n\nconst stateOf = (console: object): DispatchState => states.get(console)!\n\n/** The lookup of the current commands, rebuilt when `commands` changes. */\nconst lookupOf = (console: object): CommandLookup => {\n const state = stateOf(console)\n const record = liveRecord(console)\n const { commands } = record.options\n if (state.lookup?.commands !== commands) {\n const byName = new Map<string, CommandDefinition>()\n for (const command of commands) {\n for (const name of [command.name, ...(command.aliases ?? [])]) {\n byName.set(name, command)\n }\n }\n const names = sensitiveNames(commands)\n const value: CommandLookup = {\n find: name => byName.get(name),\n visible: () => commands.filter(command => command.hidden !== true),\n sensitiveFrom,\n matchesPredicate: line =>\n matchesPredicate(liveRecord(console).options.isSensitive, line),\n isSensitive: line =>\n isLineSensitive(line, names, liveRecord(console).options.isSensitive)\n }\n state.lookup = { commands, value }\n }\n return state.lookup.value\n}\n\nconst message = (\n code: MessageBlock['code'],\n params?: MessageBlock['params']\n): MessageBlock =>\n params === undefined\n ? { type: 'message', code }\n : { type: 'message', code, params }\n\nconst output = (\n tone: OutputEntry['tone'],\n blocks: OutputEntry['blocks'],\n inputId: string,\n quiet?: boolean\n): Omit<OutputEntry, 'id'> =>\n quiet === true\n ? { kind: 'output', tone, blocks, inputId, quiet: true }\n : { kind: 'output', tone, blocks, inputId }\n\nconst failure = (code: ErrorCode): CommandOutcome => ({\n status: 'error',\n code\n})\n\n// --- The end of a run ---------------------------------------------------------\n\n/**\n * Clears `running` when it still names `run`, cancels the echo timer,\n * records the envelope id as closed and resolves the run's promises.\n */\nconst cleanup = (console: object, run: Run) => {\n if (run.cleaned) {\n return\n }\n run.cleaned = true\n run.waiting = false\n const state = stateOf(console)\n if (state.run === run) {\n state.run = null\n }\n if (run.envelope) {\n rememberClosed(state.closed, run.envelope.id)\n }\n const cancelTimer = run.cancelTimer\n run.cancelTimer = null\n if (cancelTimer) {\n try {\n cancelTimer()\n } catch (error) {\n reportCallbackError(console, error)\n }\n }\n recordOf(console)?.store.update('running', running =>\n running?.runId === run.id ? null : running\n )\n run.resolve(true)\n run.onOutcome?.(run.outcome)\n}\n\n/** Effects in order, then the output (README: Running a line, B-29). */\nconst apply = (\n console: object,\n run: Run,\n response: CommandResponse,\n defaultTone: OutputEntry['tone']\n) => {\n const changed =\n run.contextRevision !== (contextOf(console)?.revision() ?? null)\n for (const effect of response.effects ?? []) {\n if (!(changed && contextEffects.has(effect.type))) {\n applyEffect(console, effect)\n }\n }\n const blocks = blocksOf(response.output)\n if (blocks.length > 0) {\n addEntry(\n console,\n output(response.tone ?? defaultTone, blocks, run.inputId, response.quiet)\n )\n }\n}\n\n/** Ends `run` with what it returned; an `error` tone is `failed` (C-87). */\nconst fulfil = (console: object, run: Run, value: CommandReturn) => {\n run.current = false\n try {\n const response = normalizeReturn(value)\n const summary = cutSummary(response.summary)\n run.outcome =\n response.tone === 'error'\n ? failure('failed')\n : summary === undefined\n ? { status: 'ok' }\n : { status: 'ok', summary }\n apply(console, run, response, 'default')\n } finally {\n cleanup(console, run)\n }\n}\n\n/**\n * Ends `run` as failed (C-18); `code` is the outcome's code, `failed` unless\n * the command's own `run` threw a `CommandError` (C-86).\n */\nconst fail = (\n console: object,\n run: Run,\n error: unknown,\n code: ErrorCode = 'failed'\n) => {\n run.current = false\n run.outcome = failure(code)\n try {\n const { store, options } = liveRecord(console)\n store.afterCommit(() =>\n reportError(recordOf(console)?.options.onError, error, run.info)\n )\n let response: CommandResponse | undefined\n if (options.formatError) {\n try {\n response = normalizeReturn(options.formatError(error, run.info))\n } catch {\n response = undefined\n }\n }\n if (response) {\n apply(console, run, response, 'error')\n } else {\n addEntry(\n console,\n output('error', [message('command-failed')], run.inputId)\n )\n }\n } finally {\n cleanup(console, run)\n }\n}\n\n/** Ends `run` without output and without an entry (`false`, reset, dispose). */\nconst stop = (console: object, run: Run, abort: boolean, code: ErrorCode) => {\n run.current = false\n run.outcome = failure(code)\n if (abort) {\n run.controller.abort()\n }\n cleanup(console, run)\n}\n\n/**\n * Ends an operation that did not run its command with an `operation-failed`\n * entry (C-79, C-80); `error` goes to `onError` with the run's info.\n */\nconst close = (console: object, run: Run, code: ErrorCode, error?: Error) => {\n run.current = false\n run.outcome = failure(code)\n run.controller.abort()\n try {\n if (error) {\n liveRecord(console).store.afterCommit(() =>\n reportError(recordOf(console)?.options.onError, error, run.info)\n )\n }\n addEntry(\n console,\n output('error', [message('operation-failed', { code })], run.inputId)\n )\n } finally {\n cleanup(console, run)\n }\n}\n\n/** Runs `fn` as its own action if `run` is still current (a settle). */\nconst settle = (console: object, run: Run, fn: () => void) => {\n if (!run.current || isDisposed(console)) {\n return\n }\n const { store } = liveRecord(console)\n store.action(() => {\n if (run.current) {\n fn()\n }\n })\n}\n\n/**\n * Handles a return that may be a promise: now, or in its own action. A\n * rejection fails the run with the code `codeOf` gives it.\n */\nconst whenSettled = <T>(\n console: object,\n run: Run,\n value: T | PromiseLike<T>,\n onValue: (value: T) => void,\n codeOf: (error: unknown) => ErrorCode = () => 'failed'\n) => {\n if (isThenable(value)) {\n Promise.resolve(value).then(\n result => settle(console, run, () => onValue(result)),\n (error: unknown) =>\n settle(console, run, () => fail(console, run, error, codeOf(error)))\n )\n } else {\n onValue(value)\n }\n}\n\n// --- The start of a run -------------------------------------------------------\n\nconst toRunning = (console: object, run: Run) =>\n liveRecord(console).store.update('running', running =>\n running?.runId === run.id ? { ...running, phase: 'running' } : running\n )\n\n/** Calls the command's `run`. */\nconst go = (console: object, run: Run) => {\n toRunning(console, run)\n const context: RunContext = {\n runId: run.id,\n inputId: run.inputId,\n signal: run.controller.signal,\n write: (out, tone) => write(console, run, out, tone)\n }\n let result: CommandReturn | Promise<CommandReturn>\n try {\n result = run.command.run(run.request, context)\n } catch (error) {\n fail(console, run, error, commandErrorCode(error))\n return\n }\n whenSettled(\n console,\n run,\n result,\n value => fulfil(console, run, value),\n commandErrorCode\n )\n}\n\nconst write = (\n console: object,\n run: Run,\n out: Parameters<RunContext['write']>[0],\n tone: OutputEntry['tone'] | undefined\n) => {\n settle(console, run, () => {\n const blocks = blocksOf(out)\n if (blocks.length > 0) {\n addEntry(console, output(tone ?? 'default', blocks, run.inputId))\n }\n })\n}\n\n/** What the gate delivered: the echo of the pending envelope, or nothing. */\nconst receive = (console: object, raw: unknown) => {\n const record = recordOf(console)\n const gate = record?.options.gate\n if (!record || !gate) {\n return\n }\n const parsed = parseEnvelope(raw)\n if (!parsed.ok) {\n return\n }\n const echo = parsed.envelope\n const state = stateOf(console)\n const run = state.run\n if (\n echo.target.tab !== gate.tab ||\n echo.from.tab !== echo.target.tab ||\n state.closed.has(echo.id) ||\n !run?.waiting ||\n run.envelope?.id !== echo.id\n ) {\n return\n }\n settle(console, run, () => {\n if (!run.waiting) {\n return\n }\n const local = run.envelope!\n run.waiting = false\n if (\n echo.command === local.command &&\n sameJson(echo.args, local.args) &&\n sameJson(echo.target, local.target)\n ) {\n go(console, run)\n } else {\n close(\n console,\n run,\n 'id-conflict',\n new Error(`The echo of operation ${local.id} differs from its record.`)\n )\n }\n })\n}\n\n/**\n * Sends the run's envelope and waits for its echo (C-79): the timer and the\n * send are the gate's calls, made after the action's commit.\n */\nconst send = (console: object, run: Run) => {\n const { store, options } = liveRecord(console)\n const gate = options.gate!\n toRunning(console, run)\n let envelope: Envelope\n try {\n const id = envelopeIds(options)!()\n if (\n typeof id !== 'string' ||\n id === '' ||\n stateOf(console).closed.has(id)\n ) {\n throw new Error(`createEnvelopeId returned ${id}, an id already used.`)\n }\n const { view } = run.request\n envelope = {\n v: 1,\n id,\n kind: 'request',\n actor: run.actor,\n from: { tab: gate.tab },\n target: view === undefined ? { tab: gate.tab } : { tab: gate.tab, view },\n command: run.command.name,\n args: run.request.input!\n }\n } catch (error) {\n fail(console, run, error)\n return\n }\n if (envelopeBytes(envelope) > envelopeMaxBytes) {\n close(console, run, 'too-large')\n return\n }\n run.envelope = envelope\n run.waiting = true\n const ended = (code: ErrorCode) => () =>\n settle(console, run, () => {\n if (run.waiting) {\n close(console, run, code)\n }\n })\n store.afterCommit(() => {\n const state = stateOf(console)\n if (!run.waiting) {\n return\n }\n // Any of the gate's calls may throw; each ends the run in its own action.\n try {\n if (state.unsubscribe === null) {\n state.unsubscribe = gate.subscribe(raw => receive(console, raw))\n }\n run.cancelTimer = gate.schedule(\n options.echoTimeoutMs ?? 5000,\n ended('timeout')\n )\n // The transport gets a copy, so nothing it does reaches the record.\n const copy = JSON.parse(JSON.stringify(envelope)) as Envelope\n Promise.resolve(gate.send(copy)).then(undefined, ended('connection-lost'))\n } catch {\n ended('connection-lost')()\n }\n })\n}\n\n/** After `beforeRun` lets the run go: the gate, or the command at once. */\nconst proceed = (console: object, run: Run) => {\n if (run.gated) {\n send(console, run)\n } else {\n go(console, run)\n }\n}\n\n/**\n * Applies the plan of a command with `input` (C-77): normalizes and checks\n * the value, and completes the request from its canonical line. Throws on a\n * `normalize` or `activeView` that throws, or a value the schema refuses.\n */\nconst prepare = (run: Run, plan: Plan) => {\n const { command } = run\n const schema = command.input!\n const view = plan.view()\n const mapped = command.normalize ? command.normalize(plan.value) : plan.value\n const checked = validateInput(schema, mapped)\n if (!checked.ok) {\n throw new TypeError(\n `command ${command.name}: normalize returned an input the schema refuses.`\n )\n }\n const line = formatCommandLine(command.name, checked.value, schema)\n const tokens = tokenize(line).tokens\n run.request = {\n ...run.request,\n args: tokens.slice(1).map(token => token.value),\n rest: tokens.length > 1 ? line.slice(tokens[1].start) : '',\n line,\n input: checked.value\n }\n // An empty or `null` view is no view.\n if (typeof view === 'string' && view !== '') {\n run.request.view = view\n }\n}\n\nconst start = (\n console: object,\n command: CommandDefinition,\n request: Omit<CommandRequest, 'context'>,\n inputId: string,\n sensitive: boolean,\n plan: Plan | null,\n onOutcome?: (outcome: CommandOutcome) => void\n): Promise<boolean> => {\n const { store, options } = liveRecord(console)\n const provider = contextOf(console)\n const frames: ContextFrame[] = provider?.snapshot() ?? []\n const id = newId(console)\n let resolve!: (result: boolean) => void\n const done = new Promise<boolean>(r => {\n resolve = r\n })\n const run: Run = {\n id,\n inputId,\n info: {\n runId: id,\n inputId,\n name: sensitive ? null : request.name,\n command: command.name,\n sensitive,\n context: [...frames]\n },\n request: { ...request, context: [...frames] },\n command,\n controller: new AbortController(),\n contextRevision: provider?.revision() ?? null,\n gated:\n plan !== null &&\n options.gate !== undefined &&\n !sensitive &&\n describedCommand(command),\n actor: plan?.actor ?? 'user',\n current: true,\n cleaned: false,\n envelope: null,\n waiting: false,\n cancelTimer: null,\n outcome: failure('cancelled'),\n resolve,\n onOutcome\n }\n stateOf(console).run = run\n const { beforeRun } = options\n store.update('running', () => ({\n runId: id,\n command: command.name,\n inputId,\n phase: beforeRun ? 'authorizing' : 'running'\n }))\n if (plan) {\n try {\n prepare(run, plan)\n } catch (error) {\n fail(console, run, error)\n return done\n }\n }\n if (!beforeRun) {\n proceed(console, run)\n return done\n }\n let answer: ReturnType<typeof beforeRun>\n try {\n answer = beforeRun(run.info, run.controller.signal)\n } catch (error) {\n fail(console, run, error)\n return done\n }\n whenSettled(console, run, answer, value => {\n if (value === undefined) {\n proceed(console, run)\n } else if (value === false) {\n stop(console, run, false, 'not-allowed')\n } else {\n fulfil(console, run, value)\n }\n })\n return done\n}\n\n// --- Ending a line ------------------------------------------------------------\n\n/**\n * Ends the live input as Enter does (README: Running a line, start action).\n * Runs in the open action; resolves after the run's end, or at once when\n * nothing runs.\n */\nconst submitLine = (console: object): Promise<boolean> => {\n const { store } = liveRecord(console)\n const line = store.read().input.value\n const trimmed = line.trim()\n const prompt = currentPrompt(console)\n if (trimmed === '') {\n addEntry(console, {\n kind: 'input',\n prompt,\n text: '',\n redacted: false,\n status: 'submitted'\n })\n endLine(console, false)\n return Promise.resolve(true)\n }\n const lookup = lookupOf(console)\n const sensitive = lookup.isSensitive(line)\n const inputId = addEntry(console, {\n kind: 'input',\n prompt,\n text: sensitive ? null : trimmed,\n redacted: sensitive,\n status: 'submitted'\n })\n endLine(console, sensitive)\n if (!sensitive) {\n lineSubmitted(console, trimmed)\n }\n const parsed = tokenize(trimmed)\n if (!parsed.ok) {\n const index = sensitive ? null : parsed.error.index\n addEntry(\n console,\n output('error', [message('unterminated-quote', { index })], inputId)\n )\n return Promise.resolve(true)\n }\n const [first, second] = parsed.tokens\n const command = lookup.find(first.value)\n if (!command) {\n const name = sensitive ? null : first.value\n addEntry(\n console,\n output('error', [message('command-not-found', { name })], inputId)\n )\n return Promise.resolve(true)\n }\n // An irreversible command never runs from the console, with or without\n // input, before its options are read (C-77).\n if (command.danger === 'irreversible') {\n addEntry(\n console,\n output(\n 'error',\n [message('operation-failed', { code: 'not-allowed' })],\n inputId\n )\n )\n return Promise.resolve(true)\n }\n const args = parsed.tokens.slice(1).map(token => token.value)\n let plan: Plan | null = null\n if (command.input) {\n const read = parseOptions(args, command.input)\n if (!read.ok) {\n const [error] = read.errors\n addEntry(\n console,\n output(\n 'error',\n [\n message('invalid-args', {\n path: sensitive ? null : error.path,\n reason: error.code\n })\n ],\n inputId\n )\n )\n return Promise.resolve(true)\n }\n plan = {\n value: read.value,\n view: () => liveRecord(console).options.activeView?.(),\n actor: 'user'\n }\n }\n return start(\n console,\n command,\n {\n name: first.value,\n command: command.name,\n args,\n rest: second ? trimmed.slice(second.start) : '',\n line: trimmed\n },\n inputId,\n sensitive,\n plan\n )\n}\n\n/**\n * `request()` in the open action (C-82): every refusal before the line is\n * accepted leaves no entry.\n */\nconst requestLine = (\n console: object,\n input: RequestInput\n): Promise<CommandOutcome> => {\n const refuse = (code: ErrorCode) => Promise.resolve(failure(code))\n const { store } = liveRecord(console)\n if (store.read().running !== null) {\n return refuse('busy')\n }\n const lookup = lookupOf(console)\n let command: CommandDefinition | undefined\n let tokens: string[] | null = null\n let view: () => string | undefined\n if ('line' in input) {\n const parsed = tokenize(String(input.line).trim())\n if (!parsed.ok || parsed.tokens.length === 0) {\n return refuse('invalid-args')\n }\n command = lookup.find(parsed.tokens[0].value)\n tokens = parsed.tokens.slice(1).map(token => token.value)\n view = () => liveRecord(console).options.activeView?.()\n } else {\n command =\n typeof input.command === 'string' ? lookup.find(input.command) : undefined\n const given = typeof input.view === 'string' ? input.view : undefined\n view = () => given\n }\n // A hidden command is unknown to a caller, even one that knows its name.\n if (!command || command.hidden === true) {\n return refuse('unknown-command')\n }\n if (\n !describedCommand(command) ||\n command.danger !== 'read' ||\n input.actor !== 'external-agent'\n ) {\n return refuse('not-allowed')\n }\n const schema = command.input!\n const read =\n tokens === null\n ? validateInput(schema, (input as { args: unknown }).args)\n : parseOptions(tokens, schema)\n if (!read.ok) {\n return refuse('invalid-args')\n }\n const line = formatCommandLine(command.name, read.value, schema)\n if (lookup.isSensitive(line)) {\n return refuse('not-allowed')\n }\n const inputId = addEntry(console, {\n kind: 'input',\n prompt: currentPrompt(console),\n text: line,\n redacted: false,\n status: 'submitted',\n actor: input.actor\n })\n return new Promise<CommandOutcome>(resolve => {\n void start(\n console,\n command,\n { name: command.name, command: command.name, args: [], rest: '', line },\n inputId,\n false,\n { value: read.value, view, actor: input.actor },\n resolve\n )\n })\n}\n\n/**\n * Ctrl+C without a run: the line ends as cancelled (README: Cancelling and\n * errors, B-10).\n */\nconst cancelLine = (console: object) => {\n const { store } = liveRecord(console)\n const trimmed = store.read().input.value.trim()\n const sensitive = trimmed !== '' && lookupOf(console).isSensitive(trimmed)\n addEntry(console, {\n kind: 'input',\n prompt: currentPrompt(console),\n text: sensitive ? null : trimmed,\n redacted: sensitive,\n status: 'cancelled'\n })\n endLine(console, sensitive)\n}\n\n/** Ctrl+C or `cancel()` during a run: invalidate, abort, `interrupted`. */\nconst interrupt = (console: object, run: Run) => {\n run.current = false\n run.outcome = failure('cancelled')\n run.controller.abort()\n addEntry(console, output('notice', [message('interrupted')], run.inputId))\n cleanup(console, run)\n}\n\nconst cancel = (console: object) => {\n const run = stateOf(console).run\n if (run) {\n interrupt(console, run)\n } else {\n cancelLine(console)\n }\n}\n\nexport const dispatchFeature: ConsoleFeature = {\n name: 'dispatch',\n\n constructConsoleAPIs(console: AnyConsole) {\n states.set(console, {\n run: null,\n lookup: null,\n unsubscribe: null,\n closed: new Set()\n })\n const locked = <T>(fn: () => Promise<T>, otherwise: T): Promise<T> => {\n const { store } = liveRecord(console)\n return store.action(() =>\n store.read().running === null ? fn() : Promise.resolve(otherwise)\n )\n }\n assignMethods(\n console,\n {\n submit: () => locked(() => submitLine(console), false),\n run: (line: string) =>\n locked(() => {\n replaceInput(console, line)\n return submitLine(console)\n }, false),\n cancel() {\n liveRecord(console).store.action(() => cancel(console))\n },\n request(input: RequestInput): Promise<CommandOutcome> {\n try {\n return liveRecord(console).store.action(() =>\n requestLine(console, input)\n )\n } catch (error) {\n reportCallbackError(console, error)\n return Promise.resolve(failure('failed'))\n }\n },\n isSensitive: (line: string) => lookupOf(console).isSensitive(line),\n getCommands: () => lookupOf(console).visible().map(specOf)\n },\n {\n submit: Promise.resolve(false),\n run: Promise.resolve(false),\n request: Promise.resolve(failure('cancelled')),\n isSensitive: false,\n getCommands: []\n }\n )\n },\n\n init(console: AnyConsole) {\n provideCommandLookup(console, {\n find: name => lookupOf(console).find(name),\n visible: () => lookupOf(console).visible(),\n sensitiveFrom,\n matchesPredicate: line => lookupOf(console).matchesPredicate(line),\n isSensitive: line => lookupOf(console).isSensitive(line)\n })\n registerKeyAction(console, 'submit', () => {\n void submitLine(console)\n return true\n })\n registerKeyAction(console, 'cancel', () => {\n cancel(console)\n return true\n })\n onContextChange(console, () => {\n const run = stateOf(console).run\n if (run?.current && run.waiting) {\n interrupt(console, run)\n } else if (run?.current && !run.controller.signal.aborted) {\n run.controller.abort()\n }\n })\n onReset(console, () => {\n const run = stateOf(console).run\n if (run) {\n stop(console, run, true, 'cancelled')\n }\n })\n onDispose(console, () => {\n const state = stateOf(console)\n const run = state.run\n const unsubscribe = state.unsubscribe\n state.run = null\n state.unsubscribe = null\n if (run) {\n stop(console, run, true, 'cancelled')\n }\n unsubscribe?.()\n })\n }\n}\n","import type { ConsoleFeature } from '../core/console/console.types'\nimport { consoleFeature } from '../core/console/consoleFeature'\nimport { dispatchFeature } from '../core/dispatch/dispatchFeature'\nimport { entriesFeature } from '../core/entries/entriesFeature'\nimport { inputFeature } from '../core/input/inputFeature'\n\n/** The features every console has, in construction order (ADR 0002). */\nexport const coreFeatures: readonly ConsoleFeature[] = [\n consoleFeature,\n entriesFeature,\n inputFeature,\n dispatchFeature\n]\n","// The store and the action boundary (core README: Actions and notification,\n// Controlled slices; ADR 0001, ADR 0003).\n//\n// An action is one synchronous step. Inside it every change goes to a working\n// copy of the state; a call made while an action is open joins it. When the\n// outermost action ends:\n//\n// 1. each controlled slice that changed is reported once, through an updater\n// that replays the action's changes of that slice in order;\n// 2. the other slices are committed;\n// 3. the callbacks queued by the action run;\n// 4. subscribers are notified once.\n//\n// The base of a controlled slice is the value last reported, until the\n// consumer delivers one (`deliver`) or the microtask after the report runs;\n// then it is the consumer's value again. The store knows no console type: it\n// is generic over the state and the names of the controllable slices.\nimport { composeSteps, type Step } from './action'\n\nexport interface StoreConfig<S extends object, C extends keyof S> {\n /** The state on creation, controllable slices included. */\n initial: S\n /** The slices the consumer may control. */\n controllable: readonly C[]\n /** The consumer's value of slice `key`, `undefined` when not controlled. */\n external(key: C): S[C] | undefined\n /** Reports the changes of a controlled slice to the consumer. */\n report(key: C, step: Step<S[C]>): void\n /** A callback, report or subscriber threw. */\n onCallbackError(error: unknown): void\n}\n\nexport interface Store<S extends object, C extends keyof S> {\n /**\n * The committed state; controlled slices read from the consumer. The same\n * object until the next commit or delivery.\n */\n getState(): S\n /** Calls `listener` after every action that changed something. */\n subscribe(listener: (state: S) => void): () => void\n /** Runs `fn` as an action, or as part of the open one. */\n action<R>(fn: () => R): R\n /** Whether an action is open. */\n inAction(): boolean\n /** The state as the open action sees it; the committed state outside one. */\n read(): S\n /** Changes one slice inside the open action. */\n update<K extends keyof S>(key: K, step: Step<S[K]>): void\n /** Queues `callback` to run after the open action's commit. */\n afterCommit(callback: () => void): void\n /**\n * The consumer delivered new options: `keys` are the controlled slices\n * whose value it passed. Their last reported value stops being the base.\n * Must run inside an action, which then notifies.\n */\n deliver(keys: readonly C[]): void\n /** Whether slice `key` is controlled now. */\n isControlled(key: C): boolean\n /** Drops every listener and pending base and sets `state` (dispose). */\n clear(state: S): void\n}\n\ninterface OpenAction<S, C extends keyof S> {\n working: S\n steps: Map<C, Step<S[C]>[]>\n callbacks: (() => void)[]\n changed: boolean\n}\n\nexport function createStore<S extends object, C extends keyof S>(\n config: StoreConfig<S, C>\n): Store<S, C> {\n let committed: S = { ...config.initial }\n let snapshot: S | null = null\n let open: OpenAction<S, C> | null = null\n const pending = new Map<C, S[C]>()\n const listeners = new Set<(state: S) => void>()\n\n const isControlled = (key: C) => config.external(key) !== undefined\n const isControllable = (key: keyof S): key is C =>\n (config.controllable as readonly (keyof S)[]).includes(key)\n\n /** Where an action starts for a controlled slice. */\n const base = (key: C): S[C] =>\n pending.has(key) ? (pending.get(key) as S[C]) : config.external(key)!\n\n const getState = (): S => {\n if (snapshot === null) {\n const state = { ...committed }\n for (const key of config.controllable) {\n if (isControlled(key)) {\n state[key] = config.external(key)!\n }\n }\n snapshot = state\n }\n return snapshot\n }\n\n const guarded = (fn: () => void) => {\n try {\n fn()\n } catch (error) {\n config.onCallbackError(error)\n }\n }\n\n const commit = (action: OpenAction<S, C>) => {\n const reports: [C, Step<S[C]>][] = []\n for (const [key, steps] of action.steps) {\n if (isControlled(key)) {\n reports.push([key, composeSteps(steps)])\n pending.set(key, action.working[key])\n }\n }\n committed = action.working\n if (action.changed) {\n snapshot = null\n }\n for (const [key, step] of reports) {\n guarded(() => config.report(key, step))\n const reported = action.working[key]\n // The only scheduling the core does (core README: Actions and\n // notification): after this tick the consumer's own value is the base\n // again.\n void Promise.resolve().then(() => {\n if (pending.get(key) === reported) {\n pending.delete(key)\n }\n })\n }\n for (const callback of action.callbacks) {\n guarded(callback)\n }\n if (action.changed) {\n const state = getState()\n for (const listener of [...listeners]) {\n guarded(() => listener(state))\n }\n }\n }\n\n const requireOpen = (): OpenAction<S, C> => {\n if (open === null) {\n throw new Error('A state change must run inside an action.')\n }\n return open\n }\n\n return {\n getState,\n subscribe(listener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n action(fn) {\n if (open !== null) {\n return fn()\n }\n const working = { ...committed }\n for (const key of config.controllable) {\n if (isControlled(key)) {\n working[key] = base(key)\n }\n }\n const action: OpenAction<S, C> = {\n working,\n steps: new Map(),\n callbacks: [],\n changed: false\n }\n open = action\n try {\n return fn()\n } finally {\n open = null\n commit(action)\n }\n },\n inAction: () => open !== null,\n read: () => (open === null ? getState() : open.working),\n update(key, step) {\n const action = requireOpen()\n const old = action.working[key]\n const next = step(old)\n if (Object.is(old, next)) {\n return\n }\n action.working[key] = next\n action.changed = true\n if (isControllable(key) && isControlled(key)) {\n const steps = action.steps.get(key) ?? []\n steps.push(step as unknown as Step<S[C]>)\n action.steps.set(key, steps)\n }\n },\n afterCommit(callback) {\n requireOpen().callbacks.push(callback)\n },\n deliver(keys) {\n const action = requireOpen()\n snapshot = null\n action.changed = true\n for (const key of keys) {\n pending.delete(key)\n if (isControlled(key)) {\n // The action's own changes so far, replayed on the delivered value.\n action.working[key] = composeSteps(action.steps.get(key) ?? [])(\n base(key)\n )\n }\n }\n },\n isControlled,\n clear(state) {\n committed = { ...state }\n snapshot = null\n pending.clear()\n listeners.clear()\n }\n }\n}\n","// Builds a console from its features (ADR 0002, TanStack v9 shape): the\n// options merge the features' defaults, the initial state takes\n// `initialState` and each feature's adjustment, then every feature assigns\n// its methods and, once all methods exist, registers its hooks.\nimport type {\n AnyConsole,\n AnyConsoleOptions,\n ConsoleFeature,\n ControlledSlice,\n OptionalFeatures\n} from './console.types'\nimport { reportCallbackError } from './console.utils'\nimport {\n emptyState,\n mergeOptions,\n rememberConstruction\n} from './consoleFeature'\nimport { createRecord, type SharedRecord } from '../../shared'\nimport { createStore } from '../../store/createStore'\nimport { validateCommands } from '../dispatch/dispatch.utils'\nimport { checkGateOptions } from '../dispatch/operation'\n\n/** The keys of `options.features`, in construction order. */\nconst optionalFeatureKeys: readonly (keyof OptionalFeatures)[] = [\n 'recallFeature',\n 'completionFeature',\n 'contextFeature'\n]\n\nconst controllable: readonly ControlledSlice[] = [\n 'entries',\n 'recall',\n 'context'\n]\n\nconst reporters = {\n entries: 'onEntriesChange',\n recall: 'onRecallChange',\n context: 'onContextChange'\n} as const\n\n/**\n * Builds a console from `core` (the always-present features, in order) and\n * the optional features in `options.features`. Throws on an unknown feature\n * key or an invalid command set; calls nothing of the consumer's.\n */\nexport function constructConsole(\n options: AnyConsoleOptions,\n core: readonly ConsoleFeature[]\n): AnyConsole {\n const given = (options.features ?? {}) as Record<string, unknown>\n for (const key of Object.keys(given)) {\n if (!(optionalFeatureKeys as readonly string[]).includes(key)) {\n throw new Error(\n `Unknown feature ${key}; the features are ${optionalFeatureKeys.join(', ')}.`\n )\n }\n }\n const features = [\n ...core,\n ...optionalFeatureKeys\n .filter(key => given[key] !== undefined)\n .map(key => given[key] as ConsoleFeature)\n ]\n\n const defaults: Partial<AnyConsoleOptions> = Object.assign(\n {},\n ...features.map(feature => feature.getDefaultOptions?.() ?? {})\n ) as Partial<AnyConsoleOptions>\n const merged = mergeOptions(defaults, options)\n validateCommands(merged.commands)\n checkGateOptions(merged)\n\n let initial = emptyState()\n for (const slice of controllable) {\n const value = merged.initialState?.[slice]\n if (value !== undefined) {\n initial = { ...initial, [slice]: value }\n }\n }\n for (const feature of features) {\n initial = feature.getInitialState?.(initial) ?? initial\n }\n\n const console = {} as AnyConsole\n const optionsNow = (): SharedRecord['options'] | undefined => record?.options\n let record: SharedRecord | undefined = undefined\n const store = createStore({\n initial,\n controllable,\n external: slice => optionsNow()?.state?.[slice],\n report: (slice, step) => {\n const callback = optionsNow()?.[reporters[slice]] as\n ((updater: typeof step) => void) | undefined\n callback?.(step)\n },\n onCallbackError: error => reportCallbackError(console, error)\n })\n record = createRecord(console, store, merged)\n rememberConstruction(console, defaults, initial)\n\n for (const feature of features) {\n feature.constructConsoleAPIs?.(console)\n }\n for (const feature of features) {\n feature.init?.(console)\n }\n return console\n}\n","import { coreFeatures } from './coreFeatures'\nimport type {\n Console,\n ConsoleOptions,\n OptionalFeatures\n} from '../core/console/console.types'\nimport { constructConsole } from '../core/console/constructConsole'\n\n/**\n * Keeps the type of a features object, so it can be declared once, outside\n * a component, and passed to `createConsole` (ADR 0002).\n *\n * @example\n * ```ts\n * const features = consoleFeatures({ recallFeature, contextFeature })\n * const console = createConsole({ features, commands })\n * ```\n */\nexport function consoleFeatures<T extends Partial<OptionalFeatures>>(\n features: T\n): T {\n return features\n}\n\n/**\n * Creates a console with the core features and the optional ones in\n * `options.features`. Nothing runs and nothing is called on creation.\n * Throws when a command name is invalid or repeats (C-56).\n */\n// `{}` and not its constraint: without `features` the console has no\n// optional method (ADR 0002, C-01).\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport function createConsole<T extends Partial<OptionalFeatures> = {}>(\n options: ConsoleOptions<T>\n): Console<T> {\n return constructConsole(options, coreFeatures) as unknown as Console<T>\n}\n","// The tools an agent in the browser uses (ADR 0012, C-83): plain objects in\n// the shape of a WebMCP tool. The consumer registers them; nothing here\n// touches the DOM.\nimport type {\n CommandOutcome,\n CommandSpec,\n JsonValue\n} from '@dolusoft/command-protocol'\n\nimport type { CoreConsoleAPI } from '../core/console/console.types'\n\n/** The hints a tool carries (WebMCP `ToolAnnotations`). */\nexport interface AgentToolAnnotations {\n /** The tool does not change the application. */\n readOnlyHint?: boolean\n /** The result may hold text the agent should not take as instructions. */\n untrustedContentHint?: boolean\n}\n\n/** One tool, as a WebMCP `ModelContextTool` takes it. */\nexport interface AgentTool {\n /** `context`, `help` or `run`. */\n name: string\n /** What the tool does, for the agent. */\n description: string\n /** A JSON Schema of the tool's input. */\n inputSchema: { [key: string]: JsonValue }\n /** The tool's hints. */\n annotations: AgentToolAnnotations\n /** Never rejects: a failure is an `error` outcome. */\n execute(input: unknown): Promise<JsonValue>\n}\n\n/** What `agentTools` needs besides the console. */\nexport interface AgentToolsOptions {\n /** What the `context` tool returns: the tab, its views, the active view. */\n context: () => JsonValue | Promise<JsonValue>\n}\n\n/**\n * A command an agent can see: one with `input` and `danger` whose definition\n * is not `sensitive` (what `request` could run, C-82).\n */\nconst described = (spec: CommandSpec): boolean =>\n spec.input !== undefined &&\n spec.danger !== undefined &&\n (spec.sensitive === undefined || spec.sensitive === false)\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/** `value` without its `undefined` fields, as JSON. */\nconst json = (value: Record<string, unknown>): JsonValue =>\n JSON.parse(JSON.stringify(value)) as JsonValue\n\nconst error = (code: 'invalid-args' | 'unknown-command'): CommandOutcome => ({\n status: 'error',\n code\n})\n\nconst failed: CommandOutcome = { status: 'error', code: 'failed' }\n\n/**\n * The `context`, `help` and `run` tools of `console` (C-83). `run` calls\n * `console.request` as `external-agent`, so only `read` commands run.\n */\nexport function agentTools(\n console: Pick<CoreConsoleAPI, 'getCommands' | 'request'>,\n options: AgentToolsOptions\n): [AgentTool, AgentTool, AgentTool] {\n const commands = () => console.getCommands().filter(described)\n const help = (input: unknown): JsonValue => {\n const name = isRecord(input) ? input.command : undefined\n if (name === undefined) {\n return commands().map(spec =>\n json({ name: spec.name, summary: spec.summary, danger: spec.danger })\n )\n }\n const found = commands().find(\n spec => spec.name === name || spec.aliases?.includes(name as string)\n )\n if (!found) {\n return error('unknown-command')\n }\n return json({\n name: found.name,\n summary: found.summary,\n usage: found.usage,\n danger: found.danger,\n input: found.input\n })\n }\n return [\n {\n name: 'context',\n description:\n 'The open tab, its views and the active view. Call it before run to pick a view; call help for the commands.',\n inputSchema: { type: 'object', properties: {} },\n annotations: { readOnlyHint: true, untrustedContentHint: true },\n execute: async () => {\n try {\n return await options.context()\n } catch {\n return failed\n }\n }\n },\n {\n name: 'help',\n description:\n 'Without input: the commands you can run (name, summary, danger). With a command name: its usage and input schema. Call it before run.',\n inputSchema: {\n type: 'object',\n properties: {\n command: { type: 'string', description: 'A command name.' }\n }\n },\n annotations: { readOnlyHint: true },\n execute: input => Promise.resolve(help(input))\n },\n {\n name: 'run',\n description:\n 'Runs a command: { line } as typed (name --field value), or { command, args, view? } with args matching its input schema. Returns { status, summary } or { status: \"error\", code }. Call help first.',\n inputSchema: {\n type: 'object',\n properties: {\n line: { type: 'string', description: 'A whole command line.' },\n command: { type: 'string', description: 'A command name.' },\n args: { type: 'object', description: 'The command input.' },\n view: { type: 'string', description: 'A view id from context.' }\n }\n },\n annotations: { readOnlyHint: true, untrustedContentHint: true },\n execute: async input => {\n if (isRecord(input) && typeof input.line === 'string') {\n return console.request({\n line: input.line,\n actor: 'external-agent'\n })\n }\n if (\n isRecord(input) &&\n typeof input.command === 'string' &&\n isRecord(input.args) &&\n (input.view === undefined || typeof input.view === 'string')\n ) {\n return console.request({\n command: input.command,\n args: input.args,\n ...(input.view === undefined ? {} : { view: input.view }),\n actor: 'external-agent'\n })\n }\n return error('invalid-args')\n }\n }\n ]\n}\n","import type { ContextFrame } from '@dolusoft/command-protocol'\n\n/**\n * The id sequence of `frames`, as one comparable string. Two stacks with the\n * same ids in the same order are the same context (core README: Controlled\n * slices).\n */\nexport const idsOf = (frames: readonly ContextFrame[]): string =>\n JSON.stringify(frames.map(frame => frame.id))\n\n/** `frames` with `frame` on top. */\nexport const pushFrame = (\n frames: ContextFrame[],\n frame: ContextFrame\n): ContextFrame[] => [...frames, frame]\n\n/**\n * `frames` without its top `count` frames; stops at the root. `count` is\n * rounded down; a count below 1 (or `NaN`) pops nothing, and nothing popped\n * gives `frames` back unchanged.\n */\nexport const popFrames = (\n frames: ContextFrame[],\n count: number\n): ContextFrame[] => {\n const n = Number.isNaN(count) ? 0 : Math.floor(count)\n if (n < 1 || frames.length === 0) {\n return frames\n }\n return frames.slice(0, Math.max(0, frames.length - n))\n}\n\n/** The root: no frame. `frames` itself when it is already empty. */\nexport const resetFrames = (frames: ContextFrame[]): ContextFrame[] =>\n frames.length === 0 ? frames : []\n","// The context feature (README: Context; core README: Controlled slices): a\n// stack of frames, bottom → top, with an implicit root. The top frame sets the\n// prompt of the next input entry. A run takes a snapshot of the frames and the\n// revision at its start; dispatch drops the context effects of a run whose\n// context changed by someone else, and this feature tells it when that happens.\nimport type { ContextFrame } from '@dolusoft/command-protocol'\n\nimport { idsOf, popFrames, pushFrame, resetFrames } from './context.utils'\nimport type {\n AnyConsole,\n ConsoleFeature,\n ContextFeature\n} from '../../core/console/console.types'\nimport {\n assignMethods,\n contextChanged,\n handleEffect,\n liveRecord,\n onControlledChange,\n provideContext,\n providePrompt\n} from '../../shared'\n\n/** What the feature keeps per console: the revision and the ids it counts. */\ninterface Revision {\n value: number\n /** The id sequence the value was counted for. */\n ids: string\n}\n\nconst revisions = new WeakMap<object, Revision>()\n\nconst framesOf = (console: object): ContextFrame[] =>\n liveRecord(console).store.read().context\n\n/**\n * The revision now. It changes whenever the id sequence differs from the one\n * it was last counted for, so a change nobody announced (a controlled value\n * the consumer did not hand back) still counts.\n */\nconst revisionOf = (console: object): number => {\n const revision = revisions.get(console)!\n const ids = idsOf(framesOf(console))\n if (ids !== revision.ids) {\n revision.ids = ids\n revision.value++\n }\n return revision.value\n}\n\n/** A known change: always a new revision, even if the ids come back. */\nconst markChanged = (console: object) => {\n const revision = revisions.get(console)!\n revision.ids = idsOf(framesOf(console))\n revision.value++\n}\n\n/**\n * Changes the stack in the open action. `byOther`: the change does not come\n * from a run's effects, so a running command's context is stale (C-62).\n */\nconst change = (\n console: object,\n step: (frames: ContextFrame[]) => ContextFrame[],\n byOther: boolean\n) => {\n const { store } = liveRecord(console)\n const before = store.read().context\n store.update('context', step)\n if (store.read().context === before) {\n return\n }\n markChanged(console)\n if (byOther) {\n contextChanged(console)\n }\n}\n\nconst feature = {\n name: 'context',\n\n constructConsoleAPIs(console: AnyConsole) {\n const act = (step: (frames: ContextFrame[]) => ContextFrame[]): void => {\n liveRecord(console).store.action(() => change(console, step, true))\n }\n assignMethods(console, {\n pushContext: (frame: ContextFrame) =>\n act(frames => pushFrame(frames, frame)),\n popContext: (count = 1) => act(frames => popFrames(frames, count)),\n resetContext: () => act(resetFrames)\n })\n },\n\n init(console: AnyConsole) {\n revisions.set(console, { value: 0, ids: idsOf(framesOf(console)) })\n providePrompt(console, () => framesOf(console).at(-1)?.prompt ?? null)\n provideContext(console, {\n snapshot: () => [...framesOf(console)],\n revision: () => revisionOf(console)\n })\n handleEffect(console, 'push-context', effect =>\n change(console, frames => pushFrame(frames, effect.frame), false)\n )\n handleEffect(console, 'pop-context', effect =>\n change(console, frames => popFrames(frames, effect.count ?? 1), false)\n )\n handleEffect(console, 'reset-context', () =>\n change(console, resetFrames, false)\n )\n // An external `context` with another id sequence is a context change; a\n // new array with the same ids is not (core README: Controlled slices).\n onControlledChange(console, controlled => {\n if (\n controlled.slice === 'context' &&\n idsOf(controlled.previous) !== idsOf(controlled.next)\n ) {\n markChanged(console)\n contextChanged(console)\n }\n })\n }\n} satisfies ConsoleFeature\n\n/**\n * The context feature: a stack of frames whose top sets the prompt. Adds\n * `pushContext`, `popContext` and `resetContext`, and applies the\n * `push-context`, `pop-context` and `reset-context` effects.\n *\n * @example\n * ```ts\n * const console = createConsole({ features: { contextFeature }, commands })\n * console.pushContext({ id: 'db', prompt: 'db>' })\n * ```\n */\nexport const contextFeature: ContextFeature = feature\n","// Pure helpers of the recall feature (README: Recall).\n\n/** The default of `options.recallLimit`. */\nexport const defaultRecallLimit = 100\n\n/**\n * The most lines recall keeps: a non-negative integer, `Infinity` allowed.\n * Anything else falls back to the default.\n */\nexport const limitOf = (limit: number | undefined): number => {\n if (limit === undefined || Number.isNaN(limit)) {\n return defaultRecallLimit\n }\n return limit === Infinity ? limit : Math.max(0, Math.floor(limit))\n}\n\n/**\n * `recall` with `line` recorded: an equal line already present moves to the\n * newest position, and the oldest lines beyond `limit` are dropped. Returns\n * `recall` itself when nothing changes; never mutates it.\n */\nexport const recordLine = (\n recall: readonly string[],\n line: string,\n limit: number\n): string[] => {\n if (recall.length > 0 && recall[recall.length - 1] === line) {\n return recall.length > limit\n ? recall.slice(recall.length - limit)\n : (recall as string[])\n }\n const next = [...recall.filter(old => old !== line), line]\n return next.length > limit ? next.slice(next.length - limit) : next\n}\n","// The recall feature (README: Recall, Keyboard): the submitted lines, oldest →\n// newest, browsed with ArrowUp / ArrowDown. The list is a controllable slice\n// (`recall`); the cursor and the draft are internal and die with the line.\n//\n// A sensitive line never reaches the list (dispatch does not call\n// `onLineSubmitted` for it) and never becomes the draft: browsing away from a\n// sensitive input keeps an empty draft and replaces the input element (C-31).\nimport { limitOf, recordLine, defaultRecallLimit } from './recall.utils'\nimport type {\n AnyConsole,\n ConsoleFeature,\n RecallFeature\n} from '../../core/console/console.types'\nimport {\n assignMethods,\n handleEffect,\n liveRecord,\n lookupOf,\n onControlledChange,\n onInputChange,\n onLineCleared,\n onLineSubmitted,\n registerKeyAction,\n writeInput\n} from '../../shared'\n\n/** Ends browsing: drops the cursor and the draft, keeps the input. */\nconst endBrowsing = (console: object): void => {\n const { store } = liveRecord(console)\n store.update('recallCursor', () => null)\n store.update('recallDraft', () => null)\n}\n\n/** Shows `line` in the input, the caret at its end. */\nconst show = (console: object, line: string): void =>\n writeInput(console, line, line.length, 'recall')\n\n/** ArrowUp: keeps the draft on the first press, then goes older. */\nconst previous = (console: object): boolean => {\n const { store } = liveRecord(console)\n return store.action(() => {\n const { running, recall, recallCursor, input } = store.read()\n if (running !== null || recall.length === 0) {\n return false\n }\n let next: number\n if (recallCursor === null) {\n const sensitive =\n input.value.trim() !== '' && lookupOf(console).isSensitive(input.value)\n if (sensitive) {\n // A programmatic clear replaces the element that held the line\n // (README: Sensitive lines), so its undo history goes with it.\n writeInput(console, '', 0, 'recall')\n }\n store.update('recallDraft', () => (sensitive ? '' : input.value))\n next = recall.length - 1\n } else {\n next = Math.min(recallCursor, recall.length) - 1\n if (next < 0) {\n return false\n }\n }\n store.update('recallCursor', () => next)\n show(console, recall[next])\n return true\n })\n}\n\n/** ArrowDown: goes newer; past the newest restores the draft. */\nconst following = (console: object): boolean => {\n const { store } = liveRecord(console)\n return store.action(() => {\n const { running, recall, recallCursor, recallDraft } = store.read()\n if (running !== null || recallCursor === null) {\n return false\n }\n const next = recallCursor + 1\n if (next >= recall.length) {\n endBrowsing(console)\n show(console, recallDraft ?? '')\n return true\n }\n store.update('recallCursor', () => next)\n show(console, recall[next])\n return true\n })\n}\n\n/** Empties the list and ends browsing (README: Recall, C-23). */\nconst clear = (console: object): void => {\n const { store } = liveRecord(console)\n store.update('recall', old => (old.length === 0 ? old : []))\n endBrowsing(console)\n}\n\n/**\n * Records a submitted line. `shouldRecord` runs first; a throwing\n * `shouldRecord` records nothing and its error goes to `onError` after the\n * action, like any callback's.\n */\nconst record = (console: object, line: string): void => {\n const { store, options } = liveRecord(console)\n let keep: boolean\n try {\n keep = options.shouldRecord?.(line) ?? true\n } catch (error) {\n keep = false\n store.afterCommit(() => {\n throw error\n })\n }\n if (!keep) {\n return\n }\n const limit = limitOf(options.recallLimit)\n store.update('recall', old => recordLine(old, line, limit))\n}\n\nconst feature: ConsoleFeature & RecallFeature = {\n name: 'recall',\n\n getDefaultOptions: () => ({ recallLimit: defaultRecallLimit }),\n\n constructConsoleAPIs(console: AnyConsole) {\n assignMethods(\n console,\n {\n recallPrevious: () => previous(console),\n recallNext: () => following(console),\n clearRecall() {\n const { store } = liveRecord(console)\n store.action(() => clear(console))\n }\n },\n { recallPrevious: false, recallNext: false }\n )\n },\n\n init(console: AnyConsole) {\n registerKeyAction(console, 'recallPrevious', () => previous(console))\n registerKeyAction(console, 'recallNext', () => following(console))\n handleEffect(console, 'clear-recall', () => clear(console))\n onLineSubmitted(console, line => record(console, line))\n onLineCleared(console, () => endBrowsing(console))\n onInputChange(console, change => {\n // Any edit that is not recall's own ends browsing; a caret move does\n // not, and the edited text stays.\n if (change.origin !== 'recall' && change.value !== change.previousValue) {\n endBrowsing(console)\n }\n })\n onControlledChange(console, change => {\n if (change.slice === 'recall') {\n endBrowsing(console)\n }\n })\n }\n}\n\n/**\n * The recall feature: ArrowUp / ArrowDown browse the submitted lines\n * (`recallPrevious`, `recallNext`, `clearRecall`). Options: `recallLimit`\n * (default 100), `shouldRecord`.\n *\n * @example\n * ```ts\n * const console = createConsole({ features: { recallFeature }, commands })\n * ```\n */\nexport const recallFeature: RecallFeature = feature\n","// Pure helpers of the completion feature (README: Completion): the token at the\n// caret, the filter, the longest common prefix and the quoting of written text.\nimport { quoteArgument, tokenize, type Token } from '@dolusoft/command-protocol'\n\nimport type { Quote, Target } from './completion.types'\n\n/** The opening quote of a token's raw text; `null` for a bare token. */\nexport const quoteOf = (raw: string): Quote | null => {\n const token = tokenize(raw).tokens[0] as Token | undefined\n if (!token || !(token.quoted || token.open)) {\n return null\n }\n return /['\"]/.exec(raw)![0] as Quote\n}\n\n/**\n * The token completion works on (README: Completion): the tolerant token whose\n * raw span contains the caret (its end included), else an empty token at the\n * caret.\n */\nexport const targetAt = (line: string, caret: number): Target => {\n const { tokens } = tokenize(line)\n const at = tokens.findIndex(\n token => token.start <= caret && caret <= token.end\n )\n if (at !== -1) {\n const token = tokens[at]\n const raw = line.slice(token.start, token.end)\n return {\n position: at,\n start: token.start,\n end: token.end,\n raw,\n prefix: token.value,\n quote: quoteOf(raw),\n before: tokens.slice(0, at).map(t => t.value)\n }\n }\n const before = tokens.filter(token => token.end <= caret).map(t => t.value)\n return {\n position: before.length,\n start: caret,\n end: caret,\n raw: '',\n prefix: '',\n quote: null,\n before\n }\n}\n\n/** Whether only whitespace follows `end` in `line`. */\nexport const isLast = (line: string, end: number): boolean =>\n line.slice(end).trim() === ''\n\n/**\n * Keeps the candidates whose lowercase starts with the lowercase `prefix`,\n * in their order, without duplicates and without empty strings or\n * non-strings (README: Completion). Returns a new array.\n */\nexport const filterCandidates = (\n candidates: readonly unknown[],\n prefix: string\n): string[] => {\n const lower = prefix.toLowerCase()\n const kept = new Set<string>()\n for (const candidate of candidates) {\n if (\n typeof candidate === 'string' &&\n candidate !== '' &&\n candidate.toLowerCase().startsWith(lower)\n ) {\n kept.add(candidate)\n }\n }\n return [...kept]\n}\n\n/**\n * The longest prefix every candidate shares, compared case-insensitively,\n * in the case of the first candidate.\n */\nexport const commonPrefix = (candidates: readonly string[]): string => {\n const [first, ...others] = candidates\n let length = first.length\n for (const other of others) {\n let i = 0\n while (\n i < length &&\n i < other.length &&\n first[i].toLowerCase() === other[i].toLowerCase()\n ) {\n i++\n }\n length = i\n }\n return first.slice(0, length)\n}\n\n/**\n * `text` as it is written into a token's span (C-40). A quoted or open\n * token keeps its quote character, escaped for it (a `'` token whose text\n * holds a `'` switches to `\"`, the only quote that can carry it). A bare\n * token opens a quote only when the text needs one: `'`, or `\"` when the\n * text holds a `'`. `close` writes the closing quote.\n */\nexport const encode = (\n text: string,\n quote: Quote | null,\n close: boolean\n): string => {\n let q = quote\n if (q === null) {\n if (quoteArgument(text) === text) {\n return text\n }\n q = text.includes(\"'\") ? '\"' : \"'\"\n }\n if (q === \"'\" && text.includes(\"'\")) {\n q = '\"'\n }\n const body = q === '\"' ? text.replace(/[\\\\\"]/g, char => `\\\\${char}`) : text\n return `${q}${body}${close ? q : ''}`\n}\n\n/** `line` with `[start, end)` replaced by `text`. */\nexport const splice = (\n line: string,\n start: number,\n end: number,\n text: string\n): string => line.slice(0, start) + text + line.slice(end)\n","// The completion feature (README: Completion, Keyboard, ADR 0006): Tab\n// completes the token at the caret from the visible command names or the\n// command's `complete`. The candidate list is session state, never an\n// entry. Argument positions at or after a command's `fromArg` (all of them\n// for `sensitive: true` or a predicate match) call no provider and open no\n// session (P16, C-35).\nimport type { Found, Target } from './completion.types'\nimport {\n commonPrefix,\n encode,\n filterCandidates,\n isLast,\n quoteOf,\n splice,\n targetAt\n} from './completion.utils'\nimport type {\n AnyConsole,\n CompletionFeature,\n CompletionSession,\n ConsoleFeature\n} from '../../core/console/console.types'\nimport type { CompletionResult } from '../../core/dispatch/dispatch.types'\nimport {\n assignMethods,\n contextOf,\n liveRecord,\n lookupOf,\n onInputChange,\n onKey,\n onLineCleared,\n registerKeyAction,\n writeInput\n} from '../../shared'\n\nconst none: Found = { candidates: [], final: true }\n\nconst read = (console: object) => liveRecord(console).store.read()\n\nconst setSession = (console: object, session: CompletionSession | null) =>\n liveRecord(console).store.update('completion', () => session)\n\nconst write = (console: object, value: string, caret: number) =>\n writeInput(console, value, caret, 'completion')\n\n/** A provider's result as candidates; anything else gives none. */\nconst resultOf = (result: CompletionResult, prefix: string): Found => {\n if (Array.isArray(result)) {\n return { candidates: filterCandidates(result, prefix), final: true }\n }\n if (\n typeof result === 'object' &&\n result !== null &&\n Array.isArray(result.candidates)\n ) {\n return {\n candidates: filterCandidates(result.candidates, prefix),\n final: result.final !== false\n }\n }\n return none\n}\n\n/**\n * The candidates of `target` (C-37, C-38), or `null` when its position is\n * not safe: then no provider is called and no session opens.\n * A line the predicate marks is unsafe everywhere, its name included; an\n * unknown first token that names a sensitive command case-insensitively is\n * unsafe at every argument position.\n */\nconst candidatesOf = (\n console: object,\n line: string,\n target: Target\n): Found | null => {\n const lookup = lookupOf(console)\n if (lookup.matchesPredicate(line)) {\n return null\n }\n if (target.position === 0) {\n const names = lookup\n .visible()\n .flatMap(command => [command.name, ...(command.aliases ?? [])])\n return { candidates: filterCandidates(names, target.prefix), final: true }\n }\n const command = lookup.find(target.before[0])\n if (!command) {\n return lookup.isSensitive(line) ? null : none\n }\n const index = target.position - 1\n const from = lookup.sensitiveFrom(command)\n if (from !== null && index >= from) {\n return null\n }\n if (typeof command.complete !== 'function') {\n return none\n }\n try {\n return resultOf(\n command.complete({\n command: command.name,\n args: target.before.slice(1),\n prefix: target.prefix,\n index,\n context: contextOf(console)?.snapshot() ?? []\n }),\n target.prefix\n )\n } catch {\n return none\n }\n}\n\n/**\n * Writes a completed candidate into `[start, end)` (closed), then the space\n * of step 5 when `space` holds: a whitespace already after the span is\n * stepped over instead of doubled.\n */\nconst writeCompleted = (\n console: object,\n start: number,\n end: number,\n text: string,\n space: boolean\n) => {\n const value = splice(read(console).input.value, start, end, text)\n const after = start + text.length\n if (!space) {\n write(console, value, after)\n } else if (/\\s/.test(value.charAt(after))) {\n write(console, value, after + 1)\n } else {\n write(console, splice(value, after, after, ' '), after + 1)\n }\n}\n\n/** Tab with no session (C-37 to C-41); `false` when nothing was done. */\nconst complete = (console: object): boolean => {\n const { input, running } = read(console)\n if (running !== null || input.value === '') {\n return false\n }\n setSession(console, null)\n const target = targetAt(input.value, input.caret)\n const found = candidatesOf(console, input.value, target)\n if (found === null) {\n return false\n }\n const { candidates, final } = found\n const { start, end, raw, quote } = target\n if (candidates.length === 0) {\n setSession(console, {\n status: 'none',\n candidates: [],\n final,\n active: -1,\n span: { start, end },\n original: raw\n })\n return true\n }\n if (candidates.length === 1) {\n writeCompleted(\n console,\n start,\n end,\n encode(candidates[0], quote, true),\n final && isLast(input.value, end)\n )\n return true\n }\n let spanEnd = end\n const shared = commonPrefix(candidates)\n if (shared.length > target.prefix.length) {\n const text = encode(shared, quote, false)\n spanEnd = start + text.length\n write(console, splice(input.value, start, end, text), spanEnd)\n }\n setSession(console, {\n status: 'open',\n candidates,\n final,\n active: -1,\n span: { start, end: spanEnd },\n original: raw\n })\n return true\n}\n\nconst openSession = (console: object): CompletionSession | null => {\n const session = read(console).completion\n return session?.status === 'open' ? session : null\n}\n\n/** Selects the next (`1`) or previous (`-1`) candidate, with wrap (step 8). */\nconst select = (console: object, step: 1 | -1): boolean => {\n const session = openSession(console)\n if (!session) {\n return false\n }\n const count = session.candidates.length\n const active =\n session.active === -1\n ? step === 1\n ? 0\n : count - 1\n : (session.active + step + count) % count\n const text = encode(\n session.candidates[active],\n quoteOf(session.original),\n true\n )\n const { start, end } = session.span\n write(\n console,\n splice(read(console).input.value, start, end, text),\n start + text.length\n )\n setSession(console, {\n ...session,\n active,\n span: { start, end: start + text.length }\n })\n return true\n}\n\n/** Enter on a selected candidate: the space of step 5, session closed. */\nconst accept = (console: object): boolean => {\n const session = openSession(console)\n if (!session || session.active === -1) {\n return false\n }\n const value = read(console).input.value\n const { start, end } = session.span\n setSession(console, null)\n writeCompleted(\n console,\n start,\n end,\n value.slice(start, end),\n session.final && isLast(value, end)\n )\n return true\n}\n\n/** Escape: the original token back, session closed. */\nconst close = (console: object): boolean => {\n const session = read(console).completion\n if (!session) {\n return false\n }\n setSession(console, null)\n if (session.status === 'open') {\n const { start, end } = session.span\n write(\n console,\n splice(read(console).input.value, start, end, session.original),\n start + session.original.length\n )\n }\n return true\n}\n\nconst feature = {\n name: 'completion',\n\n constructConsoleAPIs(console: AnyConsole) {\n const action = (fn: () => boolean) => () =>\n liveRecord(console).store.action(() =>\n read(console).running === null ? fn() : false\n )\n assignMethods(\n console,\n {\n complete: action(() => complete(console)),\n completeNext: action(() => select(console, 1) || complete(console)),\n completePrevious: action(() => select(console, -1)),\n acceptCompletion: action(() => accept(console)),\n closeCompletion: action(() => close(console))\n },\n {\n complete: false,\n completeNext: false,\n completePrevious: false,\n acceptCompletion: false,\n closeCompletion: false\n }\n )\n },\n\n init(console: AnyConsole) {\n registerKeyAction(console, 'completeNext', () => {\n if (select(console, 1)) {\n return true\n }\n // Tab on a non-empty input is always taken, even when nothing can be\n // completed; on an empty input it moves focus (README: Keyboard, C-59).\n complete(console)\n return read(console).input.value !== ''\n })\n registerKeyAction(console, 'completePrevious', () => select(console, -1))\n registerKeyAction(console, 'selectNext', () => select(console, 1))\n registerKeyAction(console, 'selectPrevious', () => select(console, -1))\n registerKeyAction(console, 'acceptCompletion', () => accept(console))\n registerKeyAction(console, 'closeCompletion', () =>\n openSession(console) ? close(console) : false\n )\n // A session with no candidates closes on the next key (step 4).\n onKey(console, () => {\n if (read(console).completion?.status === 'none') {\n setSession(console, null)\n }\n })\n // Any edit or caret move the session did not make closes it (step 8).\n onInputChange(console, change => {\n if (change.origin !== 'completion' && read(console).completion) {\n setSession(console, null)\n }\n })\n onLineCleared(console, () => setSession(console, null))\n }\n} satisfies ConsoleFeature & CompletionFeature\n\n/**\n * The completion feature: Tab completes command names and, through a\n * command's `complete`, its safe arguments (README: Completion).\n *\n * @example\n * ```ts\n * const console = createConsole({ commands, features: { completionFeature } })\n * ```\n */\nexport const completionFeature: CompletionFeature = feature\n"],"mappings":"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"}