@threadbase-sh/streamer 1.59.0 → 1.60.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.
package/dist/index.js CHANGED
@@ -6934,7 +6934,7 @@ var ConversationCache = class _ConversationCache {
6934
6934
  "SELECT id, project_path, project_id, last_activity FROM conversation_meta WHERE project_path IS NOT NULL"
6935
6935
  ),
6936
6936
  hasOrphanProjectId: db.prepare(
6937
- "SELECT 1 FROM conversation_meta WHERE project_id IS NULL AND project_path IS NOT NULL LIMIT 1"
6937
+ "SELECT 1 FROM conversation_meta WHERE project_id IS NULL AND project_path IS NOT NULL AND project_path != '' LIMIT 1"
6938
6938
  ),
6939
6939
  popularProjects: db.prepare(
6940
6940
  `SELECT project_path, project_name, COUNT(*) as cnt
@@ -7531,10 +7531,11 @@ var ConversationCache = class _ConversationCache {
7531
7531
  continue;
7532
7532
  }
7533
7533
  const scannerMetaJson = JSON.stringify(m);
7534
+ const projectPath = m.projectPath?.trim() || null;
7534
7535
  this.stmts.upsertFull.run({
7535
7536
  id,
7536
7537
  file_path: canonicalPath,
7537
- project_path: m.projectPath ?? null,
7538
+ project_path: projectPath,
7538
7539
  project_name: m.projectName ?? null,
7539
7540
  title: m.title ?? m.sessionName ?? m.projectName ?? null,
7540
7541
  model: m.model ?? null,
@@ -11992,7 +11993,7 @@ function isScannedSnapshotStale(snapshotTimestamp, fileMtimeMs) {
11992
11993
 
11993
11994
  // src/scanner-manager.ts
11994
11995
  var REFRESH_TTL_MS = 2e3;
11995
- var ScannerManager = class {
11996
+ var ScannerManager = class _ScannerManager {
11996
11997
  constructor(deps) {
11997
11998
  this.deps = deps;
11998
11999
  this.persistenceDisabled = deps.persistenceDisabled;
@@ -12013,6 +12014,12 @@ var ScannerManager = class {
12013
12014
  allScanners = /* @__PURE__ */ new Set();
12014
12015
  stalePaths = /* @__PURE__ */ new Set();
12015
12016
  reconcileInFlight = null;
12017
+ lastAutoFullReconcileAt = 0;
12018
+ // reconcileMode() returns "full" on every poll while a permanent drift
12019
+ // condition holds (e.g. an orphan row) — without a cooldown each poll
12020
+ // re-walks the whole corpus back-to-back. refresh=1 and per-file
12021
+ // reconciles go through other paths and are unaffected.
12022
+ static AUTO_FULL_RECONCILE_COOLDOWN_MS = 6e4;
12016
12023
  refreshInFlight = /* @__PURE__ */ new Map();
12017
12024
  log = getLogger("server");
12018
12025
  /**
@@ -12329,6 +12336,13 @@ var ScannerManager = class {
12329
12336
  // in-flight cache write before shutting the DB.
12330
12337
  startBackgroundReconcile(mode = "full") {
12331
12338
  if (this.reconcileInFlight) return;
12339
+ if (mode === "full") {
12340
+ const now = Date.now();
12341
+ if (now - this.lastAutoFullReconcileAt < _ScannerManager.AUTO_FULL_RECONCILE_COOLDOWN_MS) {
12342
+ return;
12343
+ }
12344
+ this.lastAutoFullReconcileAt = now;
12345
+ }
12332
12346
  const paths = mode === "files" ? this.takeStaleFiles() : [];
12333
12347
  const task = (paths.length > 0 ? this.reconcileStaleFilesFromDisk(paths) : this.reconcileFromDisk()).finally(() => {
12334
12348
  this.reconcileInFlight = null;