ftown 0.24.0 → 0.25.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 (40) hide show
  1. package/dist/centrifugo-client.js +15 -2
  2. package/dist/centrifugo-client.js.map +1 -1
  3. package/dist/direct-transport/loopback-server.d.ts +10 -3
  4. package/dist/direct-transport/loopback-server.js +20 -4
  5. package/dist/direct-transport/loopback-server.js.map +1 -1
  6. package/dist/direct-transport/peer-manager.d.ts +8 -3
  7. package/dist/direct-transport/peer-manager.js +20 -5
  8. package/dist/direct-transport/peer-manager.js.map +1 -1
  9. package/dist/file-stamp.d.ts +33 -0
  10. package/dist/file-stamp.js +35 -0
  11. package/dist/file-stamp.js.map +1 -0
  12. package/dist/index.js +16 -32
  13. package/dist/index.js.map +1 -1
  14. package/dist/mail-store.d.ts +15 -1
  15. package/dist/mail-store.js +78 -16
  16. package/dist/mail-store.js.map +1 -1
  17. package/dist/outbound-pipeline-types.d.ts +5 -2
  18. package/dist/outbound-pipeline-types.js.map +1 -1
  19. package/dist/security/bridge/policy.d.ts +3 -0
  20. package/dist/security/bridge/policy.js +17 -0
  21. package/dist/security/bridge/policy.js.map +1 -1
  22. package/dist/security/bridge/security.d.ts +10 -0
  23. package/dist/security/bridge/security.js +18 -11
  24. package/dist/security/bridge/security.js.map +1 -1
  25. package/dist/security/crypto.d.ts +2 -0
  26. package/dist/security/crypto.js +43 -4
  27. package/dist/security/crypto.js.map +1 -1
  28. package/dist/session-store.d.ts +22 -0
  29. package/dist/session-store.js +164 -15
  30. package/dist/session-store.js.map +1 -1
  31. package/dist/terminal-manager.d.ts +8 -0
  32. package/dist/terminal-manager.js +23 -1
  33. package/dist/terminal-manager.js.map +1 -1
  34. package/dist/terminal-output.d.ts +34 -0
  35. package/dist/terminal-output.js +68 -0
  36. package/dist/terminal-output.js.map +1 -0
  37. package/dist/terminal-pump.d.ts +48 -5
  38. package/dist/terminal-pump.js +143 -20
  39. package/dist/terminal-pump.js.map +1 -1
  40. package/package.json +2 -2
@@ -2,6 +2,7 @@ import { readFile, writeFile, mkdir, readdir, appendFile, rm, truncate, stat, op
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { join, dirname } from 'node:path';
4
4
  import { existsSync } from 'node:fs';
5
+ import { isSettledStamp, sameStamp, toFileStamp } from './file-stamp.js';
5
6
  /**
6
7
  * Drop the legacy preview shape on load: version !== 2 or a preview without a
7
8
  * files array means both fields go, so a stale descriptor never reaches the
@@ -18,6 +19,16 @@ function dropLegacyPreviewShape(session) {
18
19
  delete session.previewSource;
19
20
  }
20
21
  }
22
+ /**
23
+ * A fresh Session parsed from cached session.json text, with the legacy
24
+ * preview shape dropped. Every read path goes through here so the stat-validated
25
+ * cache never serves a legacy preview.
26
+ */
27
+ function parseSessionRecord(json) {
28
+ const session = JSON.parse(json);
29
+ dropLegacyPreviewShape(session);
30
+ return session;
31
+ }
21
32
  /**
22
33
  * Retained tail size for a session's terminal.log. A misbehaving child (e.g. a
23
34
  * TUI stuck in a runaway repaint loop) can otherwise stream unbounded output
@@ -29,6 +40,20 @@ function dropLegacyPreviewShape(session) {
29
40
  */
30
41
  const DEFAULT_MAX_TERMINAL_LOG_BYTES = 64 * 1024 * 1024;
31
42
  const NEWLINE = 0x0a;
43
+ /**
44
+ * session.json files stat'ed concurrently while listing. Each batch is awaited,
45
+ * so a listing of any size yields to the event loop between batches instead of
46
+ * holding it for the whole directory.
47
+ */
48
+ const LIST_STAT_CONCURRENCY = 32;
49
+ function isMissing(error) {
50
+ return error?.code === 'ENOENT';
51
+ }
52
+ /** The file, or a directory on the way to it, is no longer there. */
53
+ function isGone(error) {
54
+ const code = error?.code;
55
+ return code === 'ENOENT' || code === 'ENOTDIR';
56
+ }
32
57
  export class SessionStore {
33
58
  sessionsDir;
34
59
  archivePath;
@@ -36,7 +61,19 @@ export class SessionStore {
36
61
  // Removal is final for this store's lifetime; explicit revival uses a new ID.
37
62
  retiredSessionIds = new Set();
38
63
  maxTerminalLogBytes;
64
+ // session.json index, keyed by session id. An entry is served only while a
65
+ // fresh stat of the file still matches its stamp, and is stored only for a
66
+ // file that was already quiet when it was read (see file-stamp.ts), so it can
67
+ // never be stale.
68
+ recordIndex = new Map();
69
+ // Sessions whose directory this process has already created.
70
+ terminalDirsReady = new Set();
71
+ // terminal.log size in bytes, tracked after one initial stat per session.
72
+ terminalLogSizes = new Map();
73
+ flushPendingTerminalData;
74
+ now;
39
75
  constructor(dataDir, options = {}) {
76
+ this.now = options.now ?? Date.now;
40
77
  this.sessionsDir = join(dataDir, 'sessions');
41
78
  this.archivePath = join(dataDir, 'archive.jsonl');
42
79
  const envCap = Number(process.env.FTOWN_MAX_TERMINAL_LOG_BYTES);
@@ -83,51 +120,140 @@ export class SessionStore {
83
120
  // incomplete document. A same-directory rename is atomic for readers.
84
121
  // 0600: session.json carries the env map with provider tokens, the exact
85
122
  // field toWireSession strips from the wire. Never world-readable.
86
- await writeFile(tempFilePath, JSON.stringify(session, null, 2), { encoding: 'utf-8', mode: 0o600 });
123
+ const text = JSON.stringify(session, null, 2);
124
+ const handle = await open(tempFilePath, 'w', 0o600);
125
+ try {
126
+ await handle.writeFile(text, 'utf-8');
127
+ }
128
+ finally {
129
+ await handle.close();
130
+ }
87
131
  await rename(tempFilePath, filePath);
88
132
  }
89
133
  catch (error) {
90
134
  await rm(tempFilePath, { force: true }).catch(() => undefined);
91
135
  throw error;
92
136
  }
137
+ finally {
138
+ // A file published just now cannot be validated by its stamp (another
139
+ // writer in the same timestamp tick would leave it unchanged), so the
140
+ // record is read back from disk once it has settled.
141
+ this.recordIndex.delete(session.id);
142
+ }
93
143
  });
94
144
  }
95
- async loadSession(sessionId) {
96
- const filePath = this.sessionFilePath(sessionId);
97
- if (!existsSync(filePath)) {
145
+ /** One stat of a file, reduced to its stamp; undefined when it cannot be stat'ed. */
146
+ async stampOf(filePath) {
147
+ try {
148
+ return toFileStamp(await stat(filePath, { bigint: true }));
149
+ }
150
+ catch {
151
+ return undefined;
152
+ }
153
+ }
154
+ /**
155
+ * session.json content as JSON text for a stamp just taken from disk, or null
156
+ * when the file does not exist — including when it was removed between the
157
+ * stat and the read. Reads and parses only a new or changed file; corrupt
158
+ * files throw and are never indexed.
159
+ */
160
+ async recordJsonAt(sessionId, stamp) {
161
+ if (!stamp) {
162
+ this.recordIndex.delete(sessionId);
98
163
  return null;
99
164
  }
100
- const data = await readFile(filePath, 'utf-8');
101
- const session = JSON.parse(data);
102
- dropLegacyPreviewShape(session);
103
- return session;
165
+ const indexed = this.recordIndex.get(sessionId);
166
+ if (indexed && sameStamp(indexed, stamp)) {
167
+ return indexed.json;
168
+ }
169
+ // The stamp was taken BEFORE the read: if the file is replaced meanwhile,
170
+ // the next stat differs from it and the entry is re-read.
171
+ this.recordIndex.delete(sessionId);
172
+ const readStartedAt = this.now();
173
+ let raw;
174
+ try {
175
+ raw = await readFile(this.sessionFilePath(sessionId), 'utf-8');
176
+ }
177
+ catch (error) {
178
+ if (isGone(error))
179
+ return null;
180
+ throw error;
181
+ }
182
+ const json = JSON.stringify(JSON.parse(raw));
183
+ if (isSettledStamp(stamp, readStartedAt))
184
+ this.recordIndex.set(sessionId, { ...stamp, json });
185
+ return json;
186
+ }
187
+ async loadSession(sessionId) {
188
+ const json = await this.recordJsonAt(sessionId, await this.stampOf(this.sessionFilePath(sessionId)));
189
+ return json === null ? null : parseSessionRecord(json);
104
190
  }
105
191
  async listSessions() {
106
192
  if (!existsSync(this.sessionsDir)) {
193
+ this.recordIndex.clear();
107
194
  return [];
108
195
  }
109
196
  const entries = await readdir(this.sessionsDir, { withFileTypes: true });
197
+ const ids = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
110
198
  const sessions = [];
111
- for (const entry of entries) {
112
- if (entry.isDirectory()) {
113
- const session = await this.loadSession(entry.name);
199
+ // Directory order is kept: stats run a batch at a time, records are then
200
+ // resolved one by one in that order.
201
+ for (let start = 0; start < ids.length; start += LIST_STAT_CONCURRENCY) {
202
+ const batch = ids.slice(start, start + LIST_STAT_CONCURRENCY);
203
+ const stamps = await Promise.all(batch.map((id) => this.stampOf(this.sessionFilePath(id))));
204
+ for (let i = 0; i < batch.length; i++) {
205
+ const json = await this.recordJsonAt(batch[i], stamps[i]);
206
+ const session = json === null ? null : parseSessionRecord(json);
114
207
  if (session) {
115
208
  sessions.push(session);
116
209
  }
117
210
  }
118
211
  }
212
+ const present = new Set(ids);
213
+ for (const sessionId of this.recordIndex.keys()) {
214
+ if (!present.has(sessionId))
215
+ this.recordIndex.delete(sessionId);
216
+ }
119
217
  return sessions.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
120
218
  }
219
+ /**
220
+ * Registers the owner of not-yet-persisted terminal output (the pump). It is
221
+ * invoked before terminal.log is read or cleared so no reader can observe a
222
+ * log that is missing bytes still waiting in a coalescing window.
223
+ */
224
+ setPendingTerminalFlush(flush) {
225
+ this.flushPendingTerminalData = flush;
226
+ }
121
227
  async appendTerminalData(sessionId, data) {
122
228
  await this.withSessionWrite(sessionId, async () => {
123
229
  if (this.retiredSessionIds.has(sessionId))
124
230
  return;
125
- await mkdir(this.sessionDir(sessionId), { recursive: true, mode: 0o700 });
126
231
  const filePath = this.terminalLogPath(sessionId);
127
- await appendFile(filePath, data, { encoding: 'utf-8', mode: 0o600 });
128
- await this.trimTerminalLogIfNeeded(filePath);
232
+ const bytes = Buffer.from(data, 'utf-8');
233
+ try {
234
+ await this.appendTerminalBytes(sessionId, filePath, bytes);
235
+ }
236
+ catch (error) {
237
+ this.terminalDirsReady.delete(sessionId);
238
+ this.terminalLogSizes.delete(sessionId);
239
+ if (!isMissing(error))
240
+ throw error;
241
+ // The directory vanished since it was created: recreate it and retry.
242
+ await this.appendTerminalBytes(sessionId, filePath, bytes);
243
+ }
244
+ await this.trimTerminalLogIfNeeded(sessionId, filePath);
129
245
  });
130
246
  }
247
+ async appendTerminalBytes(sessionId, filePath, bytes) {
248
+ if (!this.terminalDirsReady.has(sessionId)) {
249
+ await mkdir(this.sessionDir(sessionId), { recursive: true, mode: 0o700 });
250
+ this.terminalDirsReady.add(sessionId);
251
+ }
252
+ await appendFile(filePath, bytes, { mode: 0o600 });
253
+ const known = this.terminalLogSizes.get(sessionId);
254
+ if (known !== undefined)
255
+ this.terminalLogSizes.set(sessionId, known + bytes.length);
256
+ }
131
257
  /**
132
258
  * Cap a terminal.log's on-disk size. Runs inside the per-session write lock,
133
259
  * so it never races an append. The file is allowed to grow to 2x the retained
@@ -138,10 +264,19 @@ export class SessionStore {
138
264
  * older output was discarded. Best-effort: any failure is swallowed so it can
139
265
  * never poison the write-lock chain and stall future appends.
140
266
  */
141
- async trimTerminalLogIfNeeded(filePath) {
267
+ async trimTerminalLogIfNeeded(sessionId, filePath) {
142
268
  try {
269
+ // The size is tracked in memory after one stat; the file is stat'ed again
270
+ // only when the tracked size says a trim is due (the trim needs the real
271
+ // size) or after an error dropped the tracked value.
272
+ const tracked = this.terminalLogSizes.get(sessionId);
273
+ if (tracked !== undefined && tracked <= this.maxTerminalLogBytes * 2) {
274
+ return;
275
+ }
276
+ this.terminalLogSizes.delete(sessionId);
143
277
  const { size } = await stat(filePath);
144
278
  if (size <= this.maxTerminalLogBytes * 2) {
279
+ this.terminalLogSizes.set(sessionId, size);
145
280
  return;
146
281
  }
147
282
  const keep = this.maxTerminalLogBytes;
@@ -165,14 +300,20 @@ export class SessionStore {
165
300
  const tmpPath = `${filePath}.trim-${process.pid}.tmp`;
166
301
  await writeFile(tmpPath, Buffer.concat([marker, body]), { mode: 0o600 });
167
302
  await rename(tmpPath, filePath);
303
+ this.terminalLogSizes.set(sessionId, marker.length + body.length);
168
304
  }
169
305
  catch (err) {
306
+ this.terminalLogSizes.delete(sessionId);
170
307
  console.error(`[SessionStore] Failed to trim terminal log ${filePath}:`, err);
171
308
  }
172
309
  }
173
310
  async deleteSession(sessionId) {
174
311
  await this.withSessionWrite(sessionId, async () => {
312
+ this.recordIndex.delete(sessionId);
313
+ this.terminalDirsReady.delete(sessionId);
314
+ this.terminalLogSizes.delete(sessionId);
175
315
  await rm(this.sessionDir(sessionId), { recursive: true, force: true });
316
+ this.recordIndex.delete(sessionId);
176
317
  // Latch only after successful deletion so failures remain retryable.
177
318
  this.retiredSessionIds.add(sessionId);
178
319
  });
@@ -237,16 +378,24 @@ export class SessionStore {
237
378
  return archived;
238
379
  }
239
380
  async clearTerminalLog(sessionId) {
381
+ // Queue pending output ahead of the truncate so it cannot land afterwards.
382
+ this.flushPendingTerminalData?.(sessionId);
240
383
  await this.withSessionWrite(sessionId, async () => {
241
384
  if (this.retiredSessionIds.has(sessionId))
242
385
  return;
243
386
  const filePath = this.terminalLogPath(sessionId);
387
+ this.terminalLogSizes.delete(sessionId);
244
388
  if (existsSync(filePath)) {
245
389
  await truncate(filePath, 0);
390
+ this.terminalLogSizes.set(sessionId, 0);
246
391
  }
247
392
  });
248
393
  }
249
394
  async loadTerminalLog(sessionId) {
395
+ // Pending output is handed to appendTerminalData synchronously, which joins
396
+ // the session's write chain; waiting for that chain makes the read complete.
397
+ this.flushPendingTerminalData?.(sessionId);
398
+ await this.writeLocks.get(sessionId);
250
399
  const filePath = this.terminalLogPath(sessionId);
251
400
  if (!existsSync(filePath)) {
252
401
  return '';
@@ -1 +1 @@
1
- {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"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"}
@@ -31,6 +31,14 @@ export declare class TerminalManager {
31
31
  constructor(scrollback?: number, cols?: number);
32
32
  private ensureTerminal;
33
33
  write(sessionId: string, data: string): void;
34
+ /**
35
+ * xterm parses writes asynchronously: `serialize`/`getScreen` in the same turn
36
+ * as a `write` do not contain it yet. `done` runs once the emulator holds
37
+ * exactly the bytes written before this call — synchronously inside xterm's
38
+ * write loop, before any later write is parsed — or immediately when the
39
+ * session has no emulator, or when it is destroyed while waiting.
40
+ */
41
+ whenParsed(sessionId: string, done: () => void): void;
34
42
  serialize(sessionId: string, scrollback?: number): string;
35
43
  getScreen(sessionId: string, offset?: number, limit?: number): ScreenData;
36
44
  /**
@@ -55,7 +55,7 @@ export class TerminalManager {
55
55
  });
56
56
  const serializer = new SerializeAddon();
57
57
  terminal.loadAddon(serializer);
58
- managed = { terminal, serializer };
58
+ managed = { terminal, serializer, parseWaiters: new Set() };
59
59
  this.terminals.set(sessionId, managed);
60
60
  }
61
61
  return managed;
@@ -64,6 +64,26 @@ export class TerminalManager {
64
64
  const managed = this.ensureTerminal(sessionId);
65
65
  managed.terminal.write(data, () => { });
66
66
  }
67
+ /**
68
+ * xterm parses writes asynchronously: `serialize`/`getScreen` in the same turn
69
+ * as a `write` do not contain it yet. `done` runs once the emulator holds
70
+ * exactly the bytes written before this call — synchronously inside xterm's
71
+ * write loop, before any later write is parsed — or immediately when the
72
+ * session has no emulator, or when it is destroyed while waiting.
73
+ */
74
+ whenParsed(sessionId, done) {
75
+ const managed = this.terminals.get(sessionId);
76
+ if (!managed) {
77
+ done();
78
+ return;
79
+ }
80
+ const settle = () => {
81
+ if (managed.parseWaiters.delete(settle))
82
+ done();
83
+ };
84
+ managed.parseWaiters.add(settle);
85
+ managed.terminal.write('', settle);
86
+ }
67
87
  serialize(sessionId, scrollback) {
68
88
  const managed = this.terminals.get(sessionId);
69
89
  if (!managed)
@@ -124,6 +144,8 @@ export class TerminalManager {
124
144
  if (managed) {
125
145
  managed.terminal.dispose();
126
146
  this.terminals.delete(sessionId);
147
+ for (const settle of [...managed.parseWaiters])
148
+ settle();
127
149
  }
128
150
  }
129
151
  has(sessionId) {
@@ -1 +1 @@
1
- {"version":3,"file":"terminal-manager.js","sourceRoot":"","sources":["../src/terminal-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"terminal-manager.js","sourceRoot":"","sources":["../src/terminal-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { ProcessRunner } from './claude-runner.js';
2
+ import type { SessionStore } from './session-store.js';
3
+ import type { TerminalManager } from './terminal-manager.js';
4
+ import { TerminalPump, type TerminalPumpDeps } from './terminal-pump.js';
5
+ export interface TerminalOutputDeps {
6
+ store: TerminalPumpDeps['store'] & Pick<SessionStore, 'setPendingTerminalFlush'>;
7
+ terminalManager: Pick<TerminalManager, 'write' | 'destroy' | 'serialize' | 'whenParsed'>;
8
+ runner: Pick<ProcessRunner, 'on' | 'stopAll'>;
9
+ /** Fan-out to direct peers and, when remotely watched, Centrifugo. */
10
+ router: {
11
+ hasAttachedPeers(sessionId: string): boolean;
12
+ publishTerminalData(sessionId: string, data: string): void;
13
+ publishTerminalScreen(sessionId: string, screen: string): void;
14
+ };
15
+ watchRegistry: {
16
+ hasWatchers(sessionId: string): boolean;
17
+ };
18
+ lifecycle: Pick<TerminalPumpDeps, 'publishSessionUpdate' | 'publishHookEvent' | 'unregisterSession' | 'collectUsage'>;
19
+ }
20
+ export interface TerminalOutput {
21
+ pump: TerminalPump;
22
+ /** Screen for a direct/loopback peer that attaches; `deliver` joins it to the stream. */
23
+ attachScreen(sessionId: string, deliver: (screen: string) => void): void;
24
+ /** Full screen resync for every viewer of the session. */
25
+ publishScreenDump(sessionId: string): void;
26
+ /** Stop the runner's PTY clients and persist all output still in the pump. */
27
+ stop(): Promise<void>;
28
+ }
29
+ /**
30
+ * Wires the terminal output path: runner -> pump -> store + transports, the
31
+ * watched/unwatched cadence, and every reader that needs output which is still
32
+ * coalescing (screen snapshots, terminal.log readers, shutdown).
33
+ */
34
+ export declare function createTerminalOutput(deps: TerminalOutputDeps): TerminalOutput;
@@ -0,0 +1,68 @@
1
+ import { TerminalPump } from './terminal-pump.js';
2
+ /** Scrollback lines replayed to a viewer that attaches or asks for a resync. */
3
+ const ATTACH_SCROLLBACK_LINES = 20000;
4
+ /**
5
+ * Cap for a published screen dump. Accounts for ~50% JSON-encoding inflation on
6
+ * ANSI-heavy buffers (each \x1b expands 1 -> 6 bytes), keeping the on-wire
7
+ * Centrifugo frame under websocket_message_size_limit.
8
+ */
9
+ const MAX_SCREEN_DUMP_BYTES = 2_500_000;
10
+ /**
11
+ * RIS (full reset), sent in-band at the head of every screen. A viewer resets
12
+ * its terminal when a screen arrives, but that reset is synchronous while its
13
+ * terminal parses writes asynchronously: output received just before the screen
14
+ * is still queued and would be painted AFTER the reset, under the screen's
15
+ * content (wrong cursor, repeated text, later lines overwritten). Carrying the
16
+ * reset inside the data orders it after everything the viewer queued earlier.
17
+ */
18
+ const SCREEN_RESET = '\x1bc';
19
+ /**
20
+ * Wires the terminal output path: runner -> pump -> store + transports, the
21
+ * watched/unwatched cadence, and every reader that needs output which is still
22
+ * coalescing (screen snapshots, terminal.log readers, shutdown).
23
+ */
24
+ export function createTerminalOutput(deps) {
25
+ const { store, terminalManager, runner, router, watchRegistry } = deps;
26
+ const pump = new TerminalPump({
27
+ store,
28
+ terminalManager,
29
+ publishTerminalData: (sessionId, data) => router.publishTerminalData(sessionId, data),
30
+ isWatched: (sessionId) => router.hasAttachedPeers(sessionId) || watchRegistry.hasWatchers(sessionId),
31
+ ...deps.lifecycle,
32
+ });
33
+ pump.attach(runner);
34
+ // terminal.log readers (screen/grep fallbacks, clear) see pending output too.
35
+ store.setPendingTerminalFlush((sessionId) => pump.flush(sessionId));
36
+ return {
37
+ pump,
38
+ attachScreen(sessionId, deliver) {
39
+ pump.snapshot(sessionId, () => deliver(SCREEN_RESET + (terminalManager.serialize(sessionId, ATTACH_SCROLLBACK_LINES) ?? '')));
40
+ },
41
+ publishScreenDump(sessionId) {
42
+ pump.snapshot(sessionId, () => {
43
+ // Phase 1: viewport-only dump (~rows*cols bytes) for instant render.
44
+ const viewportRaw = terminalManager.serialize(sessionId, 0);
45
+ if (viewportRaw) {
46
+ router.publishTerminalScreen(sessionId, SCREEN_RESET + viewportRaw);
47
+ }
48
+ // Phase 2: full dump with scrollback. Client re-renders on top of phase 1.
49
+ let scrollback = ATTACH_SCROLLBACK_LINES;
50
+ let raw = terminalManager.serialize(sessionId, scrollback);
51
+ while (raw && Buffer.byteLength(raw, 'utf8') > MAX_SCREEN_DUMP_BYTES && scrollback > 100) {
52
+ scrollback = Math.floor(scrollback / 2);
53
+ raw = terminalManager.serialize(sessionId, scrollback);
54
+ }
55
+ if (!raw)
56
+ return;
57
+ if (raw === viewportRaw)
58
+ return;
59
+ router.publishTerminalScreen(sessionId, SCREEN_RESET + raw);
60
+ });
61
+ },
62
+ async stop() {
63
+ runner.stopAll();
64
+ await pump.drain();
65
+ },
66
+ };
67
+ }
68
+ //# sourceMappingURL=terminal-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-output.js","sourceRoot":"","sources":["../src/terminal-output.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAyB,MAAM,oBAAoB,CAAC;AAEzE,gFAAgF;AAChF,MAAM,uBAAuB,GAAG,KAAK,CAAC;AACtC;;;;GAIG;AACH,MAAM,qBAAqB,GAAG,SAAS,CAAC;AACxC;;;;;;;GAOG;AACH,MAAM,YAAY,GAAG,OAAO,CAAC;AA0B7B;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAwB;IAC3D,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IACvE,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC;QAC5B,KAAK;QACL,eAAe;QACf,mBAAmB,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC;QACrF,SAAS,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,IAAI,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC;QACpG,GAAG,IAAI,CAAC,SAAS;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpB,8EAA8E;IAC9E,KAAK,CAAC,uBAAuB,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAEpE,OAAO;QACL,IAAI;QAEJ,YAAY,CAAC,SAAS,EAAE,OAAO;YAC7B,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,YAAY,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,SAAS,EAAE,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChI,CAAC;QAED,iBAAiB,CAAC,SAAS;YACzB,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;gBAC5B,qEAAqE;gBACrE,MAAM,WAAW,GAAG,eAAe,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;gBAC5D,IAAI,WAAW,EAAE,CAAC;oBAChB,MAAM,CAAC,qBAAqB,CAAC,SAAS,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC;gBACtE,CAAC;gBAED,2EAA2E;gBAC3E,IAAI,UAAU,GAAG,uBAAuB,CAAC;gBACzC,IAAI,GAAG,GAAG,eAAe,CAAC,SAAS,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;gBAC3D,OAAO,GAAG,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,qBAAqB,IAAI,UAAU,GAAG,GAAG,EAAE,CAAC;oBACzF,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;oBACxC,GAAG,GAAG,eAAe,CAAC,SAAS,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;gBACzD,CAAC;gBACD,IAAI,CAAC,GAAG;oBAAE,OAAO;gBACjB,IAAI,GAAG,KAAK,WAAW;oBAAE,OAAO;gBAChC,MAAM,CAAC,qBAAqB,CAAC,SAAS,EAAE,YAAY,GAAG,GAAG,CAAC,CAAC;YAC9D,CAAC,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,IAAI;YACR,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -5,7 +5,7 @@ import type { Session, SessionUsage } from './types.js';
5
5
  export type SyntheticStopReason = 'complete' | 'error' | 'stopped';
6
6
  export interface TerminalPumpDeps {
7
7
  store: Pick<SessionStore, 'appendTerminalData' | 'loadSession' | 'saveSession' | 'loadTerminalLog'>;
8
- terminalManager: Pick<TerminalManager, 'write' | 'destroy'>;
8
+ terminalManager: Pick<TerminalManager, 'write' | 'destroy'> & Partial<Pick<TerminalManager, 'whenParsed'>>;
9
9
  publishTerminalData: (sessionId: string, data: string) => void;
10
10
  publishSessionUpdate: (session: Session) => Promise<void>;
11
11
  publishHookEvent: (sessionId: string, event: Record<string, unknown>) => Promise<void>;
@@ -17,30 +17,73 @@ export interface TerminalPumpDeps {
17
17
  * previously persisted usage.
18
18
  */
19
19
  collectUsage?: (session: Session) => Promise<SessionUsage | null>;
20
+ /**
21
+ * Whether anyone is receiving this session's live output right now (a direct
22
+ * peer or an unexpired remote watcher). Unwatched sessions coalesce output in
23
+ * a longer window. Whoever makes a session watched must call `flush` before
24
+ * producing the attach snapshot. Defaults to "always watched".
25
+ */
26
+ isWatched?: (sessionId: string) => boolean;
20
27
  /** Test seams; production uses the defaults. */
21
28
  flushIntervalMs?: number;
22
29
  maxBufferBytes?: number;
30
+ unwatchedFlushIntervalMs?: number;
31
+ unwatchedMaxBufferBytes?: number;
32
+ snapshotTimeoutMs?: number;
23
33
  }
24
34
  /**
25
35
  * Terminal output pump: buffers runner PTY output per session (coalescing into
26
- * ≤16ms / ≤32KB flushes to the store + transports), and owns the runner
27
- * lifecycle handlers ('complete'/'error') that persist final session statuses.
36
+ * ≤16ms / ≤32KB flushes to the store + transports while the session is watched,
37
+ * ≤250ms / ≤256KiB while nobody is), and owns the runner lifecycle handlers
38
+ * ('complete'/'error') that persist final session statuses. The live emulator
39
+ * (terminalManager) is fed immediately and never waits for a flush.
28
40
  */
29
41
  export declare class TerminalPump {
30
42
  private readonly deps;
31
- private readonly outputBuffers;
32
- private readonly flushTimers;
43
+ private readonly pending;
44
+ private readonly pendingAppends;
45
+ private readonly snapshotHolds;
33
46
  private readonly sessionWrites;
34
47
  private readonly pendingAsync;
35
48
  private track;
36
49
  isIdle(): boolean;
37
50
  private readonly flushIntervalMs;
38
51
  private readonly maxBufferBytes;
52
+ private readonly unwatchedFlushIntervalMs;
53
+ private readonly unwatchedMaxBufferBytes;
54
+ private readonly snapshotTimeoutMs;
39
55
  constructor(deps: TerminalPumpDeps);
40
56
  /** Wire the pump onto the runner's data/lifecycle events. */
41
57
  attach(runner: Pick<ProcessRunner, 'on'>): void;
42
58
  handleData(sessionId: string, data: string): void;
59
+ /**
60
+ * Hand a session's pending output to the store and the transports now. Runs
61
+ * before terminal.log is read or cleared, on session exit and on shutdown.
62
+ * Screen snapshots go through `snapshot`, never a bare flush.
63
+ */
43
64
  flush(sessionId: string): void;
65
+ /**
66
+ * Produce a screen snapshot (attach replay, screen dump) at an exact cut in
67
+ * the output stream. Everything received so far is sent as output first;
68
+ * `produce` then runs once the emulator has parsed exactly those bytes, and
69
+ * output received in between is delivered only after it. A viewer that is
70
+ * reset by the snapshot therefore neither loses nor repeats a byte, whether
71
+ * it joined the stream before or after the cut. Concurrent snapshots of one
72
+ * session share a cut. `produce` runs synchronously only for a session that
73
+ * has no emulator (or a pump without one); otherwise it runs later, from the
74
+ * emulator's write loop.
75
+ *
76
+ * If the emulator has not caught up within the timeout (a very large
77
+ * backlog), the held output is released as plain output and NO snapshot is
78
+ * produced from that cut — a screen taken then could be missing bytes that
79
+ * were already sent. The producers stay queued; when the emulator finally
80
+ * reports, a new cut is taken for them. A snapshot is therefore late in that
81
+ * case, never inconsistent.
82
+ */
83
+ snapshot(sessionId: string, produce: () => void): void;
84
+ private startSnapshot;
85
+ /** Flush every session and wait until the store has taken all of it (shutdown). */
86
+ drain(): Promise<void>;
44
87
  withSessionWrite(sessionId: string, task: () => Promise<void>): Promise<void>;
45
88
  publishSyntheticStop(sessionId: string, reason: SyntheticStopReason): void;
46
89
  /**