@fnndsc/chell 4.3.1 → 4.4.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.
Files changed (124) hide show
  1. package/dist/builtins/debug.d.ts +3 -1
  2. package/dist/builtins/debug.js +14 -22
  3. package/dist/builtins/debug.js.map +1 -1
  4. package/dist/builtins/fs/cat.d.ts +8 -8
  5. package/dist/builtins/fs/cat.js +37 -20
  6. package/dist/builtins/fs/cat.js.map +1 -1
  7. package/dist/builtins/fs/cd.d.ts +3 -2
  8. package/dist/builtins/fs/cd.js +48 -33
  9. package/dist/builtins/fs/cd.js.map +1 -1
  10. package/dist/builtins/fs/cp.d.ts +4 -1
  11. package/dist/builtins/fs/cp.js +23 -10
  12. package/dist/builtins/fs/cp.js.map +1 -1
  13. package/dist/builtins/fs/download.js +5 -1
  14. package/dist/builtins/fs/download.js.map +1 -1
  15. package/dist/builtins/fs/edit.d.ts +2 -2
  16. package/dist/builtins/fs/edit.js +37 -19
  17. package/dist/builtins/fs/edit.js.map +1 -1
  18. package/dist/builtins/fs/mkdir.d.ts +4 -1
  19. package/dist/builtins/fs/mkdir.js +20 -6
  20. package/dist/builtins/fs/mkdir.js.map +1 -1
  21. package/dist/builtins/fs/mv.d.ts +4 -1
  22. package/dist/builtins/fs/mv.js +23 -10
  23. package/dist/builtins/fs/mv.js.map +1 -1
  24. package/dist/builtins/fs/pull.d.ts +2 -2
  25. package/dist/builtins/fs/pull.js +57 -29
  26. package/dist/builtins/fs/pull.js.map +1 -1
  27. package/dist/builtins/fs/pwd.d.ts +6 -3
  28. package/dist/builtins/fs/pwd.js +8 -10
  29. package/dist/builtins/fs/pwd.js.map +1 -1
  30. package/dist/builtins/fs/rm.d.ts +7 -1
  31. package/dist/builtins/fs/rm.js +61 -12
  32. package/dist/builtins/fs/rm.js.map +1 -1
  33. package/dist/builtins/fs/touch.d.ts +4 -1
  34. package/dist/builtins/fs/touch.js +24 -12
  35. package/dist/builtins/fs/touch.js.map +1 -1
  36. package/dist/builtins/fs/upload.js +4 -1
  37. package/dist/builtins/fs/upload.js.map +1 -1
  38. package/dist/builtins/help.js +3 -3
  39. package/dist/builtins/index.d.ts +1 -0
  40. package/dist/builtins/index.js +1 -0
  41. package/dist/builtins/index.js.map +1 -1
  42. package/dist/builtins/net/cubepath.d.ts +1 -1
  43. package/dist/builtins/net/cubepath.js +1 -1
  44. package/dist/builtins/net/query.d.ts +1 -1
  45. package/dist/builtins/net/query.js +1 -1
  46. package/dist/builtins/sys/physicalmode.d.ts +3 -1
  47. package/dist/builtins/sys/physicalmode.js +13 -20
  48. package/dist/builtins/sys/physicalmode.js.map +1 -1
  49. package/dist/builtins/sys/timing.d.ts +3 -1
  50. package/dist/builtins/sys/timing.js +13 -20
  51. package/dist/builtins/sys/timing.js.map +1 -1
  52. package/dist/builtins/sys/version.d.ts +15 -0
  53. package/dist/builtins/sys/version.js +23 -0
  54. package/dist/builtins/sys/version.js.map +1 -0
  55. package/dist/builtins/sys/whoami.d.ts +9 -4
  56. package/dist/builtins/sys/whoami.js +20 -13
  57. package/dist/builtins/sys/whoami.js.map +1 -1
  58. package/dist/calypso.d.ts +13 -0
  59. package/dist/calypso.js +44 -0
  60. package/dist/calypso.js.map +1 -0
  61. package/dist/chell.d.ts +2 -1
  62. package/dist/chell.js +2 -1
  63. package/dist/chell.js.map +1 -1
  64. package/dist/core/boot.d.ts +3 -1
  65. package/dist/core/boot.js +50 -100
  66. package/dist/core/boot.js.map +1 -1
  67. package/dist/core/cli.d.ts +3 -1
  68. package/dist/core/cli.js +11 -1
  69. package/dist/core/cli.js.map +1 -1
  70. package/dist/core/cliSurface.d.ts +26 -0
  71. package/dist/core/cliSurface.js +152 -0
  72. package/dist/core/cliSurface.js.map +1 -0
  73. package/dist/core/dispatch.d.ts +63 -10
  74. package/dist/core/dispatch.js +326 -234
  75. package/dist/core/dispatch.js.map +1 -1
  76. package/dist/core/engine.d.ts +91 -0
  77. package/dist/core/engine.js +222 -0
  78. package/dist/core/engine.js.map +1 -0
  79. package/dist/core/progress.d.ts +25 -0
  80. package/dist/core/progress.js +10 -0
  81. package/dist/core/progress.js.map +1 -0
  82. package/dist/core/progressRenderer.d.ts +42 -0
  83. package/dist/core/progressRenderer.js +176 -0
  84. package/dist/core/progressRenderer.js.map +1 -0
  85. package/dist/core/prompt/session.d.ts +20 -0
  86. package/dist/core/prompt/session.js +43 -0
  87. package/dist/core/prompt/session.js.map +1 -0
  88. package/dist/core/question.d.ts +11 -18
  89. package/dist/core/question.js +14 -57
  90. package/dist/core/question.js.map +1 -1
  91. package/dist/core/repl.d.ts +25 -5
  92. package/dist/core/repl.js +56 -45
  93. package/dist/core/repl.js.map +1 -1
  94. package/dist/core/sink.d.ts +201 -0
  95. package/dist/core/sink.js +300 -0
  96. package/dist/core/sink.js.map +1 -0
  97. package/dist/core/surface.d.ts +172 -0
  98. package/dist/core/surface.js +105 -0
  99. package/dist/core/surface.js.map +1 -0
  100. package/dist/core/version.d.ts +20 -0
  101. package/dist/core/version.js +82 -0
  102. package/dist/core/version.js.map +1 -0
  103. package/dist/core/warnings.d.ts +14 -0
  104. package/dist/core/warnings.js +25 -0
  105. package/dist/core/warnings.js.map +1 -0
  106. package/dist/daemon/launch.d.ts +9 -0
  107. package/dist/daemon/launch.js +82 -0
  108. package/dist/daemon/launch.js.map +1 -0
  109. package/dist/index.js +2 -12
  110. package/dist/index.js.map +1 -1
  111. package/dist/lib/spinner.js +5 -4
  112. package/dist/lib/spinner.js.map +1 -1
  113. package/dist/lib/vfs/vfs.js +7 -3
  114. package/dist/lib/vfs/vfs.js.map +1 -1
  115. package/dist/remote/client.d.ts +6 -0
  116. package/dist/remote/client.js +71 -0
  117. package/dist/remote/client.js.map +1 -0
  118. package/dist/remote/discovery.d.ts +23 -0
  119. package/dist/remote/discovery.js +55 -0
  120. package/dist/remote/discovery.js.map +1 -0
  121. package/dist/remote/remoteEngine.d.ts +125 -0
  122. package/dist/remote/remoteEngine.js +283 -0
  123. package/dist/remote/remoteEngine.js.map +1 -0
  124. package/package.json +8 -6
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @file Same-user daemon discovery.
3
+ *
4
+ * The daemon writes its URL and attach token to a user-only-readable file so a
5
+ * `chell --remote` client running as the same user can find it without the
6
+ * token crossing any other channel. This mirrors the local-daemon model: the
7
+ * perimeter is the loopback bind plus a token whose only distribution is a
8
+ * 0600 file on the same machine.
9
+ *
10
+ * @module
11
+ */
12
+ import { writeFileSync, readFileSync, existsSync } from 'fs';
13
+ import { join } from 'path';
14
+ import { tmpdir } from 'os';
15
+ import { userInfo } from 'os';
16
+ /**
17
+ * The per-user discovery file path.
18
+ *
19
+ * @returns The path the daemon writes and a client reads.
20
+ */
21
+ export function discovery_path() {
22
+ return join(tmpdir(), `chell-calypso-${userInfo().username}.json`);
23
+ }
24
+ /**
25
+ * Writes the discovery file, readable only by the current user.
26
+ *
27
+ * @param discovery - The URL and token to record.
28
+ */
29
+ export function discovery_write(discovery) {
30
+ writeFileSync(discovery_path(), JSON.stringify(discovery), { mode: 0o600 });
31
+ }
32
+ /**
33
+ * Reads the discovery file.
34
+ *
35
+ * @returns The recorded URL and token, or null when no daemon has advertised.
36
+ */
37
+ export function discovery_read() {
38
+ const path = discovery_path();
39
+ if (!existsSync(path)) {
40
+ return null;
41
+ }
42
+ try {
43
+ const parsed = JSON.parse(readFileSync(path, 'utf-8'));
44
+ if (typeof parsed === 'object' && parsed !== null &&
45
+ typeof parsed.url === 'string' &&
46
+ typeof parsed.token === 'string') {
47
+ return parsed;
48
+ }
49
+ return null;
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ }
55
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/remote/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAQ9B;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,QAAQ,EAAE,CAAC,QAAQ,OAAO,CAAC,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,SAAoB;IAClD,aAAa,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,IAAI,GAAW,cAAc,EAAE,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,IACE,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;YAC7C,OAAQ,MAAoB,CAAC,GAAG,KAAK,QAAQ;YAC7C,OAAQ,MAAoB,CAAC,KAAK,KAAK,QAAQ,EAC/C,CAAC;YACD,OAAO,MAAmB,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,125 @@
1
+ import type { CommandEnvelope } from '@fnndsc/cumin';
2
+ import type { ChellEngine, CompletionResult } from '../core/engine.js';
3
+ /** Options for connecting a remote engine. */
4
+ export interface RemoteEngineOptions {
5
+ /** The daemon WebSocket URL, e.g. `ws://127.0.0.1:4300`. */
6
+ url: string;
7
+ /** The attach token. */
8
+ token: string;
9
+ /** Called with each session-bus broadcast from another surface. */
10
+ onSession?: (surface: string, envelope: CommandEnvelope) => void;
11
+ /** Answers a prompt the daemon raised during a command (password, confirmation). */
12
+ onPrompt?: (message: string, hidden: boolean) => Promise<string>;
13
+ /** Runs a pipeline segment on this machine and returns its output. */
14
+ onPipe?: (command: string, input: Buffer) => Promise<Buffer>;
15
+ /** Opens content in this machine's editor and returns the edited result. */
16
+ onEdit?: (content: string, extension: string | undefined) => Promise<{
17
+ content: string;
18
+ changed: boolean;
19
+ }>;
20
+ /** Called when the connection closes unexpectedly. */
21
+ onClose?: () => void;
22
+ }
23
+ /**
24
+ * A `ChellEngine` implementation that drives a remote daemon.
25
+ */
26
+ export declare class RemoteEngine implements ChellEngine {
27
+ private readonly ws;
28
+ private readonly pending;
29
+ private readonly onSession;
30
+ private readonly onPrompt;
31
+ private readonly onPipe;
32
+ private readonly onEdit;
33
+ private latestPrompt;
34
+ private nextId;
35
+ private readonly liveEnvelopeChannels;
36
+ /**
37
+ * @param ws - An open, already-attached socket to the daemon.
38
+ * @param options - The callbacks for session broadcasts and prompts.
39
+ */
40
+ private constructor();
41
+ /**
42
+ * Connects to a daemon, performs the attach handshake, and returns a ready
43
+ * remote engine.
44
+ *
45
+ * @param options - The daemon URL, attach token, and callbacks.
46
+ * @returns The connected remote engine.
47
+ * @throws {Error} When the connection fails or the attach is refused.
48
+ */
49
+ static connect(options: RemoteEngineOptions): Promise<RemoteEngine>;
50
+ /** @inheritdoc */
51
+ line_execute(line: string): Promise<CommandEnvelope[]>;
52
+ /** @inheritdoc */
53
+ line_complete(linePrefix: string): Promise<CompletionResult>;
54
+ /**
55
+ * Sends a correlated request and returns a promise for its reply.
56
+ *
57
+ * @param type - The request message type.
58
+ * @param fields - The message fields besides `type` and `id`.
59
+ * @returns The reply payload.
60
+ */
61
+ private request;
62
+ /**
63
+ * Dispatches a message from the daemon: correlated replies resolve their
64
+ * pending request, session broadcasts reach the callback, and uncorrelated
65
+ * errors are surfaced.
66
+ *
67
+ * @param payload - The raw message bytes.
68
+ */
69
+ private message_handle;
70
+ /**
71
+ * Answers a prompt the daemon raised: asks the local surface and sends the
72
+ * answer back. With no prompt handler, answers empty so the command does not
73
+ * hang.
74
+ *
75
+ * @param promptId - The prompt correlation id.
76
+ * @param message - The prompt text.
77
+ * @param hidden - Whether the entry should be hidden (a password).
78
+ */
79
+ private prompt_answer;
80
+ /**
81
+ * Runs a pipeline segment the daemon asked for on this machine and returns
82
+ * its output. Data crosses the wire base64-encoded. With no pipe handler,
83
+ * returns the input unchanged so the pipeline does not hang.
84
+ *
85
+ * @param pipeId - The pipe correlation id.
86
+ * @param command - The segment command line.
87
+ * @param input - The base64-encoded input bytes.
88
+ */
89
+ private pipe_run;
90
+ /**
91
+ * Opens content in this machine's editor (the daemon asked for it) and
92
+ * returns the edited result. With no edit handler, returns the content
93
+ * unchanged so the command does not hang.
94
+ *
95
+ * @param editId - The edit correlation id.
96
+ * @param content - The content to edit.
97
+ * @param extension - An optional filename extension.
98
+ */
99
+ private edit_run;
100
+ /**
101
+ * Renders a streamed output chunk to the local sink on its channel.
102
+ *
103
+ * @param channel - The sink channel the chunk belongs to.
104
+ * @param chunk - The streamed text.
105
+ */
106
+ private output_render;
107
+ /**
108
+ * Applies a settlement to the pending request for an id, if one exists.
109
+ *
110
+ * @param id - The correlation id.
111
+ * @param settle - The settlement to apply.
112
+ */
113
+ private pending_settle;
114
+ /**
115
+ * The latest themed prompt string the daemon pushed, or empty before the
116
+ * first push.
117
+ *
118
+ * @returns The current prompt string.
119
+ */
120
+ promptLine(): string;
121
+ /**
122
+ * Closes the connection.
123
+ */
124
+ close(): void;
125
+ }
@@ -0,0 +1,283 @@
1
+ /**
2
+ * @file The remote engine: a `ChellEngine` backed by a daemon over the wire.
3
+ *
4
+ * This is the transport swap that lets the same REPL drive either an in-process
5
+ * engine or a CALYPSO daemon. It implements the engine interface by sending
6
+ * `execute` / `complete` messages over a WebSocket and awaiting the correlated
7
+ * `result` / completion replies, validating every message against calypso's
8
+ * wire contract at the boundary. Session-bus broadcasts (another surface's
9
+ * activity) are delivered to an optional callback so the host can render them.
10
+ *
11
+ * @module
12
+ */
13
+ import { WebSocket } from 'ws';
14
+ import { serverMessage_parse, CONTRACT_VERSION } from '@fnndsc/calypso';
15
+ import { envelope_deliver, sink_get } from '../core/sink.js';
16
+ /**
17
+ * A `ChellEngine` implementation that drives a remote daemon.
18
+ */
19
+ export class RemoteEngine {
20
+ ws;
21
+ pending = new Map();
22
+ onSession;
23
+ onPrompt;
24
+ onPipe;
25
+ onEdit;
26
+ latestPrompt = '';
27
+ nextId = 0;
28
+ liveEnvelopeChannels = new Map();
29
+ /**
30
+ * @param ws - An open, already-attached socket to the daemon.
31
+ * @param options - The callbacks for session broadcasts and prompts.
32
+ */
33
+ constructor(ws, options) {
34
+ this.ws = ws;
35
+ this.onSession = options.onSession;
36
+ this.onPrompt = options.onPrompt;
37
+ this.onPipe = options.onPipe;
38
+ this.onEdit = options.onEdit;
39
+ }
40
+ /**
41
+ * Connects to a daemon, performs the attach handshake, and returns a ready
42
+ * remote engine.
43
+ *
44
+ * @param options - The daemon URL, attach token, and callbacks.
45
+ * @returns The connected remote engine.
46
+ * @throws {Error} When the connection fails or the attach is refused.
47
+ */
48
+ static connect(options) {
49
+ return new Promise((resolve, reject) => {
50
+ const ws = new WebSocket(options.url);
51
+ ws.once('error', (err) => reject(err));
52
+ ws.once('open', () => {
53
+ ws.send(JSON.stringify({ type: 'attach', protocolVersion: CONTRACT_VERSION, token: options.token }));
54
+ ws.once('message', (data) => {
55
+ const parsed = serverMessage_parse(safeJson_parse(data.toString()));
56
+ if (!parsed.ok || parsed.value === undefined) {
57
+ reject(new Error(`attach failed: ${parsed.error ?? 'invalid response'}`));
58
+ ws.close();
59
+ return;
60
+ }
61
+ const message = parsed.value;
62
+ if (message.type === 'error') {
63
+ reject(new Error(`attach refused: ${message.reason}`));
64
+ ws.close();
65
+ return;
66
+ }
67
+ if (message.type !== 'attached') {
68
+ reject(new Error(`unexpected attach response: ${message.type}`));
69
+ ws.close();
70
+ return;
71
+ }
72
+ const engine = new RemoteEngine(ws, options);
73
+ ws.on('message', (payload) => engine.message_handle(payload));
74
+ if (options.onClose) {
75
+ ws.on('close', () => options.onClose?.());
76
+ }
77
+ resolve(engine);
78
+ });
79
+ });
80
+ });
81
+ }
82
+ /** @inheritdoc */
83
+ async line_execute(line) {
84
+ const id = String(this.nextId++);
85
+ const envelopes = await this.request('execute', { line }, id);
86
+ const liveChannels = this.liveEnvelopeChannels.get(id);
87
+ this.liveEnvelopeChannels.delete(id);
88
+ // Deliver to the active sink exactly as the in-process engine delivers
89
+ // live, so the REPL host renders remote output without any change.
90
+ for (const envelope of envelopes) {
91
+ envelope_deliver(liveChannels ? {
92
+ ...envelope,
93
+ rendered: liveChannels.has('data') ? '' : envelope.rendered,
94
+ renderedErr: liveChannels.has('err') ? undefined : envelope.renderedErr,
95
+ } : envelope);
96
+ }
97
+ return envelopes;
98
+ }
99
+ /** @inheritdoc */
100
+ line_complete(linePrefix) {
101
+ return this.request('complete', { prefix: linePrefix });
102
+ }
103
+ /**
104
+ * Sends a correlated request and returns a promise for its reply.
105
+ *
106
+ * @param type - The request message type.
107
+ * @param fields - The message fields besides `type` and `id`.
108
+ * @returns The reply payload.
109
+ */
110
+ request(type, fields, requestId) {
111
+ const id = requestId ?? String(this.nextId++);
112
+ return new Promise((resolve, reject) => {
113
+ this.pending.set(id, { resolve, reject });
114
+ this.ws.send(JSON.stringify({ type, id, ...fields }));
115
+ });
116
+ }
117
+ /**
118
+ * Dispatches a message from the daemon: correlated replies resolve their
119
+ * pending request, session broadcasts reach the callback, and uncorrelated
120
+ * errors are surfaced.
121
+ *
122
+ * @param payload - The raw message bytes.
123
+ */
124
+ message_handle(payload) {
125
+ const parsed = serverMessage_parse(safeJson_parse(payload.toString()));
126
+ if (!parsed.ok || parsed.value === undefined) {
127
+ return;
128
+ }
129
+ const message = parsed.value;
130
+ switch (message.type) {
131
+ case 'result':
132
+ this.pending_settle(message.id, (p) => p.resolve(message.envelopes));
133
+ break;
134
+ case 'complete':
135
+ this.pending_settle(message.id, (p) => p.resolve({ candidates: message.candidates, prefix: message.prefix }));
136
+ break;
137
+ case 'session':
138
+ // The wire envelope is a CommandEnvelope; calypso's schema infers the
139
+ // model payload as optional-unknown, a zod nicety the runtime shape
140
+ // does not reflect. Narrow at this single boundary.
141
+ if (this.onSession)
142
+ this.onSession(message.surface, message.envelope);
143
+ break;
144
+ case 'prompt':
145
+ void this.prompt_answer(message.promptId, message.message, message.hidden);
146
+ break;
147
+ case 'promptline':
148
+ this.latestPrompt = message.text;
149
+ break;
150
+ case 'progress':
151
+ {
152
+ const { type: _type, id: _id, ...event } = message;
153
+ sink_get().progress_write(event);
154
+ }
155
+ break;
156
+ case 'output':
157
+ if (message.channel === 'data' || message.channel === 'err') {
158
+ const channels = this.liveEnvelopeChannels.get(message.id) ?? new Set();
159
+ channels.add(message.channel);
160
+ this.liveEnvelopeChannels.set(message.id, channels);
161
+ }
162
+ this.output_render(message.channel, message.chunk);
163
+ break;
164
+ case 'pipe':
165
+ void this.pipe_run(message.pipeId, message.command, message.input);
166
+ break;
167
+ case 'edit':
168
+ void this.edit_run(message.editId, message.content, message.extension);
169
+ break;
170
+ case 'error':
171
+ if (message.id !== undefined) {
172
+ this.pending_settle(message.id, (p) => p.reject(new Error(message.reason)));
173
+ }
174
+ break;
175
+ default:
176
+ break;
177
+ }
178
+ }
179
+ /**
180
+ * Answers a prompt the daemon raised: asks the local surface and sends the
181
+ * answer back. With no prompt handler, answers empty so the command does not
182
+ * hang.
183
+ *
184
+ * @param promptId - The prompt correlation id.
185
+ * @param message - The prompt text.
186
+ * @param hidden - Whether the entry should be hidden (a password).
187
+ */
188
+ async prompt_answer(promptId, message, hidden) {
189
+ const answer = this.onPrompt ? await this.onPrompt(message, hidden) : '';
190
+ this.ws.send(JSON.stringify({ type: 'promptAnswer', promptId, answer }));
191
+ }
192
+ /**
193
+ * Runs a pipeline segment the daemon asked for on this machine and returns
194
+ * its output. Data crosses the wire base64-encoded. With no pipe handler,
195
+ * returns the input unchanged so the pipeline does not hang.
196
+ *
197
+ * @param pipeId - The pipe correlation id.
198
+ * @param command - The segment command line.
199
+ * @param input - The base64-encoded input bytes.
200
+ */
201
+ async pipe_run(pipeId, command, input) {
202
+ const inputBytes = Buffer.from(input, 'base64');
203
+ const output = this.onPipe ? await this.onPipe(command, inputBytes) : inputBytes;
204
+ this.ws.send(JSON.stringify({ type: 'pipeResult', pipeId, output: output.toString('base64') }));
205
+ }
206
+ /**
207
+ * Opens content in this machine's editor (the daemon asked for it) and
208
+ * returns the edited result. With no edit handler, returns the content
209
+ * unchanged so the command does not hang.
210
+ *
211
+ * @param editId - The edit correlation id.
212
+ * @param content - The content to edit.
213
+ * @param extension - An optional filename extension.
214
+ */
215
+ async edit_run(editId, content, extension) {
216
+ const result = this.onEdit
217
+ ? await this.onEdit(content, extension)
218
+ : { content, changed: false };
219
+ this.ws.send(JSON.stringify({ type: 'editResult', editId, content: result.content, changed: result.changed }));
220
+ }
221
+ /**
222
+ * Renders a streamed output chunk to the local sink on its channel.
223
+ *
224
+ * @param channel - The sink channel the chunk belongs to.
225
+ * @param chunk - The streamed text.
226
+ */
227
+ output_render(channel, chunk) {
228
+ const sink = sink_get();
229
+ if (channel === 'data') {
230
+ sink.data_write(chunk);
231
+ }
232
+ else if (channel === 'err') {
233
+ sink.err_write(chunk);
234
+ }
235
+ else {
236
+ sink.status_write(chunk);
237
+ }
238
+ }
239
+ /**
240
+ * Applies a settlement to the pending request for an id, if one exists.
241
+ *
242
+ * @param id - The correlation id.
243
+ * @param settle - The settlement to apply.
244
+ */
245
+ pending_settle(id, settle) {
246
+ const pending = this.pending.get(id);
247
+ if (pending) {
248
+ this.pending.delete(id);
249
+ settle(pending);
250
+ }
251
+ }
252
+ /**
253
+ * The latest themed prompt string the daemon pushed, or empty before the
254
+ * first push.
255
+ *
256
+ * @returns The current prompt string.
257
+ */
258
+ promptLine() {
259
+ return this.latestPrompt;
260
+ }
261
+ /**
262
+ * Closes the connection.
263
+ */
264
+ close() {
265
+ this.ws.close();
266
+ }
267
+ }
268
+ /**
269
+ * Parses JSON, returning `undefined` on failure so callers can validate the
270
+ * result rather than catch.
271
+ *
272
+ * @param text - The JSON text.
273
+ * @returns The parsed value, or undefined when the text is not valid JSON.
274
+ */
275
+ function safeJson_parse(text) {
276
+ try {
277
+ return JSON.parse(text);
278
+ }
279
+ catch {
280
+ return undefined;
281
+ }
282
+ }
283
+ //# sourceMappingURL=remoteEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteEngine.js","sourceRoot":"","sources":["../../src/remote/remoteEngine.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fnndsc/chell",
3
- "version": "4.3.1",
3
+ "version": "4.4.0",
4
4
  "description": "ChELL Executes Layered Logic - Interactive ChRIS REPL Shell",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,13 +13,14 @@
13
13
  "main": "dist/index.js",
14
14
  "type": "module",
15
15
  "bin": {
16
- "chell": "./dist/index.js"
16
+ "chell": "./dist/index.js",
17
+ "calypso": "./dist/calypso.js"
17
18
  },
18
19
  "files": [
19
20
  "dist"
20
21
  ],
21
22
  "scripts": {
22
- "build": "tsc && chmod +x ./dist/index.js",
23
+ "build": "tsc && chmod +x ./dist/index.js ./dist/calypso.js",
23
24
  "exemplars:build": "tsc -p exemplars/ts",
24
25
  "start": "node dist/index.js",
25
26
  "test": "NODE_OPTIONS='--experimental-vm-modules --disable-warning=ExperimentalWarning' jest --forceExit --coverage",
@@ -38,8 +39,8 @@
38
39
  "license": "MIT",
39
40
  "dependencies": {
40
41
  "@fnndsc/chili": "^3.3.0",
41
- "@fnndsc/cumin": "^3.4.0",
42
- "@fnndsc/salsa": "^3.2.5",
42
+ "@fnndsc/cumin": "^3.5.0",
43
+ "@fnndsc/salsa": "^3.2.6",
43
44
  "chalk": "^4.1.2",
44
45
  "cli-progress": "^3.12.0",
45
46
  "commander": "^12.1.0",
@@ -48,7 +49,8 @@
48
49
  "marked": "^15.0.12",
49
50
  "marked-terminal": "^7.3.0",
50
51
  "minimatch": "^10.1.1",
51
- "ws": "^8.21.0"
52
+ "ws": "^8.21.0",
53
+ "@fnndsc/calypso": "^0.2.0"
52
54
  },
53
55
  "devDependencies": {
54
56
  "@types/cli-progress": "^3.11.6",