@mnmal-ai/surface-core 0.0.0 → 0.14.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ /**
2
+ * One panel at a time, by construction. The open panel is one value, a tagged union, so
3
+ * opening any panel closes whichever was open and two can never stack. The component keeps
4
+ * per-panel views of it (`panelOf`) and per-panel setters (`setPanel`) with React's own
5
+ * contract: a value or an updater, `null` to close.
6
+ */
7
+ /** The open panel: which one, and its state. `null` when none is. */
8
+ export type Overlay<P> = {
9
+ [K in keyof P]: {
10
+ kind: K;
11
+ panel: P[K];
12
+ };
13
+ }[keyof P] | null;
14
+ /** A panel's state when it is the one open, else `null`. */
15
+ export declare function panelOf<P, K extends keyof P>(o: Overlay<P>, kind: K): P[K] | null;
16
+ /**
17
+ * The overlay after one panel's setter ran. The updater sees this panel's state, or `null`
18
+ * when another panel (or none) is open, exactly as a per-panel `useState` would have shown it.
19
+ *
20
+ * - A value opens this panel and replaces whatever was open.
21
+ * - `null` closes this panel only if it is the one open. Closing a panel that is not open
22
+ * must not close the one that is.
23
+ * - An updater returning what it was given changes nothing. That is how a slow read landing
24
+ * for a panel that has since closed, or been replaced, is dropped.
25
+ */
26
+ export declare function setPanel<P, K extends keyof P>(o: Overlay<P>, kind: K, next: P[K] | null | ((current: P[K] | null) => P[K] | null)): Overlay<P>;
27
+ //# sourceMappingURL=overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qEAAqE;AACrE,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE;CAAE,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;AAEtF,4DAA4D;AAC5D,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAEjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EAC3C,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EACb,IAAI,EAAE,CAAC,EACP,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAC1D,OAAO,CAAC,CAAC,CAAC,CAOZ"}
@@ -0,0 +1,38 @@
1
+ import type { CommandSpec } from './module.js';
2
+ type AnyCommand = CommandSpec<unknown>;
3
+ /** The palette's filter text: the draft after a leading '/', until the name ends. */
4
+ export declare function paletteQuery(draft: string): string | null;
5
+ export interface PaletteRow {
6
+ readonly cmd: AnyCommand;
7
+ /** True when the name starts with the query; false when it only contains it. */
8
+ readonly prefix: boolean;
9
+ }
10
+ /** Prefix matches first, then substring-only, each group alphabetical. Case-insensitive. */
11
+ export declare function paletteRows(commands: readonly AnyCommand[], query: string): PaletteRow[];
12
+ export declare function paletteMatches(commands: readonly AnyCommand[], query: string): AnyCommand[];
13
+ /**
14
+ * The command Enter runs, or null when the line should be sent as typed. A substring-only row
15
+ * runs only after the user moved onto it: Enter on a typo must never run a different command.
16
+ */
17
+ export declare function enterRuns(rows: readonly PaletteRow[], selected: number, moved: boolean): AnyCommand | null;
18
+ export declare function moveSelection(selected: number, delta: number, count: number): number;
19
+ export declare function clampSelection(selected: number, count: number): number;
20
+ export declare function completeDraft(c: AnyCommand): string;
21
+ export declare function commandUsage(c: AnyCommand): string;
22
+ export declare function parseCommandLine(line: string): {
23
+ name: string;
24
+ args: string[];
25
+ } | null;
26
+ /** Width of the palette's name column. */
27
+ export declare const MENU_NAME_WIDTH = 22;
28
+ /**
29
+ * The slice of a menu `height` rows tall, centred on the selection so moving keeps it in view, and
30
+ * the position to show beside ↑↓ when some rows are out of view (empty when every row fits).
31
+ */
32
+ export declare function menuWindow(count: number, selected: number, height: number): {
33
+ start: number;
34
+ end: number;
35
+ position: string;
36
+ };
37
+ export {};
38
+ //# sourceMappingURL=palette.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.d.ts","sourceRoot":"","sources":["../src/palette.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,KAAK,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;AAEvC,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEzD;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAaxF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAE3F;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,SAAS,UAAU,EAAE,EAC3B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,GACb,UAAU,GAAG,IAAI,CAInB;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGpF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAEnD;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAGlD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAQtF;AAED,0CAA0C;AAC1C,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;GAGG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAKlD"}
package/dist/pure.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ export { applyInput } from './apply-input.js';
2
+ export { applySuggestion, mergeCompletions } from './complete.js';
3
+ export { assertComposes, CompositionError, composeModules, RESERVED_GLOBAL_KEYS, type Registry } from './compose.js';
4
+ export { atEnd, type Draft, type EditKeys, EMPTY_DRAFT, editKey, insertChunk, maskDraft, pasteToLine, wordLeft, wordRight } from './editor.js';
5
+ export { CTRL_C_WINDOW_MS, ctrlC } from './exit-chord.js';
6
+ export { EMPTY_HISTORY, HISTORY_MAX, type HistoryState, mayWalk, remember, settle, walk } from './history.js';
7
+ export { normaliseKeySpec } from './key-spec.js';
8
+ export { type KeyState, keySpecOf, type Route, resolveKey } from './keys.js';
9
+ export { type ArgSpec, type Armed, type Chip, type CommandSpec, type Completer, type ConfirmBinding, defineModule, type GlobalBinding, type Key, type KeySpec, type ModuleCtx, type ModuleSpec, type PanelDef, type PresenceSpec, type RailItem, type Renderer, type Reply, type Size, type SubmitOptions, type Suggestion, type TuiEvents, type TuiModule, type TurnContext, type TurnHandler, type TurnPhase, type TurnUpdate } from './module.js';
10
+ export { type Overlay, panelOf, setPanel } from './overlay.js';
11
+ export { clampSelection, commandUsage, completeDraft, enterRuns, MENU_NAME_WIDTH, menuWindow, moveSelection, type PaletteRow, paletteMatches, paletteQuery, paletteRows, parseCommandLine } from './palette.js';
12
+ export { type InputRoute, routeInput } from './route-input.js';
13
+ export { sanitise } from './sanitise.js';
14
+ export { anchorPadding, CLEAR_PANE, DEFAULT_GROUND, groundSequence, type LiveMeasure, liveShrink, type PrepareTerminalOptions, prepareSequence, prepareTerminal, RESET_GROUND, reflowSequence, type TerminalOut, type TerminalProcess } from './terminal.js';
15
+ export { type AnswerEntry, type AppEntry, type AskEntry, addGap, answerEntry, arriveTurn, commitEntry, type Entry, emptyTranscript, type Flight, type GapEntry, heldAsks, markedFlights, type NoteEntry, sendTurn, type Transcript } from './transcript.js';
16
+ //# sourceMappingURL=pure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pure.d.ts","sourceRoot":"","sources":["../src/pure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,KAAK,QAAQ,EACd,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,EACL,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,WAAW,EACX,OAAO,EACP,WAAW,EACX,SAAS,EACT,WAAW,EACX,QAAQ,EACR,SAAS,EACV,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EACL,aAAa,EACb,WAAW,EACX,KAAK,YAAY,EACjB,OAAO,EACP,QAAQ,EACR,MAAM,EACN,IAAI,EACL,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,KAAK,QAAQ,EAAE,SAAS,EAAE,KAAK,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,GAAG,EACR,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,KAAK,EACV,KAAK,IAAI,EACT,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,SAAS,EACT,eAAe,EACf,UAAU,EACV,aAAa,EACb,KAAK,UAAU,EACf,cAAc,EACd,YAAY,EACZ,WAAW,EACX,gBAAgB,EACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EACL,aAAa,EACb,UAAU,EACV,cAAc,EACd,cAAc,EACd,KAAK,WAAW,EAChB,UAAU,EACV,KAAK,sBAAsB,EAC3B,eAAe,EACf,eAAe,EACf,YAAY,EACZ,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,MAAM,EACN,WAAW,EACX,UAAU,EACV,WAAW,EACX,KAAK,KAAK,EACV,eAAe,EACf,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,QAAQ,EACR,aAAa,EACb,KAAK,SAAS,EACd,QAAQ,EACR,KAAK,UAAU,EAChB,MAAM,iBAAiB,CAAC"}
package/dist/pure.js ADDED
@@ -0,0 +1,3 @@
1
+ import { $ as wordRight, A as moveSelection, B as remember, D as completeDraft, E as commandUsage, F as keySpecOf, G as EMPTY_DRAFT, H as walk, I as resolveKey, K as atEnd, L as EMPTY_HISTORY, M as paletteQuery, N as paletteRows, O as enterRuns, P as parseCommandLine, Q as wordLeft, R as HISTORY_MAX, S as routeInput, T as clampSelection, U as CTRL_C_WINDOW_MS, V as settle, W as ctrlC, X as maskDraft, Y as insertChunk, Z as pasteToLine, _ as liveShrink, a as answerEntry, at as normaliseKeySpec, b as reflowSequence, c as emptyTranscript, d as sendTurn, et as applyInput, f as CLEAR_PANE, g as groundSequence, h as anchorPadding, i as addGap, it as composeModules, j as paletteMatches, k as menuWindow, l as heldAsks, m as RESET_GROUND, n as setPanel, nt as RESERVED_GLOBAL_KEYS, o as arriveTurn, ot as applySuggestion, p as DEFAULT_GROUND, q as editKey, r as defineModule, rt as assertComposes, s as commitEntry, st as mergeCompletions, t as panelOf, tt as CompositionError, u as markedFlights, v as prepareSequence, w as MENU_NAME_WIDTH, x as sanitise, y as prepareTerminal, z as mayWalk } from "./overlay-DIAFXlMT.js";
2
+
3
+ export { CLEAR_PANE, CTRL_C_WINDOW_MS, CompositionError, DEFAULT_GROUND, EMPTY_DRAFT, EMPTY_HISTORY, HISTORY_MAX, MENU_NAME_WIDTH, RESERVED_GLOBAL_KEYS, RESET_GROUND, addGap, anchorPadding, answerEntry, applyInput, applySuggestion, arriveTurn, assertComposes, atEnd, clampSelection, commandUsage, commitEntry, completeDraft, composeModules, ctrlC, defineModule, editKey, emptyTranscript, enterRuns, groundSequence, heldAsks, insertChunk, keySpecOf, liveShrink, markedFlights, maskDraft, mayWalk, menuWindow, mergeCompletions, moveSelection, normaliseKeySpec, paletteMatches, paletteQuery, paletteRows, panelOf, parseCommandLine, pasteToLine, prepareSequence, prepareTerminal, reflowSequence, remember, resolveKey, routeInput, sanitise, sendTurn, setPanel, settle, walk, wordLeft, wordRight };
@@ -0,0 +1,28 @@
1
+ import type { Registry } from './compose.js';
2
+ import type { CommandSpec, TurnHandler } from './module.js';
3
+ export type InputRoute = {
4
+ readonly kind: 'command';
5
+ readonly module: string;
6
+ readonly spec: CommandSpec<unknown>;
7
+ readonly args: string[];
8
+ } | {
9
+ readonly kind: 'unknown-command';
10
+ readonly name: string;
11
+ } | {
12
+ readonly kind: 'unavailable-command';
13
+ readonly name: string;
14
+ readonly reason: string;
15
+ } | {
16
+ readonly kind: 'turn';
17
+ readonly module: string;
18
+ readonly handler: TurnHandler<unknown>;
19
+ } | {
20
+ readonly kind: 'no-handler';
21
+ };
22
+ /**
23
+ * A command's `unavailable` reason, or null. A throwing thunk, or an empty reason, is unavailable
24
+ * with the reason `unavailable`; an undefined one (a loose JS consumer) is available.
25
+ */
26
+ export declare function unavailableReason(spec: CommandSpec<unknown>): string | null;
27
+ export declare function routeInput(line: string, registry: Registry, defaultTurn?: string): InputRoute;
28
+ //# sourceMappingURL=route-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-input.d.ts","sourceRoot":"","sources":["../src/route-input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG5D,MAAM,MAAM,UAAU,GAClB;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;CACzB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACxF;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;CAAE,GAC1F;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAAE,CAAC;AAWpC;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAS3E;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAqB7F"}
@@ -0,0 +1,3 @@
1
+ /** Strips ESC sequences and C0/C1 control characters; keeps `\n`, and a tab becomes a space. */
2
+ export declare function sanitise(text: string): string;
3
+ //# sourceMappingURL=sanitise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitise.d.ts","sourceRoot":"","sources":["../src/sanitise.ts"],"names":[],"mappings":"AAWA,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO7C"}
@@ -0,0 +1,70 @@
1
+ import { DEFAULT_GROUND } from '@mnmal-ai/surface-theme';
2
+ export { DEFAULT_GROUND };
3
+ /**
4
+ * OSC 11 sets the terminal's default background, so every cell written without one — prose and
5
+ * the empty space around it — sits on it; Ink could only colour what it draws. `none` (or an
6
+ * empty value) leaves the terminal's background alone. Only `#rrggbb` is accepted: anything else
7
+ * inside an OSC is an escape-injection seam into the operator's terminal, so it is dropped.
8
+ */
9
+ export declare function groundSequence(ground: string | undefined): string | null;
10
+ /** OSC 111: restore the terminal's configured background. */
11
+ export declare const RESET_GROUND = "\u001B]111\u0007";
12
+ /** Erase the visible pane (2J) and its scrollback (3J), cursor home. */
13
+ export declare const CLEAR_PANE = "\u001B[2J\u001B[3J\u001B[H";
14
+ /**
15
+ * Blank lines that put the cursor on the last row before the first frame, so the input is
16
+ * bottom-anchored: Ink draws its live region where the cursor is, and printed turns then push the
17
+ * pane up rather than the input down.
18
+ */
19
+ export declare function anchorPadding(rows: number | undefined): string;
20
+ /**
21
+ * What a re-lay writes before the transcript is printed again: the pane and its scrollback wiped,
22
+ * then the input anchored to the last row. A resize cannot be patched, only redone — what `Static`
23
+ * printed was laid out at the old width — and a closed panel left the conversation scrolled up,
24
+ * which a terminal cannot scroll back down. The cost: scrollback from before the session goes too.
25
+ */
26
+ export declare function reflowSequence(rows: number | undefined): string;
27
+ /** The live region as last measured: its height, the entries printed above it, the layout epoch. */
28
+ export interface LiveMeasure {
29
+ readonly height: number;
30
+ readonly committed: number;
31
+ readonly epoch: number;
32
+ }
33
+ /**
34
+ * Rows the live region just gave up with nothing printed above it — rows that would otherwise open
35
+ * up below the input. Ink redraws its live region from where it began, so when it shrinks the input
36
+ * rises; printing that many blank rows above it scrolls the pane back. Zero when something was
37
+ * printed in the same step (the print scrolled the pane already) or after a re-lay (which anchors
38
+ * on its own).
39
+ */
40
+ export declare function liveShrink(prev: LiveMeasure | null, now: LiveMeasure): number;
41
+ export interface PrepareTerminalOptions {
42
+ /** `#rrggbb`, or `none` to leave the background alone. Default {@link DEFAULT_GROUND}. */
43
+ readonly ground?: string | undefined;
44
+ /** Wipe the pane and its scrollback first. Default true. */
45
+ readonly clear?: boolean;
46
+ /** Bottom-anchor the input. Default true. */
47
+ readonly anchor?: boolean;
48
+ }
49
+ export interface TerminalOut {
50
+ readonly isTTY?: boolean;
51
+ readonly rows?: number;
52
+ write(chunk: string): unknown;
53
+ }
54
+ /** The bytes {@link prepareTerminal} writes, in order. */
55
+ export declare function prepareSequence(rows: number | undefined, opts?: PrepareTerminalOptions): string;
56
+ /** The process hooks {@link prepareTerminal} needs; injectable for tests. */
57
+ export interface TerminalProcess {
58
+ once(event: 'exit', listener: () => void): unknown;
59
+ once(event: 'SIGHUP' | 'SIGTERM' | 'SIGINT', listener: () => void): unknown;
60
+ exit(code: number): never;
61
+ }
62
+ /**
63
+ * Ground, clear and anchor the terminal before `render`. Returns a restore function that puts the
64
+ * terminal's background back. It is also registered on `exit`, and SIGHUP / SIGTERM / SIGINT exit
65
+ * through it, since their default action kills the process with no `exit` event (under Ink's raw
66
+ * mode ctrl+c is input, so SIGINT only arrives from outside: `kill -INT`, a supervisor, tmux).
67
+ * A terminal left black is worse than any rendering bug. A no-op off a TTY.
68
+ */
69
+ export declare function prepareTerminal(out: TerminalOut, opts?: PrepareTerminalOptions, proc?: TerminalProcess): () => void;
70
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAKxE;AAED,6DAA6D;AAC7D,eAAO,MAAM,YAAY,qBAAiB,CAAC;AAE3C,wEAAwE;AACxE,eAAO,MAAM,UAAU,+BAAyB,CAAC;AAEjD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG9D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE/D;AAED,oGAAoG;AACpG,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,EAAE,GAAG,EAAE,WAAW,GAAG,MAAM,CAG7E;AAED,MAAM,WAAW,sBAAsB;IACrC,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC/B;AAED,0DAA0D;AAC1D,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,IAAI,GAAE,sBAA2B,GAChC,MAAM,CAMR;AAED,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;IAC5E,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,EAChB,IAAI,GAAE,sBAA2B,EACjC,IAAI,GAAE,eAAyB,GAC9B,MAAM,IAAI,CAeZ"}
@@ -0,0 +1,63 @@
1
+ import type { Tone } from '@mnmal-ai/surface-theme';
2
+ export interface AskEntry {
3
+ readonly key: string;
4
+ readonly kind: 'ask';
5
+ readonly question: string;
6
+ readonly mark: number | null;
7
+ readonly emphasis?: string;
8
+ }
9
+ export interface AnswerEntry<R> {
10
+ readonly key: string;
11
+ readonly kind: 'answer';
12
+ readonly question: string;
13
+ readonly reply: R;
14
+ readonly mark: number | null;
15
+ /** The far side started this line (a greeting, an offer); it answers no question. */
16
+ readonly unprompted?: boolean;
17
+ /** When an unprompted line landed, epoch ms. */
18
+ readonly at?: number;
19
+ }
20
+ /** The surface speaking, not the conversation: a command's reply. */
21
+ export interface NoteEntry {
22
+ readonly key: string;
23
+ readonly kind: 'note';
24
+ readonly text: string;
25
+ readonly tone?: Tone;
26
+ }
27
+ /** Blank rows printed so the input returns to the bottom after the live region shrinks. */
28
+ export interface GapEntry {
29
+ readonly key: string;
30
+ readonly kind: 'gap';
31
+ readonly lines: number;
32
+ readonly epoch: number;
33
+ }
34
+ export type AppEntry = {
35
+ readonly key: string;
36
+ readonly kind: string;
37
+ };
38
+ export type Entry<R, X extends AppEntry = never> = AskEntry | AnswerEntry<R> | NoteEntry | GapEntry | X;
39
+ export interface Flight {
40
+ readonly id: number;
41
+ readonly question: string;
42
+ /** Null while the ask is held; set when a later answer overtook it and it was printed. */
43
+ readonly mark: number | null;
44
+ readonly emphasis?: string;
45
+ }
46
+ export interface Transcript<R, X extends AppEntry = never> {
47
+ /** Append-only: exactly what Static requires. */
48
+ readonly committed: readonly Entry<R, X>[];
49
+ /** Unanswered turns, in send order. */
50
+ readonly flights: readonly Flight[];
51
+ /** Marks number up for the whole session and never reset. */
52
+ readonly nextMark: number;
53
+ }
54
+ export declare function emptyTranscript<R, X extends AppEntry = never>(): Transcript<R, X>;
55
+ export declare function sendTurn<R, X extends AppEntry>(t: Transcript<R, X>, id: number, question: string, emphasis?: string): Transcript<R, X>;
56
+ export declare function arriveTurn<R, X extends AppEntry>(t: Transcript<R, X>, id: number, reply: R): Transcript<R, X>;
57
+ export declare function heldAsks<R, X extends AppEntry>(t: Transcript<R, X>): readonly Flight[];
58
+ export declare function markedFlights<R, X extends AppEntry>(t: Transcript<R, X>): readonly Flight[];
59
+ export declare function commitEntry<R, X extends AppEntry>(t: Transcript<R, X>, entry: Entry<R, NoInfer<X>>): Transcript<R, X>;
60
+ /** The last answer printed, or the one carrying mark `n`. */
61
+ export declare function answerEntry<R, X extends AppEntry>(t: Transcript<R, X>, mark: number | null): AnswerEntry<R> | null;
62
+ export declare function addGap<R, X extends AppEntry>(t: Transcript<R, X>, lines: number, epoch: number): Transcript<R, X>;
63
+ //# sourceMappingURL=transcript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,57 @@
1
1
  {
2
2
  "name": "@mnmal-ai/surface-core",
3
- "version": "0.0.0",
4
- "description": "Reserved by MNMAL. Not yet released.",
3
+ "version": "0.14.5",
4
+ "description": "Pluggable terminal UI base on Ink 7 + React 19: module registry, createApp, the turn engine and the shell.",
5
5
  "license": "Apache-2.0",
6
- "files": ["README.md"]
7
- }
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/mnmal-ai/surface.git",
9
+ "directory": "packages/surface-core"
10
+ },
11
+ "type": "module",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ },
17
+ "./pure": {
18
+ "types": "./dist/pure.d.ts",
19
+ "import": "./dist/pure.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "dependencies": {
26
+ "@mnmal-ai/surface-kit": "0.14.5",
27
+ "@mnmal-ai/surface-theme": "0.14.5"
28
+ },
29
+ "peerDependencies": {
30
+ "ink": "^7.1.1",
31
+ "react": "^19.3.0"
32
+ },
33
+ "devDependencies": {
34
+ "@mnmal-ai/substrate-config": "1.0.0-alpha.0",
35
+ "@types/node": "^26.6.4",
36
+ "@types/react": "^19.2.0",
37
+ "ink": "^7.1.1",
38
+ "ink-testing-library": "^4.0.0",
39
+ "react": "^19.3.0",
40
+ "tsdown": "^0.23.0",
41
+ "typescript": "^7.0.2",
42
+ "vitest": "^5.0.3"
43
+ },
44
+ "engines": {
45
+ "node": ">=26.2.0"
46
+ },
47
+ "publishConfig": {
48
+ "registry": "https://registry.npmjs.org/",
49
+ "access": "public"
50
+ },
51
+ "scripts": {
52
+ "build": "tsdown && tsc -p tsconfig.dts.json",
53
+ "test": "vitest run",
54
+ "check-types": "tsc -p tsconfig.json --noEmit",
55
+ "lint": "biome check ."
56
+ }
57
+ }