ftown 0.21.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 (107) hide show
  1. package/dist/attention-events.d.ts +1 -1
  2. package/dist/attention-store.d.ts +3 -0
  3. package/dist/attention-store.js +25 -1
  4. package/dist/attention-store.js.map +1 -1
  5. package/dist/centrifugo-client.d.ts +14 -1
  6. package/dist/centrifugo-client.js +38 -4
  7. package/dist/centrifugo-client.js.map +1 -1
  8. package/dist/command-rpc.d.ts +2 -0
  9. package/dist/command-rpc.js +55 -9
  10. package/dist/command-rpc.js.map +1 -1
  11. package/dist/direct-transport/loopback-server.d.ts +10 -3
  12. package/dist/direct-transport/loopback-server.js +20 -4
  13. package/dist/direct-transport/loopback-server.js.map +1 -1
  14. package/dist/direct-transport/peer-manager.d.ts +8 -3
  15. package/dist/direct-transport/peer-manager.js +20 -5
  16. package/dist/direct-transport/peer-manager.js.map +1 -1
  17. package/dist/file-stamp.d.ts +33 -0
  18. package/dist/file-stamp.js +35 -0
  19. package/dist/file-stamp.js.map +1 -0
  20. package/dist/identity-reset.d.ts +3 -1
  21. package/dist/identity-reset.js +27 -5
  22. package/dist/identity-reset.js.map +1 -1
  23. package/dist/index.js +31 -37
  24. package/dist/index.js.map +1 -1
  25. package/dist/ledger-pairing-client.d.ts +1 -1
  26. package/dist/ledger-pairing-client.js +5 -3
  27. package/dist/ledger-pairing-client.js.map +1 -1
  28. package/dist/ledger-relay.d.ts +42 -7
  29. package/dist/ledger-relay.js +175 -33
  30. package/dist/ledger-relay.js.map +1 -1
  31. package/dist/ledger-reoffer.d.ts +56 -0
  32. package/dist/ledger-reoffer.js +210 -0
  33. package/dist/ledger-reoffer.js.map +1 -0
  34. package/dist/ledger-startup.d.ts +30 -5
  35. package/dist/ledger-startup.js +40 -10
  36. package/dist/ledger-startup.js.map +1 -1
  37. package/dist/local-api-server.d.ts +3 -0
  38. package/dist/local-api-server.js +68 -6
  39. package/dist/local-api-server.js.map +1 -1
  40. package/dist/mail-delivery.d.ts +26 -3
  41. package/dist/mail-delivery.js +65 -7
  42. package/dist/mail-delivery.js.map +1 -1
  43. package/dist/mail-store.d.ts +15 -1
  44. package/dist/mail-store.js +78 -16
  45. package/dist/mail-store.js.map +1 -1
  46. package/dist/outbound-pipeline-types.d.ts +5 -2
  47. package/dist/outbound-pipeline-types.js.map +1 -1
  48. package/dist/preview-protocol.d.ts +19 -3
  49. package/dist/preview-protocol.js +14 -0
  50. package/dist/preview-protocol.js.map +1 -1
  51. package/dist/relay-token.d.ts +6 -0
  52. package/dist/relay-token.js +9 -1
  53. package/dist/relay-token.js.map +1 -1
  54. package/dist/security/bridge/ledger-rpc.d.ts +34 -0
  55. package/dist/security/bridge/ledger-rpc.js +58 -0
  56. package/dist/security/bridge/ledger-rpc.js.map +1 -0
  57. package/dist/security/bridge/ledger-store.d.ts +82 -13
  58. package/dist/security/bridge/ledger-store.js +394 -54
  59. package/dist/security/bridge/ledger-store.js.map +1 -1
  60. package/dist/security/bridge/permissions.js +2 -1
  61. package/dist/security/bridge/permissions.js.map +1 -1
  62. package/dist/security/bridge/policy.d.ts +5 -1
  63. package/dist/security/bridge/policy.js +17 -0
  64. package/dist/security/bridge/policy.js.map +1 -1
  65. package/dist/security/bridge/security.d.ts +148 -10
  66. package/dist/security/bridge/security.js +270 -65
  67. package/dist/security/bridge/security.js.map +1 -1
  68. package/dist/security/crypto.d.ts +2 -0
  69. package/dist/security/crypto.js +43 -4
  70. package/dist/security/crypto.js.map +1 -1
  71. package/dist/security/ledger/announce.d.ts +32 -0
  72. package/dist/security/ledger/announce.js +101 -0
  73. package/dist/security/ledger/announce.js.map +1 -0
  74. package/dist/security/ledger/ledger.d.ts +107 -14
  75. package/dist/security/ledger/ledger.js +364 -83
  76. package/dist/security/ledger/ledger.js.map +1 -1
  77. package/dist/security/ledger/proof.d.ts +12 -0
  78. package/dist/security/ledger/proof.js +40 -8
  79. package/dist/security/ledger/proof.js.map +1 -1
  80. package/dist/security/ledger/protocol.d.ts +14 -1
  81. package/dist/security/ledger/protocol.js.map +1 -1
  82. package/dist/session-controller.d.ts +9 -3
  83. package/dist/session-controller.js +120 -20
  84. package/dist/session-controller.js.map +1 -1
  85. package/dist/session-inbox-protocol.d.ts +2 -0
  86. package/dist/session-preview.d.ts +20 -5
  87. package/dist/session-preview.js +185 -37
  88. package/dist/session-preview.js.map +1 -1
  89. package/dist/session-store.d.ts +22 -0
  90. package/dist/session-store.js +180 -13
  91. package/dist/session-store.js.map +1 -1
  92. package/dist/sessions-commands.js +41 -7
  93. package/dist/sessions-commands.js.map +1 -1
  94. package/dist/terminal-manager.d.ts +8 -0
  95. package/dist/terminal-manager.js +23 -1
  96. package/dist/terminal-manager.js.map +1 -1
  97. package/dist/terminal-output.d.ts +34 -0
  98. package/dist/terminal-output.js +68 -0
  99. package/dist/terminal-output.js.map +1 -0
  100. package/dist/terminal-pump.d.ts +48 -5
  101. package/dist/terminal-pump.js +143 -20
  102. package/dist/terminal-pump.js.map +1 -1
  103. package/dist/types.d.ts +1 -1
  104. package/opencode-plugin/ftown.js +15 -2
  105. package/package.json +2 -2
  106. package/skills/ftown/SKILL.md +18 -7
  107. package/skills/ftown/references/sessions.md +35 -10
@@ -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
  /**
@@ -1,5 +1,9 @@
1
1
  const FLUSH_INTERVAL_MS = 16;
2
2
  const MAX_BUFFER_BYTES = 32_000;
3
+ const UNWATCHED_FLUSH_INTERVAL_MS = 250;
4
+ const UNWATCHED_MAX_BUFFER_BYTES = 256 * 1024;
5
+ /** Upper bound on how long a snapshot may hold back a session's output. */
6
+ const SNAPSHOT_TIMEOUT_MS = 1000;
3
7
  /** Raw terminal chars considered for the errorReason tail (pre-sanitize). */
4
8
  const ERROR_TAIL_RAW_CHARS = 1200;
5
9
  /** Max sanitized tail chars kept in errorReason. */
@@ -17,13 +21,16 @@ function sanitizeTerminalTail(raw) {
17
21
  }
18
22
  /**
19
23
  * Terminal output pump: buffers runner PTY output per session (coalescing into
20
- * ≤16ms / ≤32KB flushes to the store + transports), and owns the runner
21
- * lifecycle handlers ('complete'/'error') that persist final session statuses.
24
+ * ≤16ms / ≤32KB flushes to the store + transports while the session is watched,
25
+ * ≤250ms / ≤256KiB while nobody is), and owns the runner lifecycle handlers
26
+ * ('complete'/'error') that persist final session statuses. The live emulator
27
+ * (terminalManager) is fed immediately and never waits for a flush.
22
28
  */
23
29
  export class TerminalPump {
24
30
  deps;
25
- outputBuffers = new Map();
26
- flushTimers = new Map();
31
+ pending = new Map();
32
+ pendingAppends = new Set();
33
+ snapshotHolds = new Map();
27
34
  // Per-session write queue so concurrent load/modify/save flows (hooks,
28
35
  // runner exit handlers, stop_session) cannot interleave and resurrect a
29
36
  // stale status.
@@ -35,14 +42,20 @@ export class TerminalPump {
35
42
  return work;
36
43
  }
37
44
  isIdle() {
38
- return this.outputBuffers.size === 0 && this.sessionWrites.size === 0 && this.pendingAsync.size === 0;
45
+ return this.pending.size === 0 && this.sessionWrites.size === 0 && this.pendingAsync.size === 0;
39
46
  }
40
47
  flushIntervalMs;
41
48
  maxBufferBytes;
49
+ unwatchedFlushIntervalMs;
50
+ unwatchedMaxBufferBytes;
51
+ snapshotTimeoutMs;
42
52
  constructor(deps) {
43
53
  this.deps = deps;
44
54
  this.flushIntervalMs = deps.flushIntervalMs ?? FLUSH_INTERVAL_MS;
45
55
  this.maxBufferBytes = deps.maxBufferBytes ?? MAX_BUFFER_BYTES;
56
+ this.unwatchedFlushIntervalMs = deps.unwatchedFlushIntervalMs ?? UNWATCHED_FLUSH_INTERVAL_MS;
57
+ this.unwatchedMaxBufferBytes = deps.unwatchedMaxBufferBytes ?? UNWATCHED_MAX_BUFFER_BYTES;
58
+ this.snapshotTimeoutMs = deps.snapshotTimeoutMs ?? SNAPSHOT_TIMEOUT_MS;
46
59
  }
47
60
  /** Wire the pump onto the runner's data/lifecycle events. */
48
61
  attach(runner) {
@@ -52,28 +65,138 @@ export class TerminalPump {
52
65
  }
53
66
  handleData(sessionId, data) {
54
67
  this.deps.terminalManager.write(sessionId, data);
55
- const existing = this.outputBuffers.get(sessionId) ?? '';
56
- this.outputBuffers.set(sessionId, existing + data);
57
- if ((existing.length + data.length) >= this.maxBufferBytes) {
68
+ let pending = this.pending.get(sessionId);
69
+ if (!pending) {
70
+ pending = { data: '', bytes: 0, unwatchedTimer: false };
71
+ this.pending.set(sessionId, pending);
72
+ }
73
+ pending.data += data;
74
+ pending.bytes += Buffer.byteLength(data, 'utf-8');
75
+ // A viewer waiting for its snapshot is not attached yet but is watching.
76
+ if (this.snapshotHolds.has(sessionId) || (this.deps.isWatched?.(sessionId) ?? true)) {
77
+ // A buffer still riding the long window means a watcher appeared without
78
+ // an explicit flush: deliver now instead of making it wait.
79
+ if (pending.data.length >= this.maxBufferBytes || pending.unwatchedTimer) {
80
+ this.flush(sessionId);
81
+ }
82
+ else if (!pending.timer) {
83
+ pending.timer = setTimeout(() => this.flush(sessionId), this.flushIntervalMs);
84
+ }
85
+ }
86
+ else if (pending.bytes > this.unwatchedMaxBufferBytes) {
58
87
  this.flush(sessionId);
59
88
  }
60
- else if (!this.flushTimers.has(sessionId)) {
61
- this.flushTimers.set(sessionId, setTimeout(() => this.flush(sessionId), this.flushIntervalMs));
89
+ else if (!pending.timer) {
90
+ pending.timer = setTimeout(() => this.flush(sessionId), this.unwatchedFlushIntervalMs);
91
+ pending.unwatchedTimer = true;
62
92
  }
63
93
  }
94
+ /**
95
+ * Hand a session's pending output to the store and the transports now. Runs
96
+ * before terminal.log is read or cleared, on session exit and on shutdown.
97
+ * Screen snapshots go through `snapshot`, never a bare flush.
98
+ */
64
99
  flush(sessionId) {
65
- const buf = this.outputBuffers.get(sessionId);
66
- if (!buf)
100
+ const pending = this.pending.get(sessionId);
101
+ if (!pending)
67
102
  return;
68
- this.outputBuffers.delete(sessionId);
69
- const timer = this.flushTimers.get(sessionId);
70
- if (timer)
71
- clearTimeout(timer);
72
- this.flushTimers.delete(sessionId);
73
- this.track(this.deps.store.appendTerminalData(sessionId, buf)).catch((err) => {
103
+ this.pending.delete(sessionId);
104
+ if (pending.timer)
105
+ clearTimeout(pending.timer);
106
+ const append = this.track(this.deps.store.appendTerminalData(sessionId, pending.data)).catch((err) => {
74
107
  console.error(`[Bridge] Failed to store terminal data for ${sessionId}:`, err);
75
108
  });
76
- this.deps.publishTerminalData(sessionId, buf);
109
+ this.pendingAppends.add(append);
110
+ void append.then(() => this.pendingAppends.delete(append));
111
+ const hold = this.snapshotHolds.get(sessionId);
112
+ if (hold)
113
+ hold.deferred.push(pending.data);
114
+ else
115
+ this.deps.publishTerminalData(sessionId, pending.data);
116
+ }
117
+ /**
118
+ * Produce a screen snapshot (attach replay, screen dump) at an exact cut in
119
+ * the output stream. Everything received so far is sent as output first;
120
+ * `produce` then runs once the emulator has parsed exactly those bytes, and
121
+ * output received in between is delivered only after it. A viewer that is
122
+ * reset by the snapshot therefore neither loses nor repeats a byte, whether
123
+ * it joined the stream before or after the cut. Concurrent snapshots of one
124
+ * session share a cut. `produce` runs synchronously only for a session that
125
+ * has no emulator (or a pump without one); otherwise it runs later, from the
126
+ * emulator's write loop.
127
+ *
128
+ * If the emulator has not caught up within the timeout (a very large
129
+ * backlog), the held output is released as plain output and NO snapshot is
130
+ * produced from that cut — a screen taken then could be missing bytes that
131
+ * were already sent. The producers stay queued; when the emulator finally
132
+ * reports, a new cut is taken for them. A snapshot is therefore late in that
133
+ * case, never inconsistent.
134
+ */
135
+ snapshot(sessionId, produce) {
136
+ const active = this.snapshotHolds.get(sessionId);
137
+ if (active)
138
+ active.producers.push(produce);
139
+ else
140
+ this.startSnapshot(sessionId, [produce]);
141
+ }
142
+ startSnapshot(sessionId, producers) {
143
+ this.flush(sessionId);
144
+ const hold = { producers, deferred: [] };
145
+ this.snapshotHolds.set(sessionId, hold);
146
+ let timer;
147
+ const release = () => {
148
+ this.snapshotHolds.delete(sessionId);
149
+ for (const data of hold.deferred)
150
+ this.deps.publishTerminalData(sessionId, data);
151
+ // Output that arrived during the hold follows at once, not a window later.
152
+ this.flush(sessionId);
153
+ };
154
+ const onParsed = () => {
155
+ if (timer)
156
+ clearTimeout(timer);
157
+ if (this.snapshotHolds.get(sessionId) !== hold) {
158
+ // Timed out earlier and its output has moved on: cut again.
159
+ const current = this.snapshotHolds.get(sessionId);
160
+ if (current)
161
+ current.producers.push(...hold.producers);
162
+ else
163
+ this.startSnapshot(sessionId, hold.producers);
164
+ return;
165
+ }
166
+ try {
167
+ for (const run of hold.producers) {
168
+ try {
169
+ run();
170
+ }
171
+ catch (err) {
172
+ console.error(`[Bridge] Failed to produce terminal snapshot for ${sessionId}:`, err);
173
+ }
174
+ }
175
+ }
176
+ finally {
177
+ release();
178
+ }
179
+ };
180
+ const whenParsed = this.deps.terminalManager.whenParsed;
181
+ if (!whenParsed) {
182
+ onParsed();
183
+ return;
184
+ }
185
+ // Output must never stay held because an emulator is slow to report back.
186
+ timer = setTimeout(() => {
187
+ if (this.snapshotHolds.get(sessionId) === hold)
188
+ release();
189
+ }, this.snapshotTimeoutMs);
190
+ timer.unref?.();
191
+ whenParsed.call(this.deps.terminalManager, sessionId, onParsed);
192
+ }
193
+ /** Flush every session and wait until the store has taken all of it (shutdown). */
194
+ async drain() {
195
+ for (const sessionId of [...this.pending.keys()])
196
+ this.flush(sessionId);
197
+ while (this.pendingAppends.size > 0) {
198
+ await Promise.all([...this.pendingAppends]);
199
+ }
77
200
  }
78
201
  withSessionWrite(sessionId, task) {
79
202
  const prev = this.sessionWrites.get(sessionId) ?? Promise.resolve();
@@ -176,7 +299,7 @@ export class TerminalPump {
176
299
  handleError(sessionId, error) {
177
300
  // Capture what's still buffered BEFORE flush drains it — the errorReason
178
301
  // tail needs it if the (unawaited) flush append hasn't hit the store yet.
179
- const pendingAtError = this.outputBuffers.get(sessionId) ?? '';
302
+ const pendingAtError = this.pending.get(sessionId)?.data ?? '';
180
303
  this.flush(sessionId);
181
304
  this.publishSyntheticStop(sessionId, 'error');
182
305
  void this.track(this.withSessionWrite(sessionId, async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"terminal-pump.js","sourceRoot":"","sources":["../src/terminal-pump.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"terminal-pump.js","sourceRoot":"","sources":["../src/terminal-pump.ts"],"names":[],"mappings":"AAoCA,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAC7B,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAChC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AACxC,MAAM,0BAA0B,GAAG,GAAG,GAAG,IAAI,CAAC;AAC9C,2EAA2E;AAC3E,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAkBjC,6EAA6E;AAC7E,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAClC,oDAAoD;AACpD,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACjC,gDAAgD;AAChD,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAEnC,8EAA8E;AAC9E,MAAM,cAAc,GAAG,IAAI,MAAM,CAC/B,oFAAoF,EACpF,GAAG,CACJ,CAAC;AAEF,oFAAoF;AACpF,SAAS,oBAAoB,CAAC,GAAW;IACvC,OAAO,GAAG;SACP,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;SAC3B,OAAO,CAAC,2BAA2B,EAAE,GAAG,CAAC;SACzC,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IAuBM;IAtBZ,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC3C,cAAc,GAAG,IAAI,GAAG,EAAiB,CAAC;IAC1C,aAAa,GAAG,IAAI,GAAG,EAAwB,CAAC;IACjE,uEAAuE;IACvE,wEAAwE;IACxE,gBAAgB;IACC,aAAa,GAAG,IAAI,GAAG,EAAyB,CAAC;IACjD,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC;IACpD,KAAK,CAAI,IAAgB;QAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5B,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3F,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,CAAC;IAClG,CAAC;IACgB,eAAe,CAAS;IACxB,cAAc,CAAS;IACvB,wBAAwB,CAAS;IACjC,uBAAuB,CAAS;IAChC,iBAAiB,CAAS;IAE3C,YAA6B,IAAsB;QAAtB,SAAI,GAAJ,IAAI,CAAkB;QACjD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,IAAI,iBAAiB,CAAC;QACjE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,gBAAgB,CAAC;QAC9D,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC,wBAAwB,IAAI,2BAA2B,CAAC;QAC7F,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,uBAAuB,IAAI,0BAA0B,CAAC;QAC1F,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,IAAI,mBAAmB,CAAC;IACzE,CAAC;IAED,6DAA6D;IAC7D,MAAM,CAAC,MAAiC;QACtC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QACzE,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/E,CAAC;IAED,UAAU,CAAC,SAAiB,EAAE,IAAY;QACxC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAEjD,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;YACxD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC;QACrB,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAElD,yEAAyE;QACzE,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC;YACpF,yEAAyE;YACzE,4DAA4D;YAC5D,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;gBACzE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACxB,CAAC;iBAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;YAChF,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACxD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;aAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,wBAAwB,CAAC,CAAC;YACvF,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;QAChC,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAiB;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/B,IAAI,OAAO,CAAC,KAAK;YAAE,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACnG,OAAO,CAAC,KAAK,CAAC,8CAA8C,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,IAAI;YAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;;YACtC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,SAAiB,EAAE,OAAmB;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,MAAM;YAAE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;;YACtC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAChD,CAAC;IAEO,aAAa,CAAC,SAAiB,EAAE,SAA4B;QACnE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACtB,MAAM,IAAI,GAAiB,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACxC,IAAI,KAAgD,CAAC;QACrD,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACrC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ;gBAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YACjF,2EAA2E;YAC3E,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC,CAAC;QACF,MAAM,QAAQ,GAAG,GAAS,EAAE;YAC1B,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC/C,4DAA4D;gBAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAClD,IAAI,OAAO;oBAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;;oBAClD,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;gBACnD,OAAO;YACT,CAAC;YACD,IAAI,CAAC;gBACH,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACjC,IAAI,CAAC;wBAAC,GAAG,EAAE,CAAC;oBAAC,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBAC1B,OAAO,CAAC,KAAK,CAAC,oDAAoD,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC;oBACvF,CAAC;gBACH,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC;QACF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;QACxD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,QAAQ,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QACD,0EAA0E;QAC1E,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACtB,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,IAAI;gBAAE,OAAO,EAAE,CAAC;QAC5D,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC3B,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAChB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;IAED,mFAAmF;IACnF,KAAK,CAAC,KAAK;QACT,KAAK,MAAM,SAAS,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,gBAAgB,CAAC,SAAiB,EAAE,IAAyB;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpE,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC3C,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;YACxB,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,OAAO,EAAE,CAAC;gBAClD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC;IACb,CAAC;IAED,2EAA2E;IAC3E,6EAA6E;IAC7E,8EAA8E;IAC9E,sEAAsE;IACtE,uEAAuE;IACvE,oBAAoB,CAAC,SAAiB,EAAE,MAA2B;QACjE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE;YACpC,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,MAAM;YACjB,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;SAClC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACf,OAAO,CAAC,KAAK,CAAC,iDAAiD,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC;QACpF,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACK,sBAAsB,CAAC,SAAiB;QAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;QACvC,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,EAAE;YAC1B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YAC7D,IAAI,CAAC,OAAO;gBAAE,OAAO;YACrB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;YACrC,IAAI,CAAC,KAAK;gBAAE,OAAO;YACnB,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;gBAChD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;gBAC3D,IAAI,CAAC,KAAK;oBAAE,OAAO;gBACnB,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;gBACpB,KAAK,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBAC3C,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACzC,MAAM,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YAClB,OAAO,CAAC,KAAK,CAAC,gDAAgD,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC;QACnF,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,cAAc,CAAC,SAAiB;QACtC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACtB,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QACjD,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YAC7D,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC;gBAC7B,OAAO,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBAC7C,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;gBAC3C,MAAM,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;YAChD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,oBAAoB,SAAS,YAAY,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACf,OAAO,CAAC,KAAK,CAAC,oDAAoD,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC;QACvF,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;;;;;OAMG;IACK,KAAK,CAAC,gBAAgB,CAC5B,SAAiB,EACjB,KAAY,EACZ,cAAsB;QAEtB,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;QAC5E,CAAC;QACD,MAAM,MAAM,GAAG,cAAc,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC;YAC5D,CAAC,CAAC,GAAG,GAAG,cAAc;YACtB,CAAC,CAAC,GAAG,CAAC;QACR,MAAM,IAAI,GAAG,oBAAoB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,CAAC;aACnE,KAAK,CAAC,CAAC,oBAAoB,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;QACnE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;IACjD,CAAC;IAEO,WAAW,CAAC,SAAiB,EAAE,KAAY;QACjD,yEAAyE;QACzE,0EAA0E;QAC1E,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;QAC/D,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACtB,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC9C,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YAC7D,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC;gBACzB,OAAO,CAAC,WAAW,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;gBACpF,OAAO,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBAC7C,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;gBAC3C,MAAM,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;YAChD,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,oBAAoB,SAAS,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACf,OAAO,CAAC,KAAK,CAAC,+CAA+C,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC,CAAC;IACN,CAAC;CACF"}
package/dist/types.d.ts CHANGED
@@ -90,7 +90,7 @@ export interface Command {
90
90
  payload: CommandPayload;
91
91
  requestId: string;
92
92
  }
93
- export type CommandType = 'get_pull_request_review' | 'get_pull_request_review_chunk' | 'preview_chat_list' | 'preview_chat_send' | 'preview_chat_reply' | 'get_pull_request_statuses' | 'session_preview_status' | 'session_preview_chunk' | 'get_bridge_update' | 'update_bridge' | 'security_devices' | 'security_invite' | 'security_revoke' | 'create_session' | 'stop_session' | 'list_sessions' | 'get_history' | 'retry_session' | 'send_message' | 'rename_session' | 'remove_session' | 'bridge_exec' | 'clear_terminal' | 'update_session_parent' | 'get_session_usage' | 'get_sessions_usage' | 'get_session_attention' | 'resolve_session_attention' | 'answer_session_attention';
93
+ export type CommandType = 'get_pull_request_review' | 'get_pull_request_review_chunk' | 'preview_chat_list' | 'preview_chat_send' | 'preview_chat_reply' | 'get_pull_request_statuses' | 'session_preview_status' | 'session_preview_chunk' | 'get_bridge_update' | 'update_bridge' | 'security_devices' | 'security_invite' | 'security_revoke' | 'ledger_head' | 'ledger_chain' | 'create_session' | 'stop_session' | 'list_sessions' | 'get_history' | 'retry_session' | 'send_message' | 'rename_session' | 'remove_session' | 'bridge_exec' | 'clear_terminal' | 'update_session_parent' | 'get_session_usage' | 'get_sessions_usage' | 'get_session_attention' | 'resolve_session_attention' | 'answer_session_attention';
94
94
  export interface GetSessionAttentionPayload {
95
95
  bridgeId: string;
96
96
  sessionId: string;
@@ -85,6 +85,7 @@ export function registerFtownOpencodePlugin(client, options = {}) {
85
85
  let polling = false;
86
86
  let inflight = false;
87
87
  let seen = new Set();
88
+ const postedPromptIds = new Set();
88
89
  let retryAt = 0;
89
90
  let retryDelay = 5_000;
90
91
 
@@ -145,6 +146,8 @@ export function registerFtownOpencodePlugin(client, options = {}) {
145
146
  inflight = true;
146
147
  for (const messageId of ids) seen.add(messageId);
147
148
  try {
149
+ // Tell the bridge first so the wake's no-text prompt hook is one-shot injected.
150
+ await postHook('FtownWakeSubmitted');
148
151
  const result = await client.session.prompt({ path: { id }, body: {
149
152
  parts: [{ type: 'text', text: `[ftown mail] ${MAIL_WAKE_TEXT}` }],
150
153
  } });
@@ -229,9 +232,19 @@ export function registerFtownOpencodePlugin(client, options = {}) {
229
232
  await postHook('SessionStart');
230
233
  await poll();
231
234
  break;
232
- case 'message.updated':
233
- if (event.properties?.info?.role === 'user') { busy = true; await postHook('UserPromptSubmit'); }
235
+ case 'message.updated': {
236
+ const info = event.properties?.info;
237
+ if (info?.role === 'user') {
238
+ busy = true;
239
+ const messageId = info?.id;
240
+ if (typeof messageId === 'string' && messageId) {
241
+ if (postedPromptIds.has(messageId)) break;
242
+ postedPromptIds.add(messageId);
243
+ }
244
+ await postHook('UserPromptSubmit');
245
+ }
234
246
  break;
247
+ }
235
248
  case 'session.status':
236
249
  if (event.properties?.status?.type === 'busy') { busy = true; await postHook('PreToolUse'); break; }
237
250
  if (event.properties?.status?.type !== 'idle') break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ftown",
3
- "version": "0.21.0",
3
+ "version": "0.25.0",
4
4
  "description": "CLI bridge for ftown — generic PTY-over-Centrifugo relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -72,5 +72,5 @@
72
72
  "overrides": {
73
73
  "qs": "6.16.1"
74
74
  },
75
- "gitHead": "47c0c38840ff1e0dfb6d8d7fe1c622dc560b9538"
75
+ "gitHead": "e4010193f960ffff69015be86c5e06aa18dc060c"
76
76
  }
@@ -45,7 +45,9 @@ ftown sessions attention --title "Pick a database" --message "Which database sho
45
45
  ftown sessions attention-status <event-id> --wait
46
46
  ftown sessions pr https://github.com/owner/repo/pull/123
47
47
  ftown sessions pr --clear
48
- ftown sessions preview ./preview.html
48
+ ftown sessions preview ./preview.html ./notes.md
49
+ ftown sessions preview --add ./extra.html
50
+ ftown sessions preview --remove notes.md
49
51
  ftown sessions preview --clear
50
52
  ftown sessions preview-reply --message "The preview is ready."
51
53
  ftown harness mail send <session-id> --type task "review the API client"
@@ -59,12 +61,21 @@ Read `references/sessions.md` for the session, mail and terminal command
59
61
  reference. Read `references/orchestrator.md` for practical worker coordination
60
62
  examples. Each command group also has `--help`.
61
63
 
62
- `ftown sessions preview <path>` registers a self-contained HTML file in the
63
- current session's working directory for the dashboard. Inline CSS and scripts
64
- and data images work; sibling assets and network access are unsupported. Publish
65
- updates by writing a temporary file and atomically renaming it into place. Use
66
- `--session-id <id>` for an explicit target or `--clear` to remove registration;
67
- clearing never deletes the file.
64
+ `ftown sessions preview <path...>` registers up to 12 files in the current
65
+ session's working directory for the dashboard, in this order. Kind is by
66
+ extension: `.html`/`.htm` → HTML, `.md`/`.markdown` → Markdown, anything else
67
+ is rejected. Each file is at most 1 MiB. A duplicate basename is rejected.
68
+ `--add <path...>` appends to the current set, `--remove <name...>` removes by
69
+ basename, and `--clear` removes the whole registration (never deletes files).
70
+ HTML previews are self-contained: inline CSS and scripts and data images work;
71
+ sibling assets and network access are unsupported. Markdown is rendered as a
72
+ readable document with GFM (tables, task lists, fenced code) in the same
73
+ sandbox iframe, with no network and only `data:` images; raw HTML inside the
74
+ markdown is isolated the same way. With two or more registered files, the
75
+ dashboard shows a selector in the preview toolbar; a relative link between
76
+ registered files switches the selector. Publish updates by writing a temporary
77
+ file and atomically renaming it into place. Use `--session-id <id>` for an
78
+ explicit target.
68
79
 
69
80
  Messages from the preview conversation arrive as ftown mail. Respond explicitly
70
81
  with `ftown sessions preview-reply --message "Your response"`; use