@threadbase-sh/streamer 1.46.0 → 1.46.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -2340,6 +2340,27 @@ declare class ConversationWatcher {
2340
2340
  * Watch a directory of conversation JSONL files. Fires
2341
2341
  * onConversationChanged for any add/change/unlink event so the caller
2342
2342
  * can mark the cache dirty without scanning everything immediately.
2343
+ *
2344
+ * **This costs one OS watch handle per file under `directory`, not one per
2345
+ * directory.** chokidar recurses the tree and registers a separate fs.watch
2346
+ * per entry, because a directory watch alone does not report writes to files
2347
+ * inside it — and per-file `change` events are exactly what the caller needs
2348
+ * (they drive poke()'s tail self-heal and the external-tail attach). So the
2349
+ * handle count tracks the size of the conversation corpus on disk, not the
2350
+ * number of live sessions, and it does not shrink until transcripts are
2351
+ * deleted. `ignoreInitial` suppresses the startup *events*, not the walk.
2352
+ *
2353
+ * Measured 2026-08-09 on the live macOS instance: 2131 open .jsonl fds
2354
+ * against 2133 files under the watched roots — 1:1, ~88% of all fds on the
2355
+ * process, at 2.0% of that box's 122 880 per-process ceiling. Comfortable
2356
+ * there. **Linux is the tight one**: these are inotify watches billed to the
2357
+ * per-user `max_user_watches`, which can be 8192 and is shared with every
2358
+ * other watcher the user runs. Exhaustion surfaces as ENOSPC on the `error`
2359
+ * event — which is why server.ts wires onError rather than leaving it unset.
2360
+ *
2361
+ * Before trading handles for a bound here, note the regression it invites: a
2362
+ * conversation excluded from the walk (by age or by an LRU cap) is one whose
2363
+ * external appends produce no event at all, and that failure is silent.
2343
2364
  */
2344
2365
  watchDirectory(directory: string): void;
2345
2366
  unwatchDirectory(directory: string): void;
package/dist/index.d.ts CHANGED
@@ -2340,6 +2340,27 @@ declare class ConversationWatcher {
2340
2340
  * Watch a directory of conversation JSONL files. Fires
2341
2341
  * onConversationChanged for any add/change/unlink event so the caller
2342
2342
  * can mark the cache dirty without scanning everything immediately.
2343
+ *
2344
+ * **This costs one OS watch handle per file under `directory`, not one per
2345
+ * directory.** chokidar recurses the tree and registers a separate fs.watch
2346
+ * per entry, because a directory watch alone does not report writes to files
2347
+ * inside it — and per-file `change` events are exactly what the caller needs
2348
+ * (they drive poke()'s tail self-heal and the external-tail attach). So the
2349
+ * handle count tracks the size of the conversation corpus on disk, not the
2350
+ * number of live sessions, and it does not shrink until transcripts are
2351
+ * deleted. `ignoreInitial` suppresses the startup *events*, not the walk.
2352
+ *
2353
+ * Measured 2026-08-09 on the live macOS instance: 2131 open .jsonl fds
2354
+ * against 2133 files under the watched roots — 1:1, ~88% of all fds on the
2355
+ * process, at 2.0% of that box's 122 880 per-process ceiling. Comfortable
2356
+ * there. **Linux is the tight one**: these are inotify watches billed to the
2357
+ * per-user `max_user_watches`, which can be 8192 and is shared with every
2358
+ * other watcher the user runs. Exhaustion surfaces as ENOSPC on the `error`
2359
+ * event — which is why server.ts wires onError rather than leaving it unset.
2360
+ *
2361
+ * Before trading handles for a bound here, note the regression it invites: a
2362
+ * conversation excluded from the walk (by age or by an LRU cap) is one whose
2363
+ * external appends produce no event at all, and that failure is silent.
2343
2364
  */
2344
2365
  watchDirectory(directory: string): void;
2345
2366
  unwatchDirectory(directory: string): void;
package/dist/index.js CHANGED
@@ -8387,6 +8387,27 @@ var ConversationWatcher = class {
8387
8387
  * Watch a directory of conversation JSONL files. Fires
8388
8388
  * onConversationChanged for any add/change/unlink event so the caller
8389
8389
  * can mark the cache dirty without scanning everything immediately.
8390
+ *
8391
+ * **This costs one OS watch handle per file under `directory`, not one per
8392
+ * directory.** chokidar recurses the tree and registers a separate fs.watch
8393
+ * per entry, because a directory watch alone does not report writes to files
8394
+ * inside it — and per-file `change` events are exactly what the caller needs
8395
+ * (they drive poke()'s tail self-heal and the external-tail attach). So the
8396
+ * handle count tracks the size of the conversation corpus on disk, not the
8397
+ * number of live sessions, and it does not shrink until transcripts are
8398
+ * deleted. `ignoreInitial` suppresses the startup *events*, not the walk.
8399
+ *
8400
+ * Measured 2026-08-09 on the live macOS instance: 2131 open .jsonl fds
8401
+ * against 2133 files under the watched roots — 1:1, ~88% of all fds on the
8402
+ * process, at 2.0% of that box's 122 880 per-process ceiling. Comfortable
8403
+ * there. **Linux is the tight one**: these are inotify watches billed to the
8404
+ * per-user `max_user_watches`, which can be 8192 and is shared with every
8405
+ * other watcher the user runs. Exhaustion surfaces as ENOSPC on the `error`
8406
+ * event — which is why server.ts wires onError rather than leaving it unset.
8407
+ *
8408
+ * Before trading handles for a bound here, note the regression it invites: a
8409
+ * conversation excluded from the walk (by age or by an LRU cap) is one whose
8410
+ * external appends produce no event at all, and that failure is silent.
8390
8411
  */
8391
8412
  watchDirectory(directory) {
8392
8413
  if (this.directories.has(directory)) return;
@@ -10683,6 +10704,13 @@ var StreamerServer = class {
10683
10704
  event: "cache.invalidate_on_unlink"
10684
10705
  });
10685
10706
  this.cacheMonitor?.recordUnlink(filePath);
10707
+ },
10708
+ onError: (filePath, err) => {
10709
+ const enospc = err.code === "ENOSPC";
10710
+ this.log.error(
10711
+ enospc ? `Watcher hit the OS watch-handle limit on ${filePath} \u2014 raise fs.inotify.max_user_watches (Linux) or the process fd limit; conversation discovery and live tails are degraded until then` : `Watcher error on ${filePath}: ${err.message}`,
10712
+ { filePath, err, event: enospc ? "watcher.limit_exhausted" : "watcher.error" }
10713
+ );
10686
10714
  }
10687
10715
  });
10688
10716
  this.ptyManager = new LiveSessionManager({