@threadbase-sh/scanner 0.9.0 → 0.9.2
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.js +41 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +40 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +40 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1361,7 +1361,7 @@ var import_fs7 = require("fs");
|
|
|
1361
1361
|
var import_path6 = require("path");
|
|
1362
1362
|
|
|
1363
1363
|
// src/persistent/schema.ts
|
|
1364
|
-
var SCHEMA_VERSION =
|
|
1364
|
+
var SCHEMA_VERSION = 4;
|
|
1365
1365
|
var SCHEMA_SQL = `
|
|
1366
1366
|
CREATE TABLE IF NOT EXISTS conversation_files (
|
|
1367
1367
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -2528,10 +2528,21 @@ var ConversationScanner = class {
|
|
|
2528
2528
|
dbPath;
|
|
2529
2529
|
sidecarEnabled;
|
|
2530
2530
|
engineInstance = null;
|
|
2531
|
+
// The most recent scan()'s promise while it is still running, or null when
|
|
2532
|
+
// idle. close() awaits it before closing the SQLite handle so a fire-and-
|
|
2533
|
+
// forget scan can't have its DB shut mid-indexAll ("database connection is
|
|
2534
|
+
// not open"). Tracks the latest scan only — concurrent scans on one instance
|
|
2535
|
+
// aren't a supported pattern (a single writer DB), and the latest resolving
|
|
2536
|
+
// implies earlier ones already settled in practice.
|
|
2537
|
+
inFlightScan = null;
|
|
2531
2538
|
emitter = new import_events.EventEmitter();
|
|
2532
2539
|
watcher = null;
|
|
2533
2540
|
queue = null;
|
|
2534
2541
|
periodicTimer = null;
|
|
2542
|
+
// The in-flight periodicReconcile() job, if one is mid-run. unwatch() awaits
|
|
2543
|
+
// it before dropping the queue/engine so its post-await engine.files access
|
|
2544
|
+
// can't hit a closed DB (the watch-mode half of Bug #4).
|
|
2545
|
+
inFlightReconcile = null;
|
|
2535
2546
|
constructor(options) {
|
|
2536
2547
|
this.conversationLRU = new LRUCache(options?.conversationCacheSize ?? 5);
|
|
2537
2548
|
if (options?.persistent === false) {
|
|
@@ -2554,14 +2565,31 @@ var ConversationScanner = class {
|
|
|
2554
2565
|
return this.engineInstance;
|
|
2555
2566
|
}
|
|
2556
2567
|
// Release the SQLite connection. No-op in legacy mode. Safe to call
|
|
2557
|
-
// repeatedly.
|
|
2558
|
-
//
|
|
2559
|
-
close()
|
|
2560
|
-
|
|
2568
|
+
// repeatedly. Awaits watcher teardown AND any in-flight scan before closing
|
|
2569
|
+
// the DB handle, so a fire-and-forget scan() can never have its connection
|
|
2570
|
+
// shut mid-indexAll() ("database connection is not open"). This is why close()
|
|
2571
|
+
// is async — callers should await it during shutdown. (Scanner review Bug #4.)
|
|
2572
|
+
async close() {
|
|
2573
|
+
if (this.watcher || this.queue || this.periodicTimer) await this.unwatch();
|
|
2574
|
+
if (this.inFlightScan) {
|
|
2575
|
+
try {
|
|
2576
|
+
await this.inFlightScan;
|
|
2577
|
+
} catch {
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2561
2580
|
this.engineInstance?.close();
|
|
2562
2581
|
this.engineInstance = null;
|
|
2563
2582
|
}
|
|
2564
2583
|
async scan(options = {}) {
|
|
2584
|
+
const promise = this.runScan(options);
|
|
2585
|
+
this.inFlightScan = promise;
|
|
2586
|
+
try {
|
|
2587
|
+
return await promise;
|
|
2588
|
+
} finally {
|
|
2589
|
+
if (this.inFlightScan === promise) this.inFlightScan = null;
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
async runScan(options) {
|
|
2565
2593
|
const profiles = await this.resolveProfiles(options.profiles);
|
|
2566
2594
|
const activeProfiles = profiles.filter((p) => p.enabled && p.scanHistory !== false);
|
|
2567
2595
|
this.lastTier = resolveTier(options.tier ?? "standard", options.tiers);
|
|
@@ -2997,7 +3025,10 @@ var ConversationScanner = class {
|
|
|
2997
3025
|
const periodicMs = options.periodicMs ?? 6e4;
|
|
2998
3026
|
if (periodicMs > 0) {
|
|
2999
3027
|
this.periodicTimer = setInterval(() => {
|
|
3000
|
-
|
|
3028
|
+
const job = this.periodicReconcile(activeProfiles).finally(() => {
|
|
3029
|
+
if (this.inFlightReconcile === job) this.inFlightReconcile = null;
|
|
3030
|
+
});
|
|
3031
|
+
this.inFlightReconcile = job;
|
|
3001
3032
|
}, periodicMs);
|
|
3002
3033
|
this.periodicTimer.unref?.();
|
|
3003
3034
|
}
|
|
@@ -3041,6 +3072,9 @@ var ConversationScanner = class {
|
|
|
3041
3072
|
clearInterval(this.periodicTimer);
|
|
3042
3073
|
this.periodicTimer = null;
|
|
3043
3074
|
}
|
|
3075
|
+
if (this.inFlightReconcile) {
|
|
3076
|
+
await this.inFlightReconcile;
|
|
3077
|
+
}
|
|
3044
3078
|
if (this.watcher) {
|
|
3045
3079
|
await this.watcher.stop();
|
|
3046
3080
|
this.watcher = null;
|