@threadbase-sh/streamer 1.24.1 → 1.24.3

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/cli.cjs CHANGED
@@ -138849,14 +138849,41 @@ function scrapePermissionGate(lines) {
138849
138849
  }
138850
138850
  if (options.length === 0) return null;
138851
138851
  let prompt;
138852
+ let promptLine = -1;
138852
138853
  for (let i = firstOptionLine - 1; i >= 0; i--) {
138853
138854
  const t2 = stripGutter(lines[i]).trim();
138854
138855
  if (t2.length === 0) continue;
138855
138856
  if (BOX_ONLY_RE.test(lines[i].trim()) || FOOTER_RE.test(t2) || PROMPT_ARROW_RE.test(t2)) continue;
138856
138857
  prompt = t2 || void 0;
138858
+ promptLine = i;
138857
138859
  break;
138858
138860
  }
138859
- return { ...prompt ? { prompt } : {}, options, ...cursor !== void 0 ? { cursor } : {} };
138861
+ const detail = promptLine > 0 ? scrapeDetail(lines, promptLine) : void 0;
138862
+ return {
138863
+ ...prompt ? { prompt } : {},
138864
+ ...detail ? { detail } : {},
138865
+ options,
138866
+ ...cursor !== void 0 ? { cursor } : {}
138867
+ };
138868
+ }
138869
+ var MAX_DETAIL_LINES = 6;
138870
+ function scrapeDetail(lines, promptLine) {
138871
+ const collected = [];
138872
+ let blankRun = 0;
138873
+ for (let i = promptLine - 1; i >= 0; i--) {
138874
+ const t2 = stripGutter(lines[i]).trim();
138875
+ if (BOX_ONLY_RE.test(t2)) break;
138876
+ if (t2.length === 0) {
138877
+ blankRun++;
138878
+ if (blankRun >= 2) break;
138879
+ continue;
138880
+ }
138881
+ blankRun = 0;
138882
+ if (FOOTER_RE.test(t2) || PROMPT_ARROW_RE.test(t2)) continue;
138883
+ collected.push(t2);
138884
+ if (collected.length >= MAX_DETAIL_LINES) break;
138885
+ }
138886
+ return collected.length > 0 ? collected.reverse().join("\n") : void 0;
138860
138887
  }
138861
138888
 
138862
138889
  // src/services/questions/detectQuestionFromScreen.ts
@@ -142609,6 +142636,11 @@ var StreamerServer = class {
142609
142636
  // /input { keys }. Cleared when the gate closes.
142610
142637
  pendingPermission = /* @__PURE__ */ new Map();
142611
142638
  scanner = null;
142639
+ // Set when better-sqlite3 is unusable (e.g. node ABI mismatch made
142640
+ // ConversationCache.open throw). All scanners are then built with
142641
+ // persistent: false so requests serve from disk instead of 500ing on
142642
+ // every touch of the scanner's own SQLite index.
142643
+ scannerPersistenceDisabled = false;
142612
142644
  // Tracks every ConversationScanner ever created so close() can shut them all
142613
142645
  // down and release SQLite handles (open handles block temp-dir deletion on Windows).
142614
142646
  allScanners = /* @__PURE__ */ new Set();
@@ -143108,11 +143140,12 @@ var StreamerServer = class {
143108
143140
  const message = err instanceof Error ? err.message : String(err);
143109
143141
  const abiMismatch = message.includes("NODE_MODULE_VERSION") || message.includes("was compiled against a different Node.js version");
143110
143142
  this.log.error(
143111
- `ConversationCache failed to open \u2014 running WITHOUT cache; /api/conversations, /api/conversations/count and /project-chats will 500.` + (abiMismatch ? ` Fix: npm rebuild better-sqlite3` : "") + ` (${message})`,
143143
+ `ConversationCache failed to open \u2014 running WITHOUT cache; /api/conversations, /api/conversations/count and /project-chats serve from disk (degraded).` + (abiMismatch ? ` Fix: npm rebuild better-sqlite3` : "") + ` (${message})`,
143112
143144
  { error: message, abiMismatch, event: "cache.open_failed" }
143113
143145
  );
143146
+ this.scannerPersistenceDisabled = true;
143114
143147
  }
143115
- const warmupScanner = new ConversationScanner();
143148
+ const warmupScanner = this.newScanner();
143116
143149
  this.allScanners.add(warmupScanner);
143117
143150
  const warmupStatCache = this.buildStatCache(null);
143118
143151
  const shouldEmitProgress = createScanProgressThrottle();
@@ -143129,6 +143162,10 @@ var StreamerServer = class {
143129
143162
  }
143130
143163
  }
143131
143164
  }).then(async () => {
143165
+ if (!this.scannerReady && !this.scanner) {
143166
+ this.scanner = warmupScanner;
143167
+ this.scannerReady = Promise.resolve();
143168
+ }
143132
143169
  if (!this.cache) return;
143133
143170
  const metas = [...warmupScanner.getMetadataCache().values()];
143134
143171
  const upsertedIds = new Set(this.cache.upsertFromScannerMeta(metas));
@@ -143177,10 +143214,6 @@ var StreamerServer = class {
143177
143214
  event: "cache.warmup_failed"
143178
143215
  });
143179
143216
  }).finally(() => {
143180
- if (!this.scannerReady && !this.scanner) {
143181
- this.scanner = warmupScanner;
143182
- this.scannerReady = Promise.resolve();
143183
- }
143184
143217
  this.cacheReady = true;
143185
143218
  this.wsHub.broadcast({ type: "cache_ready" });
143186
143219
  resolveWarm();
@@ -143563,6 +143596,11 @@ var StreamerServer = class {
143563
143596
  // this — its per-file refreshFile (in findConversationByUuid) already
143564
143597
  // reconciles the one conversation being requested, so paying a full-tree
143565
143598
  // rescan just because some OTHER file changed is the stall this avoids.
143599
+ newScanner() {
143600
+ return new ConversationScanner(
143601
+ this.scannerPersistenceDisabled ? { persistent: false } : void 0
143602
+ );
143603
+ }
143566
143604
  async getScanner(skipStaleRescan = false) {
143567
143605
  if (this.scannerReady) {
143568
143606
  await this.scannerReady;
@@ -143579,14 +143617,20 @@ var StreamerServer = class {
143579
143617
  }
143580
143618
  this.scannerStale = false;
143581
143619
  const statCache = this.buildStatCache(this.scanner);
143582
- this.scanner = new ConversationScanner();
143620
+ this.scanner = this.newScanner();
143583
143621
  this.allScanners.add(this.scanner);
143584
143622
  this.scannerReady = this.scanner.scan({
143585
143623
  ...this.scanProfiles ? { profiles: this.scanProfiles } : {},
143586
143624
  ...this.codexScanOpts(),
143587
143625
  ...statCache ? { statCache } : {}
143588
143626
  });
143589
- await this.scannerReady;
143627
+ try {
143628
+ await this.scannerReady;
143629
+ } catch (err) {
143630
+ this.scanner = null;
143631
+ this.scannerReady = null;
143632
+ throw err;
143633
+ }
143590
143634
  const scanner = this.scanner;
143591
143635
  if (!scanner) return this.getScanner();
143592
143636
  return scanner;
@@ -143641,7 +143685,7 @@ var StreamerServer = class {
143641
143685
  const filePath2 = this.findJsonlPath(uuid3);
143642
143686
  if (filePath2) {
143643
143687
  const account = this.cache?.getMetaById(uuid3)?.account ?? void 0;
143644
- const coldScanner = this.scanner ?? new ConversationScanner();
143688
+ const coldScanner = this.scanner ?? this.newScanner();
143645
143689
  const page = await coldScanner.parseSingleFilePage(filePath2, account, {
143646
143690
  limit: Number.MAX_SAFE_INTEGER
143647
143691
  });
@@ -144123,6 +144167,7 @@ var StreamerServer = class {
144123
144167
  type: "permission",
144124
144168
  sessionId,
144125
144169
  ...gate.prompt ? { prompt: gate.prompt } : {},
144170
+ ...gate.detail ? { detail: gate.detail } : {},
144126
144171
  options: gate.options,
144127
144172
  ...gate.cursor !== void 0 ? { cursor: gate.cursor } : {}
144128
144173
  });