@thenewlabs/entangle-serve 2.6.1 → 2.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/index.js CHANGED
@@ -1,128 +1,385 @@
1
1
  #!/usr/bin/env node
2
+ import * as net from 'net';
3
+ import * as fs from 'fs';
4
+ import { spawn } from 'child_process';
5
+ import { fileURLToPath } from 'url';
2
6
  import { Command } from 'commander';
3
7
  import { getConfig, getVersionInfo, OutputHandler, parseOutputMode } from '@thenewlabs/entangle-utils';
4
8
  import { startAgent } from './agent.js';
5
9
  import { createCapability, resolveServeTarget } from './capability.js';
6
10
  import { promptHidden } from './prompt.js';
7
11
  import { SharedWorkspace } from './shared-workspace.js';
12
+ import { LocalHostSession } from './host-session.js';
8
13
  import { attachHostTerminal } from './host-terminal.js';
9
- const program = new Command();
10
- program
11
- .name('entangle-serve')
12
- .description('Entangle secure agent for exposing CLI tools')
13
- .version(getVersionInfo())
14
- .option('--output-mode <mode>', 'Output mode: text or stream-json', 'text');
15
- program
16
- // Default command: `entangle serve [url]` runs the agent without needing an
17
- // explicit `start`. The positional URL is either a bare relay origin
18
- // (mint a fresh capability there) or a full capability URL (serve that exact
19
- // capability); flags still work and take precedence over the positional.
20
- .command('start', { isDefault: true })
21
- .description('Start the agent (mint a fresh capability or serve a pinned one) and register with the relay')
22
- .argument('[url]', 'Relay origin (https://relay) to mint a fresh capability on, or a full capability URL (https://relay/cap/<capId>#S=<secret>) to serve that exact capability')
23
- .option('--server <url>', 'Relay server URL (overrides the origin of the positional URL)')
24
- .option('--password [password]', 'Require a password to connect; pass the flag alone to be prompted, or set AGENT_PASSWORD')
25
- .option('--capability <url>', 'Serve a specific capability URL (https://relay/cap/<capId>#S=<secret>) instead of minting a fresh ephemeral one; its host is also used as the relay server')
26
- .option('--shared', 'Serve one shared terminal that everyone with the URL attaches to (default when run in a terminal)')
27
- .option('--headless', 'Run headless: each connection gets its own shell instead of a shared terminal')
28
- .action(async (url, options) => {
29
- try {
30
- // Propagate output mode to all loggers in this process
31
- process.env.OUTPUT_MODE = program.opts().outputMode;
32
- const outputMode = parseOutputMode(program.opts().outputMode);
33
- const output = new OutputHandler({ mode: outputMode });
34
- output.version('Entangle Agent', getVersionInfo());
35
- const config = getConfig();
36
- const { serverUrl, pinnedCapability } = await resolveServeTarget({
37
- positionalUrl: url,
38
- capabilityFlag: options.capability,
39
- serverFlag: options.server,
40
- envCapability: process.env.ENTANGLE_CAPABILITY,
41
- configRelayUrl: config.relayUrl,
42
- });
43
- // `--password` with no value (commander yields `true`) prompts interactively
44
- // so the secret never appears in argv; a string value or AGENT_PASSWORD is
45
- // used verbatim.
46
- let password;
47
- if (options.password === true) {
48
- password = await promptHidden('Agent password: ');
49
- }
50
- else if (typeof options.password === 'string') {
51
- password = options.password;
14
+ import { RemoteHostSession } from './remote-host-session.js';
15
+ import { cleanupStale, defaultSessionName, ensureRunDir, findSession, isAlive, listSessions, logPath, removeSession, socketPath, } from './session-registry.js';
16
+ // Hidden daemon entry: the interactive shared path spawns this same binary as
17
+ // `node <index.js> __daemon` (detached), which must run the headless daemon
18
+ // (see daemon.ts) rather than the CLI. Detected before the commander program is
19
+ // built/parsed so the daemon never touches argv parsing. Uses .then() rather
20
+ // than top-level await so the esbuild (cjs) standalone bundle still builds.
21
+ if (process.argv[2] === '__daemon') {
22
+ import('./daemon.js')
23
+ .then(({ runDaemon }) => runDaemon())
24
+ .catch((err) => {
25
+ console.error('Daemon failed to start:', err instanceof Error ? err.message : String(err));
26
+ process.exit(1);
27
+ });
28
+ }
29
+ else {
30
+ runCli();
31
+ }
32
+ /** How long to wait for a freshly spawned daemon's socket to become connectable. */
33
+ const SOCKET_POLL_INTERVAL_MS = 100;
34
+ const SOCKET_POLL_TIMEOUT_MS = 8000;
35
+ /** Resolve after `ms`. */
36
+ function delay(ms) {
37
+ return new Promise((resolve) => setTimeout(resolve, ms));
38
+ }
39
+ /** Connect to a unix socket, rejecting on connection error. */
40
+ function connectSocket(path) {
41
+ return new Promise((resolve, reject) => {
42
+ const socket = net.connect(path);
43
+ const onError = (err) => reject(err);
44
+ socket.once('error', onError);
45
+ socket.once('connect', () => { socket.removeListener('error', onError); resolve(socket); });
46
+ });
47
+ }
48
+ /**
49
+ * Poll a socket path until it accepts a connection, resolving the connected
50
+ * socket. Rejects with a pointer to `logFile` if it never comes up in time. The
51
+ * socket is left flowing-paused (no 'data' listener) so no daemon frames are
52
+ * lost before the RemoteHostSession attaches its reader.
53
+ */
54
+ async function pollSocket(path, logFile) {
55
+ const deadline = Date.now() + SOCKET_POLL_TIMEOUT_MS;
56
+ for (;;) {
57
+ try {
58
+ return await connectSocket(path);
59
+ }
60
+ catch {
61
+ if (Date.now() >= deadline) {
62
+ throw new Error(`Session daemon did not come up within ${SOCKET_POLL_TIMEOUT_MS / 1000}s (socket ${path}); see log: ${logFile}`);
63
+ }
64
+ await delay(SOCKET_POLL_INTERVAL_MS);
52
65
  }
53
- else {
54
- password = process.env.AGENT_PASSWORD;
55
- }
56
- // Shared-terminal mode: on by default when attached to a real terminal,
57
- // forced by --shared, disabled by --headless/--no-shared. Only meaningful
58
- // in text mode (stream-json is for programmatic invokers).
59
- const isTty = !!process.stdout.isTTY && !!process.stdin.isTTY;
60
- const shared = options.headless === true ? false
61
- : options.shared === true ? true
62
- : isTty && outputMode === 'text';
63
- let sharedWorkspace;
64
- // The host UI (when attached) sizes the active window to the box interior
65
- // and takes the session URL for its bottom bar once the relay assigns it.
66
- let hostHandle;
67
- if (shared) {
68
- const cols = process.stdout.columns || 80;
69
- const rows = process.stdout.rows || 24;
70
- sharedWorkspace = new SharedWorkspace(output, { cols, rows });
71
- if (isTty)
72
- hostHandle = attachHostTerminal(sharedWorkspace, output);
73
- }
74
- await startAgent({
75
- serverUrl,
76
- outputMode: program.opts().outputMode,
77
- ...(password ? { password } : {}),
78
- ...(pinnedCapability && { pinnedCapability }),
79
- ...(sharedWorkspace && {
80
- sharedWorkspace,
81
- onCapabilityReady: ({ link }) => {
82
- if (hostHandle)
83
- hostHandle.setUrl(link);
84
- else
85
- output.info(`⧉ entangle session shared — open to collaborate:\n ${link}\n`);
86
- },
87
- }),
88
- });
89
66
  }
90
- catch (error) {
91
- const outputMode = parseOutputMode(program.opts().outputMode);
92
- const output = new OutputHandler({ mode: outputMode });
93
- output.error('Failed to start agent', error instanceof Error ? error.message : String(error));
94
- process.exit(1);
67
+ }
68
+ /**
69
+ * Spawn the detached daemon for `sessionName` (this same binary re-invoked with
70
+ * the hidden `__daemon` arg) and poll its socket, resolving the connected socket
71
+ * the host UI attaches to. The daemon inherits its config via env vars.
72
+ */
73
+ async function spawnDaemon(opts) {
74
+ const { sessionName, serverUrl, cap, password } = opts;
75
+ ensureRunDir();
76
+ const sock = socketPath(sessionName);
77
+ const logFile = logPath(sessionName);
78
+ const logFd = fs.openSync(logFile, 'a');
79
+ const entry = fileURLToPath(import.meta.url);
80
+ const child = spawn(process.execPath, [entry, '__daemon'], {
81
+ detached: true,
82
+ stdio: ['ignore', logFd, logFd],
83
+ env: {
84
+ ...process.env,
85
+ ENTANGLE_DAEMON_SESSION: sessionName,
86
+ ENTANGLE_DAEMON_SOCKET: sock,
87
+ ENTANGLE_DAEMON_SERVER: serverUrl,
88
+ ENTANGLE_DAEMON_CAP: JSON.stringify(cap),
89
+ ...(password ? { ENTANGLE_DAEMON_PASSWORD: password } : {}),
90
+ },
91
+ });
92
+ child.unref();
93
+ fs.closeSync(logFd); // the child holds its own fd
94
+ return pollSocket(sock, logFile);
95
+ }
96
+ /**
97
+ * Attach this terminal to a daemon over its (already connected) socket: wrap it
98
+ * in a RemoteHostSession sized to the current terminal and hand it to the host
99
+ * UI. host-terminal keeps the process alive and calls process.exit on the
100
+ * session's exit/detach path.
101
+ */
102
+ function attachToSocket(socket, output) {
103
+ const session = new RemoteHostSession(socket, {
104
+ cols: process.stdout.columns || 80,
105
+ rows: process.stdout.rows || 24,
106
+ });
107
+ attachHostTerminal(session, output);
108
+ }
109
+ /** Reduce a session URL to a short, secret-free form (drops the `#S=` fragment). */
110
+ function shortUrl(url) {
111
+ if (!url)
112
+ return '';
113
+ try {
114
+ const u = new URL(url);
115
+ return `${u.origin}${u.pathname}`;
95
116
  }
96
- });
97
- program
98
- .command('create-cap')
99
- .description('Create a new capability')
100
- .option('--single-run', 'Allow only one run per session (default: multiple runs allowed)')
101
- .action(async (options) => {
117
+ catch {
118
+ return url;
119
+ }
120
+ }
121
+ /** SIGTERM a session, drop it from the registry, and unlink its socket. */
122
+ function killSession(info, output) {
102
123
  try {
103
- process.env.OUTPUT_MODE = program.opts().outputMode;
104
- const outputMode = parseOutputMode(program.opts().outputMode);
105
- const output = new OutputHandler({ mode: outputMode });
106
- const cap = await createCapability({
107
- singleRun: options.singleRun,
108
- outputMode: program.opts().outputMode,
109
- });
110
- output.info('\nCapability created:');
111
- output.info(`capId: ${cap.capId}`);
112
- output.info(`S: ${cap.S}`);
113
- const config = getConfig();
114
- const relayUrl = config.relayUrl || config.publicOrigin || 'https://suncoder.dev';
115
- const link = `${relayUrl}/cap/${cap.capId}#S=${cap.S}`;
116
- output.info(`\nWeb URL: ${link}`);
124
+ process.kill(info.pid, 'SIGTERM');
117
125
  }
118
- catch (error) {
119
- const outputMode = parseOutputMode(program.opts().outputMode);
120
- const output = new OutputHandler({ mode: outputMode });
121
- output.error('Failed to create capability', error instanceof Error ? error.message : String(error));
122
- process.exit(1);
126
+ catch { /* already gone */ }
127
+ removeSession(info.name);
128
+ try {
129
+ fs.unlinkSync(info.socket);
123
130
  }
124
- });
125
- program.addHelpText('after', `
131
+ catch { /* already gone */ }
132
+ output.info(`Killed session "${info.name}" (pid ${info.pid}).`);
133
+ }
134
+ function runCli() {
135
+ const program = new Command();
136
+ program
137
+ .name('entangle-serve')
138
+ .description('Entangle secure agent for exposing CLI tools')
139
+ .version(getVersionInfo())
140
+ .option('--output-mode <mode>', 'Output mode: text or stream-json', 'text');
141
+ program
142
+ // Default command: `entangle serve [url]` runs the agent without needing an
143
+ // explicit `start`. The positional URL is either a bare relay origin
144
+ // (mint a fresh capability there) or a full capability URL (serve that exact
145
+ // capability); flags still work and take precedence over the positional.
146
+ .command('start', { isDefault: true })
147
+ .description('Start the agent (mint a fresh capability or serve a pinned one) and register with the relay')
148
+ .argument('[url]', 'Relay origin (https://relay) to mint a fresh capability on, or a full capability URL (https://relay/cap/<capId>#S=<secret>) to serve that exact capability')
149
+ .option('--server <url>', 'Relay server URL (overrides the origin of the positional URL)')
150
+ .option('--password [password]', 'Require a password to connect; pass the flag alone to be prompted, or set AGENT_PASSWORD')
151
+ .option('--capability <url>', 'Serve a specific capability URL (https://relay/cap/<capId>#S=<secret>) instead of minting a fresh ephemeral one; its host is also used as the relay server')
152
+ .option('--shared', 'Serve one shared terminal that everyone with the URL attaches to (default when run in a terminal)')
153
+ .option('--headless', 'Run headless: each connection gets its own shell instead of a shared terminal')
154
+ .option('--session <name>', 'Name of the detachable session to start or reattach to (defaults to one derived from the capability)')
155
+ .action(async (url, options) => {
156
+ try {
157
+ // Propagate output mode to all loggers in this process
158
+ process.env.OUTPUT_MODE = program.opts().outputMode;
159
+ const outputMode = parseOutputMode(program.opts().outputMode);
160
+ const output = new OutputHandler({ mode: outputMode });
161
+ output.version('Entangle Agent', getVersionInfo());
162
+ const config = getConfig();
163
+ const { serverUrl, pinnedCapability } = await resolveServeTarget({
164
+ positionalUrl: url,
165
+ capabilityFlag: options.capability,
166
+ serverFlag: options.server,
167
+ envCapability: process.env.ENTANGLE_CAPABILITY,
168
+ configRelayUrl: config.relayUrl,
169
+ });
170
+ // `--password` with no value (commander yields `true`) prompts interactively
171
+ // so the secret never appears in argv; a string value or AGENT_PASSWORD is
172
+ // used verbatim.
173
+ let password;
174
+ if (options.password === true) {
175
+ password = await promptHidden('Agent password: ');
176
+ }
177
+ else if (typeof options.password === 'string') {
178
+ password = options.password;
179
+ }
180
+ else {
181
+ password = process.env.AGENT_PASSWORD;
182
+ }
183
+ // Shared-terminal mode: on by default when attached to a real terminal,
184
+ // forced by --shared, disabled by --headless/--no-shared. Only meaningful
185
+ // in text mode (stream-json is for programmatic invokers).
186
+ const isTty = !!process.stdout.isTTY && !!process.stdin.isTTY;
187
+ const shared = options.headless === true ? false
188
+ : options.shared === true ? true
189
+ : isTty && outputMode === 'text';
190
+ // The interactive shared path (a real terminal serving one shared session
191
+ // in text mode) is daemonized tmux-style: a detached daemon owns the
192
+ // session + relay connection and this process is just a client that
193
+ // attaches to it, so closing the terminal (or Ctrl-B d) leaves the session
194
+ // running. Every other path keeps today's in-foreground behavior below.
195
+ if (shared && isTty && outputMode === 'text') {
196
+ // The daemon must pin a concrete capability, so mint the ephemeral one
197
+ // here (instead of letting startAgent mint it) when none was pinned.
198
+ const cap = pinnedCapability ?? await createCapability({ singleRun: false });
199
+ const sessionName = options.session || defaultSessionName(cap.capId);
200
+ cleanupStale();
201
+ const existing = findSession(sessionName);
202
+ let socket;
203
+ if (existing && isAlive(existing)) {
204
+ // Reattach to the live daemon. It may be serving a different
205
+ // capability than the one we just resolved (e.g. a reused --session
206
+ // name); attaching to the running one is the least surprising choice.
207
+ if (existing.capId !== cap.capId) {
208
+ output.info(`A session named "${sessionName}" is already running with a different capability; attaching to it.`);
209
+ }
210
+ socket = await connectSocket(existing.socket);
211
+ }
212
+ else {
213
+ socket = await spawnDaemon({ sessionName, serverUrl, cap, ...(password ? { password } : {}) });
214
+ }
215
+ attachToSocket(socket, output);
216
+ return; // host-terminal drives the process lifetime from here
217
+ }
218
+ let sharedWorkspace;
219
+ // The host UI (when attached) renders against a HostSession — an
220
+ // abstraction over the workspace + log/URL sources — so the same UI can
221
+ // later run against a socket-backed session. It sizes the active window to
222
+ // the box interior and takes the session URL for its bottom bar once the
223
+ // relay assigns it.
224
+ let hostSession;
225
+ if (shared) {
226
+ const cols = process.stdout.columns || 80;
227
+ const rows = process.stdout.rows || 24;
228
+ sharedWorkspace = new SharedWorkspace(output, { cols, rows });
229
+ if (isTty) {
230
+ hostSession = new LocalHostSession(sharedWorkspace, output);
231
+ attachHostTerminal(hostSession, output);
232
+ }
233
+ }
234
+ await startAgent({
235
+ serverUrl,
236
+ outputMode: program.opts().outputMode,
237
+ ...(password ? { password } : {}),
238
+ ...(pinnedCapability && { pinnedCapability }),
239
+ ...(sharedWorkspace && {
240
+ sharedWorkspace,
241
+ onCapabilityReady: ({ link }) => {
242
+ if (hostSession)
243
+ hostSession.setUrl(link);
244
+ else
245
+ output.info(`⧉ entangle session shared — open to collaborate:\n ${link}\n`);
246
+ },
247
+ }),
248
+ });
249
+ }
250
+ catch (error) {
251
+ const outputMode = parseOutputMode(program.opts().outputMode);
252
+ const output = new OutputHandler({ mode: outputMode });
253
+ output.error('Failed to start agent', error instanceof Error ? error.message : String(error));
254
+ process.exit(1);
255
+ }
256
+ });
257
+ program
258
+ .command('create-cap')
259
+ .description('Create a new capability')
260
+ .option('--single-run', 'Allow only one run per session (default: multiple runs allowed)')
261
+ .action(async (options) => {
262
+ try {
263
+ process.env.OUTPUT_MODE = program.opts().outputMode;
264
+ const outputMode = parseOutputMode(program.opts().outputMode);
265
+ const output = new OutputHandler({ mode: outputMode });
266
+ const cap = await createCapability({
267
+ singleRun: options.singleRun,
268
+ outputMode: program.opts().outputMode,
269
+ });
270
+ output.info('\nCapability created:');
271
+ output.info(`capId: ${cap.capId}`);
272
+ output.info(`S: ${cap.S}`);
273
+ const config = getConfig();
274
+ const relayUrl = config.relayUrl || config.publicOrigin || 'https://suncoder.dev';
275
+ const link = `${relayUrl}/cap/${cap.capId}#S=${cap.S}`;
276
+ output.info(`\nWeb URL: ${link}`);
277
+ }
278
+ catch (error) {
279
+ const outputMode = parseOutputMode(program.opts().outputMode);
280
+ const output = new OutputHandler({ mode: outputMode });
281
+ output.error('Failed to create capability', error instanceof Error ? error.message : String(error));
282
+ process.exit(1);
283
+ }
284
+ });
285
+ program
286
+ .command('ls')
287
+ .alias('list')
288
+ .description('List running serve sessions')
289
+ .action(() => {
290
+ const output = new OutputHandler({ mode: parseOutputMode(program.opts().outputMode) });
291
+ cleanupStale();
292
+ const sessions = listSessions();
293
+ if (sessions.length === 0) {
294
+ output.info('No sessions.');
295
+ return;
296
+ }
297
+ for (const s of sessions) {
298
+ const alive = isAlive(s) ? `alive(${s.pid})` : 'dead';
299
+ const created = new Date(s.createdAt).toISOString();
300
+ const where = shortUrl(s.url) || s.capId;
301
+ output.text(`${s.name}\t${alive}\t${created}\t${where}`);
302
+ }
303
+ });
304
+ program
305
+ .command('kill [name]')
306
+ .description('Kill a running session by name (SIGTERM); with no name, the only session')
307
+ .option('--all', 'Kill every running session')
308
+ .action((name, options) => {
309
+ const output = new OutputHandler({ mode: parseOutputMode(program.opts().outputMode) });
310
+ cleanupStale();
311
+ const sessions = listSessions();
312
+ if (options.all) {
313
+ if (sessions.length === 0) {
314
+ output.info('No sessions.');
315
+ return;
316
+ }
317
+ for (const s of sessions)
318
+ killSession(s, output);
319
+ return;
320
+ }
321
+ let target;
322
+ if (name) {
323
+ target = findSession(name);
324
+ if (!target) {
325
+ output.error(`No session named "${name}".`);
326
+ process.exit(1);
327
+ }
328
+ }
329
+ else if (sessions.length === 0) {
330
+ output.info('No sessions.');
331
+ return;
332
+ }
333
+ else if (sessions.length === 1) {
334
+ target = sessions[0];
335
+ }
336
+ else {
337
+ output.error('Multiple sessions; specify one to kill (or --all):');
338
+ for (const s of sessions)
339
+ output.text(` ${s.name}`);
340
+ process.exit(1);
341
+ }
342
+ if (target)
343
+ killSession(target, output);
344
+ });
345
+ program
346
+ .command('attach [name]')
347
+ .description('Attach to a running session by name (or the only one) without a URL')
348
+ .action(async (name) => {
349
+ const output = new OutputHandler({ mode: parseOutputMode(program.opts().outputMode) });
350
+ cleanupStale();
351
+ const sessions = listSessions();
352
+ let target;
353
+ if (name) {
354
+ target = findSession(name);
355
+ }
356
+ else if (sessions.length === 0) {
357
+ output.error('No sessions to attach to.');
358
+ process.exit(1);
359
+ }
360
+ else if (sessions.length === 1) {
361
+ target = sessions[0];
362
+ }
363
+ else {
364
+ output.error('Multiple sessions; specify one to attach to:');
365
+ for (const s of sessions)
366
+ output.text(` ${s.name}`);
367
+ process.exit(1);
368
+ }
369
+ if (!target || !isAlive(target)) {
370
+ output.error(`No live session named "${name ?? ''}".`);
371
+ process.exit(1);
372
+ }
373
+ try {
374
+ const socket = await connectSocket(target.socket);
375
+ attachToSocket(socket, output);
376
+ }
377
+ catch (error) {
378
+ output.error('Failed to attach', error instanceof Error ? error.message : String(error));
379
+ process.exit(1);
380
+ }
381
+ });
382
+ program.addHelpText('after', `
126
383
  Examples:
127
384
  # Mint a fresh capability and serve it on a relay
128
385
  entangle serve https://entangle.thenewlabs.com
@@ -133,7 +390,13 @@ Examples:
133
390
  # Mint on the configured/default relay
134
391
  entangle serve
135
392
 
393
+ # List / attach / kill detachable sessions
394
+ entangle serve ls
395
+ entangle serve attach <name>
396
+ entangle serve kill <name>
397
+
136
398
  # Just create a capability without starting the agent
137
399
  entangle serve create-cap`);
138
- program.parse();
400
+ program.parse();
401
+ }
139
402
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/ipc.d.ts ADDED
@@ -0,0 +1,103 @@
1
+ import type { Duplex } from 'stream';
2
+ import type { WindowStateBody } from '@thenewlabs/entangle-protocol';
3
+ /** Bytes of the length prefix that precedes every JSON payload. */
4
+ export declare const HEADER_BYTES = 4;
5
+ /**
6
+ * Maximum accepted payload size. A frame declaring a larger payload is rejected
7
+ * (the decoder errors) rather than buffering an unbounded amount of memory for
8
+ * a payload that may never fully arrive. 8 MB comfortably fits a full-screen
9
+ * replay while capping a hostile/framed-wrong peer.
10
+ */
11
+ export declare const MAX_FRAME_BYTES: number;
12
+ /** A window operation requested by the client (tmux-style window control). */
13
+ export type WindowOp = 'new' | 'next' | 'prev' | 'select' | 'close';
14
+ /** Messages sent from an attached terminal client to the daemon. */
15
+ export type ClientToDaemon = {
16
+ t: 'hello';
17
+ cols: number;
18
+ rows: number;
19
+ }
20
+ /** Keystrokes / raw terminal input, base64-encoded. */
21
+ | {
22
+ t: 'input';
23
+ data: string;
24
+ } | {
25
+ t: 'resize';
26
+ cols: number;
27
+ rows: number;
28
+ } | {
29
+ t: 'win';
30
+ op: WindowOp;
31
+ index?: number;
32
+ } | {
33
+ t: 'detach';
34
+ };
35
+ /** Messages sent from the daemon to an attached terminal client. */
36
+ export type DaemonToClient =
37
+ /** Live terminal output, base64-encoded. */
38
+ {
39
+ t: 'data';
40
+ chunk: string;
41
+ }
42
+ /** Scrollback replay sent right after attach, base64-encoded. */
43
+ | {
44
+ t: 'replay';
45
+ chunk: string;
46
+ } | {
47
+ t: 'window-state';
48
+ state: WindowStateBody;
49
+ }
50
+ /** Number of currently attached viewers. */
51
+ | {
52
+ t: 'viewers';
53
+ n: number;
54
+ } | {
55
+ t: 'log';
56
+ line: string;
57
+ } | {
58
+ t: 'url';
59
+ url: string;
60
+ } | {
61
+ t: 'exit';
62
+ code: number | null;
63
+ };
64
+ /** Any framed IPC message, in either direction. */
65
+ export type IpcMessage = ClientToDaemon | DaemonToClient;
66
+ /** Encode a binary terminal chunk as a base64 string for the JSON wire. */
67
+ export declare function encodeChunk(data: Uint8Array): string;
68
+ /** Decode a base64 chunk string back into a Buffer of terminal bytes. */
69
+ export declare function decodeChunk(chunk: string): Buffer;
70
+ /**
71
+ * Serialize a message to a length-prefixed frame: a 4-byte big-endian payload
72
+ * length followed by the UTF-8 JSON payload.
73
+ *
74
+ * @throws if the resulting payload exceeds {@link MAX_FRAME_BYTES}.
75
+ */
76
+ export declare function encodeMessage(msg: IpcMessage): Buffer;
77
+ /** Encode and write a single message to a socket/stream. */
78
+ export declare function writeMessage(socket: Duplex, msg: IpcMessage): boolean;
79
+ /**
80
+ * Incrementally decodes length-prefixed frames from a byte stream, tolerating
81
+ * partial reads (a frame split across chunks) and coalesced reads (many frames
82
+ * in one chunk). A frame whose declared length exceeds {@link MAX_FRAME_BYTES}
83
+ * makes {@link push} throw rather than buffering unbounded memory — callers
84
+ * should treat that as a fatal protocol error and close the socket.
85
+ */
86
+ export declare class FrameDecoder {
87
+ private buffer;
88
+ /**
89
+ * Feed received bytes; returns every message that became fully available.
90
+ * @throws if a frame declares a payload larger than {@link MAX_FRAME_BYTES}
91
+ * or if a completed payload is not valid JSON.
92
+ */
93
+ push(chunk: Uint8Array): IpcMessage[];
94
+ }
95
+ /**
96
+ * Attach a {@link FrameDecoder} to a socket and invoke `onMessage` for each
97
+ * decoded message. A decode error (oversize frame or malformed JSON) is routed
98
+ * to `onError` if provided, otherwise emitted on the socket as an `'error'`.
99
+ *
100
+ * @returns a detach function that removes the installed `'data'` listener.
101
+ */
102
+ export declare function createMessageReader(socket: Duplex, onMessage: (msg: IpcMessage) => void, onError?: (err: Error) => void): () => void;
103
+ //# sourceMappingURL=ipc.d.ts.map