crispy-recall 0.1.6 → 0.2.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/recall.js CHANGED
@@ -858,9 +858,9 @@ var require_pump = __commonJS({
858
858
  "node_modules/pump/index.js"(exports2, module2) {
859
859
  var once = require_once();
860
860
  var eos = require_end_of_stream();
861
- var fs3;
861
+ var fs5;
862
862
  try {
863
- fs3 = require("fs");
863
+ fs5 = require("fs");
864
864
  } catch (e2) {
865
865
  }
866
866
  var noop = function() {
@@ -872,9 +872,9 @@ var require_pump = __commonJS({
872
872
  var isFS = function(stream2) {
873
873
  if (!ancient)
874
874
  return false;
875
- if (!fs3)
875
+ if (!fs5)
876
876
  return false;
877
- return (stream2 instanceof (fs3.ReadStream || noop) || stream2 instanceof (fs3.WriteStream || noop)) && isFn(stream2.close);
877
+ return (stream2 instanceof (fs5.ReadStream || noop) || stream2 instanceof (fs5.WriteStream || noop)) && isFn(stream2.close);
878
878
  };
879
879
  var isRequest = function(stream2) {
880
880
  return stream2.setHeader && isFn(stream2.abort);
@@ -1098,7 +1098,7 @@ var require_pend = __commonJS({
1098
1098
  // node_modules/fd-slicer/index.js
1099
1099
  var require_fd_slicer = __commonJS({
1100
1100
  "node_modules/fd-slicer/index.js"(exports2) {
1101
- var fs3 = require("fs");
1101
+ var fs5 = require("fs");
1102
1102
  var util = require("util");
1103
1103
  var stream2 = require("stream");
1104
1104
  var Readable = stream2.Readable;
@@ -1123,7 +1123,7 @@ var require_fd_slicer = __commonJS({
1123
1123
  FdSlicer.prototype.read = function(buffer, offset2, length, position, callback) {
1124
1124
  var self = this;
1125
1125
  self.pend.go(function(cb) {
1126
- fs3.read(self.fd, buffer, offset2, length, position, function(err, bytesRead, buffer2) {
1126
+ fs5.read(self.fd, buffer, offset2, length, position, function(err, bytesRead, buffer2) {
1127
1127
  cb();
1128
1128
  callback(err, bytesRead, buffer2);
1129
1129
  });
@@ -1132,7 +1132,7 @@ var require_fd_slicer = __commonJS({
1132
1132
  FdSlicer.prototype.write = function(buffer, offset2, length, position, callback) {
1133
1133
  var self = this;
1134
1134
  self.pend.go(function(cb) {
1135
- fs3.write(self.fd, buffer, offset2, length, position, function(err, written, buffer2) {
1135
+ fs5.write(self.fd, buffer, offset2, length, position, function(err, written, buffer2) {
1136
1136
  cb();
1137
1137
  callback(err, written, buffer2);
1138
1138
  });
@@ -1155,7 +1155,7 @@ var require_fd_slicer = __commonJS({
1155
1155
  if (self.refCount < 0)
1156
1156
  throw new Error("invalid unref");
1157
1157
  if (self.autoClose) {
1158
- fs3.close(self.fd, onCloseDone);
1158
+ fs5.close(self.fd, onCloseDone);
1159
1159
  }
1160
1160
  function onCloseDone(err) {
1161
1161
  if (err) {
@@ -1194,7 +1194,7 @@ var require_fd_slicer = __commonJS({
1194
1194
  if (self.destroyed)
1195
1195
  return cb();
1196
1196
  var buffer = new Buffer(toRead);
1197
- fs3.read(self.context.fd, buffer, 0, toRead, self.pos, function(err, bytesRead) {
1197
+ fs5.read(self.context.fd, buffer, 0, toRead, self.pos, function(err, bytesRead) {
1198
1198
  if (err) {
1199
1199
  self.destroy(err);
1200
1200
  } else if (bytesRead === 0) {
@@ -1244,7 +1244,7 @@ var require_fd_slicer = __commonJS({
1244
1244
  self.context.pend.go(function(cb) {
1245
1245
  if (self.destroyed)
1246
1246
  return cb();
1247
- fs3.write(self.context.fd, buffer, 0, buffer.length, self.pos, function(err2, bytes) {
1247
+ fs5.write(self.context.fd, buffer, 0, buffer.length, self.pos, function(err2, bytes) {
1248
1248
  if (err2) {
1249
1249
  self.destroy();
1250
1250
  cb();
@@ -1673,7 +1673,7 @@ var require_buffer_crc32 = __commonJS({
1673
1673
  // node_modules/yauzl/index.js
1674
1674
  var require_yauzl = __commonJS({
1675
1675
  "node_modules/yauzl/index.js"(exports2) {
1676
- var fs3 = require("fs");
1676
+ var fs5 = require("fs");
1677
1677
  var zlib = require("zlib");
1678
1678
  var fd_slicer = require_fd_slicer();
1679
1679
  var crc32 = require_buffer_crc32();
@@ -1691,7 +1691,7 @@ var require_yauzl = __commonJS({
1691
1691
  exports2.ZipFile = ZipFile;
1692
1692
  exports2.Entry = Entry;
1693
1693
  exports2.RandomAccessReader = RandomAccessReader;
1694
- function open(path3, options, callback) {
1694
+ function open(path4, options, callback) {
1695
1695
  if (typeof options === "function") {
1696
1696
  callback = options;
1697
1697
  options = null;
@@ -1710,12 +1710,12 @@ var require_yauzl = __commonJS({
1710
1710
  options.strictFileNames = false;
1711
1711
  if (callback == null)
1712
1712
  callback = defaultCallback;
1713
- fs3.open(path3, "r", function(err, fd) {
1713
+ fs5.open(path4, "r", function(err, fd) {
1714
1714
  if (err)
1715
1715
  return callback(err);
1716
1716
  fromFd(fd, options, function(err2, zipfile) {
1717
1717
  if (err2)
1718
- fs3.close(fd, defaultCallback);
1718
+ fs5.close(fd, defaultCallback);
1719
1719
  callback(err2, zipfile);
1720
1720
  });
1721
1721
  });
@@ -1739,7 +1739,7 @@ var require_yauzl = __commonJS({
1739
1739
  options.strictFileNames = false;
1740
1740
  if (callback == null)
1741
1741
  callback = defaultCallback;
1742
- fs3.fstat(fd, function(err, stats) {
1742
+ fs5.fstat(fd, function(err, stats) {
1743
1743
  if (err)
1744
1744
  return callback(err);
1745
1745
  var reader = fd_slicer.createFromFd(fd, { autoClose: true });
@@ -2375,9 +2375,9 @@ var require_yauzl = __commonJS({
2375
2375
  var require_extract_zip = __commonJS({
2376
2376
  "node_modules/extract-zip/index.js"(exports2, module2) {
2377
2377
  var debug = require_src()("extract-zip");
2378
- var { createWriteStream: createWriteStream3, promises: fs3 } = require("fs");
2378
+ var { createWriteStream: createWriteStream3, promises: fs5 } = require("fs");
2379
2379
  var getStream = require_get_stream();
2380
- var path3 = require("path");
2380
+ var path4 = require("path");
2381
2381
  var { promisify: promisify3 } = require("util");
2382
2382
  var stream2 = require("stream");
2383
2383
  var yauzl = require_yauzl();
@@ -2414,12 +2414,12 @@ var require_extract_zip = __commonJS({
2414
2414
  this.zipfile.readEntry();
2415
2415
  return;
2416
2416
  }
2417
- const destDir = path3.dirname(path3.join(this.opts.dir, entry.fileName));
2417
+ const destDir = path4.dirname(path4.join(this.opts.dir, entry.fileName));
2418
2418
  try {
2419
- await fs3.mkdir(destDir, { recursive: true });
2420
- const canonicalDestDir = await fs3.realpath(destDir);
2421
- const relativeDestDir = path3.relative(this.opts.dir, canonicalDestDir);
2422
- if (relativeDestDir.split(path3.sep).includes("..")) {
2419
+ await fs5.mkdir(destDir, { recursive: true });
2420
+ const canonicalDestDir = await fs5.realpath(destDir);
2421
+ const relativeDestDir = path4.relative(this.opts.dir, canonicalDestDir);
2422
+ if (relativeDestDir.split(path4.sep).includes("..")) {
2423
2423
  throw new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${entry.fileName}`);
2424
2424
  }
2425
2425
  await this.extractEntry(entry);
@@ -2441,7 +2441,7 @@ var require_extract_zip = __commonJS({
2441
2441
  if (this.opts.onEntry) {
2442
2442
  this.opts.onEntry(entry, this.zipfile);
2443
2443
  }
2444
- const dest = path3.join(this.opts.dir, entry.fileName);
2444
+ const dest = path4.join(this.opts.dir, entry.fileName);
2445
2445
  const mode = entry.externalFileAttributes >> 16 & 65535;
2446
2446
  const IFMT2 = 61440;
2447
2447
  const IFDIR2 = 16384;
@@ -2456,13 +2456,13 @@ var require_extract_zip = __commonJS({
2456
2456
  isDir = madeBy === 0 && entry.externalFileAttributes === 16;
2457
2457
  debug("extracting entry", { filename: entry.fileName, isDir, isSymlink: symlink });
2458
2458
  const procMode = this.getExtractedMode(mode, isDir) & 511;
2459
- const destDir = isDir ? dest : path3.dirname(dest);
2459
+ const destDir = isDir ? dest : path4.dirname(dest);
2460
2460
  const mkdirOptions = { recursive: true };
2461
2461
  if (isDir) {
2462
2462
  mkdirOptions.mode = procMode;
2463
2463
  }
2464
2464
  debug("mkdir", { dir: destDir, ...mkdirOptions });
2465
- await fs3.mkdir(destDir, mkdirOptions);
2465
+ await fs5.mkdir(destDir, mkdirOptions);
2466
2466
  if (isDir)
2467
2467
  return;
2468
2468
  debug("opening read stream", dest);
@@ -2470,7 +2470,7 @@ var require_extract_zip = __commonJS({
2470
2470
  if (symlink) {
2471
2471
  const link = await getStream(readStream);
2472
2472
  debug("creating symlink", link, dest);
2473
- await fs3.symlink(link, dest);
2473
+ await fs5.symlink(link, dest);
2474
2474
  } else {
2475
2475
  await pipeline(readStream, createWriteStream3(dest, { mode: procMode }));
2476
2476
  }
@@ -2499,11 +2499,11 @@ var require_extract_zip = __commonJS({
2499
2499
  };
2500
2500
  module2.exports = async function(zipPath, opts) {
2501
2501
  debug("creating target directory", opts.dir);
2502
- if (!path3.isAbsolute(opts.dir)) {
2502
+ if (!path4.isAbsolute(opts.dir)) {
2503
2503
  throw new Error("Target directory is expected to be absolute");
2504
2504
  }
2505
- await fs3.mkdir(opts.dir, { recursive: true });
2506
- opts.dir = await fs3.realpath(opts.dir);
2505
+ await fs5.mkdir(opts.dir, { recursive: true });
2506
+ opts.dir = await fs5.realpath(opts.dir);
2507
2507
  return new Extractor(zipPath, opts).extract();
2508
2508
  };
2509
2509
  }
@@ -2585,11 +2585,11 @@ var init_paths = __esm({
2585
2585
  });
2586
2586
 
2587
2587
  // src/installer/settings-merge.ts
2588
- function writeFileAtomic(path3, contents) {
2589
- const tmp = `${path3}.tmp.${process.pid}`;
2588
+ function writeFileAtomic(path4, contents) {
2589
+ const tmp = `${path4}.tmp.${process.pid}`;
2590
2590
  try {
2591
2591
  (0, import_node_fs2.writeFileSync)(tmp, contents);
2592
- (0, import_node_fs2.renameSync)(tmp, path3);
2592
+ (0, import_node_fs2.renameSync)(tmp, path4);
2593
2593
  } catch (err) {
2594
2594
  try {
2595
2595
  if ((0, import_node_fs2.existsSync)(tmp))
@@ -2602,9 +2602,9 @@ function writeFileAtomic(path3, contents) {
2602
2602
  function backupStamp() {
2603
2603
  return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2604
2604
  }
2605
- function backupFile(path3) {
2606
- const dest = `${path3}.bak.${backupStamp()}`;
2607
- (0, import_node_fs2.copyFileSync)(path3, dest);
2605
+ function backupFile(path4) {
2606
+ const dest = `${path4}.bak.${backupStamp()}`;
2607
+ (0, import_node_fs2.copyFileSync)(path4, dest);
2608
2608
  return dest;
2609
2609
  }
2610
2610
  function detectLineEnding(raw2) {
@@ -2653,7 +2653,7 @@ function makeEntry(command) {
2653
2653
  return { matcher: "", hooks: [{ type: "command", command }] };
2654
2654
  }
2655
2655
  function mergeStopHook(filePath, hookScriptPath) {
2656
- const desiredCommand = `node ${hookScriptPath}`;
2656
+ const desiredCommand = `"${process.execPath}" "${hookScriptPath}"`;
2657
2657
  const exists = (0, import_node_fs2.existsSync)(filePath);
2658
2658
  const raw2 = exists ? (0, import_node_fs2.readFileSync)(filePath, "utf-8") : null;
2659
2659
  const obj = raw2 && raw2.trim().length > 0 ? parseTolerant(raw2) : {};
@@ -3409,13 +3409,13 @@ async function retryServer() {
3409
3409
  serverRetryPromise = null;
3410
3410
  }
3411
3411
  }
3412
- function httpPost(socketPath, path3, body, timeoutMs) {
3412
+ function httpPost(socketPath, path4, body, timeoutMs) {
3413
3413
  return new Promise((resolve, reject) => {
3414
3414
  const data = JSON.stringify(body);
3415
3415
  const req = (0, import_node_http.request)(
3416
3416
  {
3417
3417
  socketPath,
3418
- path: path3,
3418
+ path: path4,
3419
3419
  method: "POST",
3420
3420
  headers: {
3421
3421
  "Content-Type": "application/json",
@@ -3749,1418 +3749,842 @@ var init_quantize = __esm({
3749
3749
  }
3750
3750
  });
3751
3751
 
3752
- // node_modules/node-sqlite3-wasm/dist/node-sqlite3-wasm.js
3753
- var require_node_sqlite3_wasm = __commonJS({
3754
- "node_modules/node-sqlite3-wasm/dist/node-sqlite3-wasm.js"(exports2, module2) {
3755
- var Module = typeof Module != "undefined" ? Module : {};
3756
- var ENVIRONMENT_IS_NODE = true;
3757
- var INT32_MIN = -2147483648;
3758
- var INT32_MAX = 2147483647;
3759
- var NULL = 0;
3760
- var SQLITE_OK = 0;
3761
- var SQLITE_ROW = 100;
3762
- var SQLITE_DONE = 101;
3763
- var SQLITE_INTEGER = 1;
3764
- var SQLITE_FLOAT = 2;
3765
- var SQLITE_TEXT = 3;
3766
- var SQLITE_BLOB = 4;
3767
- var SQLITE_NULL = 5;
3768
- var SQLITE_UTF8 = 1;
3769
- var SQLITE_TRANSIENT = -1;
3770
- var SQLITE_DETERMINISTIC = 2048;
3771
- var temp;
3772
- var sqlite3 = {};
3773
- Module.onRuntimeInitialized = () => {
3774
- temp = stackAlloc(4);
3775
- const v2 = null;
3776
- const n = "number";
3777
- const s = "string";
3778
- const n1 = [n];
3779
- const n2 = [n, ...n1];
3780
- const n3 = [n, ...n2];
3781
- const n4 = [n, ...n3];
3782
- const n5 = [n, ...n4];
3783
- const signatures = { open_v2: [n, [s, n, n, s]], exec: [n, n5], errmsg: [s, n1], prepare_v2: [n, n5], close_v2: [n, n1], finalize: [n, n1], reset: [n, n1], clear_bindings: [n, n1], bind_int: [n, n3], bind_int64: [n, n3], bind_double: [n, n3], bind_text: [n, n5], bind_blob: [n, n5], bind_blob64: [n, n5], bind_null: [n, n2], bind_parameter_index: [n, [n, s]], step: [n, n1], column_int64: [n, n2], column_double: [n, n2], column_text: [s, n2], column_blob: [n, n2], column_type: [n, n2], column_name: [s, n2], column_count: [n, n1], column_bytes: [n, n2], last_insert_rowid: [n, n1], changes: [n, n1], create_function_v2: [n, [n, s, n, n, n, n, n, n, n]], value_type: [n, n1], value_text: [s, n1], value_blob: [n, n1], value_int64: [n, n1], value_double: [n, n1], value_bytes: [n, n1], result_double: [v2, n2], result_null: [v2, n1], result_text: [v2, n4], result_blob: [v2, n4], result_blob64: [v2, n4], result_int: [v2, n2], result_int64: [v2, n2], result_error: [v2, n3], column_table_name: [s, n2], get_autocommit: [n, n1] };
3784
- for (const [name, sig] of Object.entries(signatures)) {
3785
- sqlite3[name] = cwrap(`sqlite3_${name}`, sig[0], sig[1]);
3786
- }
3787
- };
3788
- var SQLite3Error = class extends Error {
3789
- constructor(message) {
3790
- super(message);
3791
- this.name = "SQLite3Error";
3752
+ // node_modules/better-sqlite3/lib/util.js
3753
+ var require_util = __commonJS({
3754
+ "node_modules/better-sqlite3/lib/util.js"(exports2) {
3755
+ "use strict";
3756
+ exports2.getBooleanOption = (options, key) => {
3757
+ let value = false;
3758
+ if (key in options && typeof (value = options[key]) !== "boolean") {
3759
+ throw new TypeError(`Expected the "${key}" option to be a boolean`);
3792
3760
  }
3761
+ return value;
3793
3762
  };
3794
- function arrayToHeap(array) {
3795
- const ptr = _malloc(array.byteLength);
3796
- HEAPU8.set(array, ptr);
3797
- return ptr;
3798
- }
3799
- function stringToHeap(str) {
3800
- const size = lengthBytesUTF8(str) + 1;
3801
- const ptr = _malloc(size);
3802
- stringToUTF8(str, ptr, size);
3803
- return ptr;
3804
- }
3805
- function toNumberOrNot(bigInt) {
3806
- if (bigInt >= Number.MIN_SAFE_INTEGER && bigInt <= Number.MAX_SAFE_INTEGER) {
3807
- return Number(bigInt);
3808
- }
3809
- return bigInt;
3810
- }
3811
- function parseFunctionArguments(argc, argv2) {
3812
- const args = [];
3813
- for (let i = 0; i < argc; i++) {
3814
- const ptr = getValue(argv2 + 4 * i, "i32");
3815
- const type = sqlite3.value_type(ptr);
3816
- let arg;
3817
- switch (type) {
3818
- case SQLITE_INTEGER:
3819
- arg = toNumberOrNot(sqlite3.value_int64(ptr));
3820
- break;
3821
- case SQLITE_FLOAT:
3822
- arg = sqlite3.value_double(ptr);
3823
- break;
3824
- case SQLITE_TEXT:
3825
- arg = sqlite3.value_text(ptr);
3826
- break;
3827
- case SQLITE_BLOB:
3828
- const p = sqlite3.value_blob(ptr);
3829
- if (p != NULL) {
3830
- arg = HEAPU8.slice(p, p + sqlite3.value_bytes(ptr));
3831
- } else {
3832
- arg = new Uint8Array();
3833
- }
3834
- break;
3835
- case SQLITE_NULL:
3836
- arg = null;
3837
- break;
3838
- }
3839
- args.push(arg);
3840
- }
3841
- return args;
3763
+ exports2.cppdb = Symbol();
3764
+ exports2.inspect = Symbol.for("nodejs.util.inspect.custom");
3765
+ }
3766
+ });
3767
+
3768
+ // node_modules/better-sqlite3/lib/sqlite-error.js
3769
+ var require_sqlite_error = __commonJS({
3770
+ "node_modules/better-sqlite3/lib/sqlite-error.js"(exports2, module2) {
3771
+ "use strict";
3772
+ var descriptor = { value: "SqliteError", writable: true, enumerable: false, configurable: true };
3773
+ function SqliteError(message, code) {
3774
+ if (new.target !== SqliteError) {
3775
+ return new SqliteError(message, code);
3776
+ }
3777
+ if (typeof code !== "string") {
3778
+ throw new TypeError("Expected second argument to be a string");
3779
+ }
3780
+ Error.call(this, message);
3781
+ descriptor.value = "" + message;
3782
+ Object.defineProperty(this, "message", descriptor);
3783
+ Error.captureStackTrace(this, SqliteError);
3784
+ this.code = code;
3842
3785
  }
3843
- function setFunctionResult(cx, result) {
3844
- switch (typeof result) {
3845
- case "boolean":
3846
- sqlite3.result_int(cx, result ? 1 : 0);
3847
- break;
3848
- case "number":
3849
- if (Number.isSafeInteger(result)) {
3850
- if (result >= INT32_MIN && result <= INT32_MAX) {
3851
- sqlite3.result_int(cx, result);
3852
- } else {
3853
- sqlite3.result_int64(cx, BigInt(result));
3854
- }
3855
- } else {
3856
- sqlite3.result_double(cx, result);
3857
- }
3858
- break;
3859
- case "bigint":
3860
- sqlite3.result_int64(cx, result);
3861
- break;
3862
- case "string":
3863
- const tempPtr = stringToHeap(result);
3864
- sqlite3.result_text(cx, tempPtr, -1, SQLITE_TRANSIENT);
3865
- _free(tempPtr);
3866
- break;
3867
- case "object":
3868
- if (result === null) {
3869
- sqlite3.result_null(cx);
3870
- } else if (result instanceof Uint8Array) {
3871
- const tempPtr2 = arrayToHeap(result);
3872
- if (result.byteLength <= INT32_MAX) {
3873
- sqlite3.result_blob(cx, tempPtr2, result.byteLength, SQLITE_TRANSIENT);
3874
- } else {
3875
- sqlite3.result_blob64(cx, tempPtr2, BigInt(result.byteLength), SQLITE_TRANSIENT);
3876
- }
3877
- _free(tempPtr2);
3878
- } else {
3879
- throw new SQLite3Error(`Unsupported type for function result: "${typeof result}"`);
3880
- }
3881
- break;
3882
- default:
3883
- throw new SQLite3Error(`Unsupported type for function result: "${typeof result}"`);
3786
+ Object.setPrototypeOf(SqliteError, Error);
3787
+ Object.setPrototypeOf(SqliteError.prototype, Error.prototype);
3788
+ Object.defineProperty(SqliteError.prototype, "name", descriptor);
3789
+ module2.exports = SqliteError;
3790
+ }
3791
+ });
3792
+
3793
+ // node_modules/file-uri-to-path/index.js
3794
+ var require_file_uri_to_path = __commonJS({
3795
+ "node_modules/file-uri-to-path/index.js"(exports2, module2) {
3796
+ var sep2 = require("path").sep || "/";
3797
+ module2.exports = fileUriToPath;
3798
+ function fileUriToPath(uri) {
3799
+ if ("string" != typeof uri || uri.length <= 7 || "file://" != uri.substring(0, 7)) {
3800
+ throw new TypeError("must pass in a file:// URI to convert to a file path");
3801
+ }
3802
+ var rest = decodeURI(uri.substring(7));
3803
+ var firstSlash = rest.indexOf("/");
3804
+ var host = rest.substring(0, firstSlash);
3805
+ var path4 = rest.substring(firstSlash + 1);
3806
+ if ("localhost" == host)
3807
+ host = "";
3808
+ if (host) {
3809
+ host = sep2 + sep2 + host;
3810
+ }
3811
+ path4 = path4.replace(/^(.+)\|/, "$1:");
3812
+ if (sep2 == "\\") {
3813
+ path4 = path4.replace(/\//g, "\\");
3814
+ }
3815
+ if (/^.+\:/.test(path4)) {
3816
+ } else {
3817
+ path4 = sep2 + path4;
3884
3818
  }
3819
+ return host + path4;
3885
3820
  }
3886
- var Database = class {
3887
- constructor(filename, { fileMustExist = false, readOnly = false } = {}) {
3888
- let flags;
3889
- if (readOnly) {
3890
- flags = SQLITE_OPEN_READONLY;
3891
- } else {
3892
- flags = SQLITE_OPEN_READWRITE;
3893
- if (!fileMustExist)
3894
- flags |= SQLITE_OPEN_CREATE;
3895
- }
3896
- const rc = sqlite3.open_v2(filename, temp, flags, NULL);
3897
- this._ptr = getValue(temp, "i32");
3898
- if (rc !== SQLITE_OK) {
3899
- if (this._ptr !== NULL)
3900
- sqlite3.close_v2(this._ptr);
3901
- throw new SQLite3Error(`Could not open the database "${filename}"`);
3902
- }
3903
- this._functions = /* @__PURE__ */ new Map();
3904
- }
3905
- get isOpen() {
3906
- return this._ptr !== null;
3907
- }
3908
- get inTransaction() {
3909
- this._assertOpen();
3910
- return sqlite3.get_autocommit(this._ptr) === 0;
3911
- }
3912
- close() {
3913
- this._assertOpen();
3914
- for (const func of this._functions.values())
3915
- removeFunction(func);
3916
- this._functions.clear();
3917
- this._handleError(sqlite3.close_v2(this._ptr));
3918
- this._ptr = null;
3919
- }
3920
- function(name, func, { deterministic = false } = {}) {
3921
- this._assertOpen();
3922
- function wrappedFunc(cx, argc, argv2) {
3923
- const args = parseFunctionArguments(argc, argv2);
3924
- let result;
3925
- try {
3926
- result = func.apply(null, args);
3927
- } catch (err2) {
3928
- const tempPtr = stringToHeap(err2.toString());
3929
- sqlite3.result_error(cx, tempPtr, -1);
3930
- _free(tempPtr);
3931
- return;
3932
- }
3933
- setFunctionResult(cx, result);
3934
- }
3935
- if (this._functions.has(name)) {
3936
- removeFunction(this._functions.get(name));
3937
- this._functions.delete(name);
3938
- }
3939
- const funcPtr = addFunction(wrappedFunc, "viii");
3940
- this._functions.set(name, funcPtr);
3941
- let eTextRep = SQLITE_UTF8;
3942
- if (deterministic)
3943
- eTextRep |= SQLITE_DETERMINISTIC;
3944
- this._handleError(sqlite3.create_function_v2(this._ptr, name, func.length, eTextRep, NULL, funcPtr, NULL, NULL, NULL));
3945
- return this;
3946
- }
3947
- exec(sql) {
3948
- this._assertOpen();
3949
- const tempPtr = stringToHeap(sql);
3950
- try {
3951
- this._handleError(sqlite3.exec(this._ptr, tempPtr, NULL, NULL, NULL));
3952
- } finally {
3953
- _free(tempPtr);
3954
- }
3955
- }
3956
- prepare(sql) {
3957
- this._assertOpen();
3958
- return new Statement(this, sql);
3959
- }
3960
- run(sql, values) {
3961
- const stmt = this.prepare(sql);
3962
- try {
3963
- return stmt.run(values);
3964
- } finally {
3965
- stmt.finalize();
3966
- }
3967
- }
3968
- all(sql, values, { expand: expand2 = false } = {}) {
3969
- return this._query(sql, values, false, expand2);
3970
- }
3971
- get(sql, values, { expand: expand2 = false } = {}) {
3972
- return this._query(sql, values, true, expand2);
3973
- }
3974
- _query(sql, values, single, expand2) {
3975
- const stmt = this.prepare(sql);
3976
- try {
3977
- if (single) {
3978
- return stmt.get(values, { expand: expand2 });
3979
- } else {
3980
- return stmt.all(values, { expand: expand2 });
3981
- }
3982
- } finally {
3983
- stmt.finalize();
3984
- }
3985
- }
3986
- _assertOpen() {
3987
- if (!this.isOpen)
3988
- throw new SQLite3Error("Database already closed");
3989
- }
3990
- _handleError(returnCode) {
3991
- if (returnCode !== SQLITE_OK)
3992
- throw new SQLite3Error(sqlite3.errmsg(this._ptr));
3821
+ }
3822
+ });
3823
+
3824
+ // node_modules/bindings/bindings.js
3825
+ var require_bindings = __commonJS({
3826
+ "node_modules/bindings/bindings.js"(exports2, module2) {
3827
+ var fs5 = require("fs");
3828
+ var path4 = require("path");
3829
+ var fileURLToPath3 = require_file_uri_to_path();
3830
+ var join17 = path4.join;
3831
+ var dirname5 = path4.dirname;
3832
+ var exists = fs5.accessSync && function(path5) {
3833
+ try {
3834
+ fs5.accessSync(path5);
3835
+ } catch (e2) {
3836
+ return false;
3993
3837
  }
3838
+ return true;
3839
+ } || fs5.existsSync || path4.existsSync;
3840
+ var defaults2 = {
3841
+ arrow: process.env.NODE_BINDINGS_ARROW || " \u2192 ",
3842
+ compiled: process.env.NODE_BINDINGS_COMPILED_DIR || "compiled",
3843
+ platform: process.platform,
3844
+ arch: process.arch,
3845
+ nodePreGyp: "node-v" + process.versions.modules + "-" + process.platform + "-" + process.arch,
3846
+ version: process.versions.node,
3847
+ bindings: "bindings.node",
3848
+ try: [
3849
+ // node-gyp's linked version in the "build" dir
3850
+ ["module_root", "build", "bindings"],
3851
+ // node-waf and gyp_addon (a.k.a node-gyp)
3852
+ ["module_root", "build", "Debug", "bindings"],
3853
+ ["module_root", "build", "Release", "bindings"],
3854
+ // Debug files, for development (legacy behavior, remove for node v0.9)
3855
+ ["module_root", "out", "Debug", "bindings"],
3856
+ ["module_root", "Debug", "bindings"],
3857
+ // Release files, but manually compiled (legacy behavior, remove for node v0.9)
3858
+ ["module_root", "out", "Release", "bindings"],
3859
+ ["module_root", "Release", "bindings"],
3860
+ // Legacy from node-waf, node <= 0.4.x
3861
+ ["module_root", "build", "default", "bindings"],
3862
+ // Production "Release" buildtype binary (meh...)
3863
+ ["module_root", "compiled", "version", "platform", "arch", "bindings"],
3864
+ // node-qbs builds
3865
+ ["module_root", "addon-build", "release", "install-root", "bindings"],
3866
+ ["module_root", "addon-build", "debug", "install-root", "bindings"],
3867
+ ["module_root", "addon-build", "default", "install-root", "bindings"],
3868
+ // node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch}
3869
+ ["module_root", "lib", "binding", "nodePreGyp", "bindings"]
3870
+ ]
3994
3871
  };
3995
- var Statement = class {
3996
- constructor(db4, sql) {
3997
- const tempPtr = stringToHeap(sql);
3998
- try {
3999
- db4._handleError(sqlite3.prepare_v2(db4._ptr, tempPtr, -1, temp, NULL));
4000
- } finally {
4001
- _free(tempPtr);
4002
- }
4003
- this._ptr = getValue(temp, "i32");
4004
- if (this._ptr === NULL)
4005
- throw new SQLite3Error("Nothing to prepare");
4006
- this._db = db4;
4007
- }
4008
- get database() {
4009
- return this._db;
4010
- }
4011
- get isFinalized() {
4012
- return this._ptr === null;
4013
- }
4014
- run(values) {
4015
- this._assertReady();
4016
- this._bind(values);
4017
- this._step();
4018
- return { changes: sqlite3.changes(this._db._ptr), lastInsertRowid: toNumberOrNot(sqlite3.last_insert_rowid(this._db._ptr)) };
4019
- }
4020
- iterate(values, { expand: expand2 = false } = {}) {
4021
- return this._queryRows(values, expand2);
4022
- }
4023
- all(values, { expand: expand2 = false } = {}) {
4024
- return Array.from(this.iterate(values, { expand: expand2 }));
4025
- }
4026
- get(values, { expand: expand2 = false } = {}) {
4027
- const result = this._queryRows(values, expand2).next();
4028
- return result.done ? null : result.value;
3872
+ function bindings(opts) {
3873
+ if (typeof opts == "string") {
3874
+ opts = { bindings: opts };
3875
+ } else if (!opts) {
3876
+ opts = {};
4029
3877
  }
4030
- finalize() {
4031
- if (this.isFinalized)
4032
- throw new SQLite3Error("Statement already finalized");
3878
+ Object.keys(defaults2).map(function(i2) {
3879
+ if (!(i2 in opts))
3880
+ opts[i2] = defaults2[i2];
3881
+ });
3882
+ if (!opts.module_root) {
3883
+ opts.module_root = exports2.getRoot(exports2.getFileName());
3884
+ }
3885
+ if (path4.extname(opts.bindings) != ".node") {
3886
+ opts.bindings += ".node";
3887
+ }
3888
+ var requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require;
3889
+ var tries = [], i = 0, l2 = opts.try.length, n, b3, err;
3890
+ for (; i < l2; i++) {
3891
+ n = join17.apply(
3892
+ null,
3893
+ opts.try[i].map(function(p) {
3894
+ return opts[p] || p;
3895
+ })
3896
+ );
3897
+ tries.push(n);
4033
3898
  try {
4034
- this._db._handleError(sqlite3.finalize(this._ptr));
4035
- } finally {
4036
- this._ptr = null;
4037
- }
4038
- }
4039
- _reset() {
4040
- return sqlite3.clear_bindings(this._ptr) === SQLITE_OK && sqlite3.reset(this._ptr) === SQLITE_OK;
4041
- }
4042
- *_queryRows(values, expand2) {
4043
- this._assertReady();
4044
- this._bind(values);
4045
- const columns = this._getColumnNames();
4046
- while (this._step())
4047
- yield this._getRow(columns, expand2);
4048
- }
4049
- _bind(values) {
4050
- if (!this._reset()) {
4051
- throw new SQLite3Error("Could not reset statement prior to binding new values");
4052
- }
4053
- if (Array.isArray(values)) {
4054
- this._bindArray(values);
4055
- } else if (values != null && typeof values === "object") {
4056
- this._bindObject(values);
4057
- } else if (typeof values !== "undefined") {
4058
- this._bindValue(values, 1);
4059
- }
4060
- }
4061
- _step() {
4062
- const ret = sqlite3.step(this._ptr);
4063
- switch (ret) {
4064
- case SQLITE_ROW:
4065
- return true;
4066
- case SQLITE_DONE:
4067
- return false;
4068
- default:
4069
- this._db._handleError(ret);
3899
+ b3 = opts.path ? requireFunc.resolve(n) : requireFunc(n);
3900
+ if (!opts.path) {
3901
+ b3.path = n;
3902
+ }
3903
+ return b3;
3904
+ } catch (e2) {
3905
+ if (e2.code !== "MODULE_NOT_FOUND" && e2.code !== "QUALIFIED_PATH_RESOLUTION_FAILED" && !/not find/i.test(e2.message)) {
3906
+ throw e2;
3907
+ }
4070
3908
  }
4071
3909
  }
4072
- _getRow(columns, expand2) {
4073
- const row = {};
4074
- for (let i = 0; i < columns.length; i++) {
4075
- let v2;
4076
- const colType = sqlite3.column_type(this._ptr, i);
4077
- switch (colType) {
4078
- case SQLITE_INTEGER:
4079
- v2 = toNumberOrNot(sqlite3.column_int64(this._ptr, i));
4080
- break;
4081
- case SQLITE_FLOAT:
4082
- v2 = sqlite3.column_double(this._ptr, i);
4083
- break;
4084
- case SQLITE_TEXT:
4085
- v2 = sqlite3.column_text(this._ptr, i);
4086
- break;
4087
- case SQLITE_BLOB:
4088
- const p = sqlite3.column_blob(this._ptr, i);
4089
- if (p != NULL) {
4090
- v2 = HEAPU8.slice(p, p + sqlite3.column_bytes(this._ptr, i));
4091
- } else {
4092
- v2 = new Uint8Array();
3910
+ err = new Error(
3911
+ "Could not locate the bindings file. Tried:\n" + tries.map(function(a3) {
3912
+ return opts.arrow + a3;
3913
+ }).join("\n")
3914
+ );
3915
+ err.tries = tries;
3916
+ throw err;
3917
+ }
3918
+ module2.exports = exports2 = bindings;
3919
+ exports2.getFileName = function getFileName(calling_file) {
3920
+ var origPST = Error.prepareStackTrace, origSTL = Error.stackTraceLimit, dummy = {}, fileName;
3921
+ Error.stackTraceLimit = 10;
3922
+ Error.prepareStackTrace = function(e2, st) {
3923
+ for (var i = 0, l2 = st.length; i < l2; i++) {
3924
+ fileName = st[i].getFileName();
3925
+ if (fileName !== __filename) {
3926
+ if (calling_file) {
3927
+ if (fileName !== calling_file) {
3928
+ return;
4093
3929
  }
4094
- break;
4095
- case SQLITE_NULL:
4096
- v2 = null;
4097
- break;
4098
- }
4099
- const column = columns[i];
4100
- if (expand2) {
4101
- let table = sqlite3.column_table_name(this._ptr, i);
4102
- table = table === "" ? "$" : table;
4103
- if (Object.hasOwn(row, table)) {
4104
- row[table][column] = v2;
4105
3930
  } else {
4106
- row[table] = { [column]: v2 };
3931
+ return;
4107
3932
  }
4108
- } else {
4109
- row[column] = v2;
4110
3933
  }
4111
3934
  }
4112
- return row;
4113
- }
4114
- _getColumnNames() {
4115
- const names = [];
4116
- const columns = sqlite3.column_count(this._ptr);
4117
- for (let i = 0; i < columns; i++)
4118
- names.push(sqlite3.column_name(this._ptr, i));
4119
- return names;
4120
- }
4121
- _bindArray(values) {
4122
- for (let i = 0; i < values.length; i++)
4123
- this._bindValue(values[i], i + 1);
4124
- }
4125
- _bindObject(values) {
4126
- for (const [param, value] of Object.entries(values)) {
4127
- const i = sqlite3.bind_parameter_index(this._ptr, param);
4128
- if (i === 0)
4129
- throw new SQLite3Error(`Unknown binding parameter: "${param}"`);
4130
- this._bindValue(value, i);
4131
- }
4132
- }
4133
- _bindValue(value, position) {
4134
- let ret;
4135
- switch (typeof value) {
4136
- case "string":
4137
- const tempPtr = stringToHeap(value);
4138
- ret = sqlite3.bind_text(this._ptr, position, tempPtr, -1, SQLITE_TRANSIENT);
4139
- _free(tempPtr);
4140
- break;
4141
- case "number":
4142
- if (Number.isSafeInteger(value)) {
4143
- if (value >= INT32_MIN && value <= INT32_MAX) {
4144
- ret = sqlite3.bind_int(this._ptr, position, value);
4145
- } else {
4146
- ret = sqlite3.bind_int64(this._ptr, position, BigInt(value));
4147
- }
4148
- } else {
4149
- ret = sqlite3.bind_double(this._ptr, position, value);
4150
- }
4151
- break;
4152
- case "bigint":
4153
- ret = sqlite3.bind_int64(this._ptr, position, value);
4154
- break;
4155
- case "boolean":
4156
- ret = sqlite3.bind_int(this._ptr, position, value ? 1 : 0);
4157
- break;
4158
- case "object":
4159
- if (value === null) {
4160
- ret = sqlite3.bind_null(this._ptr, position);
4161
- } else if (value instanceof Uint8Array) {
4162
- const tempPtr2 = arrayToHeap(value);
4163
- if (value.byteLength <= INT32_MAX) {
4164
- ret = sqlite3.bind_blob(this._ptr, position, tempPtr2, value.byteLength, SQLITE_TRANSIENT);
4165
- } else {
4166
- ret = sqlite3.bind_blob64(this._ptr, position, tempPtr2, BigInt(value.byteLength), SQLITE_TRANSIENT);
4167
- }
4168
- _free(tempPtr2);
4169
- } else {
4170
- throw new SQLite3Error(`Unsupported type for binding: "${typeof value}"`);
4171
- }
4172
- break;
4173
- default:
4174
- throw new SQLite3Error(`Unsupported type for binding: "${typeof value}"`);
3935
+ };
3936
+ Error.captureStackTrace(dummy);
3937
+ dummy.stack;
3938
+ Error.prepareStackTrace = origPST;
3939
+ Error.stackTraceLimit = origSTL;
3940
+ var fileSchema = "file://";
3941
+ if (fileName.indexOf(fileSchema) === 0) {
3942
+ fileName = fileURLToPath3(fileName);
3943
+ }
3944
+ return fileName;
3945
+ };
3946
+ exports2.getRoot = function getRoot(file) {
3947
+ var dir = dirname5(file), prev;
3948
+ while (true) {
3949
+ if (dir === ".") {
3950
+ dir = process.cwd();
4175
3951
  }
4176
- if (ret !== SQLITE_OK)
4177
- this._db._handleError(ret);
4178
- }
4179
- _assertReady() {
4180
- if (this.isFinalized)
4181
- throw new SQLite3Error("Statement already finalized");
4182
- if (!this._db.isOpen)
4183
- throw new SQLite3Error("Database is closed");
3952
+ if (exists(join17(dir, "package.json")) || exists(join17(dir, "node_modules"))) {
3953
+ return dir;
3954
+ }
3955
+ if (prev === dir) {
3956
+ throw new Error(
3957
+ 'Could not find module root given file: "' + file + '". Do you have a `package.json` file? '
3958
+ );
3959
+ }
3960
+ prev = dir;
3961
+ dir = join17(dir, "..");
4184
3962
  }
4185
3963
  };
4186
- Module.Database = Database;
4187
- Module.SQLite3Error = SQLite3Error;
4188
- var path3 = require("node:path");
4189
- var crypto = require("node:crypto");
4190
- var SQLITE_CANTOPEN = 14;
4191
- var SQLITE_IOERR_READ = 266;
4192
- var SQLITE_IOERR_SHORT_READ = 522;
4193
- var SQLITE_IOERR_FSYNC = 1034;
4194
- var SQLITE_IOERR_WRITE = 778;
4195
- var SQLITE_IOERR_DELETE = 2570;
4196
- var SQLITE_IOERR_CLOSE = 4106;
4197
- var SQLITE_IOERR_TRUNCATE = 1546;
4198
- var SQLITE_IOERR_FSTAT = 1802;
4199
- var SQLITE_IOERR_LOCK = 3850;
4200
- var SQLITE_IOERR_UNLOCK = 2058;
4201
- var SQLITE_OPEN_READONLY = 1;
4202
- var SQLITE_OPEN_READWRITE = 2;
4203
- var SQLITE_OPEN_CREATE = 4;
4204
- var SQLITE_OPEN_EXCLUSIVE = 16;
4205
- var SQLITE_ACCESS_READWRITE = 1;
4206
- var SQLITE_ACCESS_READ = 2;
4207
- var SQLITE_LOCK_NONE = 0;
4208
- var SQLITE_BUSY = 5;
4209
- function _fd(fileInfo) {
4210
- return getValue(fileInfo + 4, "i32");
4211
- }
4212
- function _isLocked(fileInfo) {
4213
- return getValue(fileInfo + 8, "i32") != 0;
4214
- }
4215
- function _setLocked(fileInfo, locked) {
4216
- setValue(fileInfo + 8, locked ? 1 : 0, "i32");
4217
- }
4218
- function _path(fileInfo) {
4219
- return UTF8ToString(getValue(fileInfo + 12, "i32"));
4220
- }
4221
- function _safeInt(bigInt) {
4222
- if (bigInt < Number.MIN_SAFE_INTEGER || bigInt > Number.MAX_SAFE_INTEGER)
4223
- throw 0;
4224
- return Number(bigInt);
4225
- }
4226
- var arguments_ = [];
4227
- var thisProgram = "./this.program";
4228
- var quit_ = (status2, toThrow) => {
4229
- throw toThrow;
3964
+ }
3965
+ });
3966
+
3967
+ // node_modules/better-sqlite3/lib/methods/wrappers.js
3968
+ var require_wrappers = __commonJS({
3969
+ "node_modules/better-sqlite3/lib/methods/wrappers.js"(exports2) {
3970
+ "use strict";
3971
+ var { cppdb } = require_util();
3972
+ exports2.prepare = function prepare(sql) {
3973
+ return this[cppdb].prepare(sql, this, false);
4230
3974
  };
4231
- var _scriptName;
4232
- if (typeof __filename != "undefined") {
4233
- _scriptName = __filename;
4234
- } else {
4235
- }
4236
- var scriptDirectory = "";
4237
- function locateFile(path4) {
4238
- if (Module["locateFile"]) {
4239
- return Module["locateFile"](path4, scriptDirectory);
4240
- }
4241
- return scriptDirectory + path4;
4242
- }
4243
- var readAsync;
4244
- var readBinary;
4245
- if (ENVIRONMENT_IS_NODE) {
4246
- fs3 = require("node:fs");
4247
- scriptDirectory = __dirname + "/";
4248
- readBinary = (filename) => {
4249
- filename = isFileURI(filename) ? new URL(filename) : filename;
4250
- var ret = fs3.readFileSync(filename);
4251
- return ret;
4252
- };
4253
- readAsync = async (filename, binary = true) => {
4254
- filename = isFileURI(filename) ? new URL(filename) : filename;
4255
- var ret = fs3.readFileSync(filename, binary ? void 0 : "utf8");
4256
- return ret;
4257
- };
4258
- if (process.argv.length > 1) {
4259
- thisProgram = process.argv[1].replace(/\\/g, "/");
4260
- }
4261
- arguments_ = process.argv.slice(2);
4262
- if (typeof module2 != "undefined") {
4263
- module2["exports"] = Module;
4264
- }
4265
- quit_ = (status2, toThrow) => {
4266
- process.exitCode = status2;
4267
- throw toThrow;
4268
- };
4269
- } else {
4270
- }
4271
- var fs3;
4272
- var out = console.log.bind(console);
4273
- var err = console.error.bind(console);
4274
- var wasmBinary;
4275
- var ABORT2 = false;
4276
- var EXITSTATUS;
4277
- var isFileURI = (filename) => filename.startsWith("file://");
4278
- var runtimeInitialized = false;
4279
- function updateMemoryViews() {
4280
- var b3 = wasmMemory.buffer;
4281
- HEAP8 = new Int8Array(b3);
4282
- HEAP16 = new Int16Array(b3);
4283
- HEAPU8 = new Uint8Array(b3);
4284
- HEAPU16 = new Uint16Array(b3);
4285
- HEAP32 = new Int32Array(b3);
4286
- HEAPU32 = new Uint32Array(b3);
4287
- HEAPF32 = new Float32Array(b3);
4288
- HEAPF64 = new Float64Array(b3);
4289
- HEAP64 = new BigInt64Array(b3);
4290
- HEAPU64 = new BigUint64Array(b3);
4291
- }
4292
- function preRun() {
4293
- if (Module["preRun"]) {
4294
- if (typeof Module["preRun"] == "function")
4295
- Module["preRun"] = [Module["preRun"]];
4296
- while (Module["preRun"].length) {
4297
- addOnPreRun(Module["preRun"].shift());
4298
- }
4299
- }
4300
- callRuntimeCallbacks(onPreRuns);
4301
- }
4302
- function initRuntime() {
4303
- runtimeInitialized = true;
4304
- wasmExports["z"]();
4305
- }
4306
- function postRun() {
4307
- if (Module["postRun"]) {
4308
- if (typeof Module["postRun"] == "function")
4309
- Module["postRun"] = [Module["postRun"]];
4310
- while (Module["postRun"].length) {
4311
- addOnPostRun(Module["postRun"].shift());
4312
- }
4313
- }
4314
- callRuntimeCallbacks(onPostRuns);
4315
- }
4316
- function abort(what) {
4317
- Module["onAbort"]?.(what);
4318
- what = `Aborted(${what})`;
4319
- err(what);
4320
- ABORT2 = true;
4321
- what += ". Build with -sASSERTIONS for more info.";
4322
- var e2 = new WebAssembly.RuntimeError(what);
4323
- throw e2;
4324
- }
4325
- var wasmBinaryFile;
4326
- function findWasmBinary() {
4327
- return locateFile("node-sqlite3-wasm.wasm");
4328
- }
4329
- function getBinarySync(file) {
4330
- if (file == wasmBinaryFile && wasmBinary) {
4331
- return new Uint8Array(wasmBinary);
4332
- }
4333
- if (readBinary) {
4334
- return readBinary(file);
4335
- }
4336
- throw 'sync fetching of the wasm failed: you can preload it to Module["wasmBinary"] manually, or emcc.py will do that for you when generating HTML (but not JS)';
4337
- }
4338
- function instantiateSync(file, info) {
4339
- var module3;
4340
- var binary = getBinarySync(file);
4341
- module3 = new WebAssembly.Module(binary);
4342
- var instance = new WebAssembly.Instance(module3, info);
4343
- return [instance, module3];
4344
- }
4345
- function getWasmImports() {
4346
- var imports = { a: wasmImports };
4347
- return imports;
4348
- }
4349
- function createWasm() {
4350
- function receiveInstance(instance, module3) {
4351
- wasmExports = instance.exports;
4352
- assignWasmExports(wasmExports);
4353
- updateMemoryViews();
4354
- return wasmExports;
4355
- }
4356
- var info = getWasmImports();
4357
- if (Module["instantiateWasm"]) {
4358
- return new Promise((resolve, reject) => {
4359
- Module["instantiateWasm"](info, (inst, mod) => {
4360
- resolve(receiveInstance(inst, mod));
4361
- });
4362
- });
4363
- }
4364
- wasmBinaryFile ??= findWasmBinary();
4365
- var result = instantiateSync(wasmBinaryFile, info);
4366
- return receiveInstance(result[0]);
4367
- }
4368
- var ExitStatus = class {
4369
- name = "ExitStatus";
4370
- constructor(status2) {
4371
- this.message = `Program terminated with exit(${status2})`;
4372
- this.status = status2;
4373
- }
3975
+ exports2.exec = function exec(sql) {
3976
+ this[cppdb].exec(sql);
3977
+ return this;
4374
3978
  };
4375
- var HEAP16;
4376
- var HEAP32;
4377
- var HEAP64;
4378
- var HEAP8;
4379
- var HEAPF32;
4380
- var HEAPF64;
4381
- var HEAPU16;
4382
- var HEAPU32;
4383
- var HEAPU64;
4384
- var HEAPU8;
4385
- var callRuntimeCallbacks = (callbacks) => {
4386
- while (callbacks.length > 0) {
4387
- callbacks.shift()(Module);
4388
- }
3979
+ exports2.close = function close() {
3980
+ this[cppdb].close();
3981
+ return this;
4389
3982
  };
4390
- var onPostRuns = [];
4391
- var addOnPostRun = (cb) => onPostRuns.push(cb);
4392
- var onPreRuns = [];
4393
- var addOnPreRun = (cb) => onPreRuns.push(cb);
4394
- function getValue(ptr, type = "i8") {
4395
- if (type.endsWith("*"))
4396
- type = "*";
4397
- switch (type) {
4398
- case "i1":
4399
- return HEAP8[ptr];
4400
- case "i8":
4401
- return HEAP8[ptr];
4402
- case "i16":
4403
- return HEAP16[ptr >> 1];
4404
- case "i32":
4405
- return HEAP32[ptr >> 2];
4406
- case "i64":
4407
- return HEAP64[ptr >> 3];
4408
- case "float":
4409
- return HEAPF32[ptr >> 2];
4410
- case "double":
4411
- return HEAPF64[ptr >> 3];
4412
- case "*":
4413
- return HEAPU32[ptr >> 2];
4414
- default:
4415
- abort(`invalid type for getValue: ${type}`);
4416
- }
4417
- }
4418
- var noExitRuntime = true;
4419
- function setValue(ptr, value, type = "i8") {
4420
- if (type.endsWith("*"))
4421
- type = "*";
4422
- switch (type) {
4423
- case "i1":
4424
- HEAP8[ptr] = value;
4425
- break;
4426
- case "i8":
4427
- HEAP8[ptr] = value;
4428
- break;
4429
- case "i16":
4430
- HEAP16[ptr >> 1] = value;
4431
- break;
4432
- case "i32":
4433
- HEAP32[ptr >> 2] = value;
4434
- break;
4435
- case "i64":
4436
- HEAP64[ptr >> 3] = BigInt(value);
4437
- break;
4438
- case "float":
4439
- HEAPF32[ptr >> 2] = value;
4440
- break;
4441
- case "double":
4442
- HEAPF64[ptr >> 3] = value;
4443
- break;
4444
- case "*":
4445
- HEAPU32[ptr >> 2] = value;
4446
- break;
4447
- default:
4448
- abort(`invalid type for setValue: ${type}`);
4449
- }
4450
- }
4451
- var stackRestore = (val) => __emscripten_stack_restore(val);
4452
- var stackSave = () => _emscripten_stack_get_current();
4453
- var __abort_js = () => abort("");
4454
- var runtimeKeepaliveCounter = 0;
4455
- var __emscripten_runtime_keepalive_clear = () => {
4456
- noExitRuntime = false;
4457
- runtimeKeepaliveCounter = 0;
3983
+ exports2.loadExtension = function loadExtension(...args) {
3984
+ this[cppdb].loadExtension(...args);
3985
+ return this;
4458
3986
  };
4459
- var isLeapYear = (year) => year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
4460
- var MONTH_DAYS_LEAP_CUMULATIVE = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335];
4461
- var MONTH_DAYS_REGULAR_CUMULATIVE = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
4462
- var ydayFromDate = (date) => {
4463
- var leap = isLeapYear(date.getFullYear());
4464
- var monthDaysCumulative = leap ? MONTH_DAYS_LEAP_CUMULATIVE : MONTH_DAYS_REGULAR_CUMULATIVE;
4465
- var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1;
4466
- return yday;
3987
+ exports2.defaultSafeIntegers = function defaultSafeIntegers(...args) {
3988
+ this[cppdb].defaultSafeIntegers(...args);
3989
+ return this;
4467
3990
  };
4468
- var INT53_MAX = 9007199254740992;
4469
- var INT53_MIN = -9007199254740992;
4470
- var bigintToI53Checked = (num) => num < INT53_MIN || num > INT53_MAX ? NaN : Number(num);
4471
- function __localtime_js(time, tmPtr) {
4472
- time = bigintToI53Checked(time);
4473
- var date = new Date(time * 1e3);
4474
- HEAP32[tmPtr >> 2] = date.getSeconds();
4475
- HEAP32[tmPtr + 4 >> 2] = date.getMinutes();
4476
- HEAP32[tmPtr + 8 >> 2] = date.getHours();
4477
- HEAP32[tmPtr + 12 >> 2] = date.getDate();
4478
- HEAP32[tmPtr + 16 >> 2] = date.getMonth();
4479
- HEAP32[tmPtr + 20 >> 2] = date.getFullYear() - 1900;
4480
- HEAP32[tmPtr + 24 >> 2] = date.getDay();
4481
- var yday = ydayFromDate(date) | 0;
4482
- HEAP32[tmPtr + 28 >> 2] = yday;
4483
- HEAP32[tmPtr + 36 >> 2] = -(date.getTimezoneOffset() * 60);
4484
- var start = new Date(date.getFullYear(), 0, 1);
4485
- var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
4486
- var winterOffset = start.getTimezoneOffset();
4487
- var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0;
4488
- HEAP32[tmPtr + 32 >> 2] = dst;
4489
- }
4490
- var timers = {};
4491
- var handleException = (e2) => {
4492
- if (e2 instanceof ExitStatus || e2 == "unwind") {
4493
- return EXITSTATUS;
4494
- }
4495
- quit_(1, e2);
3991
+ exports2.unsafeMode = function unsafeMode(...args) {
3992
+ this[cppdb].unsafeMode(...args);
3993
+ return this;
4496
3994
  };
4497
- var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
4498
- var _proc_exit = (code) => {
4499
- EXITSTATUS = code;
4500
- if (!keepRuntimeAlive()) {
4501
- Module["onExit"]?.(code);
4502
- ABORT2 = true;
4503
- }
4504
- quit_(code, new ExitStatus(code));
3995
+ exports2.getters = {
3996
+ name: {
3997
+ get: function name() {
3998
+ return this[cppdb].name;
3999
+ },
4000
+ enumerable: true
4001
+ },
4002
+ open: {
4003
+ get: function open() {
4004
+ return this[cppdb].open;
4005
+ },
4006
+ enumerable: true
4007
+ },
4008
+ inTransaction: {
4009
+ get: function inTransaction() {
4010
+ return this[cppdb].inTransaction;
4011
+ },
4012
+ enumerable: true
4013
+ },
4014
+ readonly: {
4015
+ get: function readonly() {
4016
+ return this[cppdb].readonly;
4017
+ },
4018
+ enumerable: true
4019
+ },
4020
+ memory: {
4021
+ get: function memory() {
4022
+ return this[cppdb].memory;
4023
+ },
4024
+ enumerable: true
4025
+ }
4505
4026
  };
4506
- var exitJS = (status2, implicit) => {
4507
- EXITSTATUS = status2;
4508
- _proc_exit(status2);
4027
+ }
4028
+ });
4029
+
4030
+ // node_modules/better-sqlite3/lib/methods/transaction.js
4031
+ var require_transaction = __commonJS({
4032
+ "node_modules/better-sqlite3/lib/methods/transaction.js"(exports2, module2) {
4033
+ "use strict";
4034
+ var { cppdb } = require_util();
4035
+ var controllers = /* @__PURE__ */ new WeakMap();
4036
+ module2.exports = function transaction(fn) {
4037
+ if (typeof fn !== "function")
4038
+ throw new TypeError("Expected first argument to be a function");
4039
+ const db4 = this[cppdb];
4040
+ const controller = getController(db4, this);
4041
+ const { apply } = Function.prototype;
4042
+ const properties = {
4043
+ default: { value: wrapTransaction(apply, fn, db4, controller.default) },
4044
+ deferred: { value: wrapTransaction(apply, fn, db4, controller.deferred) },
4045
+ immediate: { value: wrapTransaction(apply, fn, db4, controller.immediate) },
4046
+ exclusive: { value: wrapTransaction(apply, fn, db4, controller.exclusive) },
4047
+ database: { value: this, enumerable: true }
4048
+ };
4049
+ Object.defineProperties(properties.default.value, properties);
4050
+ Object.defineProperties(properties.deferred.value, properties);
4051
+ Object.defineProperties(properties.immediate.value, properties);
4052
+ Object.defineProperties(properties.exclusive.value, properties);
4053
+ return properties.default.value;
4509
4054
  };
4510
- var _exit = exitJS;
4511
- var maybeExit = () => {
4512
- if (!keepRuntimeAlive()) {
4513
- try {
4514
- _exit(EXITSTATUS);
4515
- } catch (e2) {
4516
- handleException(e2);
4517
- }
4055
+ var getController = (db4, self) => {
4056
+ let controller = controllers.get(db4);
4057
+ if (!controller) {
4058
+ const shared = {
4059
+ commit: db4.prepare("COMMIT", self, false),
4060
+ rollback: db4.prepare("ROLLBACK", self, false),
4061
+ savepoint: db4.prepare("SAVEPOINT ` _bs3. `", self, false),
4062
+ release: db4.prepare("RELEASE ` _bs3. `", self, false),
4063
+ rollbackTo: db4.prepare("ROLLBACK TO ` _bs3. `", self, false)
4064
+ };
4065
+ controllers.set(db4, controller = {
4066
+ default: Object.assign({ begin: db4.prepare("BEGIN", self, false) }, shared),
4067
+ deferred: Object.assign({ begin: db4.prepare("BEGIN DEFERRED", self, false) }, shared),
4068
+ immediate: Object.assign({ begin: db4.prepare("BEGIN IMMEDIATE", self, false) }, shared),
4069
+ exclusive: Object.assign({ begin: db4.prepare("BEGIN EXCLUSIVE", self, false) }, shared)
4070
+ });
4518
4071
  }
4072
+ return controller;
4519
4073
  };
4520
- var callUserCallback = (func) => {
4521
- if (ABORT2) {
4522
- return;
4074
+ var wrapTransaction = (apply, fn, db4, { begin, commit, rollback, savepoint, release, rollbackTo }) => function sqliteTransaction() {
4075
+ let before, after, undo;
4076
+ if (db4.inTransaction) {
4077
+ before = savepoint;
4078
+ after = release;
4079
+ undo = rollbackTo;
4080
+ } else {
4081
+ before = begin;
4082
+ after = commit;
4083
+ undo = rollback;
4523
4084
  }
4085
+ before.run();
4524
4086
  try {
4525
- return func();
4526
- } catch (e2) {
4527
- handleException(e2);
4528
- } finally {
4529
- maybeExit();
4087
+ const result = apply.call(fn, this, arguments);
4088
+ if (result && typeof result.then === "function") {
4089
+ throw new TypeError("Transaction function cannot return a promise");
4090
+ }
4091
+ after.run();
4092
+ return result;
4093
+ } catch (ex) {
4094
+ if (db4.inTransaction) {
4095
+ undo.run();
4096
+ if (undo !== rollback)
4097
+ after.run();
4098
+ }
4099
+ throw ex;
4530
4100
  }
4531
4101
  };
4532
- var _emscripten_get_now = () => performance.now();
4533
- var __setitimer_js = (which, timeout_ms) => {
4534
- if (timers[which]) {
4535
- clearTimeout(timers[which].id);
4536
- delete timers[which];
4537
- }
4538
- if (!timeout_ms)
4539
- return 0;
4540
- var id = setTimeout(() => {
4541
- delete timers[which];
4542
- callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now()));
4543
- }, timeout_ms);
4544
- timers[which] = { id, timeout_ms };
4545
- return 0;
4102
+ }
4103
+ });
4104
+
4105
+ // node_modules/better-sqlite3/lib/methods/pragma.js
4106
+ var require_pragma = __commonJS({
4107
+ "node_modules/better-sqlite3/lib/methods/pragma.js"(exports2, module2) {
4108
+ "use strict";
4109
+ var { getBooleanOption, cppdb } = require_util();
4110
+ module2.exports = function pragma(source, options) {
4111
+ if (options == null)
4112
+ options = {};
4113
+ if (typeof source !== "string")
4114
+ throw new TypeError("Expected first argument to be a string");
4115
+ if (typeof options !== "object")
4116
+ throw new TypeError("Expected second argument to be an options object");
4117
+ const simple = getBooleanOption(options, "simple");
4118
+ const stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true);
4119
+ return simple ? stmt.pluck().get() : stmt.all();
4546
4120
  };
4547
- var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
4548
- if (!(maxBytesToWrite > 0))
4549
- return 0;
4550
- var startIdx = outIdx;
4551
- var endIdx = outIdx + maxBytesToWrite - 1;
4552
- for (var i = 0; i < str.length; ++i) {
4553
- var u = str.codePointAt(i);
4554
- if (u <= 127) {
4555
- if (outIdx >= endIdx)
4556
- break;
4557
- heap[outIdx++] = u;
4558
- } else if (u <= 2047) {
4559
- if (outIdx + 1 >= endIdx)
4560
- break;
4561
- heap[outIdx++] = 192 | u >> 6;
4562
- heap[outIdx++] = 128 | u & 63;
4563
- } else if (u <= 65535) {
4564
- if (outIdx + 2 >= endIdx)
4565
- break;
4566
- heap[outIdx++] = 224 | u >> 12;
4567
- heap[outIdx++] = 128 | u >> 6 & 63;
4568
- heap[outIdx++] = 128 | u & 63;
4569
- } else {
4570
- if (outIdx + 3 >= endIdx)
4571
- break;
4572
- heap[outIdx++] = 240 | u >> 18;
4573
- heap[outIdx++] = 128 | u >> 12 & 63;
4574
- heap[outIdx++] = 128 | u >> 6 & 63;
4575
- heap[outIdx++] = 128 | u & 63;
4576
- i++;
4577
- }
4578
- }
4579
- heap[outIdx] = 0;
4580
- return outIdx - startIdx;
4121
+ }
4122
+ });
4123
+
4124
+ // node_modules/better-sqlite3/lib/methods/backup.js
4125
+ var require_backup = __commonJS({
4126
+ "node_modules/better-sqlite3/lib/methods/backup.js"(exports2, module2) {
4127
+ "use strict";
4128
+ var fs5 = require("fs");
4129
+ var path4 = require("path");
4130
+ var { promisify: promisify3 } = require("util");
4131
+ var { cppdb } = require_util();
4132
+ var fsAccess = promisify3(fs5.access);
4133
+ module2.exports = async function backup(filename, options) {
4134
+ if (options == null)
4135
+ options = {};
4136
+ if (typeof filename !== "string")
4137
+ throw new TypeError("Expected first argument to be a string");
4138
+ if (typeof options !== "object")
4139
+ throw new TypeError("Expected second argument to be an options object");
4140
+ filename = filename.trim();
4141
+ const attachedName = "attached" in options ? options.attached : "main";
4142
+ const handler = "progress" in options ? options.progress : null;
4143
+ if (!filename)
4144
+ throw new TypeError("Backup filename cannot be an empty string");
4145
+ if (filename === ":memory:")
4146
+ throw new TypeError('Invalid backup filename ":memory:"');
4147
+ if (typeof attachedName !== "string")
4148
+ throw new TypeError('Expected the "attached" option to be a string');
4149
+ if (!attachedName)
4150
+ throw new TypeError('The "attached" option cannot be an empty string');
4151
+ if (handler != null && typeof handler !== "function")
4152
+ throw new TypeError('Expected the "progress" option to be a function');
4153
+ await fsAccess(path4.dirname(filename)).catch(() => {
4154
+ throw new TypeError("Cannot save backup because the directory does not exist");
4155
+ });
4156
+ const isNewFile = await fsAccess(filename).then(() => false, () => true);
4157
+ return runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);
4581
4158
  };
4582
- var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
4583
- var __tzset_js = (timezone, daylight, std_name, dst_name) => {
4584
- var currentYear = (/* @__PURE__ */ new Date()).getFullYear();
4585
- var winter = new Date(currentYear, 0, 1);
4586
- var summer = new Date(currentYear, 6, 1);
4587
- var winterOffset = winter.getTimezoneOffset();
4588
- var summerOffset = summer.getTimezoneOffset();
4589
- var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
4590
- HEAPU32[timezone >> 2] = stdTimezoneOffset * 60;
4591
- HEAP32[daylight >> 2] = Number(winterOffset != summerOffset);
4592
- var extractZone = (timezoneOffset) => {
4593
- var sign = timezoneOffset >= 0 ? "-" : "+";
4594
- var absOffset = Math.abs(timezoneOffset);
4595
- var hours = String(Math.floor(absOffset / 60)).padStart(2, "0");
4596
- var minutes = String(absOffset % 60).padStart(2, "0");
4597
- return `UTC${sign}${hours}${minutes}`;
4598
- };
4599
- var winterName = extractZone(winterOffset);
4600
- var summerName = extractZone(summerOffset);
4601
- if (summerOffset < winterOffset) {
4602
- stringToUTF8(winterName, std_name, 17);
4603
- stringToUTF8(summerName, dst_name, 17);
4604
- } else {
4605
- stringToUTF8(winterName, dst_name, 17);
4606
- stringToUTF8(summerName, std_name, 17);
4607
- }
4159
+ var runBackup = (backup, handler) => {
4160
+ let rate = 0;
4161
+ let useDefault = true;
4162
+ return new Promise((resolve, reject) => {
4163
+ setImmediate(function step() {
4164
+ try {
4165
+ const progress = backup.transfer(rate);
4166
+ if (!progress.remainingPages) {
4167
+ backup.close();
4168
+ resolve(progress);
4169
+ return;
4170
+ }
4171
+ if (useDefault) {
4172
+ useDefault = false;
4173
+ rate = 100;
4174
+ }
4175
+ if (handler) {
4176
+ const ret = handler(progress);
4177
+ if (ret !== void 0) {
4178
+ if (typeof ret === "number" && ret === ret)
4179
+ rate = Math.max(0, Math.min(2147483647, Math.round(ret)));
4180
+ else
4181
+ throw new TypeError("Expected progress callback to return a number or undefined");
4182
+ }
4183
+ }
4184
+ setImmediate(step);
4185
+ } catch (err) {
4186
+ backup.close();
4187
+ reject(err);
4188
+ }
4189
+ });
4190
+ });
4608
4191
  };
4609
- var _emscripten_date_now = () => Date.now();
4610
- var getHeapMax = () => 2147483648;
4611
- var alignMemory = (size, alignment) => Math.ceil(size / alignment) * alignment;
4612
- var growMemory = (size) => {
4613
- var oldHeapSize = wasmMemory.buffer.byteLength;
4614
- var pages = (size - oldHeapSize + 65535) / 65536 | 0;
4615
- try {
4616
- wasmMemory.grow(pages);
4617
- updateMemoryViews();
4618
- return 1;
4619
- } catch (e2) {
4620
- }
4192
+ }
4193
+ });
4194
+
4195
+ // node_modules/better-sqlite3/lib/methods/serialize.js
4196
+ var require_serialize = __commonJS({
4197
+ "node_modules/better-sqlite3/lib/methods/serialize.js"(exports2, module2) {
4198
+ "use strict";
4199
+ var { cppdb } = require_util();
4200
+ module2.exports = function serialize2(options) {
4201
+ if (options == null)
4202
+ options = {};
4203
+ if (typeof options !== "object")
4204
+ throw new TypeError("Expected first argument to be an options object");
4205
+ const attachedName = "attached" in options ? options.attached : "main";
4206
+ if (typeof attachedName !== "string")
4207
+ throw new TypeError('Expected the "attached" option to be a string');
4208
+ if (!attachedName)
4209
+ throw new TypeError('The "attached" option cannot be an empty string');
4210
+ return this[cppdb].serialize(attachedName);
4621
4211
  };
4622
- var _emscripten_resize_heap = (requestedSize) => {
4623
- var oldSize = HEAPU8.length;
4624
- requestedSize >>>= 0;
4625
- var maxHeapSize = getHeapMax();
4626
- if (requestedSize > maxHeapSize) {
4627
- return false;
4628
- }
4629
- for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
4630
- var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown);
4631
- overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
4632
- var newSize = Math.min(maxHeapSize, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536));
4633
- var replacement = growMemory(newSize);
4634
- if (replacement) {
4635
- return true;
4636
- }
4212
+ }
4213
+ });
4214
+
4215
+ // node_modules/better-sqlite3/lib/methods/function.js
4216
+ var require_function = __commonJS({
4217
+ "node_modules/better-sqlite3/lib/methods/function.js"(exports2, module2) {
4218
+ "use strict";
4219
+ var { getBooleanOption, cppdb } = require_util();
4220
+ module2.exports = function defineFunction(name, options, fn) {
4221
+ if (options == null)
4222
+ options = {};
4223
+ if (typeof options === "function") {
4224
+ fn = options;
4225
+ options = {};
4637
4226
  }
4638
- return false;
4227
+ if (typeof name !== "string")
4228
+ throw new TypeError("Expected first argument to be a string");
4229
+ if (typeof fn !== "function")
4230
+ throw new TypeError("Expected last argument to be a function");
4231
+ if (typeof options !== "object")
4232
+ throw new TypeError("Expected second argument to be an options object");
4233
+ if (!name)
4234
+ throw new TypeError("User-defined function name cannot be an empty string");
4235
+ const safeIntegers = "safeIntegers" in options ? +getBooleanOption(options, "safeIntegers") : 2;
4236
+ const deterministic = getBooleanOption(options, "deterministic");
4237
+ const directOnly = getBooleanOption(options, "directOnly");
4238
+ const varargs = getBooleanOption(options, "varargs");
4239
+ let argCount = -1;
4240
+ if (!varargs) {
4241
+ argCount = fn.length;
4242
+ if (!Number.isInteger(argCount) || argCount < 0)
4243
+ throw new TypeError("Expected function.length to be a positive integer");
4244
+ if (argCount > 100)
4245
+ throw new RangeError("User-defined functions cannot have more than 100 arguments");
4246
+ }
4247
+ this[cppdb].function(fn, name, argCount, safeIntegers, deterministic, directOnly);
4248
+ return this;
4639
4249
  };
4640
- var UTF8Decoder = globalThis.TextDecoder && new TextDecoder();
4641
- var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
4642
- var maxIdx = idx + maxBytesToRead;
4643
- if (ignoreNul)
4644
- return maxIdx;
4645
- while (heapOrArray[idx] && !(idx >= maxIdx))
4646
- ++idx;
4647
- return idx;
4250
+ }
4251
+ });
4252
+
4253
+ // node_modules/better-sqlite3/lib/methods/aggregate.js
4254
+ var require_aggregate = __commonJS({
4255
+ "node_modules/better-sqlite3/lib/methods/aggregate.js"(exports2, module2) {
4256
+ "use strict";
4257
+ var { getBooleanOption, cppdb } = require_util();
4258
+ module2.exports = function defineAggregate(name, options) {
4259
+ if (typeof name !== "string")
4260
+ throw new TypeError("Expected first argument to be a string");
4261
+ if (typeof options !== "object" || options === null)
4262
+ throw new TypeError("Expected second argument to be an options object");
4263
+ if (!name)
4264
+ throw new TypeError("User-defined function name cannot be an empty string");
4265
+ const start = "start" in options ? options.start : null;
4266
+ const step = getFunctionOption(options, "step", true);
4267
+ const inverse = getFunctionOption(options, "inverse", false);
4268
+ const result = getFunctionOption(options, "result", false);
4269
+ const safeIntegers = "safeIntegers" in options ? +getBooleanOption(options, "safeIntegers") : 2;
4270
+ const deterministic = getBooleanOption(options, "deterministic");
4271
+ const directOnly = getBooleanOption(options, "directOnly");
4272
+ const varargs = getBooleanOption(options, "varargs");
4273
+ let argCount = -1;
4274
+ if (!varargs) {
4275
+ argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);
4276
+ if (argCount > 0)
4277
+ argCount -= 1;
4278
+ if (argCount > 100)
4279
+ throw new RangeError("User-defined functions cannot have more than 100 arguments");
4280
+ }
4281
+ this[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic, directOnly);
4282
+ return this;
4648
4283
  };
4649
- var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => {
4650
- var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul);
4651
- if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
4652
- return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
4653
- }
4654
- var str = "";
4655
- while (idx < endPtr) {
4656
- var u0 = heapOrArray[idx++];
4657
- if (!(u0 & 128)) {
4658
- str += String.fromCharCode(u0);
4659
- continue;
4660
- }
4661
- var u1 = heapOrArray[idx++] & 63;
4662
- if ((u0 & 224) == 192) {
4663
- str += String.fromCharCode((u0 & 31) << 6 | u1);
4664
- continue;
4665
- }
4666
- var u2 = heapOrArray[idx++] & 63;
4667
- if ((u0 & 240) == 224) {
4668
- u0 = (u0 & 15) << 12 | u1 << 6 | u2;
4669
- } else {
4670
- u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63;
4671
- }
4672
- if (u0 < 65536) {
4673
- str += String.fromCharCode(u0);
4674
- } else {
4675
- var ch = u0 - 65536;
4676
- str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
4677
- }
4678
- }
4679
- return str;
4284
+ var getFunctionOption = (options, key, required) => {
4285
+ const value = key in options ? options[key] : null;
4286
+ if (typeof value === "function")
4287
+ return value;
4288
+ if (value != null)
4289
+ throw new TypeError(`Expected the "${key}" option to be a function`);
4290
+ if (required)
4291
+ throw new TypeError(`Missing required option "${key}"`);
4292
+ return null;
4680
4293
  };
4681
- var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead, ignoreNul) : "";
4682
- function _nodejsAccess(vfs, filePath, flags, outResult) {
4683
- let aflags = fs3.constants.F_OK;
4684
- if (flags == SQLITE_ACCESS_READWRITE)
4685
- aflags = fs3.constants.R_OK | fs3.constants.W_OK;
4686
- if (flags == SQLITE_ACCESS_READ)
4687
- aflags = fs3.constants.R_OK;
4688
- try {
4689
- fs3.accessSync(UTF8ToString(filePath), aflags);
4690
- setValue(outResult, 1, "i32");
4691
- } catch {
4692
- setValue(outResult, 0, "i32");
4294
+ var getLength = ({ length }) => {
4295
+ if (Number.isInteger(length) && length >= 0)
4296
+ return length;
4297
+ throw new TypeError("Expected function.length to be a positive integer");
4298
+ };
4299
+ }
4300
+ });
4301
+
4302
+ // node_modules/better-sqlite3/lib/methods/table.js
4303
+ var require_table = __commonJS({
4304
+ "node_modules/better-sqlite3/lib/methods/table.js"(exports2, module2) {
4305
+ "use strict";
4306
+ var { cppdb } = require_util();
4307
+ module2.exports = function defineTable(name, factory) {
4308
+ if (typeof name !== "string")
4309
+ throw new TypeError("Expected first argument to be a string");
4310
+ if (!name)
4311
+ throw new TypeError("Virtual table module name cannot be an empty string");
4312
+ let eponymous = false;
4313
+ if (typeof factory === "object" && factory !== null) {
4314
+ eponymous = true;
4315
+ factory = defer2(parseTableDefinition(factory, "used", name));
4316
+ } else {
4317
+ if (typeof factory !== "function")
4318
+ throw new TypeError("Expected second argument to be a function or a table definition object");
4319
+ factory = wrapFactory(factory);
4693
4320
  }
4694
- return SQLITE_OK;
4321
+ this[cppdb].table(factory, name, eponymous);
4322
+ return this;
4323
+ };
4324
+ function wrapFactory(factory) {
4325
+ return function virtualTableFactory(moduleName, databaseName, tableName, ...args) {
4326
+ const thisObject = {
4327
+ module: moduleName,
4328
+ database: databaseName,
4329
+ table: tableName
4330
+ };
4331
+ const def = apply.call(factory, thisObject, args);
4332
+ if (typeof def !== "object" || def === null) {
4333
+ throw new TypeError(`Virtual table module "${moduleName}" did not return a table definition object`);
4334
+ }
4335
+ return parseTableDefinition(def, "returned", moduleName);
4336
+ };
4695
4337
  }
4696
- function _nodejsCheckReservedLock(fi, outResult) {
4697
- try {
4698
- fs3.accessSync(`${_path(fi)}.lock`, fs3.constants.F_OK);
4699
- setValue(outResult, 1, "i32");
4700
- } catch {
4701
- setValue(outResult, 0, "i32");
4338
+ function parseTableDefinition(def, verb, moduleName) {
4339
+ if (!hasOwnProperty.call(def, "rows")) {
4340
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "rows" property`);
4702
4341
  }
4703
- return SQLITE_OK;
4704
- }
4705
- function _nodejsClose(fi) {
4706
- _nodejsUnlock(fi, SQLITE_LOCK_NONE);
4707
- try {
4708
- fs3.closeSync(_fd(fi));
4709
- } catch {
4710
- return SQLITE_IOERR_CLOSE;
4342
+ if (!hasOwnProperty.call(def, "columns")) {
4343
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "columns" property`);
4711
4344
  }
4712
- return SQLITE_OK;
4713
- }
4714
- function _nodejsDelete(vfs, filePath, dirSync) {
4715
- const pathStr = UTF8ToString(filePath);
4716
- try {
4717
- fs3.unlinkSync(pathStr);
4718
- } catch (err2) {
4719
- if (err2.code != "ENOENT")
4720
- return SQLITE_IOERR_DELETE;
4345
+ const rows = def.rows;
4346
+ if (typeof rows !== "function" || Object.getPrototypeOf(rows) !== GeneratorFunctionPrototype) {
4347
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "rows" property (should be a generator function)`);
4721
4348
  }
4722
- if (dirSync) {
4723
- let fd = -1;
4724
- try {
4725
- fd = fs3.openSync(path3.dirname(pathStr), "r");
4726
- fs3.fsyncSync(fd);
4727
- } catch {
4728
- return SQLITE_IOERR_FSYNC;
4729
- } finally {
4730
- try {
4731
- fs3.closeSync(fd);
4732
- } catch {
4733
- return SQLITE_IOERR_FSYNC;
4734
- }
4735
- }
4349
+ let columns = def.columns;
4350
+ if (!Array.isArray(columns) || !(columns = [...columns]).every((x3) => typeof x3 === "string")) {
4351
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "columns" property (should be an array of strings)`);
4736
4352
  }
4737
- return SQLITE_OK;
4738
- }
4739
- function _nodejsFileSize(fi, outSize) {
4740
- try {
4741
- setValue(outSize, fs3.fstatSync(_fd(fi)).size, "i64");
4742
- } catch {
4743
- return SQLITE_IOERR_FSTAT;
4353
+ if (columns.length !== new Set(columns).size) {
4354
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate column names`);
4744
4355
  }
4745
- return SQLITE_OK;
4746
- }
4747
- function _nodejsFullPathname(vfs, relPath, sizeFullPath, outFullPath) {
4748
- const full = path3.resolve(UTF8ToString(relPath));
4749
- stringToUTF8(full, outFullPath, sizeFullPath);
4750
- return full.length < sizeFullPath ? SQLITE_OK : SQLITE_CANTOPEN;
4751
- }
4752
- function _nodejsLock(fi, level) {
4753
- if (!_isLocked(fi)) {
4754
- try {
4755
- fs3.mkdirSync(`${_path(fi)}.lock`);
4756
- } catch (err2) {
4757
- return err2.code == "EEXIST" ? SQLITE_BUSY : SQLITE_IOERR_LOCK;
4758
- }
4759
- _setLocked(fi, true);
4760
- }
4761
- return SQLITE_OK;
4762
- }
4763
- function _nodejsRandomness(vfs, bytes, outBuffer) {
4764
- const buf = HEAPU8.subarray(outBuffer, outBuffer + bytes);
4765
- crypto.randomFillSync(buf);
4766
- return bytes;
4767
- }
4768
- function _nodejsRead(fi, outBuffer, bytes, offset2) {
4769
- const buf = HEAPU8.subarray(outBuffer, outBuffer + bytes);
4770
- let bytesRead;
4771
- try {
4772
- bytesRead = fs3.readSync(_fd(fi), buf, 0, bytes, offset2);
4773
- } catch {
4774
- return SQLITE_IOERR_READ;
4356
+ if (!columns.length) {
4357
+ throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with zero columns`);
4775
4358
  }
4776
- if (bytesRead == bytes) {
4777
- return SQLITE_OK;
4778
- } else if (bytesRead >= 0) {
4779
- if (bytesRead < bytes) {
4780
- try {
4781
- buf.fill(0, bytesRead);
4782
- } catch {
4783
- return SQLITE_IOERR_READ;
4784
- }
4359
+ let parameters;
4360
+ if (hasOwnProperty.call(def, "parameters")) {
4361
+ parameters = def.parameters;
4362
+ if (!Array.isArray(parameters) || !(parameters = [...parameters]).every((x3) => typeof x3 === "string")) {
4363
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "parameters" property (should be an array of strings)`);
4785
4364
  }
4786
- return SQLITE_IOERR_SHORT_READ;
4365
+ } else {
4366
+ parameters = inferParameters(rows);
4787
4367
  }
4788
- return SQLITE_IOERR_READ;
4789
- }
4790
- function _nodejsSync(fi, flags) {
4791
- try {
4792
- fs3.fsyncSync(_fd(fi));
4793
- } catch {
4794
- return SQLITE_IOERR_FSYNC;
4368
+ if (parameters.length !== new Set(parameters).size) {
4369
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate parameter names`);
4795
4370
  }
4796
- return SQLITE_OK;
4797
- }
4798
- function _nodejsTruncate(fi, size) {
4799
- try {
4800
- fs3.ftruncateSync(_fd(fi), _safeInt(size));
4801
- } catch {
4802
- return SQLITE_IOERR_TRUNCATE;
4371
+ if (parameters.length > 32) {
4372
+ throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with more than the maximum number of 32 parameters`);
4803
4373
  }
4804
- return SQLITE_OK;
4805
- }
4806
- function _nodejsUnlock(fi, level) {
4807
- if (level == SQLITE_LOCK_NONE && _isLocked(fi)) {
4808
- try {
4809
- fs3.rmdirSync(`${_path(fi)}.lock`);
4810
- } catch (err2) {
4811
- if (err2.code != "ENOENT")
4812
- return SQLITE_IOERR_UNLOCK;
4374
+ for (const parameter of parameters) {
4375
+ if (columns.includes(parameter)) {
4376
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with column "${parameter}" which was ambiguously defined as both a column and parameter`);
4813
4377
  }
4814
- _setLocked(fi, false);
4815
4378
  }
4816
- return SQLITE_OK;
4817
- }
4818
- function _nodejsWrite(fi, buffer, bytes, offset2) {
4819
- try {
4820
- const bytesWritten = fs3.writeSync(_fd(fi), HEAPU8.subarray(buffer, buffer + bytes), 0, bytes, _safeInt(offset2));
4821
- return bytesWritten != bytes ? SQLITE_IOERR_WRITE : SQLITE_OK;
4822
- } catch {
4823
- return SQLITE_IOERR_WRITE;
4824
- }
4825
- }
4826
- function _nodejs_max_path_length() {
4827
- return process.platform == "win32" ? 260 : 4096;
4828
- }
4829
- function _nodejs_open(filePath, flags, mode) {
4830
- let oflags = 0;
4831
- if (flags & SQLITE_OPEN_EXCLUSIVE)
4832
- oflags |= fs3.constants.O_EXCL;
4833
- if (flags & SQLITE_OPEN_CREATE)
4834
- oflags |= fs3.constants.O_CREAT;
4835
- if (flags & SQLITE_OPEN_READONLY)
4836
- oflags |= fs3.constants.O_RDONLY;
4837
- if (flags & SQLITE_OPEN_READWRITE)
4838
- oflags |= fs3.constants.O_RDWR;
4839
- try {
4840
- return fs3.openSync(UTF8ToString(filePath), oflags, mode);
4841
- } catch {
4842
- return -1;
4379
+ let safeIntegers = 2;
4380
+ if (hasOwnProperty.call(def, "safeIntegers")) {
4381
+ const bool = def.safeIntegers;
4382
+ if (typeof bool !== "boolean") {
4383
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "safeIntegers" property (should be a boolean)`);
4384
+ }
4385
+ safeIntegers = +bool;
4843
4386
  }
4844
- }
4845
- var getCFunc = (ident) => {
4846
- var func = Module["_" + ident];
4847
- return func;
4848
- };
4849
- var writeArrayToMemory = (array, buffer) => {
4850
- HEAP8.set(array, buffer);
4851
- };
4852
- var lengthBytesUTF8 = (str) => {
4853
- var len = 0;
4854
- for (var i = 0; i < str.length; ++i) {
4855
- var c = str.charCodeAt(i);
4856
- if (c <= 127) {
4857
- len++;
4858
- } else if (c <= 2047) {
4859
- len += 2;
4860
- } else if (c >= 55296 && c <= 57343) {
4861
- len += 4;
4862
- ++i;
4863
- } else {
4864
- len += 3;
4387
+ let directOnly = false;
4388
+ if (hasOwnProperty.call(def, "directOnly")) {
4389
+ directOnly = def.directOnly;
4390
+ if (typeof directOnly !== "boolean") {
4391
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "directOnly" property (should be a boolean)`);
4865
4392
  }
4866
4393
  }
4867
- return len;
4868
- };
4869
- var stackAlloc = (sz) => __emscripten_stack_alloc(sz);
4870
- var stringToUTF8OnStack = (str) => {
4871
- var size = lengthBytesUTF8(str) + 1;
4872
- var ret = stackAlloc(size);
4873
- stringToUTF8(str, ret, size);
4874
- return ret;
4875
- };
4876
- var ccall = (ident, returnType, argTypes, args, opts) => {
4877
- var toC = { string: (str) => {
4878
- var ret2 = 0;
4879
- if (str !== null && str !== void 0 && str !== 0) {
4880
- ret2 = stringToUTF8OnStack(str);
4881
- }
4882
- return ret2;
4883
- }, array: (arr) => {
4884
- var ret2 = stackAlloc(arr.length);
4885
- writeArrayToMemory(arr, ret2);
4886
- return ret2;
4887
- } };
4888
- function convertReturnValue(ret2) {
4889
- if (returnType === "string") {
4890
- return UTF8ToString(ret2);
4891
- }
4892
- if (returnType === "boolean")
4893
- return Boolean(ret2);
4894
- return ret2;
4895
- }
4896
- var func = getCFunc(ident);
4897
- var cArgs = [];
4898
- var stack = 0;
4899
- if (args) {
4900
- for (var i = 0; i < args.length; i++) {
4901
- var converter = toC[argTypes[i]];
4902
- if (converter) {
4903
- if (stack === 0)
4904
- stack = stackSave();
4905
- cArgs[i] = converter(args[i]);
4394
+ const columnDefinitions = [
4395
+ ...parameters.map(identifier).map((str) => `${str} HIDDEN`),
4396
+ ...columns.map(identifier)
4397
+ ];
4398
+ return [
4399
+ `CREATE TABLE x(${columnDefinitions.join(", ")});`,
4400
+ wrapGenerator(rows, new Map(columns.map((x3, i) => [x3, parameters.length + i])), moduleName),
4401
+ parameters,
4402
+ safeIntegers,
4403
+ directOnly
4404
+ ];
4405
+ }
4406
+ function wrapGenerator(generator, columnMap, moduleName) {
4407
+ return function* virtualTable(...args) {
4408
+ const output = args.map((x3) => Buffer.isBuffer(x3) ? Buffer.from(x3) : x3);
4409
+ for (let i = 0; i < columnMap.size; ++i) {
4410
+ output.push(null);
4411
+ }
4412
+ for (const row of generator(...args)) {
4413
+ if (Array.isArray(row)) {
4414
+ extractRowArray(row, output, columnMap.size, moduleName);
4415
+ yield output;
4416
+ } else if (typeof row === "object" && row !== null) {
4417
+ extractRowObject(row, output, columnMap, moduleName);
4418
+ yield output;
4906
4419
  } else {
4907
- cArgs[i] = args[i];
4420
+ throw new TypeError(`Virtual table module "${moduleName}" yielded something that isn't a valid row object`);
4908
4421
  }
4909
4422
  }
4423
+ };
4424
+ }
4425
+ function extractRowArray(row, output, columnCount, moduleName) {
4426
+ if (row.length !== columnCount) {
4427
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an incorrect number of columns`);
4910
4428
  }
4911
- var ret = func(...cArgs);
4912
- function onDone(ret2) {
4913
- if (stack !== 0)
4914
- stackRestore(stack);
4915
- return convertReturnValue(ret2);
4916
- }
4917
- ret = onDone(ret);
4918
- return ret;
4919
- };
4920
- var cwrap = (ident, returnType, argTypes, opts) => {
4921
- var numericArgs = !argTypes || argTypes.every((type) => type === "number" || type === "boolean");
4922
- var numericRet = returnType !== "string";
4923
- if (numericRet && numericArgs && !opts) {
4924
- return getCFunc(ident);
4925
- }
4926
- return (...args) => ccall(ident, returnType, argTypes, args, opts);
4927
- };
4928
- var wasmTableMirror = [];
4929
- var getWasmTableEntry = (funcPtr) => {
4930
- var func = wasmTableMirror[funcPtr];
4931
- if (!func) {
4932
- wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
4429
+ const offset2 = output.length - columnCount;
4430
+ for (let i = 0; i < columnCount; ++i) {
4431
+ output[i + offset2] = row[i];
4933
4432
  }
4934
- return func;
4935
- };
4936
- var updateTableMap = (offset2, count) => {
4937
- if (functionsInTableMap) {
4938
- for (var i = offset2; i < offset2 + count; i++) {
4939
- var item = getWasmTableEntry(i);
4940
- if (item) {
4941
- functionsInTableMap.set(item, i);
4942
- }
4433
+ }
4434
+ function extractRowObject(row, output, columnMap, moduleName) {
4435
+ let count = 0;
4436
+ for (const key of Object.keys(row)) {
4437
+ const index = columnMap.get(key);
4438
+ if (index === void 0) {
4439
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an undeclared column "${key}"`);
4943
4440
  }
4441
+ output[index] = row[key];
4442
+ count += 1;
4944
4443
  }
4945
- };
4946
- var functionsInTableMap;
4947
- var getFunctionAddress = (func) => {
4948
- if (!functionsInTableMap) {
4949
- functionsInTableMap = /* @__PURE__ */ new WeakMap();
4950
- updateTableMap(0, wasmTable.length);
4951
- }
4952
- return functionsInTableMap.get(func) || 0;
4953
- };
4954
- var freeTableIndexes = [];
4955
- var getEmptyTableSlot = () => {
4956
- if (freeTableIndexes.length) {
4957
- return freeTableIndexes.pop();
4444
+ if (count !== columnMap.size) {
4445
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with missing columns`);
4958
4446
  }
4959
- return wasmTable["grow"](1);
4960
- };
4961
- var setWasmTableEntry = (idx, func) => {
4962
- wasmTable.set(idx, func);
4963
- wasmTableMirror[idx] = wasmTable.get(idx);
4964
- };
4965
- var uleb128EncodeWithLen = (arr) => {
4966
- const n = arr.length;
4967
- return [n % 128 | 128, n >> 7, ...arr];
4968
- };
4969
- var wasmTypeCodes = { i: 127, p: 127, j: 126, f: 125, d: 124, e: 111 };
4970
- var generateTypePack = (types2) => uleb128EncodeWithLen(Array.from(types2, (type) => {
4971
- var code = wasmTypeCodes[type];
4972
- return code;
4973
- }));
4974
- var convertJsFunctionToWasm = (func, sig) => {
4975
- var bytes = Uint8Array.of(0, 97, 115, 109, 1, 0, 0, 0, 1, ...uleb128EncodeWithLen([1, 96, ...generateTypePack(sig.slice(1)), ...generateTypePack(sig[0] === "v" ? "" : sig[0])]), 2, 7, 1, 1, 101, 1, 102, 0, 0, 7, 5, 1, 1, 102, 0, 0);
4976
- var module3 = new WebAssembly.Module(bytes);
4977
- var instance = new WebAssembly.Instance(module3, { e: { f: func } });
4978
- var wrappedFunc = instance.exports["f"];
4979
- return wrappedFunc;
4980
- };
4981
- var addFunction = (func, sig) => {
4982
- var rtn = getFunctionAddress(func);
4983
- if (rtn) {
4984
- return rtn;
4447
+ }
4448
+ function inferParameters({ length }) {
4449
+ if (!Number.isInteger(length) || length < 0) {
4450
+ throw new TypeError("Expected function.length to be a positive integer");
4985
4451
  }
4986
- var ret = getEmptyTableSlot();
4987
- try {
4988
- setWasmTableEntry(ret, func);
4989
- } catch (err2) {
4990
- if (!(err2 instanceof TypeError)) {
4991
- throw err2;
4992
- }
4993
- var wrapped = convertJsFunctionToWasm(func, sig);
4994
- setWasmTableEntry(ret, wrapped);
4452
+ const params = [];
4453
+ for (let i = 0; i < length; ++i) {
4454
+ params.push(`$${i + 1}`);
4995
4455
  }
4996
- functionsInTableMap.set(func, ret);
4997
- return ret;
4456
+ return params;
4457
+ }
4458
+ var { hasOwnProperty } = Object.prototype;
4459
+ var { apply } = Function.prototype;
4460
+ var GeneratorFunctionPrototype = Object.getPrototypeOf(function* () {
4461
+ });
4462
+ var identifier = (str) => `"${str.replace(/"/g, '""')}"`;
4463
+ var defer2 = (x3) => () => x3;
4464
+ }
4465
+ });
4466
+
4467
+ // node_modules/better-sqlite3/lib/methods/inspect.js
4468
+ var require_inspect = __commonJS({
4469
+ "node_modules/better-sqlite3/lib/methods/inspect.js"(exports2, module2) {
4470
+ "use strict";
4471
+ var DatabaseInspection = function Database4() {
4998
4472
  };
4999
- var removeFunction = (index) => {
5000
- functionsInTableMap.delete(getWasmTableEntry(index));
5001
- setWasmTableEntry(index, null);
5002
- freeTableIndexes.push(index);
4473
+ module2.exports = function inspect(depth, opts) {
4474
+ return Object.assign(new DatabaseInspection(), this);
5003
4475
  };
5004
- {
5005
- if (Module["noExitRuntime"])
5006
- noExitRuntime = Module["noExitRuntime"];
5007
- if (Module["print"])
5008
- out = Module["print"];
5009
- if (Module["printErr"])
5010
- err = Module["printErr"];
5011
- if (Module["wasmBinary"])
5012
- wasmBinary = Module["wasmBinary"];
5013
- if (Module["arguments"])
5014
- arguments_ = Module["arguments"];
5015
- if (Module["thisProgram"])
5016
- thisProgram = Module["thisProgram"];
5017
- if (Module["preInit"]) {
5018
- if (typeof Module["preInit"] == "function")
5019
- Module["preInit"] = [Module["preInit"]];
5020
- while (Module["preInit"].length > 0) {
5021
- Module["preInit"].shift()();
5022
- }
5023
- }
5024
- }
5025
- Module["cwrap"] = cwrap;
5026
- Module["addFunction"] = addFunction;
5027
- Module["removeFunction"] = removeFunction;
5028
- var _sqlite3_finalize;
5029
- var _sqlite3_reset;
5030
- var _sqlite3_clear_bindings;
5031
- var _sqlite3_value_blob;
5032
- var _sqlite3_value_text;
5033
- var _sqlite3_value_bytes;
5034
- var _sqlite3_value_double;
5035
- var _sqlite3_value_int64;
5036
- var _sqlite3_value_type;
5037
- var _sqlite3_result_blob;
5038
- var _sqlite3_result_blob64;
5039
- var _sqlite3_result_double;
5040
- var _sqlite3_result_error;
5041
- var _sqlite3_result_int;
5042
- var _sqlite3_result_int64;
5043
- var _sqlite3_result_null;
5044
- var _sqlite3_result_text;
5045
- var _sqlite3_step;
5046
- var _sqlite3_column_count;
5047
- var _sqlite3_column_blob;
5048
- var _sqlite3_column_bytes;
5049
- var _sqlite3_column_double;
5050
- var _sqlite3_column_int64;
5051
- var _sqlite3_column_text;
5052
- var _sqlite3_column_type;
5053
- var _sqlite3_column_name;
5054
- var _sqlite3_column_table_name;
5055
- var _sqlite3_bind_blob;
5056
- var _sqlite3_bind_blob64;
5057
- var _sqlite3_bind_double;
5058
- var _sqlite3_bind_int;
5059
- var _sqlite3_bind_int64;
5060
- var _sqlite3_bind_null;
5061
- var _sqlite3_bind_text;
5062
- var _sqlite3_bind_parameter_index;
5063
- var _sqlite3_exec;
5064
- var _sqlite3_prepare_v2;
5065
- var _sqlite3_errmsg;
5066
- var _sqlite3_last_insert_rowid;
5067
- var _sqlite3_changes;
5068
- var _sqlite3_close_v2;
5069
- var _sqlite3_create_function_v2;
5070
- var _sqlite3_open_v2;
5071
- var _sqlite3_get_autocommit;
5072
- var _malloc;
5073
- var _free;
5074
- var __emscripten_timeout;
5075
- var __emscripten_stack_restore;
5076
- var __emscripten_stack_alloc;
5077
- var _emscripten_stack_get_current;
5078
- var memory;
5079
- var __indirect_function_table;
5080
- var wasmMemory;
5081
- var wasmTable;
5082
- function assignWasmExports(wasmExports2) {
5083
- _sqlite3_finalize = Module["_sqlite3_finalize"] = wasmExports2["A"];
5084
- _sqlite3_reset = Module["_sqlite3_reset"] = wasmExports2["B"];
5085
- _sqlite3_clear_bindings = Module["_sqlite3_clear_bindings"] = wasmExports2["C"];
5086
- _sqlite3_value_blob = Module["_sqlite3_value_blob"] = wasmExports2["D"];
5087
- _sqlite3_value_text = Module["_sqlite3_value_text"] = wasmExports2["E"];
5088
- _sqlite3_value_bytes = Module["_sqlite3_value_bytes"] = wasmExports2["F"];
5089
- _sqlite3_value_double = Module["_sqlite3_value_double"] = wasmExports2["G"];
5090
- _sqlite3_value_int64 = Module["_sqlite3_value_int64"] = wasmExports2["H"];
5091
- _sqlite3_value_type = Module["_sqlite3_value_type"] = wasmExports2["I"];
5092
- _sqlite3_result_blob = Module["_sqlite3_result_blob"] = wasmExports2["J"];
5093
- _sqlite3_result_blob64 = Module["_sqlite3_result_blob64"] = wasmExports2["K"];
5094
- _sqlite3_result_double = Module["_sqlite3_result_double"] = wasmExports2["L"];
5095
- _sqlite3_result_error = Module["_sqlite3_result_error"] = wasmExports2["M"];
5096
- _sqlite3_result_int = Module["_sqlite3_result_int"] = wasmExports2["N"];
5097
- _sqlite3_result_int64 = Module["_sqlite3_result_int64"] = wasmExports2["O"];
5098
- _sqlite3_result_null = Module["_sqlite3_result_null"] = wasmExports2["P"];
5099
- _sqlite3_result_text = Module["_sqlite3_result_text"] = wasmExports2["Q"];
5100
- _sqlite3_step = Module["_sqlite3_step"] = wasmExports2["R"];
5101
- _sqlite3_column_count = Module["_sqlite3_column_count"] = wasmExports2["S"];
5102
- _sqlite3_column_blob = Module["_sqlite3_column_blob"] = wasmExports2["T"];
5103
- _sqlite3_column_bytes = Module["_sqlite3_column_bytes"] = wasmExports2["U"];
5104
- _sqlite3_column_double = Module["_sqlite3_column_double"] = wasmExports2["V"];
5105
- _sqlite3_column_int64 = Module["_sqlite3_column_int64"] = wasmExports2["W"];
5106
- _sqlite3_column_text = Module["_sqlite3_column_text"] = wasmExports2["X"];
5107
- _sqlite3_column_type = Module["_sqlite3_column_type"] = wasmExports2["Y"];
5108
- _sqlite3_column_name = Module["_sqlite3_column_name"] = wasmExports2["Z"];
5109
- _sqlite3_column_table_name = Module["_sqlite3_column_table_name"] = wasmExports2["_"];
5110
- _sqlite3_bind_blob = Module["_sqlite3_bind_blob"] = wasmExports2["$"];
5111
- _sqlite3_bind_blob64 = Module["_sqlite3_bind_blob64"] = wasmExports2["aa"];
5112
- _sqlite3_bind_double = Module["_sqlite3_bind_double"] = wasmExports2["ba"];
5113
- _sqlite3_bind_int = Module["_sqlite3_bind_int"] = wasmExports2["ca"];
5114
- _sqlite3_bind_int64 = Module["_sqlite3_bind_int64"] = wasmExports2["da"];
5115
- _sqlite3_bind_null = Module["_sqlite3_bind_null"] = wasmExports2["ea"];
5116
- _sqlite3_bind_text = Module["_sqlite3_bind_text"] = wasmExports2["fa"];
5117
- _sqlite3_bind_parameter_index = Module["_sqlite3_bind_parameter_index"] = wasmExports2["ga"];
5118
- _sqlite3_exec = Module["_sqlite3_exec"] = wasmExports2["ha"];
5119
- _sqlite3_prepare_v2 = Module["_sqlite3_prepare_v2"] = wasmExports2["ia"];
5120
- _sqlite3_errmsg = Module["_sqlite3_errmsg"] = wasmExports2["ja"];
5121
- _sqlite3_last_insert_rowid = Module["_sqlite3_last_insert_rowid"] = wasmExports2["ka"];
5122
- _sqlite3_changes = Module["_sqlite3_changes"] = wasmExports2["la"];
5123
- _sqlite3_close_v2 = Module["_sqlite3_close_v2"] = wasmExports2["ma"];
5124
- _sqlite3_create_function_v2 = Module["_sqlite3_create_function_v2"] = wasmExports2["na"];
5125
- _sqlite3_open_v2 = Module["_sqlite3_open_v2"] = wasmExports2["oa"];
5126
- _sqlite3_get_autocommit = Module["_sqlite3_get_autocommit"] = wasmExports2["pa"];
5127
- _malloc = Module["_malloc"] = wasmExports2["qa"];
5128
- _free = Module["_free"] = wasmExports2["ra"];
5129
- __emscripten_timeout = wasmExports2["ta"];
5130
- __emscripten_stack_restore = wasmExports2["ua"];
5131
- __emscripten_stack_alloc = wasmExports2["va"];
5132
- _emscripten_stack_get_current = wasmExports2["wa"];
5133
- memory = wasmMemory = wasmExports2["y"];
5134
- __indirect_function_table = wasmTable = wasmExports2["sa"];
5135
- }
5136
- var wasmImports = { n: __abort_js, l: __emscripten_runtime_keepalive_clear, o: __localtime_js, i: __setitimer_js, p: __tzset_js, q: _emscripten_date_now, a: _emscripten_get_now, j: _emscripten_resize_heap, w: _nodejsAccess, s: _nodejsCheckReservedLock, f: _nodejsClose, x: _nodejsDelete, v: _nodejsFileSize, m: _nodejsFullPathname, u: _nodejsLock, h: _nodejsRandomness, e: _nodejsRead, b: _nodejsSync, c: _nodejsTruncate, t: _nodejsUnlock, d: _nodejsWrite, g: _nodejs_max_path_length, r: _nodejs_open, k: _proc_exit };
5137
- function run() {
5138
- preRun();
5139
- function doRun() {
5140
- Module["calledRun"] = true;
5141
- if (ABORT2)
5142
- return;
5143
- initRuntime();
5144
- Module["onRuntimeInitialized"]?.();
5145
- postRun();
5146
- }
5147
- if (Module["setStatus"]) {
5148
- Module["setStatus"]("Running...");
5149
- setTimeout(() => {
5150
- setTimeout(() => Module["setStatus"](""), 1);
5151
- doRun();
5152
- }, 1);
4476
+ }
4477
+ });
4478
+
4479
+ // node_modules/better-sqlite3/lib/database.js
4480
+ var require_database = __commonJS({
4481
+ "node_modules/better-sqlite3/lib/database.js"(exports2, module2) {
4482
+ "use strict";
4483
+ var fs5 = require("fs");
4484
+ var path4 = require("path");
4485
+ var util = require_util();
4486
+ var SqliteError = require_sqlite_error();
4487
+ var DEFAULT_ADDON;
4488
+ function Database4(filenameGiven, options) {
4489
+ if (new.target == null) {
4490
+ return new Database4(filenameGiven, options);
4491
+ }
4492
+ let buffer;
4493
+ if (Buffer.isBuffer(filenameGiven)) {
4494
+ buffer = filenameGiven;
4495
+ filenameGiven = ":memory:";
4496
+ }
4497
+ if (filenameGiven == null)
4498
+ filenameGiven = "";
4499
+ if (options == null)
4500
+ options = {};
4501
+ if (typeof filenameGiven !== "string")
4502
+ throw new TypeError("Expected first argument to be a string");
4503
+ if (typeof options !== "object")
4504
+ throw new TypeError("Expected second argument to be an options object");
4505
+ if ("readOnly" in options)
4506
+ throw new TypeError('Misspelled option "readOnly" should be "readonly"');
4507
+ if ("memory" in options)
4508
+ throw new TypeError('Option "memory" was removed in v7.0.0 (use ":memory:" filename instead)');
4509
+ const filename = filenameGiven.trim();
4510
+ const anonymous = filename === "" || filename === ":memory:";
4511
+ const readonly = util.getBooleanOption(options, "readonly");
4512
+ const fileMustExist = util.getBooleanOption(options, "fileMustExist");
4513
+ const timeout = "timeout" in options ? options.timeout : 5e3;
4514
+ const verbose = "verbose" in options ? options.verbose : null;
4515
+ const nativeBinding = "nativeBinding" in options ? options.nativeBinding : null;
4516
+ if (readonly && anonymous && !buffer)
4517
+ throw new TypeError("In-memory/temporary databases cannot be readonly");
4518
+ if (!Number.isInteger(timeout) || timeout < 0)
4519
+ throw new TypeError('Expected the "timeout" option to be a positive integer');
4520
+ if (timeout > 2147483647)
4521
+ throw new RangeError('Option "timeout" cannot be greater than 2147483647');
4522
+ if (verbose != null && typeof verbose !== "function")
4523
+ throw new TypeError('Expected the "verbose" option to be a function');
4524
+ if (nativeBinding != null && typeof nativeBinding !== "string" && typeof nativeBinding !== "object")
4525
+ throw new TypeError('Expected the "nativeBinding" option to be a string or addon object');
4526
+ let addon;
4527
+ if (nativeBinding == null) {
4528
+ addon = DEFAULT_ADDON || (DEFAULT_ADDON = require_bindings()("better_sqlite3.node"));
4529
+ } else if (typeof nativeBinding === "string") {
4530
+ const requireFunc = typeof __non_webpack_require__ === "function" ? __non_webpack_require__ : require;
4531
+ addon = requireFunc(path4.resolve(nativeBinding).replace(/(\.node)?$/, ".node"));
5153
4532
  } else {
5154
- doRun();
4533
+ addon = nativeBinding;
4534
+ }
4535
+ if (!addon.isInitialized) {
4536
+ addon.setErrorConstructor(SqliteError);
4537
+ addon.isInitialized = true;
5155
4538
  }
4539
+ if (!anonymous && !filename.startsWith("file:") && !fs5.existsSync(path4.dirname(filename))) {
4540
+ throw new TypeError("Cannot open database because the directory does not exist");
4541
+ }
4542
+ Object.defineProperties(this, {
4543
+ [util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },
4544
+ ...wrappers.getters
4545
+ });
5156
4546
  }
5157
- var wasmExports;
5158
- wasmExports = createWasm();
5159
- run();
4547
+ var wrappers = require_wrappers();
4548
+ Database4.prototype.prepare = wrappers.prepare;
4549
+ Database4.prototype.transaction = require_transaction();
4550
+ Database4.prototype.pragma = require_pragma();
4551
+ Database4.prototype.backup = require_backup();
4552
+ Database4.prototype.serialize = require_serialize();
4553
+ Database4.prototype.function = require_function();
4554
+ Database4.prototype.aggregate = require_aggregate();
4555
+ Database4.prototype.table = require_table();
4556
+ Database4.prototype.loadExtension = wrappers.loadExtension;
4557
+ Database4.prototype.exec = wrappers.exec;
4558
+ Database4.prototype.close = wrappers.close;
4559
+ Database4.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;
4560
+ Database4.prototype.unsafeMode = wrappers.unsafeMode;
4561
+ Database4.prototype[util.inspect] = require_inspect();
4562
+ module2.exports = Database4;
4563
+ }
4564
+ });
4565
+
4566
+ // node_modules/better-sqlite3/lib/index.js
4567
+ var require_lib = __commonJS({
4568
+ "node_modules/better-sqlite3/lib/index.js"(exports2, module2) {
4569
+ "use strict";
4570
+ module2.exports = require_database();
4571
+ module2.exports.SqliteError = require_sqlite_error();
5160
4572
  }
5161
4573
  });
5162
4574
 
5163
4575
  // src/db.ts
4576
+ function isBindingLoadError(e2) {
4577
+ if (!e2 || typeof e2 !== "object")
4578
+ return false;
4579
+ const err = e2;
4580
+ const code = typeof err.code === "string" ? err.code : "";
4581
+ if (code === "ERR_DLOPEN_FAILED" || code === "MODULE_NOT_FOUND")
4582
+ return true;
4583
+ const msg = typeof err.message === "string" ? err.message : "";
4584
+ return /NODE_MODULE_VERSION|different Node\.?js version|dlopen|invalid ELF|not a valid Win32 application|better_sqlite3\.node|Could not locate the bindings|was compiled against/i.test(
4585
+ msg
4586
+ );
4587
+ }
5164
4588
  function getDb(dbPath2) {
5165
4589
  if (db && currentDbPath === dbPath2)
5166
4590
  return db;
@@ -5168,15 +4592,16 @@ function getDb(dbPath2) {
5168
4592
  closeDb();
5169
4593
  }
5170
4594
  (0, import_node_fs5.mkdirSync)((0, import_node_path4.dirname)(dbPath2), { recursive: true });
5171
- clearStaleLock(dbPath2);
5172
- writeOwnerFile(dbPath2);
5173
- db = new import_node_sqlite3_wasm.Database(dbPath2);
4595
+ cleanupWasmArtifacts(dbPath2);
4596
+ const raw2 = openDatabase(dbPath2);
4597
+ try {
4598
+ configurePragmas(raw2, dbPath2);
4599
+ } catch (e2) {
4600
+ raw2.close();
4601
+ throw e2;
4602
+ }
4603
+ db = createAdapter(raw2);
5174
4604
  currentDbPath = dbPath2;
5175
- db.exec("PRAGMA busy_timeout = 5000");
5176
- db.exec("PRAGMA journal_mode = WAL");
5177
- db.exec("PRAGMA synchronous = NORMAL");
5178
- db.exec("PRAGMA wal_autocheckpoint = 1000");
5179
- db.exec("PRAGMA foreign_keys = ON");
5180
4605
  ensureSchema(db);
5181
4606
  log({ source: "db", level: "info", summary: `DB: initialized at ${dbPath2}` });
5182
4607
  return db;
@@ -5184,84 +4609,114 @@ function getDb(dbPath2) {
5184
4609
  function closeDb() {
5185
4610
  if (db) {
5186
4611
  db.close();
5187
- if (currentDbPath)
5188
- removeOwnerFile(currentDbPath);
5189
4612
  db = null;
5190
4613
  currentDbPath = null;
5191
4614
  }
5192
4615
  }
5193
- function ownerFilePath(dbPath2) {
5194
- return `${dbPath2}.owner`;
4616
+ function _resetDb() {
4617
+ closeDb();
5195
4618
  }
5196
- function processStartToken(pid) {
5197
- if (process.platform !== "linux")
5198
- return "";
4619
+ function openDatabase(dbPath2) {
4620
+ const nativeBinding = resolveNativeBinding();
5199
4621
  try {
5200
- const stat = (0, import_node_fs5.readFileSync)(`/proc/${pid}/stat`, "utf-8");
5201
- const close = stat.lastIndexOf(")");
5202
- if (close === -1)
5203
- return "";
5204
- const rest = stat.slice(close + 2).trim().split(/\s+/);
5205
- const starttime = rest[19];
5206
- return starttime ?? "";
5207
- } catch {
5208
- return "";
4622
+ return nativeBinding ? new import_better_sqlite3.default(dbPath2, { nativeBinding }) : new import_better_sqlite3.default(dbPath2);
4623
+ } catch (e2) {
4624
+ if (isBindingLoadError(e2))
4625
+ throw new BindingLoadError(dbPath2, e2);
4626
+ throw e2;
5209
4627
  }
5210
4628
  }
5211
- function writeOwnerFile(dbPath2) {
5212
- try {
5213
- const token = processStartToken(process.pid);
5214
- (0, import_node_fs5.writeFileSync)(ownerFilePath(dbPath2), `${process.pid}:${token}`, "utf-8");
5215
- } catch {
5216
- }
4629
+ function resolveNativeBinding() {
4630
+ const sibling = (0, import_node_path4.join)(__dirname, "better_sqlite3.node");
4631
+ if ((0, import_node_fs5.existsSync)(sibling))
4632
+ return sibling;
4633
+ const resolved = resolveInstalledBinding();
4634
+ if (resolved)
4635
+ return resolved;
4636
+ const staged = (0, import_node_path4.join)(binDir(), "better_sqlite3.node");
4637
+ if ((0, import_node_fs5.existsSync)(staged))
4638
+ return staged;
4639
+ return null;
5217
4640
  }
5218
- function removeOwnerFile(dbPath2) {
4641
+ function resolveInstalledBinding() {
5219
4642
  try {
5220
- (0, import_node_fs5.unlinkSync)(ownerFilePath(dbPath2));
4643
+ const pkgJson = (0, import_node_module.createRequire)(__filename).resolve("better-sqlite3/package.json");
4644
+ return findNativeBinding((0, import_node_path4.dirname)(pkgJson));
5221
4645
  } catch {
4646
+ return null;
5222
4647
  }
5223
4648
  }
5224
- function isProcessAlive2(pid) {
5225
- try {
5226
- process.kill(pid, 0);
5227
- return true;
5228
- } catch {
5229
- return false;
4649
+ function findNativeBinding(baseDir) {
4650
+ for (const c of [
4651
+ (0, import_node_path4.join)(baseDir, "build", "Release", "better_sqlite3.node"),
4652
+ (0, import_node_path4.join)(baseDir, "build", "Debug", "better_sqlite3.node")
4653
+ ]) {
4654
+ try {
4655
+ if ((0, import_node_fs5.statSync)(c).isFile())
4656
+ return c;
4657
+ } catch {
4658
+ }
5230
4659
  }
5231
- }
5232
- function clearStaleLock(dbPath2) {
5233
- const lockDir = `${dbPath2}.lock`;
5234
- if (!(0, import_node_fs5.existsSync)(lockDir))
5235
- return;
5236
- const ownerFile = ownerFilePath(dbPath2);
5237
- if ((0, import_node_fs5.existsSync)(ownerFile)) {
4660
+ const stack = [baseDir];
4661
+ while (stack.length) {
4662
+ const dir = stack.pop();
4663
+ let entries;
5238
4664
  try {
5239
- const raw2 = (0, import_node_fs5.readFileSync)(ownerFile, "utf-8").trim();
5240
- const sep2 = raw2.indexOf(":");
5241
- const pidStr = sep2 === -1 ? raw2 : raw2.slice(0, sep2);
5242
- const storedToken = sep2 === -1 ? "" : raw2.slice(sep2 + 1);
5243
- const pid = parseInt(pidStr, 10);
5244
- if (!isNaN(pid) && isProcessAlive2(pid)) {
5245
- if (storedToken === "" || storedToken === processStartToken(pid)) {
5246
- return;
5247
- }
5248
- }
4665
+ entries = (0, import_node_fs5.readdirSync)(dir, { withFileTypes: true });
5249
4666
  } catch {
4667
+ continue;
4668
+ }
4669
+ for (const e2 of entries) {
4670
+ const p = (0, import_node_path4.join)(dir, e2.name);
4671
+ if (e2.isDirectory())
4672
+ stack.push(p);
4673
+ else if (e2.name.endsWith(".node"))
4674
+ return p;
5250
4675
  }
5251
4676
  }
4677
+ return null;
4678
+ }
4679
+ function createAdapter(raw2) {
4680
+ return {
4681
+ all: (sql, params) => raw2.prepare(sql).all(...params ?? []),
4682
+ get: (sql, params) => raw2.prepare(sql).get(...params ?? []),
4683
+ run: (sql, params) => raw2.prepare(sql).run(...params ?? []),
4684
+ exec: (sql) => {
4685
+ raw2.exec(sql);
4686
+ },
4687
+ prepare: (sql) => {
4688
+ const st = raw2.prepare(sql);
4689
+ return {
4690
+ run: (p) => st.run(...p ?? []),
4691
+ all: (p) => st.all(...p ?? []),
4692
+ get: (p) => st.get(...p ?? [])
4693
+ };
4694
+ },
4695
+ close: () => raw2.close()
4696
+ };
4697
+ }
4698
+ function configurePragmas(raw2, dbPath2) {
4699
+ const isMemory = dbPath2 === ":memory:" || dbPath2.includes(":memory:") || dbPath2.startsWith("file::memory:");
4700
+ raw2.pragma("busy_timeout = 5000");
4701
+ const mode = raw2.pragma("journal_mode = WAL", { simple: true });
4702
+ if (!isMemory && mode !== "wal") {
4703
+ throw new Error(
4704
+ `recall: expected WAL journal_mode, got '${String(mode)}' \u2014 refusing to run on a non-WAL DB (${dbPath2}). A native build on a delete-mode DB is drift; run \`recall doctor\`.`
4705
+ );
4706
+ }
4707
+ raw2.pragma("synchronous = NORMAL");
4708
+ raw2.pragma("wal_autocheckpoint = 1000");
4709
+ raw2.pragma("foreign_keys = ON");
4710
+ }
4711
+ function cleanupWasmArtifacts(dbPath2) {
5252
4712
  try {
5253
- (0, import_node_fs5.rmSync)(lockDir, { recursive: true, force: true });
5254
- log({
5255
- source: "db",
5256
- level: "warn",
5257
- summary: `DB: removed stale lock directory (${lockDir}) \u2014 owning process is dead`
5258
- });
5259
- } catch (err) {
5260
- log({
5261
- source: "db",
5262
- level: "error",
5263
- summary: `DB: failed to remove stale lock directory: ${err}`
5264
- });
4713
+ (0, import_node_fs5.rmSync)(`${dbPath2}.lock`, { recursive: true, force: true });
4714
+ } catch {
4715
+ }
4716
+ try {
4717
+ if ((0, import_node_fs5.existsSync)(`${dbPath2}.owner`))
4718
+ (0, import_node_fs5.unlinkSync)(`${dbPath2}.owner`);
4719
+ } catch {
5265
4720
  }
5266
4721
  }
5267
4722
  function ensureSchema(db4) {
@@ -5279,6 +4734,12 @@ function ensureSchema(db4) {
5279
4734
 
5280
4735
  CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id, created_at);
5281
4736
  CREATE INDEX IF NOT EXISTS idx_messages_project ON messages(project_id);
4737
+ -- getUnembeddedMessages() orders the whole table by created_at DESC (LIMIT N).
4738
+ -- Without a standalone created_at index SQLite full-scans messages and builds
4739
+ -- a TEMP B-TREE to sort on every call \u2014 a ~4s/batch cost that dominates the
4740
+ -- embed drain and every Stop-hook catch-up. This index serves the ORDER BY so
4741
+ -- the planner walks it and early-terminates at LIMIT instead.
4742
+ CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages(created_at);
5282
4743
  `);
5283
4744
  db4.exec(`
5284
4745
  CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(
@@ -5319,9 +4780,19 @@ function ensureSchema(db4) {
5319
4780
  message_id TEXT PRIMARY KEY REFERENCES messages(message_id) ON DELETE CASCADE,
5320
4781
  embedding_q8 BLOB NOT NULL,
5321
4782
  norm REAL NOT NULL,
5322
- quant_scale REAL NOT NULL
4783
+ quant_scale REAL NOT NULL,
4784
+ embed_version INTEGER NOT NULL DEFAULT 1
5323
4785
  );
5324
4786
  `);
4787
+ const hasEmbedVersion = () => db4.all(`PRAGMA table_info(message_vectors)`).some((c) => c.name === "embed_version");
4788
+ if (!hasEmbedVersion()) {
4789
+ try {
4790
+ db4.exec(`ALTER TABLE message_vectors ADD COLUMN embed_version INTEGER NOT NULL DEFAULT 1`);
4791
+ } catch (e2) {
4792
+ if (!hasEmbedVersion())
4793
+ throw e2;
4794
+ }
4795
+ }
5325
4796
  db4.exec(`
5326
4797
  CREATE TABLE IF NOT EXISTS ingest_watermark (
5327
4798
  transcript_path TEXT PRIMARY KEY,
@@ -5332,14 +4803,27 @@ function ensureSchema(db4) {
5332
4803
  CREATE INDEX IF NOT EXISTS idx_watermark_vendor ON ingest_watermark(vendor);
5333
4804
  `);
5334
4805
  }
5335
- var import_node_fs5, import_node_path4, import_node_sqlite3_wasm, db, currentDbPath;
4806
+ var import_node_fs5, import_node_path4, import_node_module, import_better_sqlite3, BindingLoadError, db, currentDbPath;
5336
4807
  var init_db = __esm({
5337
4808
  "src/db.ts"() {
5338
4809
  "use strict";
5339
4810
  import_node_fs5 = require("node:fs");
5340
4811
  import_node_path4 = require("node:path");
4812
+ import_node_module = require("node:module");
5341
4813
  init_log();
5342
- import_node_sqlite3_wasm = __toESM(require_node_sqlite3_wasm());
4814
+ init_paths();
4815
+ import_better_sqlite3 = __toESM(require_lib());
4816
+ BindingLoadError = class extends Error {
4817
+ constructor(dbPath2, cause) {
4818
+ super(
4819
+ `recall: failed to load the better-sqlite3 native binding while opening ${dbPath2}: ${cause.message}
4820
+ The binding is ABI-locked to the Node it was built for \u2014 run \`recall doctor\` (usually fixed by re-running \`recall install\`).`
4821
+ );
4822
+ this.dbPath = dbPath2;
4823
+ this.cause = cause;
4824
+ this.name = "BindingLoadError";
4825
+ }
4826
+ };
5343
4827
  db = null;
5344
4828
  currentDbPath = null;
5345
4829
  }
@@ -5393,7 +4877,7 @@ function normalizeTokenSeparators(input) {
5393
4877
  return part.replace(/(\w)[-_](\w)/g, "$1 $2");
5394
4878
  }).join("");
5395
4879
  }
5396
- function sanitizeFts5Query(raw2) {
4880
+ function sanitizeFts5Query(raw2, opts) {
5397
4881
  const trimmed = raw2.trim();
5398
4882
  if (!trimmed)
5399
4883
  return null;
@@ -5416,21 +4900,23 @@ function sanitizeFts5Query(raw2) {
5416
4900
  if (words.length <= 2)
5417
4901
  return words.map((w3) => `"${w3}"`).join(" ");
5418
4902
  const originalCount = words.length;
5419
- const dropped = [];
5420
- words = words.filter((w3) => {
5421
- const df = getTermDocFrequency(w3);
5422
- if (df >= IDF_PERCENTILE_THRESHOLD) {
5423
- dropped.push(`${w3}(${(df * 100).toFixed(0)}%)`);
5424
- return false;
5425
- }
5426
- return true;
5427
- });
5428
- if (dropped.length > 0) {
5429
- log({
5430
- source: "query-sanitizer",
5431
- level: "debug",
5432
- summary: `IDF filter: ${originalCount} \u2192 ${words.length} terms, dropped: ${dropped.join(", ")}`
4903
+ if (!opts?.skipIdf) {
4904
+ const dropped = [];
4905
+ words = words.filter((w3) => {
4906
+ const df = getTermDocFrequency(w3);
4907
+ if (df >= IDF_PERCENTILE_THRESHOLD) {
4908
+ dropped.push(`${w3}(${(df * 100).toFixed(0)}%)`);
4909
+ return false;
4910
+ }
4911
+ return true;
5433
4912
  });
4913
+ if (dropped.length > 0) {
4914
+ log({
4915
+ source: "query-sanitizer",
4916
+ level: "debug",
4917
+ summary: `IDF filter: ${originalCount} \u2192 ${words.length} terms, dropped: ${dropped.join(", ")}`
4918
+ });
4919
+ }
5434
4920
  }
5435
4921
  words = [...new Set(words.map((w3) => w3.toLowerCase()))];
5436
4922
  if (words.length === 0) {
@@ -5467,6 +4953,25 @@ var init_query_sanitizer = __esm({
5467
4953
  }
5468
4954
  });
5469
4955
 
4956
+ // src/recall/embed-config.ts
4957
+ function buildEmbedText(messageText, prevText) {
4958
+ if (messageText.length >= ENRICH_MAX_CHARS || !prevText)
4959
+ return messageText;
4960
+ return prevText.slice(-ENRICH_PREV_CHARS) + ENRICH_SEP + messageText;
4961
+ }
4962
+ var DOC_PREFIX, QUERY_PREFIX, EMBED_VERSION, ENRICH_MAX_CHARS, ENRICH_PREV_CHARS, ENRICH_SEP;
4963
+ var init_embed_config = __esm({
4964
+ "src/recall/embed-config.ts"() {
4965
+ "use strict";
4966
+ DOC_PREFIX = "search_document: ";
4967
+ QUERY_PREFIX = "search_query: ";
4968
+ EMBED_VERSION = 3;
4969
+ ENRICH_MAX_CHARS = 200;
4970
+ ENRICH_PREV_CHARS = 512;
4971
+ ENRICH_SEP = "\n";
4972
+ }
4973
+ });
4974
+
5470
4975
  // src/recall/message-store.ts
5471
4976
  function db2() {
5472
4977
  return getDb(dbPath());
@@ -5482,7 +4987,7 @@ function insertMessages(messages, opts) {
5482
4987
  return;
5483
4988
  ensureDir2();
5484
4989
  const d3 = db2();
5485
- d3.exec("BEGIN");
4990
+ d3.exec("BEGIN IMMEDIATE");
5486
4991
  try {
5487
4992
  if (opts?.replaceSessionId) {
5488
4993
  d3.run(
@@ -5497,20 +5002,16 @@ function insertMessages(messages, opts) {
5497
5002
  (message_id, session_id, message_seq, message_text, project_id, created_at, message_role)
5498
5003
  VALUES (?, ?, ?, ?, ?, ?, ?)`
5499
5004
  );
5500
- try {
5501
- for (const m2 of messages) {
5502
- stmt.run([
5503
- m2.message_id,
5504
- m2.session_id,
5505
- m2.message_seq,
5506
- m2.message_text,
5507
- m2.project_id,
5508
- m2.created_at,
5509
- m2.message_role
5510
- ]);
5511
- }
5512
- } finally {
5513
- stmt.finalize();
5005
+ for (const m2 of messages) {
5006
+ stmt.run([
5007
+ m2.message_id,
5008
+ m2.session_id,
5009
+ m2.message_seq,
5010
+ m2.message_text,
5011
+ m2.project_id,
5012
+ m2.created_at,
5013
+ m2.message_role
5014
+ ]);
5514
5015
  }
5515
5016
  d3.exec("COMMIT");
5516
5017
  } catch (e2) {
@@ -5518,9 +5019,9 @@ function insertMessages(messages, opts) {
5518
5019
  throw e2;
5519
5020
  }
5520
5021
  }
5521
- function searchMessagesFts(query, limit2 = 20, projectId, sessionId, excludeSessionId) {
5022
+ function searchMessagesFts(query, limit2 = 20, projectId, sessionId, excludeSessionId, skipIdf) {
5522
5023
  try {
5523
- const sanitized = sanitizeFts5Query(query);
5024
+ const sanitized = sanitizeFts5Query(query, { skipIdf });
5524
5025
  if (!sanitized)
5525
5026
  return [];
5526
5027
  const params = [sanitized];
@@ -5631,24 +5132,21 @@ function insertMessageVectors(records) {
5631
5132
  return;
5632
5133
  ensureDir2();
5633
5134
  const d3 = db2();
5634
- d3.exec("BEGIN");
5135
+ d3.exec("BEGIN IMMEDIATE");
5635
5136
  try {
5636
5137
  const stmt = d3.prepare(
5637
5138
  `INSERT OR REPLACE INTO message_vectors
5638
- (message_id, embedding_q8, norm, quant_scale)
5639
- VALUES (?, ?, ?, ?)`
5139
+ (message_id, embedding_q8, norm, quant_scale, embed_version)
5140
+ VALUES (?, ?, ?, ?, ?)`
5640
5141
  );
5641
- try {
5642
- for (const r2 of records) {
5643
- stmt.run([
5644
- r2.messageId,
5645
- Buffer.from(r2.embeddingQ8.buffer, r2.embeddingQ8.byteOffset, r2.embeddingQ8.byteLength),
5646
- r2.norm,
5647
- r2.quantScale
5648
- ]);
5649
- }
5650
- } finally {
5651
- stmt.finalize();
5142
+ for (const r2 of records) {
5143
+ stmt.run([
5144
+ r2.messageId,
5145
+ Buffer.from(r2.embeddingQ8.buffer, r2.embeddingQ8.byteOffset, r2.embeddingQ8.byteLength),
5146
+ r2.norm,
5147
+ r2.quantScale,
5148
+ EMBED_VERSION
5149
+ ]);
5652
5150
  }
5653
5151
  d3.exec("COMMIT");
5654
5152
  } catch (e2) {
@@ -5656,6 +5154,23 @@ function insertMessageVectors(records) {
5656
5154
  throw e2;
5657
5155
  }
5658
5156
  }
5157
+ function getEmbedVersionStats() {
5158
+ try {
5159
+ const row = db2().get(
5160
+ `SELECT COUNT(*) AS total,
5161
+ COALESCE(SUM(CASE WHEN embed_version = ? THEN 1 ELSE 0 END), 0) AS current
5162
+ FROM message_vectors`,
5163
+ [EMBED_VERSION]
5164
+ );
5165
+ const total = row ? row.total : 0;
5166
+ const current = row ? row.current ?? 0 : 0;
5167
+ const stale = total - current;
5168
+ const coverage = total === 0 ? 1 : current / total;
5169
+ return { total, current, stale, coverage };
5170
+ } catch {
5171
+ return { total: 0, current: 0, stale: 0, coverage: 1 };
5172
+ }
5173
+ }
5659
5174
  function searchMessagesSemantic(queryQ8, queryNorm, queryScale, opts) {
5660
5175
  try {
5661
5176
  const limit2 = opts?.limit ?? 20;
@@ -5673,13 +5188,16 @@ function searchMessagesSemantic(queryQ8, queryNorm, queryScale, opts) {
5673
5188
  filterClauses += " AND m.session_id != ?";
5674
5189
  params.push(opts.excludeSessionId);
5675
5190
  }
5191
+ const versionClause = opts?.tolerant ? "" : " AND mv.embed_version = ?";
5192
+ if (!opts?.tolerant)
5193
+ params.push(EMBED_VERSION);
5676
5194
  const rows = db2().all(
5677
5195
  `SELECT mv.message_id, mv.embedding_q8, mv.norm, mv.quant_scale,
5678
5196
  m.session_id, m.message_seq, m.project_id, m.created_at, m.message_role,
5679
5197
  SUBSTR(m.message_text, 1, 401) as message_preview_raw
5680
5198
  FROM message_vectors mv
5681
5199
  JOIN messages m ON m.message_id = mv.message_id
5682
- WHERE 1=1${filterClauses}`,
5200
+ WHERE 1=1${filterClauses}${versionClause}`,
5683
5201
  params
5684
5202
  );
5685
5203
  if (rows.length === 0)
@@ -5692,6 +5210,8 @@ function searchMessagesSemantic(queryQ8, queryNorm, queryScale, opts) {
5692
5210
  if (storedNorm === 0 || queryNorm === 0)
5693
5211
  continue;
5694
5212
  const storedQ8Buf = row.embedding_q8;
5213
+ if (storedQ8Buf.byteLength !== queryQ8.byteLength)
5214
+ continue;
5695
5215
  const storedQ8 = new Int8Array(
5696
5216
  storedQ8Buf.buffer,
5697
5217
  storedQ8Buf.byteOffset,
@@ -5740,9 +5260,12 @@ function getEmbeddingGapStats() {
5740
5260
  const row = db2().get(
5741
5261
  `SELECT
5742
5262
  COUNT(*) as total,
5743
- SUM(CASE WHEN NOT EXISTS (SELECT 1 FROM message_vectors mv WHERE mv.message_id = m.message_id)
5744
- AND LENGTH(m.message_text) >= ${MIN_EMBED_CHARS} THEN 1 ELSE 0 END) as gap
5745
- FROM messages m WHERE m.message_text != ''`
5263
+ SUM(CASE WHEN NOT EXISTS (SELECT 1 FROM message_vectors mv WHERE mv.message_id = m.message_id AND mv.embed_version = ?)
5264
+ AND (LENGTH(m.message_text) >= ${MIN_EMBED_CHARS}
5265
+ OR EXISTS (SELECT 1 FROM messages p WHERE p.session_id = m.session_id AND p.message_seq < m.message_seq))
5266
+ THEN 1 ELSE 0 END) as gap
5267
+ FROM messages m WHERE m.message_text != ''`,
5268
+ [EMBED_VERSION]
5746
5269
  );
5747
5270
  return {
5748
5271
  totalMessages: row ? row.total : 0,
@@ -5755,19 +5278,29 @@ function getEmbeddingGapStats() {
5755
5278
  function getUnembeddedMessages(limit2) {
5756
5279
  try {
5757
5280
  const rows = db2().all(
5758
- `SELECT m.message_id, m.session_id, m.message_text FROM messages m
5281
+ `SELECT m.message_id, m.session_id, m.message_text,
5282
+ (SELECT p.message_text FROM messages p
5283
+ WHERE p.session_id = m.session_id AND p.message_seq < m.message_seq
5284
+ ORDER BY p.message_seq DESC LIMIT 1) AS prev_text
5285
+ FROM messages m
5759
5286
  WHERE m.message_text != ''
5760
- AND LENGTH(m.message_text) >= ${MIN_EMBED_CHARS}
5761
- AND NOT EXISTS (SELECT 1 FROM message_vectors mv WHERE mv.message_id = m.message_id)
5287
+ AND (LENGTH(m.message_text) >= ${MIN_EMBED_CHARS}
5288
+ OR EXISTS (SELECT 1 FROM messages p2 WHERE p2.session_id = m.session_id AND p2.message_seq < m.message_seq))
5289
+ AND NOT EXISTS (SELECT 1 FROM message_vectors mv WHERE mv.message_id = m.message_id AND mv.embed_version = ?)
5762
5290
  ORDER BY m.created_at DESC
5763
5291
  LIMIT ?`,
5764
- [limit2]
5292
+ [EMBED_VERSION, limit2]
5765
5293
  );
5766
- return rows.map((r2) => ({
5767
- message_id: r2.message_id,
5768
- session_id: r2.session_id,
5769
- message_text: r2.message_text
5770
- }));
5294
+ return rows.map((r2) => {
5295
+ const message_text = r2.message_text;
5296
+ const prev_text = r2.prev_text ?? null;
5297
+ return {
5298
+ message_id: r2.message_id,
5299
+ session_id: r2.session_id,
5300
+ message_text,
5301
+ embed_text: buildEmbedText(message_text, prev_text)
5302
+ };
5303
+ });
5771
5304
  } catch {
5772
5305
  return [];
5773
5306
  }
@@ -5791,6 +5324,7 @@ var init_message_store = __esm({
5791
5324
  init_paths();
5792
5325
  init_query_sanitizer();
5793
5326
  init_quantize();
5327
+ init_embed_config();
5794
5328
  dirEnsured = false;
5795
5329
  MIN_EMBED_CHARS = 50;
5796
5330
  }
@@ -10203,12 +9737,12 @@ var init_esm4 = __esm({
10203
9737
  /**
10204
9738
  * Get the Path object referenced by the string path, resolved from this Path
10205
9739
  */
10206
- resolve(path3) {
10207
- if (!path3) {
9740
+ resolve(path4) {
9741
+ if (!path4) {
10208
9742
  return this;
10209
9743
  }
10210
- const rootPath = this.getRootString(path3);
10211
- const dir = path3.substring(rootPath.length);
9744
+ const rootPath = this.getRootString(path4);
9745
+ const dir = path4.substring(rootPath.length);
10212
9746
  const dirParts = dir.split(this.splitSep);
10213
9747
  const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
10214
9748
  return result;
@@ -10960,8 +10494,8 @@ var init_esm4 = __esm({
10960
10494
  /**
10961
10495
  * @internal
10962
10496
  */
10963
- getRootString(path3) {
10964
- return import_node_path5.win32.parse(path3).root;
10497
+ getRootString(path4) {
10498
+ return import_node_path5.win32.parse(path4).root;
10965
10499
  }
10966
10500
  /**
10967
10501
  * @internal
@@ -11007,8 +10541,8 @@ var init_esm4 = __esm({
11007
10541
  /**
11008
10542
  * @internal
11009
10543
  */
11010
- getRootString(path3) {
11011
- return path3.startsWith("/") ? "/" : "";
10544
+ getRootString(path4) {
10545
+ return path4.startsWith("/") ? "/" : "";
11012
10546
  }
11013
10547
  /**
11014
10548
  * @internal
@@ -11057,8 +10591,8 @@ var init_esm4 = __esm({
11057
10591
  *
11058
10592
  * @internal
11059
10593
  */
11060
- constructor(cwd = process.cwd(), pathImpl, sep2, { nocase, childrenCacheSize = 16 * 1024, fs: fs3 = defaultFS } = {}) {
11061
- this.#fs = fsFromOption(fs3);
10594
+ constructor(cwd = process.cwd(), pathImpl, sep2, { nocase, childrenCacheSize = 16 * 1024, fs: fs5 = defaultFS } = {}) {
10595
+ this.#fs = fsFromOption(fs5);
11062
10596
  if (cwd instanceof URL || cwd.startsWith("file://")) {
11063
10597
  cwd = (0, import_node_url.fileURLToPath)(cwd);
11064
10598
  }
@@ -11097,11 +10631,11 @@ var init_esm4 = __esm({
11097
10631
  /**
11098
10632
  * Get the depth of a provided path, string, or the cwd
11099
10633
  */
11100
- depth(path3 = this.cwd) {
11101
- if (typeof path3 === "string") {
11102
- path3 = this.cwd.resolve(path3);
10634
+ depth(path4 = this.cwd) {
10635
+ if (typeof path4 === "string") {
10636
+ path4 = this.cwd.resolve(path4);
11103
10637
  }
11104
- return path3.depth();
10638
+ return path4.depth();
11105
10639
  }
11106
10640
  /**
11107
10641
  * Return the cache of child entries. Exposed so subclasses can create
@@ -11588,9 +11122,9 @@ var init_esm4 = __esm({
11588
11122
  process2();
11589
11123
  return results;
11590
11124
  }
11591
- chdir(path3 = this.cwd) {
11125
+ chdir(path4 = this.cwd) {
11592
11126
  const oldCwd = this.cwd;
11593
- this.cwd = typeof path3 === "string" ? this.cwd.resolve(path3) : path3;
11127
+ this.cwd = typeof path4 === "string" ? this.cwd.resolve(path4) : path4;
11594
11128
  this.cwd[setAsCwd](oldCwd);
11595
11129
  }
11596
11130
  };
@@ -11616,8 +11150,8 @@ var init_esm4 = __esm({
11616
11150
  /**
11617
11151
  * @internal
11618
11152
  */
11619
- newRoot(fs3) {
11620
- return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs3 });
11153
+ newRoot(fs5) {
11154
+ return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs5 });
11621
11155
  }
11622
11156
  /**
11623
11157
  * Return true if the provided path string is an absolute path
@@ -11645,8 +11179,8 @@ var init_esm4 = __esm({
11645
11179
  /**
11646
11180
  * @internal
11647
11181
  */
11648
- newRoot(fs3) {
11649
- return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs3 });
11182
+ newRoot(fs5) {
11183
+ return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs5 });
11650
11184
  }
11651
11185
  /**
11652
11186
  * Return true if the provided path string is an absolute path
@@ -11965,8 +11499,8 @@ var init_processor = __esm({
11965
11499
  }
11966
11500
  // match, absolute, ifdir
11967
11501
  entries() {
11968
- return [...this.store.entries()].map(([path3, n]) => [
11969
- path3,
11502
+ return [...this.store.entries()].map(([path4, n]) => [
11503
+ path4,
11970
11504
  !!(n & 2),
11971
11505
  !!(n & 1)
11972
11506
  ]);
@@ -12179,9 +11713,9 @@ var init_walker = __esm({
12179
11713
  signal;
12180
11714
  maxDepth;
12181
11715
  includeChildMatches;
12182
- constructor(patterns, path3, opts) {
11716
+ constructor(patterns, path4, opts) {
12183
11717
  this.patterns = patterns;
12184
- this.path = path3;
11718
+ this.path = path4;
12185
11719
  this.opts = opts;
12186
11720
  this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
12187
11721
  this.includeChildMatches = opts.includeChildMatches !== false;
@@ -12200,11 +11734,11 @@ var init_walker = __esm({
12200
11734
  });
12201
11735
  }
12202
11736
  }
12203
- #ignored(path3) {
12204
- return this.seen.has(path3) || !!this.#ignore?.ignored?.(path3);
11737
+ #ignored(path4) {
11738
+ return this.seen.has(path4) || !!this.#ignore?.ignored?.(path4);
12205
11739
  }
12206
- #childrenIgnored(path3) {
12207
- return !!this.#ignore?.childrenIgnored?.(path3);
11740
+ #childrenIgnored(path4) {
11741
+ return !!this.#ignore?.childrenIgnored?.(path4);
12208
11742
  }
12209
11743
  // backpressure mechanism
12210
11744
  pause() {
@@ -12419,8 +11953,8 @@ var init_walker = __esm({
12419
11953
  };
12420
11954
  GlobWalker = class extends GlobUtil {
12421
11955
  matches = /* @__PURE__ */ new Set();
12422
- constructor(patterns, path3, opts) {
12423
- super(patterns, path3, opts);
11956
+ constructor(patterns, path4, opts) {
11957
+ super(patterns, path4, opts);
12424
11958
  }
12425
11959
  matchEmit(e2) {
12426
11960
  this.matches.add(e2);
@@ -12457,8 +11991,8 @@ var init_walker = __esm({
12457
11991
  };
12458
11992
  GlobStream = class extends GlobUtil {
12459
11993
  results;
12460
- constructor(patterns, path3, opts) {
12461
- super(patterns, path3, opts);
11994
+ constructor(patterns, path4, opts) {
11995
+ super(patterns, path4, opts);
12462
11996
  this.results = new Minipass({
12463
11997
  signal: this.signal,
12464
11998
  objectMode: true
@@ -13689,6 +13223,7 @@ async function ingestSessionMessages(sessionId, transcriptPath, vendor, options)
13689
13223
  async function embedRowsResilient(rows) {
13690
13224
  const { embedBatch: embedBatch2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
13691
13225
  const { quantizeToQ8: quantizeToQ82, computeNorm: computeNorm2 } = await Promise.resolve().then(() => (init_quantize(), quantize_exports));
13226
+ rows = rows.map((r2) => ({ messageId: r2.messageId, text: DOC_PREFIX + r2.text }));
13692
13227
  const toRecord = (messageId, f32) => {
13693
13228
  const { q8, scale } = quantizeToQ82(f32);
13694
13229
  return { messageId, embeddingQ8: q8, norm: computeNorm2(f32), quantScale: scale };
@@ -13723,7 +13258,7 @@ async function embedMessageBatch(messages) {
13723
13258
  return 0;
13724
13259
  const truncated = [];
13725
13260
  for (const m2 of messages) {
13726
- const text = m2.message_text.trim();
13261
+ const text = (m2.embed_text ?? m2.message_text).trim();
13727
13262
  if (!text)
13728
13263
  continue;
13729
13264
  truncated.push({
@@ -13743,6 +13278,7 @@ var init_message_ingest = __esm({
13743
13278
  "use strict";
13744
13279
  init_transcript_utils();
13745
13280
  init_message_store();
13281
+ init_embed_config();
13746
13282
  init_db();
13747
13283
  init_paths();
13748
13284
  init_url_path_resolver();
@@ -15180,11 +14716,11 @@ function downloadFile2(url, destPath) {
15180
14716
  (0, import_node_https.get)(url, { headers: { "User-Agent": "recall" } }, pipeTo).on("error", done);
15181
14717
  });
15182
14718
  }
15183
- var import_node_child_process2, import_node_fs9, import_node_path9, import_node_util2, import_node_os6, import_node_https, import_extract_zip2, execFileAsync2, EXPECTED_DIMS2, OFFLOAD_TIMEOUT_MS, DEFAULT_NGL, CUDA_ASSET_NAME, CUDA_ASSET_URL, STAGE_DOWNLOAD_TIMEOUT_MS;
14719
+ var import_node_child_process3, import_node_fs9, import_node_path9, import_node_util2, import_node_os6, import_node_https, import_extract_zip2, execFileAsync2, EXPECTED_DIMS2, OFFLOAD_TIMEOUT_MS, DEFAULT_NGL, CUDA_ASSET_NAME, CUDA_ASSET_URL, STAGE_DOWNLOAD_TIMEOUT_MS;
15184
14720
  var init_gpu = __esm({
15185
14721
  "src/installer/gpu.ts"() {
15186
14722
  "use strict";
15187
- import_node_child_process2 = require("node:child_process");
14723
+ import_node_child_process3 = require("node:child_process");
15188
14724
  import_node_fs9 = require("node:fs");
15189
14725
  import_node_path9 = require("node:path");
15190
14726
  import_node_util2 = require("node:util");
@@ -15195,7 +14731,7 @@ var init_gpu = __esm({
15195
14731
  init_paths();
15196
14732
  init_config();
15197
14733
  init_log();
15198
- execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
14734
+ execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process3.execFile);
15199
14735
  EXPECTED_DIMS2 = 768;
15200
14736
  OFFLOAD_TIMEOUT_MS = 15e3;
15201
14737
  DEFAULT_NGL = 999;
@@ -15286,25 +14822,25 @@ function detectWsl() {
15286
14822
  return false;
15287
14823
  }
15288
14824
  }
15289
- function canWrite(path3) {
14825
+ function canWrite(path4) {
15290
14826
  try {
15291
- (0, import_node_fs10.accessSync)(path3, import_node_fs10.constants.W_OK);
14827
+ (0, import_node_fs10.accessSync)(path4, import_node_fs10.constants.W_OK);
15292
14828
  return true;
15293
14829
  } catch {
15294
14830
  return false;
15295
14831
  }
15296
14832
  }
15297
14833
  function checkPlatform(report, opts) {
15298
- const os2 = opts.platform ?? (0, import_node_os7.platform)();
14834
+ const os3 = opts.platform ?? (0, import_node_os7.platform)();
15299
14835
  const a3 = opts.arch ?? (0, import_node_os7.arch)();
15300
14836
  const isWsl = detectWsl();
15301
- const supported = os2 === "linux" && (a3 === "x64" || a3 === "arm64") || os2 === "darwin" && (a3 === "x64" || a3 === "arm64") || os2 === "win32" && a3 === "x64";
15302
- report.platform = { os: os2, arch: a3, isWsl, ok: supported };
14837
+ const supported = os3 === "linux" && (a3 === "x64" || a3 === "arm64") || os3 === "darwin" && (a3 === "x64" || a3 === "arm64") || os3 === "win32" && a3 === "x64";
14838
+ report.platform = { os: os3, arch: a3, isWsl, ok: supported };
15303
14839
  if (!supported) {
15304
14840
  report.failures.push({
15305
14841
  check: "platform",
15306
14842
  severity: "FAIL",
15307
- message: `Unsupported platform ${os2}/${a3}`,
14843
+ message: `Unsupported platform ${os3}/${a3}`,
15308
14844
  remediation: "recall supports Linux x64/arm64, macOS x64/arm64, Windows x64."
15309
14845
  });
15310
14846
  }
@@ -15590,10 +15126,140 @@ var init_manifest = __esm({
15590
15126
  }
15591
15127
  });
15592
15128
 
15129
+ // src/installer/upgrade-migrate.ts
15130
+ function openReadonly(dbFile) {
15131
+ const staged = (0, import_node_path11.join)(binDir(), "better_sqlite3.node");
15132
+ try {
15133
+ return (0, import_node_fs11.existsSync)(staged) ? new import_better_sqlite32.default(dbFile, { readonly: true, fileMustExist: true, nativeBinding: staged }) : new import_better_sqlite32.default(dbFile, { readonly: true, fileMustExist: true });
15134
+ } catch {
15135
+ try {
15136
+ return new import_better_sqlite32.default(dbFile, { readonly: true, fileMustExist: true });
15137
+ } catch {
15138
+ return null;
15139
+ }
15140
+ }
15141
+ }
15142
+ function classifyUpgrade() {
15143
+ const dbFile = dbPath();
15144
+ if (!(0, import_node_fs11.existsSync)(dbFile)) {
15145
+ return { state: "fresh", journalMode: null, markerPresent: false, coverage: 1 };
15146
+ }
15147
+ const markerPresent = (0, import_node_fs11.existsSync)((0, import_node_path11.join)(binDir(), ".binding-info.json"));
15148
+ let journalMode = null;
15149
+ let coverage = 1;
15150
+ const raw2 = openReadonly(dbFile);
15151
+ if (raw2) {
15152
+ try {
15153
+ journalMode = String(raw2.pragma("journal_mode", { simple: true }));
15154
+ } catch {
15155
+ journalMode = null;
15156
+ }
15157
+ try {
15158
+ const row = raw2.prepare(
15159
+ `SELECT COUNT(*) AS total,
15160
+ COALESCE(SUM(CASE WHEN embed_version = ? THEN 1 ELSE 0 END), 0) AS current
15161
+ FROM message_vectors`
15162
+ ).get(EMBED_VERSION);
15163
+ const total = row ? Number(row.total) : 0;
15164
+ const current = row ? Number(row.current ?? 0) : 0;
15165
+ coverage = total === 0 ? 1 : current / total;
15166
+ } catch {
15167
+ coverage = 1;
15168
+ }
15169
+ try {
15170
+ raw2.close();
15171
+ } catch {
15172
+ }
15173
+ }
15174
+ const state = markerPresent && journalMode === "wal" ? "already-migrated" : "needs-migration";
15175
+ return { state, journalMode, markerPresent, coverage };
15176
+ }
15177
+ function snapshotDb() {
15178
+ const dbFile = dbPath();
15179
+ if (!(0, import_node_fs11.existsSync)(dbFile))
15180
+ return null;
15181
+ const dest = `${dbFile}.pre-upgrade-${backupStamp()}`;
15182
+ try {
15183
+ (0, import_node_fs11.copyFileSync)(dbFile, dest);
15184
+ const journal = `${dbFile}-journal`;
15185
+ if ((0, import_node_fs11.existsSync)(journal))
15186
+ (0, import_node_fs11.copyFileSync)(journal, `${dest}-journal`);
15187
+ return dest;
15188
+ } catch (e2) {
15189
+ log({ source: "installer/upgrade", level: "warn", summary: `pre-upgrade snapshot failed: ${e2.message}` });
15190
+ return null;
15191
+ }
15192
+ }
15193
+ function integrityStatus() {
15194
+ try {
15195
+ const d3 = getDb(dbPath());
15196
+ const row = d3.get("PRAGMA integrity_check");
15197
+ const detail = row ? String(Object.values(row)[0] ?? "") : "unknown";
15198
+ return { ok: detail === "ok", detail };
15199
+ } catch (e2) {
15200
+ return { ok: false, detail: e2.message };
15201
+ }
15202
+ }
15203
+ function repairStemTables() {
15204
+ try {
15205
+ const d3 = getDb(dbPath());
15206
+ d3.exec("DROP TABLE IF EXISTS _stem_vocab");
15207
+ d3.exec("DROP TABLE IF EXISTS _stem");
15208
+ _resetDb();
15209
+ getDb(dbPath());
15210
+ return integrityStatus().ok;
15211
+ } catch {
15212
+ return false;
15213
+ }
15214
+ }
15215
+ function handleIntegrity() {
15216
+ const st = integrityStatus();
15217
+ if (st.ok)
15218
+ return { status: "ok" };
15219
+ if (/_stem/i.test(st.detail) && repairStemTables()) {
15220
+ return { status: "repaired-stem" };
15221
+ }
15222
+ return { status: "unrecoverable", detail: st.detail };
15223
+ }
15224
+ function backfillAlreadyRunning() {
15225
+ const pidFile = (0, import_node_path11.join)(runDir(), "backfill.pid");
15226
+ if (!(0, import_node_fs11.existsSync)(pidFile))
15227
+ return false;
15228
+ try {
15229
+ const pid = parseInt((0, import_node_fs11.readFileSync)(pidFile, "utf-8").trim(), 10);
15230
+ if (Number.isNaN(pid))
15231
+ return false;
15232
+ process.kill(pid, 0);
15233
+ return true;
15234
+ } catch {
15235
+ return false;
15236
+ }
15237
+ }
15238
+ function migrationReportLine(coverage) {
15239
+ if (coverage >= 1)
15240
+ return null;
15241
+ const pct = Math.round(coverage * 100);
15242
+ return `Embed migration: re-embedding in background (${pct}% at v${EMBED_VERSION}) \u2014 semantic search stays available`;
15243
+ }
15244
+ var import_node_fs11, import_node_path11, import_better_sqlite32;
15245
+ var init_upgrade_migrate = __esm({
15246
+ "src/installer/upgrade-migrate.ts"() {
15247
+ "use strict";
15248
+ import_node_fs11 = require("node:fs");
15249
+ import_node_path11 = require("node:path");
15250
+ import_better_sqlite32 = __toESM(require_lib());
15251
+ init_db();
15252
+ init_paths();
15253
+ init_embed_config();
15254
+ init_settings_merge();
15255
+ init_log();
15256
+ }
15257
+ });
15258
+
15593
15259
  // src/installer/claudemd-nudge.ts
15594
15260
  function applyNudge(filePath) {
15595
- const exists = (0, import_node_fs11.existsSync)(filePath);
15596
- const raw2 = exists ? (0, import_node_fs11.readFileSync)(filePath, "utf-8") : "";
15261
+ const exists = (0, import_node_fs12.existsSync)(filePath);
15262
+ const raw2 = exists ? (0, import_node_fs12.readFileSync)(filePath, "utf-8") : "";
15597
15263
  if (RECALL_HEADING.test(raw2))
15598
15264
  return { changed: false };
15599
15265
  const ending = raw2.includes("\r\n") ? "\r\n" : "\n";
@@ -15607,9 +15273,9 @@ function applyNudge(filePath) {
15607
15273
  return backup ? { changed: true, backup } : { changed: true };
15608
15274
  }
15609
15275
  function removeNudge(filePath) {
15610
- if (!(0, import_node_fs11.existsSync)(filePath))
15276
+ if (!(0, import_node_fs12.existsSync)(filePath))
15611
15277
  return { changed: false };
15612
- const raw2 = (0, import_node_fs11.readFileSync)(filePath, "utf-8");
15278
+ const raw2 = (0, import_node_fs12.readFileSync)(filePath, "utf-8");
15613
15279
  if (!RECALL_HEADING.test(raw2))
15614
15280
  return { changed: false };
15615
15281
  const ending = raw2.includes("\r\n") ? "\r\n" : "\n";
@@ -15637,11 +15303,11 @@ function removeNudge(filePath) {
15637
15303
  writeFileAtomic(filePath, next);
15638
15304
  return { changed: true, backup };
15639
15305
  }
15640
- var import_node_fs11, RECALL_BLOCK, RECALL_HEADING;
15306
+ var import_node_fs12, RECALL_BLOCK, RECALL_HEADING;
15641
15307
  var init_claudemd_nudge = __esm({
15642
15308
  "src/installer/claudemd-nudge.ts"() {
15643
15309
  "use strict";
15644
- import_node_fs11 = require("node:fs");
15310
+ import_node_fs12 = require("node:fs");
15645
15311
  init_settings_merge();
15646
15312
  RECALL_BLOCK = [
15647
15313
  "",
@@ -15665,60 +15331,132 @@ function defaultDistDir() {
15665
15331
  const argv1 = process.argv[1];
15666
15332
  if (argv1) {
15667
15333
  try {
15668
- return (0, import_node_path11.dirname)((0, import_node_fs12.realpathSync)(argv1));
15334
+ return (0, import_node_path12.dirname)((0, import_node_fs13.realpathSync)(argv1));
15669
15335
  } catch {
15670
- return (0, import_node_path11.dirname)(argv1);
15336
+ return (0, import_node_path12.dirname)(argv1);
15671
15337
  }
15672
15338
  }
15673
15339
  return __dirname;
15674
15340
  }
15675
15341
  function resolveTemplatePath(explicit) {
15676
- if (explicit && (0, import_node_fs12.existsSync)(explicit))
15342
+ if (explicit && (0, import_node_fs13.existsSync)(explicit))
15677
15343
  return explicit;
15678
15344
  const here = __dirname;
15679
15345
  const candidates = [
15680
- (0, import_node_path11.join)(here, "SKILL.md.template"),
15346
+ (0, import_node_path12.join)(here, "SKILL.md.template"),
15681
15347
  // bundled: copied next to recall.js
15682
- (0, import_node_path11.join)(here, "..", "skill", "SKILL.md.template"),
15348
+ (0, import_node_path12.join)(here, "..", "skill", "SKILL.md.template"),
15683
15349
  // dist/ sibling skill/
15684
- (0, import_node_path11.join)(here, "..", "..", "skill", "SKILL.md.template")
15350
+ (0, import_node_path12.join)(here, "..", "..", "skill", "SKILL.md.template")
15685
15351
  // source: src/installer/
15686
15352
  ];
15687
15353
  for (const c of candidates)
15688
- if ((0, import_node_fs12.existsSync)(c))
15354
+ if ((0, import_node_fs13.existsSync)(c))
15689
15355
  return c;
15690
15356
  return candidates[candidates.length - 1];
15691
15357
  }
15692
15358
  function recallBinCommand() {
15693
- return `node ${(0, import_node_path11.join)(binDir(), "recall.js")}`;
15359
+ return `"${process.execPath}" "${(0, import_node_path12.join)(binDir(), "recall.js")}"`;
15694
15360
  }
15695
15361
  function writeSkill(targetPath, templatePath, runnable) {
15696
- const template = (0, import_node_fs12.readFileSync)(templatePath, "utf-8");
15362
+ const template = (0, import_node_fs13.readFileSync)(templatePath, "utf-8");
15697
15363
  const body = template.replaceAll("$RECALL_BIN", runnable);
15698
- (0, import_node_fs12.mkdirSync)((0, import_node_path11.dirname)(targetPath), { recursive: true });
15699
- if ((0, import_node_fs12.existsSync)(targetPath)) {
15700
- if ((0, import_node_fs12.readFileSync)(targetPath, "utf-8") === body)
15364
+ (0, import_node_fs13.mkdirSync)((0, import_node_path12.dirname)(targetPath), { recursive: true });
15365
+ if ((0, import_node_fs13.existsSync)(targetPath)) {
15366
+ if ((0, import_node_fs13.readFileSync)(targetPath, "utf-8") === body)
15701
15367
  return false;
15702
15368
  backupFile(targetPath);
15703
15369
  }
15704
- (0, import_node_fs12.writeFileSync)(targetPath, body);
15370
+ (0, import_node_fs13.writeFileSync)(targetPath, body);
15705
15371
  return true;
15706
15372
  }
15707
15373
  function stageBundles(distDir, written) {
15708
- (0, import_node_fs12.mkdirSync)(binDir(), { recursive: true });
15374
+ (0, import_node_fs13.mkdirSync)(binDir(), { recursive: true });
15709
15375
  for (const name of STAGED_BUNDLES) {
15710
- const src = (0, import_node_path11.join)(distDir, name);
15711
- if (!(0, import_node_fs12.existsSync)(src)) {
15376
+ const src = (0, import_node_path12.join)(distDir, name);
15377
+ if (!(0, import_node_fs13.existsSync)(src)) {
15712
15378
  log({ source: "installer/install", level: "warn", summary: `bundle ${name} not found in ${distDir} \u2014 skipping stage` });
15713
15379
  continue;
15714
15380
  }
15715
- const dest = (0, import_node_path11.join)(binDir(), name);
15716
- (0, import_node_fs12.copyFileSync)(src, dest);
15381
+ const dest = (0, import_node_path12.join)(binDir(), name);
15382
+ (0, import_node_fs13.copyFileSync)(src, dest);
15717
15383
  written.push(dest);
15718
15384
  }
15719
- const wasm = (0, import_node_path11.join)(distDir, "node-sqlite3-wasm.wasm");
15720
- if ((0, import_node_fs12.existsSync)(wasm))
15721
- (0, import_node_fs12.copyFileSync)(wasm, (0, import_node_path11.join)(binDir(), "node-sqlite3-wasm.wasm"));
15385
+ stageNativeBinding(written);
15386
+ }
15387
+ function stageNativeBinding(written) {
15388
+ const staleWasm = (0, import_node_path12.join)(binDir(), "node-sqlite3-wasm.wasm");
15389
+ if ((0, import_node_fs13.existsSync)(staleWasm)) {
15390
+ try {
15391
+ (0, import_node_fs13.unlinkSync)(staleWasm);
15392
+ } catch {
15393
+ }
15394
+ }
15395
+ const binding = resolveInstalledBinding2();
15396
+ if (!binding) {
15397
+ log({
15398
+ source: "installer/install",
15399
+ level: "warn",
15400
+ summary: "better_sqlite3.node not found in node_modules \u2014 the CLI/hooks will fail to load SQLite until reinstalled"
15401
+ });
15402
+ return;
15403
+ }
15404
+ const dest = (0, import_node_path12.join)(binDir(), "better_sqlite3.node");
15405
+ (0, import_node_fs13.copyFileSync)(binding, dest);
15406
+ written.push(dest);
15407
+ const markerPath = (0, import_node_path12.join)(binDir(), ".binding-info.json");
15408
+ (0, import_node_fs13.writeFileSync)(
15409
+ markerPath,
15410
+ JSON.stringify(
15411
+ {
15412
+ platform: process.platform,
15413
+ arch: process.arch,
15414
+ nodeModuleVersion: process.versions.modules,
15415
+ nodePath: process.execPath
15416
+ },
15417
+ null,
15418
+ 2
15419
+ )
15420
+ );
15421
+ written.push(markerPath);
15422
+ }
15423
+ function resolveInstalledBinding2() {
15424
+ try {
15425
+ const pkgJson = (0, import_node_module2.createRequire)(__filename).resolve("better-sqlite3/package.json");
15426
+ return findDotNode((0, import_node_path12.dirname)(pkgJson));
15427
+ } catch {
15428
+ return null;
15429
+ }
15430
+ }
15431
+ function findDotNode(baseDir) {
15432
+ for (const c of [
15433
+ (0, import_node_path12.join)(baseDir, "build", "Release", "better_sqlite3.node"),
15434
+ (0, import_node_path12.join)(baseDir, "build", "Debug", "better_sqlite3.node")
15435
+ ]) {
15436
+ try {
15437
+ if ((0, import_node_fs13.statSync)(c).isFile())
15438
+ return c;
15439
+ } catch {
15440
+ }
15441
+ }
15442
+ const stack = [baseDir];
15443
+ while (stack.length) {
15444
+ const dir = stack.pop();
15445
+ let entries;
15446
+ try {
15447
+ entries = (0, import_node_fs13.readdirSync)(dir, { withFileTypes: true });
15448
+ } catch {
15449
+ continue;
15450
+ }
15451
+ for (const e2 of entries) {
15452
+ const p = (0, import_node_path12.join)(dir, e2.name);
15453
+ if (e2.isDirectory())
15454
+ stack.push(p);
15455
+ else if (e2.name.endsWith(".node"))
15456
+ return p;
15457
+ }
15458
+ }
15459
+ return null;
15722
15460
  }
15723
15461
  async function runInstall(opts = {}) {
15724
15462
  const interactive = !!process.stdout.isTTY && !opts.yes && !opts.json;
@@ -15775,21 +15513,41 @@ ${wmsg}` });
15775
15513
  log({ source: "installer/install", level: "error", summary: msg });
15776
15514
  return { aborted: true, report, selected: [...selected], gpu: { mode: "cpu", libDir: null, ngl: 0, cudaAvailable: "none" }, filesWritten: [] };
15777
15515
  }
15516
+ const migration = classifyUpgrade();
15778
15517
  const filesWritten = [];
15779
15518
  let gpu = { mode: "cpu", libDir: null, ngl: 0, cudaAvailable: "none" };
15780
15519
  let backfillPid;
15520
+ let snapshotPath;
15521
+ let integrity;
15522
+ let drainLaunched = false;
15781
15523
  try {
15524
+ if (migration.state === "needs-migration") {
15525
+ for (const p of [claudeSettingsPath(), codexHooksPath()]) {
15526
+ const r2 = removeStopHook(p);
15527
+ if (r2.changed)
15528
+ filesWritten.push(p);
15529
+ }
15530
+ say("upgrade: quiesced stale Stop hook before migration");
15531
+ }
15782
15532
  for (const d3 of [binDir(), modelsDir(), runDir(), logsDir()])
15783
- (0, import_node_fs12.mkdirSync)(d3, { recursive: true });
15533
+ (0, import_node_fs13.mkdirSync)(d3, { recursive: true });
15784
15534
  stageBundles(opts.distDir ?? defaultDistDir(), filesWritten);
15785
15535
  say(`scaffolded ${recallRoot()}`);
15786
15536
  if (opts.offline) {
15787
- const haveBin = (0, import_node_fs12.existsSync)(getBinaryPath());
15788
- const haveModel = (0, import_node_fs12.existsSync)(getModelPath());
15537
+ const haveBin = (0, import_node_fs13.existsSync)(getBinaryPath());
15538
+ const haveModel = (0, import_node_fs13.existsSync)(getModelPath());
15789
15539
  if (!haveBin || !haveModel) {
15790
- const msg = `--offline but runtime not pre-staged (binary=${haveBin}, model=${haveModel}).`;
15540
+ const msg = `--offline but runtime not pre-staged (binary=${haveBin}, model=${haveModel}). Pre-stage ~/.recall/bin + model (or drop --offline), then re-run \`recall install\`` + (migration.state === "needs-migration" ? " (which restores the recall Stop hook)." : ".");
15791
15541
  log({ source: "installer/install", level: "error", summary: msg });
15792
- return { aborted: true, report, selected: [...selected], gpu, filesWritten };
15542
+ return {
15543
+ aborted: true,
15544
+ abortReason: msg,
15545
+ report,
15546
+ selected: [...selected],
15547
+ gpu,
15548
+ filesWritten,
15549
+ migration: { state: migration.state, coverage: migration.coverage, drainLaunched: false }
15550
+ };
15793
15551
  }
15794
15552
  say("offline: CPU runtime already staged");
15795
15553
  } else {
@@ -15806,11 +15564,75 @@ ${wmsg}` });
15806
15564
  ...opts.offline ? { offline: true } : {}
15807
15565
  });
15808
15566
  say(gpu.mode === "gpu" ? `GPU acceleration enabled (${gpu.cudaAvailable})` : `using CPU embeddings${gpu.reason ? ` (${gpu.reason})` : ""}`);
15809
- getDb(dbPath());
15567
+ if (migration.state === "needs-migration") {
15568
+ snapshotPath = snapshotDb() ?? void 0;
15569
+ say(snapshotPath ? `pre-upgrade snapshot: ${snapshotPath}` : "pre-upgrade snapshot skipped (no DB / copy failed)");
15570
+ }
15571
+ try {
15572
+ getDb(dbPath());
15573
+ } catch (e2) {
15574
+ const emsg = e2.message;
15575
+ const rerun = migration.state === "needs-migration" ? " Then re-run `recall install` to finish migrating and restore the recall Stop hook." : " Then re-run `recall install`.";
15576
+ let remediation;
15577
+ if (isBindingLoadError(e2)) {
15578
+ remediation = `The native SQLite binding failed to load (${emsg}). Run \`recall install\` (or \`recall doctor\`).`;
15579
+ } else if (/database is locked|SQLITE_BUSY|busy_timeout/i.test(emsg)) {
15580
+ remediation = `A live session is holding the database. Exit all Claude/Codex sessions.${rerun}`;
15581
+ } else if (/expected WAL journal_mode/i.test(emsg)) {
15582
+ remediation = `recall could not enable WAL on this filesystem (e.g. a network / virtual mount). Put ~/.recall on a local disk (or set RECALL_HOME to one).${rerun}`;
15583
+ } else {
15584
+ remediation = `Could not open the database (${emsg}). Run \`recall doctor --integrity\`; if unrecoverable, rebuild from JSONL with \`recall repair --full\`.${rerun}`;
15585
+ }
15586
+ if (interactive)
15587
+ le(remediation, "Migration aborted");
15588
+ else
15589
+ log({ source: "installer/install", level: "error", summary: `migration aborted: ${remediation}` });
15590
+ return {
15591
+ aborted: true,
15592
+ abortReason: remediation,
15593
+ report,
15594
+ selected: [...selected],
15595
+ gpu,
15596
+ filesWritten,
15597
+ migration: {
15598
+ state: migration.state,
15599
+ coverage: migration.coverage,
15600
+ drainLaunched: false,
15601
+ ...snapshotPath ? { snapshotPath } : {}
15602
+ }
15603
+ };
15604
+ }
15810
15605
  say("database initialized");
15606
+ if (migration.state === "needs-migration") {
15607
+ const res = handleIntegrity();
15608
+ integrity = res.status;
15609
+ if (res.status === "unrecoverable") {
15610
+ const remediation = `Database integrity check failed (${res.detail ?? "unknown"}) and could not be auto-repaired. Your pre-upgrade snapshot is preserved at ${snapshotPath ?? "(snapshot unavailable)"}. Rebuild the index from JSONL with \`recall repair --full\`, then re-run \`recall install\` to restore the recall Stop hook.`;
15611
+ if (interactive)
15612
+ le(remediation, "Migration aborted");
15613
+ else
15614
+ log({ source: "installer/install", level: "error", summary: `migration aborted: ${remediation}` });
15615
+ return {
15616
+ aborted: true,
15617
+ abortReason: remediation,
15618
+ report,
15619
+ selected: [...selected],
15620
+ gpu,
15621
+ filesWritten,
15622
+ migration: {
15623
+ state: migration.state,
15624
+ coverage: migration.coverage,
15625
+ drainLaunched: false,
15626
+ integrity,
15627
+ ...snapshotPath ? { snapshotPath } : {}
15628
+ }
15629
+ };
15630
+ }
15631
+ say(res.status === "repaired-stem" ? "upgrade: repaired corrupt _stem index" : "upgrade: integrity check passed");
15632
+ }
15811
15633
  const runnable = recallBinCommand();
15812
15634
  const templatePath = resolveTemplatePath(opts.templatePath);
15813
- const hookScript = (0, import_node_path11.join)(binDir(), "stop-hook.js");
15635
+ const hookScript = (0, import_node_path12.join)(binDir(), "stop-hook.js");
15814
15636
  if (selected.has("skill")) {
15815
15637
  if (writeSkill(claudeRecallSkillPath(), templatePath, runnable))
15816
15638
  filesWritten.push(claudeRecallSkillPath());
@@ -15834,7 +15656,11 @@ ${wmsg}` });
15834
15656
  if (r2.changed)
15835
15657
  filesWritten.push(codexAgentsPath());
15836
15658
  }
15659
+ if (filesWritten.length !== new Set(filesWritten).size) {
15660
+ filesWritten.splice(0, filesWritten.length, ...new Set(filesWritten));
15661
+ }
15837
15662
  say(`wrote ${filesWritten.length} files`);
15663
+ const coverage = getEmbedVersionStats().coverage;
15838
15664
  if (opts.noBackfill) {
15839
15665
  say("backfill skipped (--no-backfill)");
15840
15666
  } else if (opts.autoBackfill) {
@@ -15845,56 +15671,84 @@ ${wmsg}` });
15845
15671
  await startRecallCatchup2({ autoEmbed: true });
15846
15672
  await mtimeScan2();
15847
15673
  sp?.stop("Backfill complete");
15674
+ drainLaunched = true;
15675
+ } else if (backfillAlreadyRunning()) {
15676
+ say("backfill already running in background \u2014 not relaunching");
15677
+ } else if (migration.state === "already-migrated" && coverage >= 1 && getEmbeddingGapStats().gapCount === 0) {
15678
+ say("already migrated (all vectors current) \u2014 no background re-embed needed");
15848
15679
  } else {
15849
15680
  backfillPid = spawnDetachedBackfill();
15681
+ drainLaunched = backfillPid !== void 0;
15850
15682
  say(backfillPid ? `backfill running in background (PID ${backfillPid})` : "backfill could not be launched");
15851
15683
  }
15852
15684
  } finally {
15853
15685
  releaseInstallLock();
15854
15686
  }
15687
+ const finalCoverage = getEmbedVersionStats().coverage;
15688
+ const migrationInfo = {
15689
+ state: migration.state,
15690
+ coverage: finalCoverage,
15691
+ drainLaunched,
15692
+ ...snapshotPath ? { snapshotPath } : {},
15693
+ ...integrity ? { integrity } : {}
15694
+ };
15695
+ const migLine = migrationReportLine(finalCoverage);
15855
15696
  if (interactive) {
15856
15697
  const lines = [
15857
15698
  gpu.mode === "gpu" ? "GPU acceleration: enabled" : `Embeddings: CPU${gpu.reason ? ` (${gpu.reason})` : ""}`,
15858
15699
  `Files written/edited: ${filesWritten.length}`,
15859
15700
  backfillPid ? `Backfill running in background (PID ${backfillPid}) \u2014 check with \`recall status\`.` : "Backfill: see above",
15701
+ ...migLine ? [migLine] : [],
15860
15702
  'Try it \u2014 ask Claude: "what did I work on yesterday?"',
15861
15703
  "Commands: recall doctor \xB7 recall status \xB7 recall uninstall"
15862
15704
  ];
15863
15705
  $e(lines.join("\n"));
15706
+ } else if (migLine) {
15707
+ log({ source: "installer/install", level: "info", summary: migLine });
15864
15708
  }
15865
- return { report, selected: [...selected], gpu, filesWritten, ...backfillPid ? { backfillPid } : {} };
15709
+ return {
15710
+ report,
15711
+ selected: [...selected],
15712
+ gpu,
15713
+ filesWritten,
15714
+ migration: migrationInfo,
15715
+ ...backfillPid ? { backfillPid } : {}
15716
+ };
15866
15717
  }
15867
15718
  function spawnDetachedBackfill() {
15868
- (0, import_node_fs12.mkdirSync)(runDir(), { recursive: true });
15869
- (0, import_node_fs12.mkdirSync)(logsDir(), { recursive: true });
15870
- const recallBundle = (0, import_node_path11.join)(binDir(), "recall.js");
15871
- const logFd = (0, import_node_fs12.openSync)((0, import_node_path11.join)(logsDir(), "backfill.log"), "a");
15872
- const child = (0, import_node_child_process3.spawn)(process.execPath, [recallBundle, "backfill", "--auto-embed"], {
15719
+ (0, import_node_fs13.mkdirSync)(runDir(), { recursive: true });
15720
+ (0, import_node_fs13.mkdirSync)(logsDir(), { recursive: true });
15721
+ const recallBundle = (0, import_node_path12.join)(binDir(), "recall.js");
15722
+ const logFd = (0, import_node_fs13.openSync)((0, import_node_path12.join)(logsDir(), "backfill.log"), "a");
15723
+ const child = (0, import_node_child_process4.spawn)(process.execPath, [recallBundle, "backfill", "--auto-embed"], {
15873
15724
  detached: true,
15874
15725
  stdio: ["ignore", logFd, logFd],
15875
15726
  windowsHide: true,
15876
15727
  env: { ...process.env }
15877
15728
  });
15878
15729
  if (child.pid !== void 0) {
15879
- (0, import_node_fs12.writeFileSync)((0, import_node_path11.join)(runDir(), "backfill.pid"), String(child.pid));
15730
+ (0, import_node_fs13.writeFileSync)((0, import_node_path12.join)(runDir(), "backfill.pid"), String(child.pid));
15880
15731
  }
15881
15732
  child.unref();
15882
15733
  return child.pid;
15883
15734
  }
15884
- var import_node_fs12, import_node_child_process3, import_node_path11, STAGED_BUNDLES;
15735
+ var import_node_fs13, import_node_child_process4, import_node_module2, import_node_path12, STAGED_BUNDLES;
15885
15736
  var init_install = __esm({
15886
15737
  "src/installer/install.ts"() {
15887
15738
  "use strict";
15888
15739
  init_dist2();
15889
- import_node_fs12 = require("node:fs");
15890
- import_node_child_process3 = require("node:child_process");
15891
- import_node_path11 = require("node:path");
15740
+ import_node_fs13 = require("node:fs");
15741
+ import_node_child_process4 = require("node:child_process");
15742
+ import_node_module2 = require("node:module");
15743
+ import_node_path12 = require("node:path");
15892
15744
  init_paths();
15893
15745
  init_db();
15746
+ init_message_store();
15894
15747
  init_preflight();
15895
15748
  init_manifest();
15896
15749
  init_gpu();
15897
15750
  init_settings_merge();
15751
+ init_upgrade_migrate();
15898
15752
  init_claudemd_nudge();
15899
15753
  init_embedder();
15900
15754
  init_log();
@@ -15910,9 +15764,9 @@ __export(uninstall_exports, {
15910
15764
  function runUninstall(opts = {}) {
15911
15765
  const removed = [];
15912
15766
  for (const skillFile of [claudeRecallSkillPath(), codexRecallSkillPath()]) {
15913
- const dir = (0, import_node_path12.dirname)(skillFile);
15914
- if ((0, import_node_fs13.existsSync)(dir)) {
15915
- (0, import_node_fs13.rmSync)(dir, { recursive: true, force: true });
15767
+ const dir = (0, import_node_path13.dirname)(skillFile);
15768
+ if ((0, import_node_fs14.existsSync)(dir)) {
15769
+ (0, import_node_fs14.rmSync)(dir, { recursive: true, force: true });
15916
15770
  removed.push(dir);
15917
15771
  }
15918
15772
  }
@@ -15927,8 +15781,8 @@ function runUninstall(opts = {}) {
15927
15781
  let purged = false;
15928
15782
  if (opts.purge) {
15929
15783
  closeDb();
15930
- if ((0, import_node_fs13.existsSync)(recallRoot())) {
15931
- (0, import_node_fs13.rmSync)(recallRoot(), { recursive: true, force: true });
15784
+ if ((0, import_node_fs14.existsSync)(recallRoot())) {
15785
+ (0, import_node_fs14.rmSync)(recallRoot(), { recursive: true, force: true });
15932
15786
  removed.push(recallRoot());
15933
15787
  }
15934
15788
  purged = true;
@@ -15936,12 +15790,12 @@ function runUninstall(opts = {}) {
15936
15790
  log({ source: "installer/uninstall", level: "info", summary: `uninstall removed ${removed.length} targets (purge=${purged})` });
15937
15791
  return { removed, purged };
15938
15792
  }
15939
- var import_node_fs13, import_node_path12;
15793
+ var import_node_fs14, import_node_path13;
15940
15794
  var init_uninstall = __esm({
15941
15795
  "src/installer/uninstall.ts"() {
15942
15796
  "use strict";
15943
- import_node_fs13 = require("node:fs");
15944
- import_node_path12 = require("node:path");
15797
+ import_node_fs14 = require("node:fs");
15798
+ import_node_path13 = require("node:path");
15945
15799
  init_settings_merge();
15946
15800
  init_claudemd_nudge();
15947
15801
  init_preflight();
@@ -15962,13 +15816,14 @@ function getStatus() {
15962
15816
  const messageCount = d3.get("SELECT COUNT(*) AS c FROM messages").c;
15963
15817
  const lastRow = d3.get("SELECT MAX(created_at) AS m FROM messages");
15964
15818
  const lastIngest = lastRow.m ? new Date(lastRow.m).toISOString() : null;
15965
- const dbSizeBytes = (0, import_node_fs14.existsSync)(dbPath()) ? (0, import_node_fs14.statSync)(dbPath()).size : 0;
15819
+ const dbSizeBytes = (0, import_node_fs15.existsSync)(dbPath()) ? (0, import_node_fs15.statSync)(dbPath()).size : 0;
15966
15820
  const embeddingGap = getEmbeddingGapStats();
15821
+ const embedVersions = getEmbedVersionStats();
15967
15822
  let backfillPid = null;
15968
15823
  let backfillRunning = false;
15969
- const pidFile = (0, import_node_path13.join)(runDir(), "backfill.pid");
15970
- if ((0, import_node_fs14.existsSync)(pidFile)) {
15971
- const pid = parseInt((0, import_node_fs14.readFileSync)(pidFile, "utf-8").trim(), 10);
15824
+ const pidFile = (0, import_node_path14.join)(runDir(), "backfill.pid");
15825
+ if ((0, import_node_fs15.existsSync)(pidFile)) {
15826
+ const pid = parseInt((0, import_node_fs15.readFileSync)(pidFile, "utf-8").trim(), 10);
15972
15827
  if (!Number.isNaN(pid)) {
15973
15828
  backfillPid = pid;
15974
15829
  try {
@@ -15985,6 +15840,7 @@ function getStatus() {
15985
15840
  messageCount,
15986
15841
  lastIngest,
15987
15842
  embeddingGap,
15843
+ embedVersions,
15988
15844
  backfillPid,
15989
15845
  backfillRunning,
15990
15846
  embedder: readEmbedderConfig().mode
@@ -16003,18 +15859,23 @@ function printStatus(json) {
16003
15859
  console.log(`Messages: ${s.messageCount}`);
16004
15860
  console.log(`Last ingest: ${s.lastIngest ?? "never"}`);
16005
15861
  console.log(`Embedding gap: ${s.embeddingGap.gapCount} of ${s.embeddingGap.totalMessages} unembedded`);
15862
+ if (s.embedVersions.coverage < 1) {
15863
+ const pct = Math.round(s.embedVersions.coverage * 100);
15864
+ console.log(`Embed migration: ${s.embedVersions.current} of ${s.embedVersions.total} at v${EMBED_VERSION} (${pct}%)`);
15865
+ }
16006
15866
  console.log(`Embedder: ${s.embedder.toUpperCase()}`);
16007
15867
  console.log(`Backfill: ${s.backfillPid === null ? "none recorded" : `PID ${s.backfillPid} (${s.backfillRunning ? "running" : "finished"})`}`);
16008
15868
  }
16009
- var import_node_fs14, import_node_path13;
15869
+ var import_node_fs15, import_node_path14;
16010
15870
  var init_status = __esm({
16011
15871
  "src/installer/status.ts"() {
16012
15872
  "use strict";
16013
- import_node_fs14 = require("node:fs");
16014
- import_node_path13 = require("node:path");
15873
+ import_node_fs15 = require("node:fs");
15874
+ import_node_path14 = require("node:path");
16015
15875
  init_db();
16016
15876
  init_paths();
16017
15877
  init_message_store();
15878
+ init_embed_config();
16018
15879
  init_config();
16019
15880
  }
16020
15881
  });
@@ -16068,7 +15929,7 @@ async function repairFull(opts = {}) {
16068
15929
  }
16069
15930
  }
16070
15931
  const d3 = db3();
16071
- d3.exec("BEGIN");
15932
+ d3.exec("BEGIN IMMEDIATE");
16072
15933
  try {
16073
15934
  d3.exec("DELETE FROM messages;");
16074
15935
  d3.exec("DELETE FROM ingest_watermark;");
@@ -16107,12 +15968,125 @@ async function runDoctor(opts = {}) {
16107
15968
  return printIntegrity(opts.json ?? false);
16108
15969
  const report = await runPreflight({ ...opts.offline ? { offline: true } : {} });
16109
15970
  const embedder = readConfig()?.embedder ?? null;
15971
+ const binding = checkBindingHealth();
16110
15972
  if (opts.json) {
16111
- console.log(JSON.stringify({ ...report, embedder }, null, 2));
15973
+ console.log(JSON.stringify({ ...report, embedder, binding }, null, 2));
16112
15974
  } else {
16113
15975
  printTable(report, embedder?.mode ?? "cpu", embedder?.fallbackReason);
15976
+ printBinding(binding);
15977
+ }
15978
+ const bindingFailed = binding.installed && binding.problems.length > 0;
15979
+ return report.failures.length > 0 || bindingFailed ? 1 : 0;
15980
+ }
15981
+ function stagedBindingPath() {
15982
+ return (0, import_node_path15.join)(binDir(), "better_sqlite3.node");
15983
+ }
15984
+ function checkBindingHealth() {
15985
+ const problems = [];
15986
+ const installed = (0, import_node_fs16.existsSync)((0, import_node_path15.join)(binDir(), "recall.js"));
15987
+ if (!installed) {
15988
+ return {
15989
+ installed: false,
15990
+ markerPresent: false,
15991
+ abiOk: null,
15992
+ pinnedNodeOk: null,
15993
+ bindingLoads: false,
15994
+ journalMode: null,
15995
+ embedCoverage: null,
15996
+ problems: ["recall is not installed \u2014 run `recall install`"]
15997
+ };
15998
+ }
15999
+ const markerPath = (0, import_node_path15.join)(binDir(), ".binding-info.json");
16000
+ const markerPresent = (0, import_node_fs16.existsSync)(markerPath);
16001
+ let abiOk = null;
16002
+ let pinnedNodeOk = null;
16003
+ if (!markerPresent) {
16004
+ problems.push("no .binding-info.json marker \u2014 pre-migration (wasm-era) install; run `recall install`");
16005
+ } else {
16006
+ try {
16007
+ const marker = JSON.parse((0, import_node_fs16.readFileSync)(markerPath, "utf-8"));
16008
+ abiOk = String(marker.nodeModuleVersion) === String(process.versions.modules);
16009
+ if (!abiOk) {
16010
+ problems.push(
16011
+ `binding ABI mismatch (staged for NODE_MODULE_VERSION ${marker.nodeModuleVersion}, current ${process.versions.modules}) \u2014 run \`recall install\``
16012
+ );
16013
+ }
16014
+ pinnedNodeOk = !!marker.nodePath && (0, import_node_fs16.existsSync)(marker.nodePath);
16015
+ if (!pinnedNodeOk) {
16016
+ problems.push(`pinned Node path missing (${marker.nodePath ?? "unset"}) \u2014 run \`recall install\``);
16017
+ }
16018
+ } catch {
16019
+ problems.push("unreadable .binding-info.json marker \u2014 run `recall install`");
16020
+ }
16021
+ }
16022
+ let bindingLoads = false;
16023
+ let journalMode = null;
16024
+ let embedCoverage = null;
16025
+ const localBinding = stagedBindingPath();
16026
+ const dbFile = dbPath();
16027
+ if ((0, import_node_fs16.existsSync)(dbFile)) {
16028
+ try {
16029
+ const raw2 = (0, import_node_fs16.existsSync)(localBinding) ? new import_better_sqlite33.default(dbFile, { readonly: true, fileMustExist: true, nativeBinding: localBinding }) : new import_better_sqlite33.default(dbFile, { readonly: true, fileMustExist: true });
16030
+ bindingLoads = true;
16031
+ journalMode = String(raw2.pragma("journal_mode", { simple: true }));
16032
+ try {
16033
+ const row = raw2.prepare(
16034
+ `SELECT COUNT(*) AS total,
16035
+ COALESCE(SUM(CASE WHEN embed_version = ? THEN 1 ELSE 0 END), 0) AS current
16036
+ FROM message_vectors`
16037
+ ).get(EMBED_VERSION);
16038
+ const total = row ? Number(row.total) : 0;
16039
+ const current = row ? Number(row.current ?? 0) : 0;
16040
+ embedCoverage = total === 0 ? null : current / total;
16041
+ } catch {
16042
+ embedCoverage = null;
16043
+ }
16044
+ raw2.close();
16045
+ if (journalMode !== "wal") {
16046
+ problems.push(
16047
+ `live DB journal_mode is '${journalMode}', not 'wal' \u2014 a native build on a non-WAL DB is drift (the WAL conversion is a separate attended step; do not restage over a delete-mode DB blindly)`
16048
+ );
16049
+ }
16050
+ } catch (e2) {
16051
+ if (isBindingLoadError(e2)) {
16052
+ problems.push("better_sqlite3.node failed to load (ABI/dlopen) \u2014 run `recall install`");
16053
+ } else {
16054
+ problems.push(`could not read live DB journal_mode: ${e2.message}`);
16055
+ }
16056
+ }
16057
+ } else {
16058
+ try {
16059
+ const raw2 = (0, import_node_fs16.existsSync)(localBinding) ? new import_better_sqlite33.default(":memory:", { nativeBinding: localBinding }) : new import_better_sqlite33.default(":memory:");
16060
+ bindingLoads = true;
16061
+ raw2.close();
16062
+ } catch (e2) {
16063
+ problems.push(
16064
+ isBindingLoadError(e2) ? "better_sqlite3.node failed to load (ABI/dlopen) \u2014 run `recall install`" : `binding self-test failed: ${e2.message}`
16065
+ );
16066
+ }
16067
+ }
16068
+ return { installed, markerPresent, abiOk, pinnedNodeOk, bindingLoads, journalMode, embedCoverage, problems };
16069
+ }
16070
+ function printBinding(b3) {
16071
+ const ok = (v2) => v2 ? "OK" : "FAIL";
16072
+ console.log("\nSQLite binding (better-sqlite3, native WAL)");
16073
+ console.log("------------------------------------------");
16074
+ if (!b3.installed) {
16075
+ console.log(" not installed \u2014 run `recall install`");
16076
+ return;
16077
+ }
16078
+ console.log(`Binding loads: ${ok(b3.bindingLoads)}`);
16079
+ console.log(`ABI marker: ${b3.markerPresent ? b3.abiOk ? "OK" : "MISMATCH" : "absent (wasm-era)"}`);
16080
+ console.log(`Pinned Node: ${b3.pinnedNodeOk === null ? "n/a" : ok(b3.pinnedNodeOk)}`);
16081
+ console.log(`journal_mode: ${b3.journalMode ?? "no DB yet"}${b3.journalMode && b3.journalMode !== "wal" ? " [DRIFT]" : ""}`);
16082
+ if (b3.embedCoverage !== null && b3.embedCoverage < 1) {
16083
+ console.log(`Embed migration: re-embedding to v${EMBED_VERSION} (${Math.round(b3.embedCoverage * 100)}%) \u2014 semantic search stays available`);
16084
+ }
16085
+ if (b3.problems.length) {
16086
+ console.log(" Issues:");
16087
+ for (const p of b3.problems)
16088
+ console.log(` \u2716 ${p}`);
16114
16089
  }
16115
- return report.failures.length > 0 ? 1 : 0;
16116
16090
  }
16117
16091
  function printIntegrity(json) {
16118
16092
  const r2 = integrityCheck();
@@ -16156,12 +16130,19 @@ function printTable(report, embedderMode, fallbackReason) {
16156
16130
  if (!report.warnings.length && !report.failures.length)
16157
16131
  console.log("\nAll checks passed.");
16158
16132
  }
16133
+ var import_node_fs16, import_node_path15, import_better_sqlite33;
16159
16134
  var init_doctor = __esm({
16160
16135
  "src/installer/doctor.ts"() {
16161
16136
  "use strict";
16137
+ import_node_fs16 = require("node:fs");
16138
+ import_node_path15 = require("node:path");
16139
+ import_better_sqlite33 = __toESM(require_lib());
16162
16140
  init_preflight();
16163
16141
  init_config();
16164
16142
  init_repair();
16143
+ init_db();
16144
+ init_paths();
16145
+ init_embed_config();
16165
16146
  }
16166
16147
  });
16167
16148
 
@@ -16169,23 +16150,31 @@ var init_doctor = __esm({
16169
16150
  init_embedder();
16170
16151
  init_quantize();
16171
16152
  init_message_store();
16153
+ init_embed_config();
16172
16154
  init_log();
16173
16155
  var DEFAULT_LIMIT = 200;
16174
16156
  var FETCH_MULTIPLIER = 3;
16175
16157
  var RRF_K = 60;
16176
- var DEFAULT_RECENCY_DECAY = 0.02;
16177
16158
  var SEMANTIC_DISCOVERY_BOOST = 1.05;
16159
+ function recencyMultiplier(decay, ageMs) {
16160
+ if (!(decay && decay > 0))
16161
+ return 1;
16162
+ const ageDays = Math.max(0, ageMs) / 864e5;
16163
+ return 1 / (1 + ageDays * decay);
16164
+ }
16178
16165
  async function dualPathSearch(query, opts) {
16179
16166
  const limit2 = opts?.limit ?? DEFAULT_LIMIT;
16180
16167
  const fetchLimit = limit2 * FETCH_MULTIPLIER;
16181
16168
  if (!query.trim())
16182
- return { results: [], scored: [], semanticAvailable: false, ftsCount: 0, semanticCount: 0 };
16169
+ return { results: [], scored: [], semanticAvailable: false, ftsCount: 0, semanticCount: 0, embedCoverage: 1 };
16170
+ const embedCoverage = getEmbedVersionStats().coverage;
16171
+ const tolerant = embedCoverage < 0.95;
16183
16172
  let queryQ8 = null;
16184
16173
  let queryNorm = 0;
16185
16174
  let queryScale = 0;
16186
16175
  let semanticAvailable = true;
16187
16176
  try {
16188
- const queryF32 = await embed(query);
16177
+ const queryF32 = await embed(QUERY_PREFIX + query);
16189
16178
  queryNorm = computeNorm(queryF32);
16190
16179
  const quantized = quantizeToQ8(queryF32);
16191
16180
  queryQ8 = quantized.q8;
@@ -16198,32 +16187,31 @@ async function dualPathSearch(query, opts) {
16198
16187
  summary: `Semantic path disabled \u2014 embed() failed: ${err instanceof Error ? err.message : String(err)}`
16199
16188
  });
16200
16189
  }
16201
- const ftsResults = searchMessagesFts(query, fetchLimit, opts?.projectId, opts?.sessionId, opts?.excludeSessionId);
16190
+ const ftsResults = searchMessagesFts(query, fetchLimit, opts?.projectId, opts?.sessionId, opts?.excludeSessionId, opts?.skipIdf);
16202
16191
  const semanticResults = queryQ8 && queryNorm > 0 ? searchMessagesSemantic(queryQ8, queryNorm, queryScale, {
16203
16192
  limit: fetchLimit,
16204
16193
  projectId: opts?.projectId,
16205
16194
  sessionId: opts?.sessionId,
16206
- excludeSessionId: opts?.excludeSessionId
16195
+ excludeSessionId: opts?.excludeSessionId,
16196
+ tolerant
16207
16197
  }) : [];
16208
16198
  log({
16209
16199
  source: "recall:dual-path",
16210
16200
  level: semanticAvailable ? "info" : "warn",
16211
16201
  summary: `FTS5: ${ftsResults.length} results, Semantic: ${semanticResults.length} results${!semanticAvailable ? " (UNAVAILABLE \u2014 embed failed)" : ""}`
16212
16202
  });
16213
- const decay = opts?.recencyDecay ?? DEFAULT_RECENCY_DECAY;
16203
+ const decay = opts?.recencyDecay;
16214
16204
  const now = Date.now();
16215
16205
  const rrfScores = /* @__PURE__ */ new Map();
16216
16206
  for (let i = 0; i < ftsResults.length; i++) {
16217
16207
  const r2 = ftsResults[i];
16218
- const ageDays = (now - r2.created_at) / 864e5;
16219
- const recency = 1 / (1 + ageDays * decay);
16208
+ const recency = recencyMultiplier(decay, now - r2.created_at);
16220
16209
  rrfScores.set(r2.message_id, { result: r2, score: 1 / (RRF_K + i) * recency, paths: ["fts5"] });
16221
16210
  }
16222
16211
  const ftsSessionIdSet = new Set(ftsResults.map((r2) => r2.session_id));
16223
16212
  for (let i = 0; i < semanticResults.length; i++) {
16224
16213
  const r2 = semanticResults[i];
16225
- const ageDays = (now - r2.created_at) / 864e5;
16226
- const recency = 1 / (1 + ageDays * decay);
16214
+ const recency = recencyMultiplier(decay, now - r2.created_at);
16227
16215
  const rrfScore = 1 / (RRF_K + i) * recency;
16228
16216
  const existing = rrfScores.get(r2.message_id);
16229
16217
  if (existing) {
@@ -16246,7 +16234,8 @@ async function dualPathSearch(query, opts) {
16246
16234
  // full list with RRF scores — groupBySession uses for gap detection
16247
16235
  semanticAvailable,
16248
16236
  ftsCount: ftsResults.length,
16249
- semanticCount: semanticResults.length
16237
+ semanticCount: semanticResults.length,
16238
+ embedCoverage
16250
16239
  };
16251
16240
  }
16252
16241
 
@@ -16307,9 +16296,451 @@ init_url_path_resolver();
16307
16296
  init_mtime_scan();
16308
16297
  init_catchup();
16309
16298
  init_paths();
16310
- var import_node_fs15 = require("node:fs");
16311
- var import_node_child_process4 = require("node:child_process");
16312
- var import_node_path14 = require("node:path");
16299
+
16300
+ // src/git-attribution.ts
16301
+ var fs4 = __toESM(require("node:fs"));
16302
+ var path3 = __toESM(require("node:path"));
16303
+ var os2 = __toESM(require("node:os"));
16304
+ var import_node_child_process2 = require("node:child_process");
16305
+
16306
+ // src/adapters/claude/transcript-edits.ts
16307
+ var fs3 = __toESM(require("node:fs"));
16308
+ var readline = __toESM(require("node:readline"));
16309
+ async function extractSessionEdits(filePath, opts = {}) {
16310
+ const sessionId = sessionIdFromPath3(filePath);
16311
+ const edits = [];
16312
+ let firstTs = Infinity;
16313
+ let lastTs = -Infinity;
16314
+ let skippedLines = 0;
16315
+ let skippedEvents = 0;
16316
+ const stream2 = fs3.createReadStream(filePath, { encoding: "utf8" });
16317
+ const rl = readline.createInterface({ input: stream2, crlfDelay: Infinity });
16318
+ const pushEdit = (fp, cnt, ts) => {
16319
+ if (typeof fp !== "string" || typeof cnt !== "string")
16320
+ return;
16321
+ edits.push({ file: normalizePath2(fp, opts.repoRoot), content: cnt, ts });
16322
+ if (ts < firstTs)
16323
+ firstTs = ts;
16324
+ if (ts > lastTs)
16325
+ lastTs = ts;
16326
+ };
16327
+ for await (const line of rl) {
16328
+ if (!line.trim())
16329
+ continue;
16330
+ let evt;
16331
+ try {
16332
+ evt = JSON.parse(line);
16333
+ } catch {
16334
+ skippedLines++;
16335
+ continue;
16336
+ }
16337
+ if (!isAssistantEvent(evt))
16338
+ continue;
16339
+ const ts = parseTimestamp(evt);
16340
+ if (!Number.isFinite(ts)) {
16341
+ skippedEvents++;
16342
+ continue;
16343
+ }
16344
+ for (const block of evt.message.content) {
16345
+ if (!isToolUseBlock(block))
16346
+ continue;
16347
+ const input = block.input;
16348
+ if (block.name === "Edit") {
16349
+ pushEdit(input.file_path, input.new_string, ts);
16350
+ } else if (block.name === "Write") {
16351
+ pushEdit(input.file_path, input.content, ts);
16352
+ } else if (block.name === "MultiEdit") {
16353
+ const fp = input.file_path;
16354
+ const edArr = input.edits;
16355
+ if (Array.isArray(edArr)) {
16356
+ for (const e2 of edArr) {
16357
+ if (e2 && typeof e2 === "object") {
16358
+ pushEdit(fp, e2.new_string, ts);
16359
+ }
16360
+ }
16361
+ }
16362
+ }
16363
+ }
16364
+ }
16365
+ return { sessionId, edits, firstTs, lastTs, skippedLines, skippedEvents };
16366
+ }
16367
+ function sessionIdFromPath3(filePath) {
16368
+ const base = filePath.replace(/^.*[\\/]/, "");
16369
+ return base.endsWith(".jsonl") ? base.slice(0, -".jsonl".length) : base;
16370
+ }
16371
+ function isAssistantEvent(evt) {
16372
+ if (!evt || typeof evt !== "object")
16373
+ return false;
16374
+ const e2 = evt;
16375
+ if (e2.type !== "assistant")
16376
+ return false;
16377
+ const m2 = e2.message;
16378
+ return !!m2 && Array.isArray(m2.content);
16379
+ }
16380
+ function isToolUseBlock(block) {
16381
+ if (!block || typeof block !== "object")
16382
+ return false;
16383
+ const b3 = block;
16384
+ if (b3.type !== "tool_use")
16385
+ return false;
16386
+ if (typeof b3.name !== "string")
16387
+ return false;
16388
+ if (b3.input && typeof b3.input !== "object")
16389
+ return false;
16390
+ return true;
16391
+ }
16392
+ function parseTimestamp(evt) {
16393
+ if (typeof evt.timestamp !== "string")
16394
+ return NaN;
16395
+ return new Date(evt.timestamp).getTime();
16396
+ }
16397
+ function normalizePath2(p, repoRoot) {
16398
+ if (!repoRoot)
16399
+ return p;
16400
+ const prefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
16401
+ if (p.startsWith(prefix))
16402
+ return p.slice(prefix.length);
16403
+ if (p === repoRoot)
16404
+ return "";
16405
+ return p;
16406
+ }
16407
+
16408
+ // src/git-attribution.ts
16409
+ init_log();
16410
+ function parseBlameSpec(s) {
16411
+ const lastColon = s.lastIndexOf(":");
16412
+ if (lastColon < 0)
16413
+ return { path: s };
16414
+ const tail = s.slice(lastColon + 1);
16415
+ const m2 = tail.match(/^(\d+)(?:-(\d+))?$/);
16416
+ if (!m2)
16417
+ return { path: s };
16418
+ const lineStart = parseInt(m2[1], 10);
16419
+ const lineEnd = m2[2] !== void 0 ? parseInt(m2[2], 10) : lineStart;
16420
+ return { path: s.slice(0, lastColon), lineStart, lineEnd };
16421
+ }
16422
+ async function findSessionsForCommit(commitHash, opts) {
16423
+ const info = getCommitInfo(opts.repoRoot, commitHash);
16424
+ return matchCommit(info, opts, /* @__PURE__ */ new Map());
16425
+ }
16426
+ async function findSessionsForBlame(specs, opts) {
16427
+ if (specs.length === 0)
16428
+ return [];
16429
+ const commitSet = /* @__PURE__ */ new Set();
16430
+ for (const spec of specs) {
16431
+ for (const h2 of blameCommits(opts.repoRoot, spec)) {
16432
+ commitSet.add(h2);
16433
+ }
16434
+ }
16435
+ const commitFileTriCache = /* @__PURE__ */ new Map();
16436
+ const all = [];
16437
+ for (const h2 of commitSet) {
16438
+ let info;
16439
+ try {
16440
+ info = getCommitInfo(opts.repoRoot, h2);
16441
+ } catch (err) {
16442
+ log({
16443
+ source: "git-attribution",
16444
+ level: "warn",
16445
+ summary: `failed to read commit ${h2}`,
16446
+ data: { error: String(err) }
16447
+ });
16448
+ continue;
16449
+ }
16450
+ const ms = await matchCommit(info, opts, commitFileTriCache);
16451
+ for (const m2 of ms)
16452
+ all.push(m2);
16453
+ }
16454
+ all.sort((a3, b3) => Date.parse(a3.last_edit_at) - Date.parse(b3.last_edit_at));
16455
+ if (opts.limit && opts.limit > 0 && all.length > opts.limit) {
16456
+ return all.slice(-opts.limit);
16457
+ }
16458
+ return all;
16459
+ }
16460
+ function getCommitInfo(repoRoot, hash) {
16461
+ const meta = git(repoRoot, ["show", "--pretty=format:%H%n%aI", "--name-only", hash]).trim().split("\n");
16462
+ const fullHash = meta[0] ?? hash;
16463
+ const commitTime = meta[1] ? Date.parse(meta[1]) : 0;
16464
+ const files = meta.slice(2).filter((f3) => f3.length > 0);
16465
+ const parentRaw = gitSafe(repoRoot, ["log", "-1", "--pretty=format:%aI", `${hash}^`]);
16466
+ const parentTime = parentRaw ? Date.parse(parentRaw.trim()) : 0;
16467
+ const diff = git(repoRoot, ["show", "-U0", hash]);
16468
+ const added = /* @__PURE__ */ new Map();
16469
+ const removed = /* @__PURE__ */ new Map();
16470
+ let curFile = null;
16471
+ for (const line of diff.split("\n")) {
16472
+ if (line.startsWith("diff --git")) {
16473
+ curFile = null;
16474
+ continue;
16475
+ }
16476
+ if (line.startsWith("+++ b/")) {
16477
+ curFile = line.slice(6);
16478
+ if (!added.has(curFile))
16479
+ added.set(curFile, []);
16480
+ if (!removed.has(curFile))
16481
+ removed.set(curFile, []);
16482
+ continue;
16483
+ }
16484
+ if (line.startsWith("--- ") || line.startsWith("+++ "))
16485
+ continue;
16486
+ if (line.startsWith("@@"))
16487
+ continue;
16488
+ if (!curFile)
16489
+ continue;
16490
+ if (line.startsWith("+"))
16491
+ added.get(curFile).push(line.slice(1));
16492
+ else if (line.startsWith("-"))
16493
+ removed.get(curFile).push(line.slice(1));
16494
+ }
16495
+ return { hash: fullHash, commitTime, parentTime, files, addedLines: added, removedLines: removed };
16496
+ }
16497
+ function cwdToProjectSlug(cwd) {
16498
+ return cwd.replace(/[^a-zA-Z0-9]/g, "-");
16499
+ }
16500
+ function cwdToProjectSlugNarrow(cwd) {
16501
+ return cwd.replace(/[:\/\\]/g, "-");
16502
+ }
16503
+ function defaultSessionsDir(repoRoot) {
16504
+ const claudeRoot = process.env["CLAUDE_CONFIG_DIR"] ?? path3.join(os2.homedir(), ".claude");
16505
+ const broad = path3.join(claudeRoot, "projects", cwdToProjectSlug(repoRoot));
16506
+ if (fs4.existsSync(broad))
16507
+ return broad;
16508
+ const narrow = path3.join(claudeRoot, "projects", cwdToProjectSlugNarrow(repoRoot));
16509
+ if (fs4.existsSync(narrow))
16510
+ return narrow;
16511
+ return broad;
16512
+ }
16513
+ async function matchCommit(info, opts, commitFileTriCache) {
16514
+ const commitFiles = new Set(info.files);
16515
+ const windowAfterMs = opts.windowAfterMs ?? 60 * 60 * 1e3;
16516
+ const lower = info.parentTime;
16517
+ const upper = info.commitTime + windowAfterMs;
16518
+ const sessionsDir = opts.sessionsDir ?? defaultSessionsDir(opts.repoRoot);
16519
+ if (!fs4.existsSync(sessionsDir)) {
16520
+ log({
16521
+ source: "git-attribution",
16522
+ level: "warn",
16523
+ summary: `sessions dir not found: ${sessionsDir}`
16524
+ });
16525
+ return [];
16526
+ }
16527
+ const candidates = collectCandidates(sessionsDir, lower, info.commitTime);
16528
+ const addedTriByFile = /* @__PURE__ */ new Map();
16529
+ for (const [file, lines] of info.addedLines) {
16530
+ addedTriByFile.set(file, triGrams(lines));
16531
+ }
16532
+ const matches = [];
16533
+ for (const cand of candidates) {
16534
+ let trace;
16535
+ try {
16536
+ trace = await extractSessionEdits(cand.jsonlPath, { repoRoot: opts.repoRoot });
16537
+ } catch (err) {
16538
+ log({
16539
+ source: "git-attribution",
16540
+ level: "debug",
16541
+ summary: `extractSessionEdits failed for ${cand.jsonlPath}`,
16542
+ data: { error: String(err) }
16543
+ });
16544
+ continue;
16545
+ }
16546
+ if (trace.skippedLines > 0 || trace.skippedEvents > 0) {
16547
+ log({
16548
+ source: "git-attribution",
16549
+ level: "debug",
16550
+ summary: `skipped content in ${cand.jsonlPath}`,
16551
+ data: { skippedLines: trace.skippedLines, skippedEvents: trace.skippedEvents }
16552
+ });
16553
+ }
16554
+ if (trace.edits.length === 0)
16555
+ continue;
16556
+ const inWindow = trace.edits.filter((e2) => e2.ts >= lower && e2.ts <= upper);
16557
+ if (inWindow.length === 0)
16558
+ continue;
16559
+ const touchedFiles = new Set(inWindow.map((e2) => e2.file).filter((f3) => commitFiles.has(f3)));
16560
+ if (touchedFiles.size === 0)
16561
+ continue;
16562
+ const sessionTriByFile = /* @__PURE__ */ new Map();
16563
+ for (const e2 of inWindow) {
16564
+ if (!commitFiles.has(e2.file))
16565
+ continue;
16566
+ let bucket = sessionTriByFile.get(e2.file);
16567
+ if (!bucket) {
16568
+ bucket = /* @__PURE__ */ new Set();
16569
+ sessionTriByFile.set(e2.file, bucket);
16570
+ }
16571
+ for (const t of triGrams(e2.content.split("\n")))
16572
+ bucket.add(t);
16573
+ }
16574
+ if (sessionTriByFile.size === 0)
16575
+ continue;
16576
+ let contentHits = 0;
16577
+ for (const [file, sessTri] of sessionTriByFile) {
16578
+ const add = addedTriByFile.get(file);
16579
+ if (!add)
16580
+ continue;
16581
+ for (const t of sessTri) {
16582
+ if (add.has(t))
16583
+ contentHits++;
16584
+ }
16585
+ }
16586
+ if (contentHits === 0)
16587
+ continue;
16588
+ let survivingHits = 0;
16589
+ let totalTris = 0;
16590
+ for (const [file, sessTri] of sessionTriByFile) {
16591
+ const commitTri = lookupCommitFileTri(opts.repoRoot, info.hash, file, commitFileTriCache);
16592
+ totalTris += sessTri.size;
16593
+ for (const t of sessTri) {
16594
+ if (commitTri.has(t))
16595
+ survivingHits++;
16596
+ }
16597
+ }
16598
+ const ratio = totalTris === 0 ? 0 : survivingHits / totalTris;
16599
+ const lastEditTs = inWindow.reduce((m2, e2) => e2.ts > m2 ? e2.ts : m2, -Infinity);
16600
+ matches.push({
16601
+ session: trace.sessionId,
16602
+ parent_session_id: cand.parentSessionId,
16603
+ agent_type: cand.agentType,
16604
+ commit: info.hash,
16605
+ matched_files: [...touchedFiles],
16606
+ content_hits: contentHits,
16607
+ edit_count: inWindow.length,
16608
+ last_edit_at: new Date(lastEditTs).toISOString(),
16609
+ surviving_in_commit: ratio >= 0.5,
16610
+ surviving_ratio: Math.round(ratio * 100) / 100
16611
+ });
16612
+ }
16613
+ matches.sort((a3, b3) => Date.parse(a3.last_edit_at) - Date.parse(b3.last_edit_at));
16614
+ return matches;
16615
+ }
16616
+ function collectCandidates(sessionsDir, lower, commitTime) {
16617
+ const mtimeLower = lower - 6e4;
16618
+ const mtimeUpper = commitTime + 24 * 60 * 60 * 1e3;
16619
+ const inWindow = (p) => {
16620
+ let stat;
16621
+ try {
16622
+ stat = fs4.statSync(p);
16623
+ } catch {
16624
+ return false;
16625
+ }
16626
+ if (stat.mtimeMs < mtimeLower)
16627
+ return false;
16628
+ if (stat.mtimeMs > mtimeUpper)
16629
+ return false;
16630
+ return true;
16631
+ };
16632
+ const out = [];
16633
+ let entries;
16634
+ try {
16635
+ entries = fs4.readdirSync(sessionsDir, { withFileTypes: true });
16636
+ } catch {
16637
+ return out;
16638
+ }
16639
+ for (const ent of entries) {
16640
+ if (ent.isFile() && ent.name.endsWith(".jsonl")) {
16641
+ const full = path3.join(sessionsDir, ent.name);
16642
+ if (inWindow(full)) {
16643
+ out.push({ jsonlPath: full, parentSessionId: null, agentType: null });
16644
+ }
16645
+ continue;
16646
+ }
16647
+ if (!ent.isDirectory())
16648
+ continue;
16649
+ const parentDir = path3.join(sessionsDir, ent.name);
16650
+ const subDir = path3.join(parentDir, "subagents");
16651
+ let subEntries;
16652
+ try {
16653
+ subEntries = fs4.readdirSync(subDir);
16654
+ } catch {
16655
+ continue;
16656
+ }
16657
+ for (const sub of subEntries) {
16658
+ if (!sub.endsWith(".jsonl"))
16659
+ continue;
16660
+ const full = path3.join(subDir, sub);
16661
+ if (!inWindow(full))
16662
+ continue;
16663
+ const metaPath = path3.join(subDir, sub.slice(0, -".jsonl".length) + ".meta.json");
16664
+ let agentType = null;
16665
+ try {
16666
+ const raw2 = fs4.readFileSync(metaPath, "utf8");
16667
+ const meta = JSON.parse(raw2);
16668
+ if (typeof meta.agentType === "string")
16669
+ agentType = meta.agentType;
16670
+ } catch {
16671
+ }
16672
+ out.push({ jsonlPath: full, parentSessionId: ent.name, agentType });
16673
+ }
16674
+ }
16675
+ return out;
16676
+ }
16677
+ function lookupCommitFileTri(repoRoot, commit, file, cache) {
16678
+ const key = `${commit}:${file}`;
16679
+ const hit = cache.get(key);
16680
+ if (hit)
16681
+ return hit;
16682
+ const raw2 = gitSafe(repoRoot, ["show", `${commit}:${file}`]);
16683
+ const tri = raw2 ? triGrams(raw2.split("\n")) : /* @__PURE__ */ new Set();
16684
+ cache.set(key, tri);
16685
+ return tri;
16686
+ }
16687
+ function triGrams(lines) {
16688
+ const nonBlank = [];
16689
+ for (const l2 of lines) {
16690
+ const t = normalizeWs(l2).trim();
16691
+ if (t.length > 0)
16692
+ nonBlank.push(t);
16693
+ }
16694
+ const out = /* @__PURE__ */ new Set();
16695
+ for (let i = 0; i + 3 <= nonBlank.length; i++) {
16696
+ out.add(nonBlank[i] + "\n" + nonBlank[i + 1] + "\n" + nonBlank[i + 2]);
16697
+ }
16698
+ return out;
16699
+ }
16700
+ function normalizeWs(s) {
16701
+ return s.replace(/[ \t]+/g, " ").replace(/[ \t]+$/g, "");
16702
+ }
16703
+ function blameCommits(repoRoot, spec) {
16704
+ const args = ["blame", "--porcelain"];
16705
+ if (spec.lineStart !== void 0) {
16706
+ const end = spec.lineEnd ?? spec.lineStart;
16707
+ if (end < spec.lineStart) {
16708
+ throw new Error(`blame range end (${end}) is before start (${spec.lineStart})`);
16709
+ }
16710
+ args.push("-L", `${spec.lineStart},${end}`);
16711
+ }
16712
+ args.push("--", spec.path);
16713
+ const out = gitSafe(repoRoot, args);
16714
+ const hashes = /* @__PURE__ */ new Set();
16715
+ if (!out)
16716
+ return hashes;
16717
+ for (const line of out.split("\n")) {
16718
+ const m2 = line.match(/^([0-9a-f]{40}) \d+ \d+/);
16719
+ if (m2 && m2[1] !== "0".repeat(40))
16720
+ hashes.add(m2[1]);
16721
+ }
16722
+ return hashes;
16723
+ }
16724
+ function git(repoRoot, args) {
16725
+ return (0, import_node_child_process2.execFileSync)("git", args, {
16726
+ cwd: repoRoot,
16727
+ encoding: "utf8",
16728
+ maxBuffer: 64 * 1024 * 1024,
16729
+ stdio: ["ignore", "pipe", "pipe"]
16730
+ });
16731
+ }
16732
+ function gitSafe(repoRoot, args) {
16733
+ try {
16734
+ return git(repoRoot, args);
16735
+ } catch {
16736
+ return null;
16737
+ }
16738
+ }
16739
+
16740
+ // src/cli/recall.ts
16741
+ var import_node_fs17 = require("node:fs");
16742
+ var import_node_child_process5 = require("node:child_process");
16743
+ var import_node_path16 = require("node:path");
16313
16744
  var UUID_PREFIX = /^[0-9a-f]{8}/i;
16314
16745
  var argv = process.argv.slice(2);
16315
16746
  function hasFlag(name) {
@@ -16329,6 +16760,8 @@ function flagInt(name, fallback) {
16329
16760
  return Number.isNaN(n) ? fallback : n;
16330
16761
  }
16331
16762
  var raw = hasFlag("--raw");
16763
+ var rawMessages = hasFlag("--raw-messages");
16764
+ var noIdf = hasFlag("--no-idf");
16332
16765
  var showHelp = hasFlag("--help") || hasFlag("-h");
16333
16766
  var showVersion = hasFlag("--version") || hasFlag("-v");
16334
16767
  var listMode = hasFlag("--list");
@@ -16340,6 +16773,8 @@ var projectFlag = flagValue("--project");
16340
16773
  var allProjects = hasFlag("--all");
16341
16774
  var reverse = hasFlag("--reverse");
16342
16775
  var recent = hasFlag("--recent");
16776
+ var commitFlag = flagValue("--commit");
16777
+ var blameMode = hasFlag("--blame");
16343
16778
  var ExitSignal = class extends Error {
16344
16779
  constructor(code) {
16345
16780
  super(`exit:${code}`);
@@ -16351,9 +16786,11 @@ function exit(code) {
16351
16786
  throw new ExitSignal(code);
16352
16787
  }
16353
16788
  var effectiveProject = allProjects ? void 0 : normalizePath(projectFlag ?? process.cwd());
16354
- var FLAG_WITH_VALUE = /* @__PURE__ */ new Set(["--limit", "--offset", "--since", "--until", "--project", "--vendor"]);
16789
+ var FLAG_WITH_VALUE = /* @__PURE__ */ new Set(["--limit", "--offset", "--since", "--until", "--project", "--vendor", "--commit"]);
16355
16790
  var FLAG_BOOLEAN = /* @__PURE__ */ new Set([
16356
16791
  "--raw",
16792
+ "--raw-messages",
16793
+ "--no-idf",
16357
16794
  "--help",
16358
16795
  "-h",
16359
16796
  "--version",
@@ -16362,6 +16799,7 @@ var FLAG_BOOLEAN = /* @__PURE__ */ new Set([
16362
16799
  "--all",
16363
16800
  "--reverse",
16364
16801
  "--recent",
16802
+ "--blame",
16365
16803
  "--no-catchup",
16366
16804
  "--auto-embed",
16367
16805
  "--detach",
@@ -16392,7 +16830,7 @@ for (let i = 0; i < argv.length; i++) {
16392
16830
  function getVersion() {
16393
16831
  try {
16394
16832
  const pkg = JSON.parse(
16395
- (0, import_node_fs15.readFileSync)((0, import_node_path14.join)(__dirname, "..", "package.json"), "utf8")
16833
+ (0, import_node_fs17.readFileSync)((0, import_node_path16.join)(__dirname, "..", "package.json"), "utf8")
16396
16834
  );
16397
16835
  return pkg.version ?? "unknown";
16398
16836
  } catch {
@@ -16408,6 +16846,9 @@ USAGE
16408
16846
  recall <session-id> Read messages from a session
16409
16847
  recall <session-id> <message-id> Read centered on matched message
16410
16848
  recall --list List recent sessions
16849
+ recall --commit <hash> Sessions that produced a commit
16850
+ recall --blame <path>[:<line>[-<line>]]... Sessions responsible for a file
16851
+ or a specific line/range (via git blame)
16411
16852
  recall backfill [flags] Catch up FTS5 + embeddings against transcript files
16412
16853
 
16413
16854
  ARGUMENTS
@@ -16425,7 +16866,15 @@ FLAGS
16425
16866
  --recent Strongly boost recent sessions in search ranking
16426
16867
  --reverse Read session messages newest-first (default: oldest-first)
16427
16868
  --raw Output raw JSON instead of formatted tables
16869
+ --raw-messages Output the FULL pre-shaping per-message ranked list as JSON
16870
+ (bypasses score-gap cutoff, session-dedup, and pagination);
16871
+ for per-turn retrieval scoring. Honors --limit as the top-k.
16872
+ --no-idf Bypass the FTS5 IDF high-frequency-term filter (keeps
16873
+ common-but-meaningful terms like when/before/after)
16428
16874
  --list List sessions mode
16875
+ --commit HASH Sessions that produced the given commit (git attribution)
16876
+ --blame SPEC... Sessions responsible for a file or line range at HEAD; takes
16877
+ one or more <path>[:<line>[-<line>]] specs (via git blame)
16429
16878
  --no-catchup Skip the per-invocation mtime catch-up scan (T1)
16430
16879
  --help, -h Show this help
16431
16880
  --version, -v Print the recall version
@@ -16450,6 +16899,18 @@ EXAMPLES
16450
16899
  recall a1b2c3d4 e5f6a7b8
16451
16900
  recall a1b2c3d4 --reverse
16452
16901
  recall --list --since 2026-04-10 --until 2026-04-10
16902
+ recall --commit 25dd0f8
16903
+ recall --blame src/paths.ts:82-84
16904
+ recall --blame src/foo.ts:42 src/bar.ts:10-20 --limit 20
16905
+
16906
+ COMMIT ATTRIBUTION (--commit / --blame)
16907
+ Returns the session(s) whose Edit/Write/MultiEdit tool calls structurally
16908
+ match each commit's diff. Sessions are listed chronologically (oldest first).
16909
+ The most recent is usually the load-bearing edit for current code; earlier
16910
+ sessions show evolution and may reveal originating intent or rejected
16911
+ approaches. --blame runs git blame to find the commits responsible for the
16912
+ current file (or line range) at HEAD, then attributes each. --limit (with
16913
+ --blame) caps the number of returned matches.
16453
16914
  `.trim());
16454
16915
  }
16455
16916
  function initDb() {
@@ -16667,7 +17128,9 @@ async function runSearch(query) {
16667
17128
  const r2 = await dualPathSearch(query, {
16668
17129
  limit: ceiling,
16669
17130
  projectId: effectiveProject,
17131
+ ...noIdf ? { skipIdf: true } : {},
16670
17132
  ...recent ? { recencyDecay: 0.1 } : {}
17133
+ // default is off; --recent opts into absolute age decay
16671
17134
  });
16672
17135
  let { scored } = r2;
16673
17136
  if (since) {
@@ -16694,6 +17157,28 @@ async function runSearch(query) {
16694
17157
  exit(1);
16695
17158
  }
16696
17159
  }
17160
+ if (rawMessages) {
17161
+ const top = scored.slice(0, ceiling);
17162
+ console.log(JSON.stringify({
17163
+ query,
17164
+ no_idf: noIdf,
17165
+ semantic_available: r2.semanticAvailable,
17166
+ semantic_count: r2.semanticCount,
17167
+ fts_count: r2.ftsCount,
17168
+ embed_coverage: r2.embedCoverage,
17169
+ total: top.length,
17170
+ messages: top.map((x3, i) => ({
17171
+ rank: i + 1,
17172
+ session_id: x3.result.session_id,
17173
+ message_id: x3.result.message_id,
17174
+ message_seq: x3.result.message_seq,
17175
+ score: x3.score,
17176
+ snippet: (x3.result.match_snippet || x3.result.message_preview || "").slice(0, 200).replace(/\n/g, " "),
17177
+ tag: x3.paths.includes("fts5") && x3.paths.includes("semantic") ? "FTS5+SEMANTIC" : x3.paths.includes("semantic") ? "SEMANTIC-ONLY" : "FTS5-ONLY"
17178
+ }))
17179
+ }, null, 2));
17180
+ return;
17181
+ }
16697
17182
  let cutoffIdx = scored.length;
16698
17183
  if (scored.length > 10) {
16699
17184
  let maxDrop = 0;
@@ -16771,6 +17256,7 @@ async function runSearch(query) {
16771
17256
  fts_count: r2.ftsCount,
16772
17257
  semantic_count: r2.semanticCount,
16773
17258
  semantic_available: r2.semanticAvailable,
17259
+ embed_coverage: r2.embedCoverage,
16774
17260
  unique_sessions: totalSessions,
16775
17261
  showing_offset: pageStart,
16776
17262
  showing_count: page.length,
@@ -16780,7 +17266,8 @@ async function runSearch(query) {
16780
17266
  } else {
16781
17267
  console.log(`Query: "${query}"`);
16782
17268
  console.log(`Results: ${trimmed.length} messages, ${totalSessions} unique sessions (showing ${pageStart + 1}-${pageEnd})`);
16783
- console.log(`Paths: FTS5=${r2.ftsCount} Semantic=${r2.semanticCount} (${r2.semanticAvailable ? "active" : "UNAVAILABLE"})`);
17269
+ const migrating = r2.embedCoverage < 0.95 ? ` (migrating: ${Math.round(r2.embedCoverage * 100)}% re-embedded)` : "";
17270
+ console.log(`Paths: FTS5=${r2.ftsCount} Semantic=${r2.semanticCount} (${r2.semanticAvailable ? "active" : "UNAVAILABLE"})${migrating}`);
16784
17271
  if (cutoffIdx < scored.length) {
16785
17272
  console.log(`Cutoff: position ${cutoffIdx} of ${scored.length} (score gap detected)`);
16786
17273
  }
@@ -16805,6 +17292,102 @@ async function runSearch(query) {
16805
17292
  }
16806
17293
  }
16807
17294
  }
17295
+ function blamePositionals() {
17296
+ const idx = argv.indexOf("--blame");
17297
+ if (idx < 0)
17298
+ return [];
17299
+ const out = [];
17300
+ for (let i = idx + 1; i < argv.length; i++) {
17301
+ const a3 = argv[i];
17302
+ if (a3.startsWith("--"))
17303
+ break;
17304
+ out.push(a3);
17305
+ }
17306
+ return out;
17307
+ }
17308
+ function printCommitAttribution(query, matches) {
17309
+ const note = "Sessions are listed chronologically (oldest first). The most recent is usually the load-bearing one for current code; earlier sessions show evolution and may reveal originating intent or rejected approaches.";
17310
+ if (raw) {
17311
+ console.log(JSON.stringify({
17312
+ query,
17313
+ note,
17314
+ count: matches.length,
17315
+ matches
17316
+ }, null, 2));
17317
+ return;
17318
+ }
17319
+ console.log(`Query: ${query}`);
17320
+ console.log(`Matches: ${matches.length}`);
17321
+ console.log(`Note: ${note}`);
17322
+ console.log("---");
17323
+ if (matches.length === 0) {
17324
+ console.log("No sessions matched.");
17325
+ return;
17326
+ }
17327
+ const sessLabels = matches.map(
17328
+ (m2) => m2.parent_session_id ? `${m2.session} \u21B3` : m2.session
17329
+ );
17330
+ const sessW = Math.max("Session".length, ...sessLabels.map((s) => s.length));
17331
+ const commitW = 12;
17332
+ const hitsW = 6;
17333
+ const survW = 5;
17334
+ const ratioW = 6;
17335
+ const dateW = 19;
17336
+ const GAP = " ";
17337
+ const header = "Session".padEnd(sessW) + GAP + "Commit".padEnd(commitW) + GAP + "Hits".padStart(hitsW) + GAP + "Surv?".padEnd(survW) + GAP + "Ratio".padStart(ratioW) + GAP + "Last edit".padEnd(dateW) + GAP + "Files";
17338
+ console.log(header);
17339
+ console.log("-".repeat(header.length));
17340
+ matches.forEach((m2, i) => {
17341
+ const date = m2.last_edit_at.slice(0, 19).replace("T", " ");
17342
+ console.log(
17343
+ sessLabels[i].padEnd(sessW) + GAP + m2.commit.slice(0, 10).padEnd(commitW) + GAP + String(m2.content_hits).padStart(hitsW) + GAP + (m2.surviving_in_commit ? "yes" : "no").padEnd(survW) + GAP + String(m2.surviving_ratio).padStart(ratioW) + GAP + date.padEnd(dateW) + GAP + m2.matched_files.join(", ")
17344
+ );
17345
+ if (m2.parent_session_id) {
17346
+ console.log(
17347
+ " ".repeat(2) + `(subagent of ${m2.parent_session_id.slice(0, 8)}${m2.agent_type ? `, type=${m2.agent_type}` : ""})`
17348
+ );
17349
+ }
17350
+ });
17351
+ }
17352
+ async function runCommitAttribution() {
17353
+ const repoRoot = projectFlag ?? process.cwd();
17354
+ if (hasFlag("--commit")) {
17355
+ if (commitFlag === void 0 || commitFlag.startsWith("--")) {
17356
+ console.error("--commit requires a commit hash. Use --help for usage.");
17357
+ exit(1);
17358
+ }
17359
+ let matches2;
17360
+ try {
17361
+ matches2 = await findSessionsForCommit(commitFlag, { repoRoot });
17362
+ } catch (err) {
17363
+ console.error(`recall --commit: git failed for "${commitFlag}" in ${repoRoot}: ${gitErrLine(err)}`);
17364
+ exit(1);
17365
+ }
17366
+ printCommitAttribution(`--commit ${commitFlag}`, matches2);
17367
+ return;
17368
+ }
17369
+ const rawSpecs = blamePositionals();
17370
+ if (rawSpecs.length === 0) {
17371
+ console.error("--blame requires at least one path or path:line[-line] spec. Use --help for usage.");
17372
+ exit(1);
17373
+ }
17374
+ const specs = rawSpecs.map(parseBlameSpec);
17375
+ const matchLimit = limit > 0 ? limit : void 0;
17376
+ let matches;
17377
+ try {
17378
+ matches = await findSessionsForBlame(specs, { repoRoot, ...matchLimit !== void 0 ? { limit: matchLimit } : {} });
17379
+ } catch (err) {
17380
+ console.error(`recall --blame: ${gitErrLine(err)}`);
17381
+ exit(1);
17382
+ }
17383
+ printCommitAttribution(`--blame ${rawSpecs.join(" ")}`, matches);
17384
+ }
17385
+ function gitErrLine(err) {
17386
+ const stderr = err.stderr;
17387
+ if (typeof stderr === "string" && stderr.trim())
17388
+ return stderr.trim().split("\n")[0];
17389
+ return err instanceof Error ? err.message.split("\n")[0] : String(err);
17390
+ }
16808
17391
  function parseVendors() {
16809
17392
  const v2 = flagValue("--vendor");
16810
17393
  if (!v2)
@@ -16823,22 +17406,22 @@ async function runBackfill() {
16823
17406
  clearCancelFlag();
16824
17407
  const detach = hasFlag("--detach");
16825
17408
  if (detach) {
16826
- (0, import_node_fs15.mkdirSync)(logsDir(), { recursive: true });
16827
- (0, import_node_fs15.mkdirSync)(runDir(), { recursive: true });
16828
- const logPath = (0, import_node_path14.join)(logsDir(), "backfill.log");
16829
- const logFd = (0, import_node_fs15.openSync)(logPath, "a");
17409
+ (0, import_node_fs17.mkdirSync)(logsDir(), { recursive: true });
17410
+ (0, import_node_fs17.mkdirSync)(runDir(), { recursive: true });
17411
+ const logPath = (0, import_node_path16.join)(logsDir(), "backfill.log");
17412
+ const logFd = (0, import_node_fs17.openSync)(logPath, "a");
16830
17413
  const args = [process.argv[1], "backfill", "--auto-embed"];
16831
17414
  const vendors2 = parseVendors();
16832
17415
  if (vendors2) {
16833
17416
  args.push("--vendor", vendors2[0]);
16834
17417
  }
16835
- const child = (0, import_node_child_process4.spawn)(process.execPath, args, {
17418
+ const child = (0, import_node_child_process5.spawn)(process.execPath, args, {
16836
17419
  detached: true,
16837
17420
  stdio: ["ignore", logFd, logFd],
16838
17421
  windowsHide: true
16839
17422
  });
16840
17423
  if (child.pid !== void 0) {
16841
- (0, import_node_fs15.writeFileSync)((0, import_node_path14.join)(runDir(), "backfill.pid"), String(child.pid));
17424
+ (0, import_node_fs17.writeFileSync)((0, import_node_path16.join)(runDir(), "backfill.pid"), String(child.pid));
16842
17425
  }
16843
17426
  child.unref();
16844
17427
  process.stderr.write(`[recall] backfill detached (pid=${child.pid}, log=${logPath})
@@ -16940,6 +17523,10 @@ async function main() {
16940
17523
  printHelp();
16941
17524
  exit(0);
16942
17525
  }
17526
+ if (hasFlag("--commit") || blameMode) {
17527
+ await runCommitAttribution();
17528
+ exit(0);
17529
+ }
16943
17530
  if (positional[0] === "backfill") {
16944
17531
  await runBackfill();
16945
17532
  exit(0);