@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/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Command } from "commander";
|
|
|
5
5
|
import pino2 from "pino";
|
|
6
6
|
|
|
7
7
|
// package.json
|
|
8
|
-
var version = "0.9.
|
|
8
|
+
var version = "0.9.2";
|
|
9
9
|
|
|
10
10
|
// src/logger.ts
|
|
11
11
|
import pino from "pino";
|
|
@@ -1220,7 +1220,7 @@ import { mkdirSync } from "fs";
|
|
|
1220
1220
|
import { dirname as dirname3 } from "path";
|
|
1221
1221
|
|
|
1222
1222
|
// src/persistent/schema.ts
|
|
1223
|
-
var SCHEMA_VERSION =
|
|
1223
|
+
var SCHEMA_VERSION = 4;
|
|
1224
1224
|
var SCHEMA_SQL = `
|
|
1225
1225
|
CREATE TABLE IF NOT EXISTS conversation_files (
|
|
1226
1226
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -2456,10 +2456,21 @@ var ConversationScanner = class {
|
|
|
2456
2456
|
dbPath;
|
|
2457
2457
|
sidecarEnabled;
|
|
2458
2458
|
engineInstance = null;
|
|
2459
|
+
// The most recent scan()'s promise while it is still running, or null when
|
|
2460
|
+
// idle. close() awaits it before closing the SQLite handle so a fire-and-
|
|
2461
|
+
// forget scan can't have its DB shut mid-indexAll ("database connection is
|
|
2462
|
+
// not open"). Tracks the latest scan only — concurrent scans on one instance
|
|
2463
|
+
// aren't a supported pattern (a single writer DB), and the latest resolving
|
|
2464
|
+
// implies earlier ones already settled in practice.
|
|
2465
|
+
inFlightScan = null;
|
|
2459
2466
|
emitter = new EventEmitter();
|
|
2460
2467
|
watcher = null;
|
|
2461
2468
|
queue = null;
|
|
2462
2469
|
periodicTimer = null;
|
|
2470
|
+
// The in-flight periodicReconcile() job, if one is mid-run. unwatch() awaits
|
|
2471
|
+
// it before dropping the queue/engine so its post-await engine.files access
|
|
2472
|
+
// can't hit a closed DB (the watch-mode half of Bug #4).
|
|
2473
|
+
inFlightReconcile = null;
|
|
2463
2474
|
constructor(options) {
|
|
2464
2475
|
this.conversationLRU = new LRUCache(options?.conversationCacheSize ?? 5);
|
|
2465
2476
|
if (options?.persistent === false) {
|
|
@@ -2482,14 +2493,31 @@ var ConversationScanner = class {
|
|
|
2482
2493
|
return this.engineInstance;
|
|
2483
2494
|
}
|
|
2484
2495
|
// Release the SQLite connection. No-op in legacy mode. Safe to call
|
|
2485
|
-
// repeatedly.
|
|
2486
|
-
//
|
|
2487
|
-
close()
|
|
2488
|
-
|
|
2496
|
+
// repeatedly. Awaits watcher teardown AND any in-flight scan before closing
|
|
2497
|
+
// the DB handle, so a fire-and-forget scan() can never have its connection
|
|
2498
|
+
// shut mid-indexAll() ("database connection is not open"). This is why close()
|
|
2499
|
+
// is async — callers should await it during shutdown. (Scanner review Bug #4.)
|
|
2500
|
+
async close() {
|
|
2501
|
+
if (this.watcher || this.queue || this.periodicTimer) await this.unwatch();
|
|
2502
|
+
if (this.inFlightScan) {
|
|
2503
|
+
try {
|
|
2504
|
+
await this.inFlightScan;
|
|
2505
|
+
} catch {
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2489
2508
|
this.engineInstance?.close();
|
|
2490
2509
|
this.engineInstance = null;
|
|
2491
2510
|
}
|
|
2492
2511
|
async scan(options = {}) {
|
|
2512
|
+
const promise = this.runScan(options);
|
|
2513
|
+
this.inFlightScan = promise;
|
|
2514
|
+
try {
|
|
2515
|
+
return await promise;
|
|
2516
|
+
} finally {
|
|
2517
|
+
if (this.inFlightScan === promise) this.inFlightScan = null;
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
async runScan(options) {
|
|
2493
2521
|
const profiles = await this.resolveProfiles(options.profiles);
|
|
2494
2522
|
const activeProfiles = profiles.filter((p) => p.enabled && p.scanHistory !== false);
|
|
2495
2523
|
this.lastTier = resolveTier(options.tier ?? "standard", options.tiers);
|
|
@@ -2925,7 +2953,10 @@ var ConversationScanner = class {
|
|
|
2925
2953
|
const periodicMs = options.periodicMs ?? 6e4;
|
|
2926
2954
|
if (periodicMs > 0) {
|
|
2927
2955
|
this.periodicTimer = setInterval(() => {
|
|
2928
|
-
|
|
2956
|
+
const job = this.periodicReconcile(activeProfiles).finally(() => {
|
|
2957
|
+
if (this.inFlightReconcile === job) this.inFlightReconcile = null;
|
|
2958
|
+
});
|
|
2959
|
+
this.inFlightReconcile = job;
|
|
2929
2960
|
}, periodicMs);
|
|
2930
2961
|
this.periodicTimer.unref?.();
|
|
2931
2962
|
}
|
|
@@ -2969,6 +3000,9 @@ var ConversationScanner = class {
|
|
|
2969
3000
|
clearInterval(this.periodicTimer);
|
|
2970
3001
|
this.periodicTimer = null;
|
|
2971
3002
|
}
|
|
3003
|
+
if (this.inFlightReconcile) {
|
|
3004
|
+
await this.inFlightReconcile;
|
|
3005
|
+
}
|
|
2972
3006
|
if (this.watcher) {
|
|
2973
3007
|
await this.watcher.stop();
|
|
2974
3008
|
this.watcher = null;
|