@thenewlabs/entangle-serve 2.12.2 → 2.14.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/daemon.js CHANGED
@@ -1,22 +1,19 @@
1
- import * as net from 'net';
2
- import * as fs from 'fs';
3
1
  import { OutputHandler, parseOutputMode } from '@thenewlabs/entangle-utils';
4
2
  import { startAgent } from './agent.js';
5
3
  import { SharedWorkspace } from './shared-workspace.js';
6
4
  import { LocalHostSession } from './host-session.js';
7
- import { addSession, logPath, removeSession } from './session-registry.js';
8
- import { createMessageReader, decodeChunk, encodeChunk, writeMessage, } from './ipc.js';
5
+ import { createDaemonServer } from './daemon-server.js';
9
6
  /**
10
7
  * The DAEMON half of the tmux-style detach/reattach split for `entangle serve`.
11
8
  *
12
9
  * Runs headless (no TTY): it owns a {@link SharedWorkspace} + {@link LocalHostSession}
13
10
  * and connects to the relay via {@link startAgent}, serving the pinned capability
14
- * handed to it. It listens on a local unix socket where zero or more terminal
15
- * CLIENTS ({@link RemoteHostSession}) attach; it fans the session's events out to
16
- * every attached client and applies each client's input/resize/window ops to the
17
- * one shared session. Detaching a client leaves the daemon (and the session)
18
- * running; the daemon exits only when the workspace's last shell exits or it is
19
- * signalled.
11
+ * handed to it. The socket server that terminal CLIENTS ({@link RemoteHostSession})
12
+ * attach to fan-out, per-client viewports, registry bookkeeping, shutdown lives
13
+ * in daemon-server.ts (shared with embedders like Locus); this file is just the
14
+ * entangle-specific composition around it. Detaching a client leaves the daemon
15
+ * (and the session) running; the daemon exits only when the workspace's last
16
+ * shell exits or it is signalled.
20
17
  *
21
18
  * Config comes entirely from the environment (set by the index wiring that spawns
22
19
  * the daemon):
@@ -40,232 +37,20 @@ export async function runDaemon() {
40
37
  // Installs the log sink (agent logs → ring buffer, fanned out to clients as
41
38
  // `log` frames) and owns the session URL via setUrl().
42
39
  const localSession = new LocalHostSession(workspace, output);
43
- const createdAt = Date.now();
44
- const register = (url) => {
45
- const info = {
46
- name,
47
- socket: socketPathValue,
48
- logFile: logPath(name),
49
- pid: process.pid,
50
- capId: cap.capId,
51
- url,
52
- createdAt,
53
- };
54
- addSession(info);
55
- };
56
- // --- client set + fan-out -------------------------------------------------
57
- const clients = new Set();
58
- const broadcast = (msg) => {
59
- for (const socket of clients) {
60
- try {
61
- writeMessage(socket, msg);
62
- }
63
- catch { /* dropped client; its close handler cleans up */ }
64
- }
65
- };
66
- // --- lifecycle / cleanup (idempotent) ------------------------------------
67
- let server;
68
- let shuttingDown = false;
69
- const shutdown = (code) => {
70
- if (shuttingDown)
71
- return;
72
- shuttingDown = true;
73
- broadcast({ t: 'exit', code });
74
- try {
75
- localSession.dispose();
76
- }
77
- catch { /* best-effort */ }
78
- try {
79
- workspace.kill();
80
- }
81
- catch { /* best-effort */ }
82
- for (const socket of clients) {
83
- try {
84
- socket.end();
85
- }
86
- catch { /* already gone */ }
87
- }
88
- clients.clear();
89
- try {
90
- server?.close();
91
- }
92
- catch { /* not listening */ }
93
- removeSession(name);
94
- try {
95
- fs.unlinkSync(socketPathValue);
96
- }
97
- catch { /* already gone */ }
98
- process.exit(0);
99
- };
100
- process.on('SIGTERM', () => shutdown(0));
101
- process.on('SIGINT', () => shutdown(0));
102
- // Subscribe ONCE to the SESSION-GLOBAL streams and fan each out to every
103
- // client. Terminal output and window-state are NOT global anymore: each client
104
- // gets its own workspace viewport (see onConnection) so it can sit on its own
105
- // active window, so we deliberately do NOT broadcast onHostData/onWindowState.
106
- localSession.onViewersChange((n) => broadcast({ t: 'viewers', n }));
107
- localSession.onLog((line) => broadcast({ t: 'log', line }));
108
- localSession.onUrl((url) => broadcast({ t: 'url', url }));
109
- // Workspace ended (last window's shell exited) → tear the daemon down.
110
- localSession.onExit((code) => shutdown(code));
111
- // --- inbound client handling ---------------------------------------------
112
- // A client's messages drive ITS OWN workspace viewport (keyed by `vpId`), so
113
- // input/window ops only move that client's active window. Sizing stays global
114
- // (the host/workspace size is authoritative), so hello/resize resize the whole
115
- // workspace as before.
116
- const handleClientMessage = (msg, socket, vpId) => {
117
- switch (msg.t) {
118
- case 'hello':
119
- workspace.resize(msg.cols, msg.rows);
120
- break;
121
- case 'input':
122
- workspace.writeFromViewport(vpId, decodeChunk(msg.data));
123
- break;
124
- case 'resize':
125
- workspace.resize(msg.cols, msg.rows);
126
- break;
127
- case 'win':
128
- switch (msg.op) {
129
- case 'new':
130
- workspace.newWindowForViewport(vpId);
131
- break;
132
- case 'next':
133
- workspace.nextWindowForViewport(vpId);
134
- break;
135
- case 'prev':
136
- workspace.prevWindowForViewport(vpId);
137
- break;
138
- case 'select':
139
- if (msg.index !== undefined)
140
- workspace.selectWindowForViewport(vpId, msg.index);
141
- break;
142
- case 'close':
143
- if (msg.index !== undefined)
144
- workspace.closeWindowFromViewport(vpId, msg.index);
145
- break;
146
- }
147
- break;
148
- case 'refresh':
149
- // Serialize the viewport's active window NOW and send it back as a
150
- // `replay` frame (getReplay()'s source client-side). Because this is a
151
- // full IPC round-trip after the client's own bytes were fed to the
152
- // emulator, the serialize reflects the window's live screen — this is
153
- // what lets a host repaint (e.g. after a full-screen app quits) paint
154
- // the CURRENT primary instead of the stale attach-time cache.
155
- try {
156
- const frame = workspace.snapshotForViewport(vpId, msg.scrollback !== undefined ? { scrollback: msg.scrollback } : undefined);
157
- writeMessage(socket, { t: 'replay', chunk: encodeChunk(frame) });
158
- }
159
- catch { /* dropped client; its close handler cleans up */ }
160
- break;
161
- case 'scrollback':
162
- // Serialize the viewport's active window buffer to plain-text lines NOW
163
- // and send them back for the client's copy-mode pager.
164
- try {
165
- writeMessage(socket, { t: 'scrollback', lines: workspace.scrollbackLinesForViewport(vpId) });
166
- }
167
- catch { /* dropped client; its close handler cleans up */ }
168
- break;
169
- case 'detach':
170
- // Drop just this client's viewport; the daemon (and session) keep running.
171
- clients.delete(socket);
172
- workspace.detachViewport(vpId);
173
- try {
174
- socket.end();
175
- }
176
- catch { /* already ending */ }
177
- break;
178
- }
179
- };
180
- let nextVpId = 0;
181
- const onConnection = (socket) => {
182
- // Each connection is its own workspace viewport with an independent active
183
- // window; reuse the connection counter as the viewport key.
184
- const vpId = `client-${nextVpId++}`;
185
- clients.add(socket);
186
- const remove = () => {
187
- clients.delete(socket);
188
- workspace.detachViewport(vpId);
189
- };
190
- socket.on('close', remove);
191
- socket.on('error', remove);
192
- // Attach this client's viewport: the workspace multiplexes ITS active
193
- // window's output onto this socket and pushes ITS own window-state.
194
- const { replay } = workspace.attachViewport({
195
- sid: vpId,
196
- onData: (chunk) => { try {
197
- writeMessage(socket, { t: 'data', chunk: encodeChunk(chunk) });
198
- }
199
- catch { /* dropped */ } },
200
- onWindowState: (state) => { try {
201
- writeMessage(socket, { t: 'window-state', state });
202
- }
203
- catch { /* dropped */ } },
204
- onExit: (code) => { try {
205
- writeMessage(socket, { t: 'exit', code });
206
- }
207
- catch { /* dropped */ } },
208
- });
209
- createMessageReader(socket, (msg) => {
210
- // Only ClientToDaemon frames are expected inbound; a single bad message
211
- // must not take down the daemon.
212
- try {
213
- handleClientMessage(msg, socket, vpId);
214
- }
215
- catch (err) {
216
- output.warn('Client message failed', err instanceof Error ? err.message : String(err));
217
- }
218
- }, () => { remove(); try {
219
- socket.destroy();
220
- }
221
- catch { /* already gone */ } });
222
- // Push this viewport's current state immediately so the client's UI
223
- // populates fast. Sent synchronously (no await) right after attach, so live
224
- // onData frames can't slip in before the replay.
225
- try {
226
- const url = localSession.getUrl();
227
- if (url)
228
- writeMessage(socket, { t: 'url', url });
229
- writeMessage(socket, { t: 'window-state', state: workspace.windowStateForViewport(vpId) });
230
- writeMessage(socket, { t: 'viewers', n: workspace.viewerCount() });
231
- for (const line of localSession.getLogBuffer())
232
- writeMessage(socket, { t: 'log', line });
233
- writeMessage(socket, { t: 'replay', chunk: encodeChunk(replay) });
234
- }
235
- catch {
236
- remove();
237
- }
238
- };
239
- // --- listen ---------------------------------------------------------------
240
- try {
241
- fs.unlinkSync(socketPathValue);
242
- }
243
- catch { /* no stale socket to remove */ }
244
- server = net.createServer(onConnection);
245
- server.on('error', (err) => output.error('Daemon socket server error', err.message));
246
- await new Promise((resolve, reject) => {
247
- const onError = (err) => reject(err);
248
- server.once('error', onError);
249
- server.listen(socketPathValue, () => {
250
- server.off('error', onError);
251
- resolve();
252
- });
40
+ const server = await createDaemonServer({
41
+ name,
42
+ socketPath: socketPathValue,
43
+ workspace,
44
+ session: localSession,
45
+ output,
46
+ registry: { capId: cap.capId, kind: 'entangle' },
253
47
  });
254
- try {
255
- fs.chmodSync(socketPathValue, 0o600);
256
- }
257
- catch { /* best-effort tightening */ }
258
- // Register now (url filled in once the relay assigns it).
259
- register('');
260
48
  // Connect to the relay and serve the pinned capability. onCapabilityReady sets
261
49
  // the session URL (fanned out as a `url` frame) and records it in the registry.
262
50
  await startAgent({
263
51
  serverUrl,
264
52
  sharedWorkspace: workspace,
265
- onCapabilityReady: ({ link }) => {
266
- localSession.setUrl(link);
267
- register(link);
268
- },
53
+ onCapabilityReady: ({ link }) => server.setUrl(link),
269
54
  ...(password ? { password } : {}),
270
55
  pinnedCapability: cap,
271
56
  });
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
@@ -82,8 +82,21 @@ export interface HostSession {
82
82
  onExit(cb: (code: number | null, signal: string | null) => void): void;
83
83
  /** Tear down any owned resources (e.g. release the captured-log sink). */
84
84
  dispose(): void;
85
+ /**
86
+ * Release just the captured-log sink (if this session owns one) so agent logs
87
+ * print to stdout — a lighter cousin of {@link dispose} for UIs with no debug
88
+ * tab to feed. Unlike dispose it must NOT tear the session down (a daemon-
89
+ * backed session's dispose ends its socket).
90
+ */
91
+ releaseLogSink?(): void;
85
92
  /** Detach without ending the session (unused for now). */
86
93
  detach?(): void;
94
+ /**
95
+ * End the WHOLE session — daemon shutdown, every client exits. Present only
96
+ * on daemon-backed sessions (the host UI's Ctrl-B q binding needs it; an
97
+ * in-process session ends by exiting its shells or Ctrl-C instead).
98
+ */
99
+ kill?(): void;
87
100
  }
88
101
  /**
89
102
  * The in-process {@link HostSession}: a thin adapter over a {@link SharedWorkspace}
@@ -135,6 +148,7 @@ export declare class LocalHostSession implements HostSession {
135
148
  /** Store the session URL (once the relay assigns it) and notify subscribers. */
136
149
  setUrl(link: string): void;
137
150
  onExit(cb: (code: number | null, signal: string | null) => void): void;
151
+ releaseLogSink(): void;
138
152
  dispose(): void;
139
153
  }
140
154
  //# sourceMappingURL=host-session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host-session.d.ts","sourceRoot":"","sources":["../src/host-session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"host-session.d.ts","sourceRoot":"","sources":["../src/host-session.ts"],"names":[],"mappings":"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"}
@@ -88,6 +88,7 @@ export class LocalHostSession {
88
88
  }
89
89
  // --- lifecycle -----------------------------------------------------------
90
90
  onExit(cb) { this.workspace.onExit(cb); }
91
- dispose() { OutputHandler.setLogSink(null); }
91
+ releaseLogSink() { OutputHandler.setLogSink(null); }
92
+ dispose() { this.releaseLogSink(); }
92
93
  }
93
94
  //# sourceMappingURL=host-session.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"host-session.js","sourceRoot":"","sources":["../src/host-session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"host-session.js","sourceRoot":"","sources":["../src/host-session.ts"],"names":[],"mappings":"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"}
@@ -251,7 +251,7 @@ function attachBarTerminal(session, output, initialCols, initialRows) {
251
251
  `Share this live session:`,
252
252
  ` ${BAR_FG}${link ?? 'connecting…'}${RESET}`,
253
253
  ``,
254
- `Ctrl-B [=scroll d=detach l=logs c=new n/p=win 1-9=select x=close`,
254
+ `Ctrl-B [=scroll d=detach l=logs c=new n/p=win 1-9=select x=close q=quit`,
255
255
  ];
256
256
  // Render the welcome/log view: a PINNED HEADER (brand, intro, share URL, key
257
257
  // hint) at the top so the URL is always findable, a "Recent activity:"
@@ -628,9 +628,19 @@ function attachBarTerminal(session, output, initialCols, initialRows) {
628
628
  // Detach fires the session's onExit path, which runs restore()+exit below;
629
629
  // don't force an exit here that would race it.
630
630
  if (ch === 'd') {
631
+ detaching = true;
631
632
  session.detach?.();
632
633
  return;
633
634
  }
635
+ // Quit = END the whole session (daemon shutdown), guarded by a y/N confirm
636
+ // on the bar row. Only offered for sessions that support it (daemon-backed):
637
+ // a persistent workspace respawns its shell on close, so without this there
638
+ // is no way out of the session from inside the terminal.
639
+ if (ch === 'q' && session.kill) {
640
+ pendingKill = true;
641
+ write(`\x1b7\x1b[${rows};1H\x1b[2K${BAR_BG}${BAR_FG} End this session for everyone? y = yes, any other key = cancel ${RESET}\x1b8`);
642
+ return;
643
+ }
634
644
  if (ch === 'l') {
635
645
  enterDebug();
636
646
  return;
@@ -699,6 +709,8 @@ function attachBarTerminal(session, output, initialCols, initialRows) {
699
709
  // other bytes forward to the active window, flushed around each prefix or mouse
700
710
  // boundary so ordering across a window switch is preserved.
701
711
  let pendingPrefix = false;
712
+ let pendingKill = false; // armed by Ctrl-B q; the next byte confirms or cancels
713
+ let detaching = false; // set by Ctrl-B d so the exit path can print a reattach hint
702
714
  const onInput = (d) => {
703
715
  // In the pager, keystrokes drive scrolling and are never sent to the shell.
704
716
  if (viewMode === 'scroll') {
@@ -708,6 +720,20 @@ function attachBarTerminal(session, output, initialCols, initialRows) {
708
720
  let start = 0;
709
721
  for (let i = 0; i < d.length;) {
710
722
  const byte = d[i];
723
+ // Kill-confirm consumes exactly one byte and never forwards it: y ends the
724
+ // session (the daemon's exit broadcast runs the normal exit path below),
725
+ // anything else cancels and repaints the bar over the prompt.
726
+ if (pendingKill) {
727
+ pendingKill = false;
728
+ if (byte === 0x79 /* y */ || byte === 0x59 /* Y */) {
729
+ session.kill();
730
+ return;
731
+ }
732
+ drawBar();
733
+ i++;
734
+ start = i;
735
+ continue;
736
+ }
711
737
  if (pendingPrefix) {
712
738
  pendingPrefix = false;
713
739
  if (byte === PREFIX)
@@ -810,7 +836,17 @@ function attachBarTerminal(session, output, initialCols, initialRows) {
810
836
  session.onExit((code) => {
811
837
  restore();
812
838
  write('\n');
813
- output.info('Shared session ended.');
839
+ if (detaching) {
840
+ // Print the FULL session URL on the primary screen: the status bar
841
+ // truncates it to the terminal width, so this is the copyable source.
842
+ output.info('Detached — the session keeps running.');
843
+ const url = session.getUrl();
844
+ if (url)
845
+ output.info(`View URL: ${url}`);
846
+ }
847
+ else {
848
+ output.info('Shared session ended.');
849
+ }
814
850
  process.exit(code ?? 0);
815
851
  });
816
852
  process.on('exit', restore);
@@ -853,9 +889,11 @@ function attachRawTerminal(session, output) {
853
889
  const stdin = process.stdin;
854
890
  const stdout = process.stdout;
855
891
  // No status bar and no debug tab here, so there's nowhere to surface captured
856
- // logs — release the session's log sink so agent logs print to stdout as they
857
- // did before this UI existed (the bar path keeps the sink for its debug tab).
858
- session.dispose();
892
+ // logs — release the session's log sink (if it owns one) so agent logs print
893
+ // to stdout as they did before this UI existed (the bar path keeps the sink
894
+ // for its debug tab). NOT dispose(): a daemon-backed session's dispose ends
895
+ // its socket, which would kill the attach right here.
896
+ session.releaseLogSink?.();
859
897
  const initial = session.getReplay();
860
898
  if (initial.length > 0) {
861
899
  try {
@@ -863,6 +901,13 @@ function attachRawTerminal(session, output) {
863
901
  }
864
902
  catch { }
865
903
  }
904
+ // A daemon-backed session delivers its post-attach replay (and any refreshed
905
+ // frames) asynchronously via onFrame — paint those too, so a raw reattach
906
+ // shows the window's current screen instead of starting blank.
907
+ session.onFrame((frame) => { try {
908
+ stdout.write(Buffer.from(frame));
909
+ }
910
+ catch { } });
866
911
  session.onHostData((chunk) => { try {
867
912
  stdout.write(chunk);
868
913
  }
@@ -871,7 +916,42 @@ function attachRawTerminal(session, output) {
871
916
  if (stdin.isTTY)
872
917
  stdin.setRawMode(true);
873
918
  stdin.resume();
874
- const onInput = (d) => session.write(new Uint8Array(d));
919
+ // A daemon-backed session gets a detach key even without the bar: Ctrl-B d
920
+ // detaches (Ctrl-B Ctrl-B sends a literal Ctrl-B; any other command byte is
921
+ // swallowed, like the bar's prefix), otherwise a raw attach could only be
922
+ // left by killing the terminal. Interactive TTYs only — piped stdin stays
923
+ // pure byte-for-byte passthrough.
924
+ const canDetach = !!stdin.isTTY && typeof session.detach === 'function';
925
+ let pendingPrefix = false;
926
+ const onInput = (d) => {
927
+ if (!canDetach) {
928
+ session.write(new Uint8Array(d));
929
+ return;
930
+ }
931
+ let start = 0;
932
+ for (let i = 0; i < d.length; i++) {
933
+ const byte = d[i];
934
+ if (pendingPrefix) {
935
+ pendingPrefix = false;
936
+ if (byte === PREFIX)
937
+ session.write(new Uint8Array([PREFIX]));
938
+ else if (byte === 0x64 /* d */) {
939
+ session.detach();
940
+ return;
941
+ }
942
+ start = i + 1;
943
+ continue;
944
+ }
945
+ if (byte === PREFIX) {
946
+ if (i > start)
947
+ session.write(new Uint8Array(d.subarray(start, i)));
948
+ pendingPrefix = true;
949
+ start = i + 1;
950
+ }
951
+ }
952
+ if (d.length > start)
953
+ session.write(new Uint8Array(d.subarray(start)));
954
+ };
875
955
  stdin.on('data', onInput);
876
956
  const onResize = () => session.resize(stdout.columns || 80, stdout.rows || 24);
877
957
  stdout.on('resize', onResize);