@fnndsc/chell 5.6.2 → 5.7.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.
- package/dist/core/daemonConsole.d.ts +88 -0
- package/dist/core/daemonConsole.js +130 -0
- package/dist/core/daemonConsole.js.map +1 -0
- package/dist/core/promptGuard.d.ts +44 -0
- package/dist/core/promptGuard.js +71 -0
- package/dist/core/promptGuard.js.map +1 -0
- package/dist/core/repl.d.ts +6 -0
- package/dist/core/repl.js +25 -2
- package/dist/core/repl.js.map +1 -1
- package/dist/core/startupWarmup.d.ts +11 -4
- package/dist/core/startupWarmup.js +99 -77
- package/dist/core/startupWarmup.js.map +1 -1
- package/dist/lib/bootsequence.d.ts +26 -1
- package/dist/lib/bootsequence.js +84 -5
- package/dist/lib/bootsequence.js.map +1 -1
- package/dist/lib/logo.d.ts +4 -5
- package/dist/lib/logo.js +21 -57
- package/dist/lib/logo.js.map +1 -1
- package/dist/lib/terminalRows.d.ts +88 -0
- package/dist/lib/terminalRows.js +151 -0
- package/dist/lib/terminalRows.js.map +1 -0
- package/dist/remote/client.js +20 -17
- package/dist/remote/client.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The daemon console: the terminal a daemon booted in becomes its
|
|
3
|
+
* first surface.
|
|
4
|
+
*
|
|
5
|
+
* A Linux boot ends at a login. A daemon boot ended at a resting face — a
|
|
6
|
+
* brain animation and a status line, with the boot log a keypress away —
|
|
7
|
+
* that was a screensaver where a session belonged. The identity is already
|
|
8
|
+
* resolved by the time the engine is ready, so the login is the attach: an
|
|
9
|
+
* ordinary `chell --remote` surface is put on the daemon's own terminal.
|
|
10
|
+
*
|
|
11
|
+
* It is a child process on the wire, not an in-process shortcut. The daemon
|
|
12
|
+
* process holds one output sink and one interaction surface for every
|
|
13
|
+
* attached session; a REPL started inside it would take those over and
|
|
14
|
+
* every other surface would go quiet. A child pays one loopback hop, which
|
|
15
|
+
* is what every surface pays, and shares nothing else.
|
|
16
|
+
*
|
|
17
|
+
* `exit` in the console detaches; the daemon stays up, its terminal idle.
|
|
18
|
+
* Enter attaches again. Ctrl-C at that idle terminal stops the daemon, as
|
|
19
|
+
* it always did. While the console holds the terminal, whatever the daemon
|
|
20
|
+
* itself writes — a roster row, a late warm-up settling — is held and
|
|
21
|
+
* handed back on detach, so it lands after the surface's last line and
|
|
22
|
+
* never across its prompt.
|
|
23
|
+
*
|
|
24
|
+
* @module
|
|
25
|
+
*/
|
|
26
|
+
import { type ChildProcess } from 'node:child_process';
|
|
27
|
+
import type { EventEmitter } from 'node:events';
|
|
28
|
+
/** What the console needs to know about the daemon it attaches to. */
|
|
29
|
+
export interface DaemonConsoleTarget {
|
|
30
|
+
identity: string;
|
|
31
|
+
url: string;
|
|
32
|
+
token: string;
|
|
33
|
+
}
|
|
34
|
+
/** The running attached surface: settles with its exit code. */
|
|
35
|
+
export interface ConsoleChild {
|
|
36
|
+
exited: Promise<number>;
|
|
37
|
+
}
|
|
38
|
+
/** The seams the console loop runs on, replaceable under test. */
|
|
39
|
+
export interface DaemonConsoleDeps {
|
|
40
|
+
/** Starts a `chell --remote` surface on this terminal. */
|
|
41
|
+
attach: (target: DaemonConsoleTarget) => ConsoleChild;
|
|
42
|
+
/** Holds the daemon's own console writes. */
|
|
43
|
+
cage_start: () => void;
|
|
44
|
+
/** Hands back what was held. */
|
|
45
|
+
cage_stop: () => string[];
|
|
46
|
+
/** Resolves true on Enter, false when the terminal's input ends. */
|
|
47
|
+
enter_wait: () => Promise<boolean>;
|
|
48
|
+
/** The terminal's own line writer. */
|
|
49
|
+
log: (line: string) => void;
|
|
50
|
+
}
|
|
51
|
+
/** The chell entry this module was built beside: the surface to spawn. */
|
|
52
|
+
export declare const CHELL_ENTRY: string;
|
|
53
|
+
/** What the spawner needs of a child: its exit and error events. */
|
|
54
|
+
export type SpawnedChild = Pick<ChildProcess, 'once'>;
|
|
55
|
+
/** A process spawner with the shape of `child_process.spawn`. */
|
|
56
|
+
export type Spawn = (command: string, args: string[], options: {
|
|
57
|
+
stdio: 'inherit';
|
|
58
|
+
env: NodeJS.ProcessEnv;
|
|
59
|
+
}) => SpawnedChild;
|
|
60
|
+
/** What the Enter wait needs of the terminal's input. */
|
|
61
|
+
export type ConsoleInput = Pick<EventEmitter, 'on' | 'once' | 'off'> & {
|
|
62
|
+
resume(): unknown;
|
|
63
|
+
pause(): unknown;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Starts a remote chell surface on this terminal, attached by address.
|
|
67
|
+
*
|
|
68
|
+
* @param target - The daemon's wire address and token.
|
|
69
|
+
* @param spawn - The process spawner; `child_process.spawn` by default.
|
|
70
|
+
* @returns The child, settling with its exit code when the operator detaches.
|
|
71
|
+
*/
|
|
72
|
+
export declare function surface_spawn(target: DaemonConsoleTarget, spawn?: Spawn): ConsoleChild;
|
|
73
|
+
/**
|
|
74
|
+
* Waits for the operator to press Enter at the idle daemon terminal.
|
|
75
|
+
*
|
|
76
|
+
* @param input - The terminal's input; `process.stdin` by default.
|
|
77
|
+
* @returns True on a line of input; false when the input ends.
|
|
78
|
+
*/
|
|
79
|
+
export declare function enter_await(input?: ConsoleInput): Promise<boolean>;
|
|
80
|
+
/**
|
|
81
|
+
* Runs the daemon console until the operator leaves the terminal idle for
|
|
82
|
+
* good: attach, detach on `exit`, attach again on Enter, until stdin ends.
|
|
83
|
+
*
|
|
84
|
+
* @param target - The daemon to attach to.
|
|
85
|
+
* @param deps - The seams; the live ones by default.
|
|
86
|
+
* @returns Resolves when the operator will not attach again.
|
|
87
|
+
*/
|
|
88
|
+
export declare function daemonConsole_run(target: DaemonConsoleTarget, deps?: DaemonConsoleDeps): Promise<void>;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The daemon console: the terminal a daemon booted in becomes its
|
|
3
|
+
* first surface.
|
|
4
|
+
*
|
|
5
|
+
* A Linux boot ends at a login. A daemon boot ended at a resting face — a
|
|
6
|
+
* brain animation and a status line, with the boot log a keypress away —
|
|
7
|
+
* that was a screensaver where a session belonged. The identity is already
|
|
8
|
+
* resolved by the time the engine is ready, so the login is the attach: an
|
|
9
|
+
* ordinary `chell --remote` surface is put on the daemon's own terminal.
|
|
10
|
+
*
|
|
11
|
+
* It is a child process on the wire, not an in-process shortcut. The daemon
|
|
12
|
+
* process holds one output sink and one interaction surface for every
|
|
13
|
+
* attached session; a REPL started inside it would take those over and
|
|
14
|
+
* every other surface would go quiet. A child pays one loopback hop, which
|
|
15
|
+
* is what every surface pays, and shares nothing else.
|
|
16
|
+
*
|
|
17
|
+
* `exit` in the console detaches; the daemon stays up, its terminal idle.
|
|
18
|
+
* Enter attaches again. Ctrl-C at that idle terminal stops the daemon, as
|
|
19
|
+
* it always did. While the console holds the terminal, whatever the daemon
|
|
20
|
+
* itself writes — a roster row, a late warm-up settling — is held and
|
|
21
|
+
* handed back on detach, so it lands after the surface's last line and
|
|
22
|
+
* never across its prompt.
|
|
23
|
+
*
|
|
24
|
+
* @module
|
|
25
|
+
*/
|
|
26
|
+
import { spawn as childSpawn } from 'node:child_process';
|
|
27
|
+
import { fileURLToPath } from 'node:url';
|
|
28
|
+
import chalk from 'chalk';
|
|
29
|
+
import { consoleCage_start, consoleCage_stop } from '@fnndsc/calypso';
|
|
30
|
+
/** The chell entry this module was built beside: the surface to spawn. */
|
|
31
|
+
export const CHELL_ENTRY = fileURLToPath(new URL('../index.js', import.meta.url));
|
|
32
|
+
/**
|
|
33
|
+
* Starts a remote chell surface on this terminal, attached by address.
|
|
34
|
+
*
|
|
35
|
+
* @param target - The daemon's wire address and token.
|
|
36
|
+
* @param spawn - The process spawner; `child_process.spawn` by default.
|
|
37
|
+
* @returns The child, settling with its exit code when the operator detaches.
|
|
38
|
+
*/
|
|
39
|
+
export function surface_spawn(target, spawn = childSpawn) {
|
|
40
|
+
// The identity rides along so the surface greets with it, not with the
|
|
41
|
+
// address twice; the environment mark tells it whose terminal it is on,
|
|
42
|
+
// so it skips the greeting the daemon's banner already gave.
|
|
43
|
+
const child = spawn(process.execPath, [CHELL_ENTRY, '--remote', target.identity, '--attach', target.url, '--token', target.token], { stdio: 'inherit', env: { ...process.env, CHELL_CONSOLE: '1' } });
|
|
44
|
+
const exited = new Promise((resolve) => {
|
|
45
|
+
child.once('exit', (code) => { resolve(code ?? 0); });
|
|
46
|
+
child.once('error', () => { resolve(1); });
|
|
47
|
+
});
|
|
48
|
+
return { exited };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Waits for the operator to press Enter at the idle daemon terminal.
|
|
52
|
+
*
|
|
53
|
+
* @param input - The terminal's input; `process.stdin` by default.
|
|
54
|
+
* @returns True on a line of input; false when the input ends.
|
|
55
|
+
*/
|
|
56
|
+
export function enter_await(input = process.stdin) {
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
const cleanup = () => {
|
|
59
|
+
input.off('data', onData);
|
|
60
|
+
input.off('end', onEnd);
|
|
61
|
+
input.pause();
|
|
62
|
+
};
|
|
63
|
+
const onData = () => { cleanup(); resolve(true); };
|
|
64
|
+
const onEnd = () => { cleanup(); resolve(false); };
|
|
65
|
+
input.on('data', onData);
|
|
66
|
+
input.once('end', onEnd);
|
|
67
|
+
input.resume();
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** The live seams: a real child on the wire, the real cage, the real terminal. */
|
|
71
|
+
const LIVE_DEPS = {
|
|
72
|
+
attach: (target) => surface_spawn(target),
|
|
73
|
+
cage_start: consoleCage_start,
|
|
74
|
+
cage_stop: consoleCage_stop,
|
|
75
|
+
enter_wait: () => enter_await(),
|
|
76
|
+
log: (line) => { console.log(line); },
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Holds the terminal's interrupt while a surface has it.
|
|
80
|
+
*
|
|
81
|
+
* The surface's readline owns Ctrl-C while attached (it clears the typed
|
|
82
|
+
* line, as chell always has); the daemon's own stop-on-interrupt is put
|
|
83
|
+
* back once the surface detaches, so Ctrl-C at the idle terminal stops
|
|
84
|
+
* the daemon as before.
|
|
85
|
+
*
|
|
86
|
+
* @returns A restore function.
|
|
87
|
+
*/
|
|
88
|
+
function interrupt_hold() {
|
|
89
|
+
const held = process.listeners('SIGINT');
|
|
90
|
+
process.removeAllListeners('SIGINT');
|
|
91
|
+
const ignore = () => { };
|
|
92
|
+
process.on('SIGINT', ignore);
|
|
93
|
+
return () => {
|
|
94
|
+
process.off('SIGINT', ignore);
|
|
95
|
+
for (const listener of held)
|
|
96
|
+
process.on('SIGINT', listener);
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Runs the daemon console until the operator leaves the terminal idle for
|
|
101
|
+
* good: attach, detach on `exit`, attach again on Enter, until stdin ends.
|
|
102
|
+
*
|
|
103
|
+
* @param target - The daemon to attach to.
|
|
104
|
+
* @param deps - The seams; the live ones by default.
|
|
105
|
+
* @returns Resolves when the operator will not attach again.
|
|
106
|
+
*/
|
|
107
|
+
export async function daemonConsole_run(target, deps = LIVE_DEPS) {
|
|
108
|
+
for (;;) {
|
|
109
|
+
deps.log(chalk.green(`[+] Console attached to ${target.identity} — 'exit' detaches, Enter attaches again, Ctrl-C then stops the daemon`));
|
|
110
|
+
deps.cage_start();
|
|
111
|
+
const restore = interrupt_hold();
|
|
112
|
+
let held;
|
|
113
|
+
try {
|
|
114
|
+
await deps.attach(target).exited;
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
restore();
|
|
118
|
+
held = deps.cage_stop();
|
|
119
|
+
}
|
|
120
|
+
if (held.length > 0) {
|
|
121
|
+
deps.log(chalk.gray('[+] While the console was attached:'));
|
|
122
|
+
for (const line of held)
|
|
123
|
+
deps.log(line);
|
|
124
|
+
}
|
|
125
|
+
deps.log(chalk.green('[+] Console detached; the daemon is still running. Enter attaches again, Ctrl-C stops the daemon.'));
|
|
126
|
+
if (!(await deps.enter_wait()))
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=daemonConsole.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemonConsole.js","sourceRoot":"","sources":["../../src/core/daemonConsole.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Keeps a stray write from landing across an idle prompt.
|
|
3
|
+
*
|
|
4
|
+
* A REPL waiting at its prompt shares the terminal with everything else
|
|
5
|
+
* the process writes: another surface's output pushed by the daemon, a
|
|
6
|
+
* warm-up settling late, a roster row. Written raw, such a line lands on
|
|
7
|
+
* the prompt line and the prompt is gone until the next keystroke. While
|
|
8
|
+
* the guard is engaged, a stray write clears the prompt line, lands on a
|
|
9
|
+
* line of its own, and the prompt is redrawn beneath it with whatever was
|
|
10
|
+
* typed still in place.
|
|
11
|
+
*
|
|
12
|
+
* readline draws through an output whose write bypasses the guard, so the
|
|
13
|
+
* prompt's own paint is never mistaken for a stray line.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
/** A write's completion callback, as the stream API passes it. */
|
|
18
|
+
type WriteCallback = (error?: Error | null) => void;
|
|
19
|
+
/** What the guard needs of the terminal: a write it can wrap and a TTY flag. */
|
|
20
|
+
export interface GuardedStream {
|
|
21
|
+
write(chunk: string | Uint8Array, callback?: WriteCallback): boolean;
|
|
22
|
+
write(chunk: string | Uint8Array, encoding?: BufferEncoding, callback?: WriteCallback): boolean;
|
|
23
|
+
isTTY?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** A prompt guard around one output stream. */
|
|
26
|
+
export interface PromptGuard<S extends GuardedStream = GuardedStream> {
|
|
27
|
+
/** The stream readline should draw on: its write is never guarded. */
|
|
28
|
+
readonly output: S;
|
|
29
|
+
/** Route stray writes above the prompt; call once the prompt is drawn. */
|
|
30
|
+
engage(): void;
|
|
31
|
+
/** Let writes flow raw; call before a command's output starts. */
|
|
32
|
+
release(): void;
|
|
33
|
+
/** Write as the terminal's own, whether or not the guard is engaged. */
|
|
34
|
+
write(text: string): void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Creates a prompt guard around a stream.
|
|
38
|
+
*
|
|
39
|
+
* @param stream - The terminal stream; `process.stdout` in a running shell.
|
|
40
|
+
* @param redraw - Repaints the prompt and the line typed so far.
|
|
41
|
+
* @returns The guard.
|
|
42
|
+
*/
|
|
43
|
+
export declare function promptGuard_create<S extends GuardedStream>(stream: S, redraw: () => void): PromptGuard<S>;
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Keeps a stray write from landing across an idle prompt.
|
|
3
|
+
*
|
|
4
|
+
* A REPL waiting at its prompt shares the terminal with everything else
|
|
5
|
+
* the process writes: another surface's output pushed by the daemon, a
|
|
6
|
+
* warm-up settling late, a roster row. Written raw, such a line lands on
|
|
7
|
+
* the prompt line and the prompt is gone until the next keystroke. While
|
|
8
|
+
* the guard is engaged, a stray write clears the prompt line, lands on a
|
|
9
|
+
* line of its own, and the prompt is redrawn beneath it with whatever was
|
|
10
|
+
* typed still in place.
|
|
11
|
+
*
|
|
12
|
+
* readline draws through an output whose write bypasses the guard, so the
|
|
13
|
+
* prompt's own paint is never mistaken for a stray line.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Creates a prompt guard around a stream.
|
|
19
|
+
*
|
|
20
|
+
* @param stream - The terminal stream; `process.stdout` in a running shell.
|
|
21
|
+
* @param redraw - Repaints the prompt and the line typed so far.
|
|
22
|
+
* @returns The guard.
|
|
23
|
+
*/
|
|
24
|
+
export function promptGuard_create(stream, redraw) {
|
|
25
|
+
const original = stream.write;
|
|
26
|
+
const realWrite = (chunk, encodingOrCallback, callback) => {
|
|
27
|
+
// Normalised to the three-argument form: the stream takes an undefined
|
|
28
|
+
// encoding as its default, and the callback lands where it belongs.
|
|
29
|
+
const encoding = typeof encodingOrCallback === 'string' ? encodingOrCallback : undefined;
|
|
30
|
+
const done = typeof encodingOrCallback === 'function' ? encodingOrCallback : callback;
|
|
31
|
+
return original.call(stream, chunk, encoding, done);
|
|
32
|
+
};
|
|
33
|
+
let engaged = false;
|
|
34
|
+
const strayWrite = (chunk, encodingOrCallback, callback) => {
|
|
35
|
+
const text = typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf8');
|
|
36
|
+
const done = typeof encodingOrCallback === 'function' ? encodingOrCallback : callback;
|
|
37
|
+
if (stream.isTTY === true)
|
|
38
|
+
realWrite('\r\x1b[2K');
|
|
39
|
+
realWrite(text.endsWith('\n') ? text : `${text}\n`);
|
|
40
|
+
redraw();
|
|
41
|
+
done?.();
|
|
42
|
+
return true;
|
|
43
|
+
};
|
|
44
|
+
const output = new Proxy(stream, {
|
|
45
|
+
get(target, property, receiver) {
|
|
46
|
+
if (property === 'write')
|
|
47
|
+
return realWrite;
|
|
48
|
+
const value = Reflect.get(target, property, receiver);
|
|
49
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
output,
|
|
54
|
+
engage() {
|
|
55
|
+
if (engaged)
|
|
56
|
+
return;
|
|
57
|
+
engaged = true;
|
|
58
|
+
stream.write = strayWrite;
|
|
59
|
+
},
|
|
60
|
+
release() {
|
|
61
|
+
if (!engaged)
|
|
62
|
+
return;
|
|
63
|
+
engaged = false;
|
|
64
|
+
stream.write = original;
|
|
65
|
+
},
|
|
66
|
+
write(text) {
|
|
67
|
+
realWrite(text);
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=promptGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promptGuard.js","sourceRoot":"","sources":["../../src/core/promptGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAwBH;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAA0B,MAAS,EAAE,MAAkB;IACvF,MAAM,QAAQ,GAA2B,MAAM,CAAC,KAAK,CAAC;IACtD,MAAM,SAAS,GAAG,CAChB,KAA0B,EAC1B,kBAAmD,EACnD,QAAwB,EACf,EAAE;QACX,uEAAuE;QACvE,oEAAoE;QACpE,MAAM,QAAQ,GAA+B,OAAO,kBAAkB,KAAK,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC;QACrH,MAAM,IAAI,GAA8B,OAAO,kBAAkB,KAAK,UAAU,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC;QACjH,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACtD,CAAC,CAAC;IACF,IAAI,OAAO,GAAY,KAAK,CAAC;IAE7B,MAAM,UAAU,GAAG,CACjB,KAA0B,EAC1B,kBAAmD,EACnD,QAAwB,EACf,EAAE;QACX,MAAM,IAAI,GAAW,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC7F,MAAM,IAAI,GAA8B,OAAO,kBAAkB,KAAK,UAAU,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC;QACjH,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI;YAAE,SAAS,CAAC,WAAW,CAAC,CAAC;QAClD,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;QACpD,MAAM,EAAE,CAAC;QACT,IAAI,EAAE,EAAE,CAAC;QACT,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,MAAM,GAAM,IAAI,KAAK,CAAC,MAAM,EAAE;QAClC,GAAG,CAAC,MAAS,EAAE,QAAyB,EAAE,QAAiB;YACzD,IAAI,QAAQ,KAAK,OAAO;gBAAE,OAAO,SAAS,CAAC;YAC3C,MAAM,KAAK,GAAY,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC/D,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAE,KAAyC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACvG,CAAC;KACF,CAAC,CAAC;IAEH,OAAO;QACL,MAAM;QACN,MAAM;YACJ,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC;QAC5B,CAAC;QACD,OAAO;YACL,IAAI,CAAC,OAAO;gBAAE,OAAO;YACrB,OAAO,GAAG,KAAK,CAAC;YAChB,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC;QAC1B,CAAC;QACD,KAAK,CAAC,IAAY;YAChB,SAAS,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/core/repl.d.ts
CHANGED
|
@@ -33,6 +33,12 @@ export declare class REPL {
|
|
|
33
33
|
private lastExitCode;
|
|
34
34
|
private promptText;
|
|
35
35
|
private readonly bytesFetch;
|
|
36
|
+
/**
|
|
37
|
+
* Keeps a stray write — another surface's output pushed by the daemon, a
|
|
38
|
+
* warm-up settling late — from landing across the idle prompt. Engaged
|
|
39
|
+
* once the prompt is drawn, released before a command's output starts.
|
|
40
|
+
*/
|
|
41
|
+
private readonly guard;
|
|
36
42
|
/**
|
|
37
43
|
* Initializes the REPL interface around an engine.
|
|
38
44
|
*
|
package/dist/core/repl.js
CHANGED
|
@@ -17,6 +17,7 @@ import { cliSurface_create } from './cliSurface.js';
|
|
|
17
17
|
import { sink_set, StdoutSink } from '@fnndsc/brasa';
|
|
18
18
|
import { TerminalProgressRenderer } from './progressRenderer.js';
|
|
19
19
|
import { surfaceLine_executeSafely } from './surfaceDispatch.js';
|
|
20
|
+
import { promptGuard_create } from './promptGuard.js';
|
|
20
21
|
/**
|
|
21
22
|
* Handles the Read-Eval-Print Loop (REPL) interaction.
|
|
22
23
|
*/
|
|
@@ -28,6 +29,12 @@ export class REPL {
|
|
|
28
29
|
lastExitCode = 0;
|
|
29
30
|
promptText;
|
|
30
31
|
bytesFetch;
|
|
32
|
+
/**
|
|
33
|
+
* Keeps a stray write — another surface's output pushed by the daemon, a
|
|
34
|
+
* warm-up settling late — from landing across the idle prompt. Engaged
|
|
35
|
+
* once the prompt is drawn, released before a command's output starts.
|
|
36
|
+
*/
|
|
37
|
+
guard;
|
|
31
38
|
/**
|
|
32
39
|
* Initializes the REPL interface around an engine.
|
|
33
40
|
*
|
|
@@ -38,9 +45,20 @@ export class REPL {
|
|
|
38
45
|
this.engine = engine;
|
|
39
46
|
this.promptText = options?.promptText;
|
|
40
47
|
this.bytesFetch = options?.bytesFetch;
|
|
48
|
+
this.guard = promptGuard_create(process.stdout, () => {
|
|
49
|
+
try {
|
|
50
|
+
this.rl.prompt(true);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Interface might be closed.
|
|
54
|
+
}
|
|
55
|
+
});
|
|
41
56
|
this.rl = readline.createInterface({
|
|
42
57
|
input: process.stdin,
|
|
43
|
-
output
|
|
58
|
+
// readline draws through the guard's own output, so the prompt's paint
|
|
59
|
+
// is never taken for a stray line.
|
|
60
|
+
output: this.guard.output,
|
|
61
|
+
terminal: process.stdout.isTTY === true,
|
|
44
62
|
prompt: '> ',
|
|
45
63
|
completer: (line, callback) => {
|
|
46
64
|
this.engine.line_complete(line)
|
|
@@ -66,6 +84,8 @@ export class REPL {
|
|
|
66
84
|
await this.history_load();
|
|
67
85
|
await this.prompt_update();
|
|
68
86
|
this.rl.on('line', async (line) => {
|
|
87
|
+
// The line is the command's now; its output flows raw.
|
|
88
|
+
this.guard.release();
|
|
69
89
|
await this.history_append(line);
|
|
70
90
|
// `exit` quits this shell, never the engine. Closing readline runs the
|
|
71
91
|
// 'close' handler (goodbye, then process exit). Crucially, for a remote
|
|
@@ -93,7 +113,7 @@ export class REPL {
|
|
|
93
113
|
// A cancellable foreground command (currently recursive scans) gets the
|
|
94
114
|
// interrupt first. Otherwise Ctrl+C retains readline's usual behavior:
|
|
95
115
|
// clear an unfinished input line and redraw the prompt.
|
|
96
|
-
|
|
116
|
+
this.guard.write('\n');
|
|
97
117
|
if (this.engine.line_cancel?.()) {
|
|
98
118
|
return;
|
|
99
119
|
}
|
|
@@ -102,6 +122,7 @@ export class REPL {
|
|
|
102
122
|
});
|
|
103
123
|
this.rl.on('close', () => {
|
|
104
124
|
this.isOpen = false;
|
|
125
|
+
this.guard.release();
|
|
105
126
|
console.log(chalk.cyan('Exiting ChELL. Goodbye!'));
|
|
106
127
|
process.exit(0);
|
|
107
128
|
});
|
|
@@ -124,6 +145,7 @@ export class REPL {
|
|
|
124
145
|
catch (e) {
|
|
125
146
|
// Interface might be closed
|
|
126
147
|
}
|
|
148
|
+
this.guard.engage();
|
|
127
149
|
return;
|
|
128
150
|
}
|
|
129
151
|
const rendered = await sessionPrompt_render({
|
|
@@ -137,6 +159,7 @@ export class REPL {
|
|
|
137
159
|
catch (e) {
|
|
138
160
|
// Interface might be closed
|
|
139
161
|
}
|
|
162
|
+
this.guard.engage();
|
|
140
163
|
}
|
|
141
164
|
/**
|
|
142
165
|
* Loads command history from file.
|
package/dist/core/repl.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repl.js","sourceRoot":"","sources":["../../src/core/repl.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAmB,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"repl.js","sourceRoot":"","sources":["../../src/core/repl.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { type BrasaEngine, type PrefetchResult } from '@fnndsc/brasa';
|
|
12
12
|
import { type HostControlInputs } from '@fnndsc/calypso';
|
|
13
|
+
import { type DaemonConsoleTarget } from './daemonConsole.js';
|
|
13
14
|
import { type BootStatus } from '../lib/bootsequence.js';
|
|
14
15
|
/** Startup cache selections shared by interactive and daemon modes. */
|
|
15
16
|
export interface StartupWarmupFlags {
|
|
@@ -77,11 +78,13 @@ export declare function queryCheckpoint_flush(): Promise<void>;
|
|
|
77
78
|
* @param user - Authenticated username used to construct the feed path.
|
|
78
79
|
* @param interactive - Whether progress may use an interactive spinner.
|
|
79
80
|
* @param reporter - Host status logger, or null for silent status reporting.
|
|
80
|
-
* @param
|
|
81
|
-
*
|
|
81
|
+
* @param reportSettlement - Whether to report outcomes that arrive after
|
|
82
|
+
* boot (the topology walk, the steps warming behind the prompt); daemon
|
|
83
|
+
* hosts enable this because the face keeps the readout, while interactive
|
|
84
|
+
* hosts use prompt progress.
|
|
82
85
|
* @returns Cache counts and the labels of any failed warm-up operations.
|
|
83
86
|
*/
|
|
84
|
-
export declare function startupWarmup_run(flags: StartupWarmupFlags, user: string | undefined, interactive: boolean, reporter: StartupWarmupReporter | null,
|
|
87
|
+
export declare function startupWarmup_run(flags: StartupWarmupFlags, user: string | undefined, interactive: boolean, reporter: StartupWarmupReporter | null, reportSettlement?: boolean): Promise<StartupWarmupCache>;
|
|
85
88
|
/**
|
|
86
89
|
* Warms a connected engine, reports readiness, then publishes its daemon.
|
|
87
90
|
*
|
|
@@ -90,5 +93,9 @@ export declare function startupWarmup_run(flags: StartupWarmupFlags, user: strin
|
|
|
90
93
|
* @param flags - Resource caches selected by daemon boot flags.
|
|
91
94
|
* @param interactive - Whether progress may use an interactive spinner.
|
|
92
95
|
* @param reporter - Daemon boot status logger.
|
|
96
|
+
* @param recovery - Asks the operator what to do after an exhausted warm-up.
|
|
97
|
+
* @param hostControlInputs - The host-control policy inputs.
|
|
98
|
+
* @param console - Puts a surface on this terminal once the daemon is up;
|
|
99
|
+
* the daemon console by default, replaceable under test.
|
|
93
100
|
*/
|
|
94
|
-
export declare function daemonSession_run(engine: BrasaEngine, user: string | undefined, flags: StartupWarmupFlags, interactive: boolean, reporter: StartupWarmupReporter, recovery?: DaemonWarmupRecovery, hostControlInputs?: HostControlInputs): Promise<void>;
|
|
101
|
+
export declare function daemonSession_run(engine: BrasaEngine, user: string | undefined, flags: StartupWarmupFlags, interactive: boolean, reporter: StartupWarmupReporter, recovery?: DaemonWarmupRecovery, hostControlInputs?: HostControlInputs, console?: (target: DaemonConsoleTarget) => Promise<void>): Promise<void>;
|