ftown-bridge 0.20.3 → 0.20.5

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.
@@ -0,0 +1,197 @@
1
+ import { OUTBOUND_CAPACITY_WARNING, OUTBOUND_FAILURE_ERROR, OUTBOUND_MAX_IN_FLIGHT_BYTES, OUTBOUND_MAX_IN_FLIGHT_PACKETS, OUTBOUND_MAX_QUEUED, OUTBOUND_WARN_INTERVAL_MS, describeError, } from './outbound-pipeline-types.js';
2
+ export const createOutboundPipeline = ({ logger }) => {
3
+ const jobs = [];
4
+ let queued = 0;
5
+ let inFlightPackets = 0;
6
+ let inFlightBytes = 0;
7
+ let running = false;
8
+ let windowWaiter = null;
9
+ let idleWaiters = [];
10
+ // Loggers must never break the pipeline.
11
+ const safeLog = (level, message) => {
12
+ try {
13
+ logger[level](message);
14
+ }
15
+ catch {
16
+ // swallow
17
+ }
18
+ };
19
+ // --- failure log window ---
20
+ let failureWindowOpen = false;
21
+ let failureSuppressed = 0;
22
+ let lastFailure = '';
23
+ const recordFailure = (label, err) => {
24
+ const detail = `${label}: ${describeError(err)}`;
25
+ if (failureWindowOpen) {
26
+ failureSuppressed += 1;
27
+ lastFailure = detail;
28
+ return;
29
+ }
30
+ failureWindowOpen = true;
31
+ failureSuppressed = 0;
32
+ safeLog('error', `${OUTBOUND_FAILURE_ERROR}: ${detail}`);
33
+ const timer = setTimeout(() => {
34
+ failureWindowOpen = false;
35
+ const n = failureSuppressed;
36
+ failureSuppressed = 0;
37
+ if (n > 0) {
38
+ safeLog('error', `${OUTBOUND_FAILURE_ERROR}: ${n} more in the last ${OUTBOUND_WARN_INTERVAL_MS / 1000}s (last: ${lastFailure})`);
39
+ }
40
+ }, OUTBOUND_WARN_INTERVAL_MS);
41
+ timer.unref();
42
+ };
43
+ // --- drop log window ---
44
+ let dropWindowOpen = false;
45
+ const suppressedDrops = new Map();
46
+ const recordDrop = (label) => {
47
+ if (dropWindowOpen) {
48
+ suppressedDrops.set(label, (suppressedDrops.get(label) ?? 0) + 1);
49
+ return;
50
+ }
51
+ dropWindowOpen = true;
52
+ suppressedDrops.clear();
53
+ safeLog('warn', `${OUTBOUND_CAPACITY_WARNING} (queued ${queued}, in flight ${inFlightPackets} packets / ${inFlightBytes} bytes); dropped ${label}`);
54
+ const timer = setTimeout(() => {
55
+ dropWindowOpen = false;
56
+ if (suppressedDrops.size > 0) {
57
+ const entries = [...suppressedDrops.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
58
+ const total = entries.reduce((sum, [, count]) => sum + count, 0);
59
+ safeLog('warn', `${OUTBOUND_CAPACITY_WARNING}: dropped ${total} more in the last ${OUTBOUND_WARN_INTERVAL_MS / 1000}s (${entries
60
+ .map(([label, count]) => `${label}=${count}`)
61
+ .join(', ')})`);
62
+ }
63
+ suppressedDrops.clear();
64
+ }, OUTBOUND_WARN_INTERVAL_MS);
65
+ timer.unref();
66
+ };
67
+ const notifyIdle = () => {
68
+ if (queued !== 0 || inFlightPackets !== 0 || idleWaiters.length === 0)
69
+ return;
70
+ const waiters = idleWaiters;
71
+ idleWaiters = [];
72
+ for (const resolve of waiters)
73
+ resolve();
74
+ };
75
+ const wakeSender = () => {
76
+ const wake = windowWaiter;
77
+ windowWaiter = null;
78
+ wake?.();
79
+ };
80
+ const hasRoom = (bytes) => inFlightPackets < OUTBOUND_MAX_IN_FLIGHT_PACKETS &&
81
+ (inFlightPackets === 0 || inFlightBytes + bytes <= OUTBOUND_MAX_IN_FLIGHT_BYTES);
82
+ const waitForRoom = async (bytes) => {
83
+ while (!hasRoom(bytes)) {
84
+ await new Promise((resolve) => {
85
+ windowWaiter = resolve;
86
+ });
87
+ }
88
+ };
89
+ const sendPacket = (label, packet) => {
90
+ const bytes = Number.isFinite(packet.bytes) && packet.bytes > 0 ? packet.bytes : 0;
91
+ inFlightPackets += 1;
92
+ inFlightBytes += bytes;
93
+ const settle = () => {
94
+ inFlightPackets -= 1;
95
+ inFlightBytes -= bytes;
96
+ wakeSender();
97
+ notifyIdle();
98
+ };
99
+ let reply;
100
+ try {
101
+ reply = Promise.resolve(packet.send());
102
+ }
103
+ catch (err) {
104
+ reply = Promise.reject(err);
105
+ }
106
+ reply.then(settle, (err) => {
107
+ settle();
108
+ safeRecordFailure(label, err);
109
+ });
110
+ };
111
+ const safeRecordFailure = (label, err) => {
112
+ try {
113
+ recordFailure(label, err);
114
+ }
115
+ catch {
116
+ // logging must never break the pipeline
117
+ }
118
+ };
119
+ const processJob = async (job) => {
120
+ let packets = [];
121
+ try {
122
+ const prepared = await job.prepare();
123
+ if (!Array.isArray(prepared))
124
+ throw new Error('prepare() did not return an array');
125
+ packets = prepared;
126
+ }
127
+ catch (err) {
128
+ safeRecordFailure(job.label, err);
129
+ }
130
+ for (const packet of packets) {
131
+ const bytes = Number.isFinite(packet.bytes) && packet.bytes > 0 ? packet.bytes : 0;
132
+ if (!hasRoom(bytes))
133
+ await waitForRoom(bytes);
134
+ sendPacket(job.label, packet);
135
+ }
136
+ };
137
+ const run = async () => {
138
+ running = true;
139
+ try {
140
+ for (let job = jobs.shift(); job; job = jobs.shift()) {
141
+ try {
142
+ await processJob(job);
143
+ }
144
+ catch (err) {
145
+ safeRecordFailure(job.label, err);
146
+ }
147
+ finally {
148
+ queued -= 1;
149
+ }
150
+ }
151
+ }
152
+ finally {
153
+ running = false;
154
+ notifyIdle();
155
+ }
156
+ };
157
+ return {
158
+ enqueue(job) {
159
+ try {
160
+ if (queued >= OUTBOUND_MAX_QUEUED) {
161
+ try {
162
+ recordDrop(job.label);
163
+ }
164
+ catch {
165
+ // logging must never break the pipeline
166
+ }
167
+ return false;
168
+ }
169
+ queued += 1;
170
+ jobs.push(job);
171
+ if (!running)
172
+ void run();
173
+ return true;
174
+ }
175
+ catch {
176
+ return false;
177
+ }
178
+ },
179
+ get queued() {
180
+ return queued;
181
+ },
182
+ get inFlightPackets() {
183
+ return inFlightPackets;
184
+ },
185
+ get inFlightBytes() {
186
+ return inFlightBytes;
187
+ },
188
+ idle() {
189
+ if (queued === 0 && inFlightPackets === 0)
190
+ return Promise.resolve();
191
+ return new Promise((resolve) => {
192
+ idleWaiters.push(resolve);
193
+ });
194
+ },
195
+ };
196
+ };
197
+ //# sourceMappingURL=outbound-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-pipeline.js","sourceRoot":"","sources":["../src/outbound-pipeline.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import type { DirectMessage } from '../../direct-transport/contract.js';
2
2
  import type { InboundTransportContext } from '../protocol.js';
3
3
  import { BridgeSecurityService } from './security.js';
4
- /** Serial crypto at the peer boundary; application frames never escape as plaintext. */
4
+ /** Serial crypto per direction at the peer boundary; application frames never escape as plaintext. */
5
5
  export declare class EncryptedPeerChannel {
6
6
  private readonly security;
7
7
  private readonly route;
@@ -1,6 +1,6 @@
1
1
  import { parseSecureEnvelope } from '../crypto.js';
2
2
  import { applicationJson } from './security.js';
3
- /** Serial crypto at the peer boundary; application frames never escape as plaintext. */
3
+ /** Serial crypto per direction at the peer boundary; application frames never escape as plaintext. */
4
4
  export class EncryptedPeerChannel {
5
5
  security;
6
6
  route;
@@ -47,7 +47,6 @@ export class EncryptedPeerChannel {
47
47
  await this.security.revalidate(verified.principal);
48
48
  this.deliver(verified.application.data);
49
49
  await this.security.complete(verified, 'succeeded');
50
- await this.outbound;
51
50
  }).catch(() => { this.teardown(); });
52
51
  return this.inbound;
53
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"direct.js","sourceRoot":"","sources":["../../../src/security/bridge/direct.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"direct.js","sourceRoot":"","sources":["../../../src/security/bridge/direct.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,11 @@
1
1
  import type { z } from 'zod';
2
- /** One process owns each instance directory. Never publish in-memory state before durable replacement. */
2
+ /** Writers replace the file atomically; reads are served from an identity-validated cache. Never publish in-memory state before durable replacement. */
3
3
  export declare class AtomicSnapshot<T> {
4
4
  private readonly file;
5
5
  private readonly schema;
6
6
  private readonly initial;
7
7
  private tail;
8
+ private cache;
8
9
  constructor(file: string, schema: z.ZodType<T>, initial: () => NoInfer<T>);
9
10
  private load;
10
11
  private save;
@@ -1,27 +1,49 @@
1
+ import { statSync } from 'node:fs';
1
2
  import { mkdir, open, rename, rm } from 'node:fs/promises';
2
3
  import { dirname } from 'node:path';
3
4
  import { randomUUID } from 'node:crypto';
4
5
  import { BridgeSecurityError } from './errors.js';
5
- /** One process owns each instance directory. Never publish in-memory state before durable replacement. */
6
+ const RACY_WINDOW_MS = 50;
7
+ const identityOf = (s) => `${s.dev}:${s.ino}:${s.size}:${s.mtimeNs}:${s.ctimeNs}`;
8
+ /** Writers replace the file atomically; reads are served from an identity-validated cache. Never publish in-memory state before durable replacement. */
6
9
  export class AtomicSnapshot {
7
10
  file;
8
11
  schema;
9
12
  initial;
10
13
  tail = Promise.resolve();
14
+ cache = null;
11
15
  constructor(file, schema, initial) {
12
16
  this.file = file;
13
17
  this.schema = schema;
14
18
  this.initial = initial;
15
19
  }
16
20
  async load() {
21
+ let stat;
22
+ try {
23
+ stat = statSync(this.file, { bigint: true });
24
+ }
25
+ catch (error) {
26
+ if (error.code === 'ENOENT') {
27
+ this.cache = null;
28
+ return this.initial();
29
+ }
30
+ throw new BridgeSecurityError('storage_unavailable');
31
+ }
32
+ if (this.cache?.identity === identityOf(stat))
33
+ return structuredClone(this.cache.value);
17
34
  let handle;
18
35
  try {
19
36
  handle = await open(this.file, 'r');
20
- if ((await handle.stat()).size > 64 * 1024 * 1024)
37
+ const fstat = await handle.stat({ bigint: true });
38
+ if (Number(fstat.size) > 64 * 1024 * 1024)
21
39
  throw new Error('Oversize snapshot');
22
- return this.schema.parse(JSON.parse(await handle.readFile('utf8')));
40
+ const value = this.schema.parse(JSON.parse(await handle.readFile('utf8')));
41
+ const newest = Math.max(Number(fstat.mtimeMs), Number(fstat.ctimeMs));
42
+ this.cache = Date.now() - newest >= RACY_WINDOW_MS ? { identity: identityOf(fstat), value } : null;
43
+ return structuredClone(value);
23
44
  }
24
45
  catch (error) {
46
+ this.cache = null;
25
47
  if (error.code === 'ENOENT')
26
48
  return this.initial();
27
49
  throw new BridgeSecurityError('storage_unavailable');
@@ -31,6 +53,7 @@ export class AtomicSnapshot {
31
53
  }
32
54
  }
33
55
  async save(value) {
56
+ this.cache = null;
34
57
  const directory = dirname(this.file);
35
58
  const temporary = `${this.file}.${randomUUID()}.tmp`;
36
59
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../src/security/bridge/snapshot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../src/security/bridge/snapshot.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { type JsonlFoldCache } from './jsonl-fold-cache.js';
1
2
  import type { Session, SessionUsage } from './types.js';
2
3
  /**
3
4
  * Per-session token usage extraction from harness-native session files.
@@ -38,6 +39,8 @@ export interface UsageCollectorOptions {
38
39
  museSessionsDir?: string;
39
40
  /** Cap on wall-clock read time per collection. Default 15s. */
40
41
  timeoutMs?: number;
42
+ /** Incremental read cache. Default: defaultJsonlFoldCache (shared process-wide). Tests inject a fresh one. */
43
+ foldCache?: JsonlFoldCache;
41
44
  }
42
45
  /**
43
46
  * Claude Code project-directory slug: every non-alphanumeric character of the