memorix 1.9.6 → 1.9.7

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.
@@ -419,6 +419,74 @@ var init_launch_root = __esm({
419
419
  }
420
420
  });
421
421
 
422
+ // src/store/sqlite-reliability.ts
423
+ function isTransientSqliteError(error) {
424
+ const code = error?.code;
425
+ if (typeof code === "string") {
426
+ return /^SQLITE_BUSY(?:_|$)/i.test(code);
427
+ }
428
+ return error instanceof Error && /\bdatabase is locked\b|\bdatabase is busy\b/i.test(error.message);
429
+ }
430
+ function isSqliteUnavailableError(error) {
431
+ return error instanceof SqliteUnavailableError || error instanceof Error && /SQLite is not available|better-sqlite3.*failed|node:sqlite.*failed|bun:sqlite.*failed/i.test(error.message);
432
+ }
433
+ function degradedReadError(storeName) {
434
+ return new Error(`[memorix] Cannot read ${storeName}: SQLite backend unavailable (memory is not loaded)`);
435
+ }
436
+ function degradedWriteError(storeName) {
437
+ return new Error(`[memorix] Cannot write ${storeName}: SQLite backend unavailable (degraded mode; read-only)`);
438
+ }
439
+ function formatSqliteFailure(error) {
440
+ return error instanceof Error && error.message ? error.message : String(error);
441
+ }
442
+ function delay(ms) {
443
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
444
+ }
445
+ async function retrySqliteBusy(operation, label) {
446
+ for (let attempt = 0; ; attempt++) {
447
+ try {
448
+ return await operation();
449
+ } catch (error) {
450
+ if (!isTransientSqliteError(error) || attempt >= SQLITE_BUSY_RETRY_DELAYS_MS.length) throw error;
451
+ const waitMs = SQLITE_BUSY_RETRY_DELAYS_MS[attempt];
452
+ console.error(
453
+ `[memorix] ${label} SQLite busy (attempt ${attempt + 1}/${SQLITE_BUSY_RETRY_DELAYS_MS.length + 1}), retrying in ${waitMs}ms`
454
+ );
455
+ await delay(waitMs);
456
+ }
457
+ }
458
+ }
459
+ async function initializeSqliteStore(factory, dataDir, label) {
460
+ try {
461
+ loadBetterSqlite3();
462
+ } catch (error) {
463
+ throw new SqliteUnavailableError(error);
464
+ }
465
+ return retrySqliteBusy(async () => {
466
+ const store = factory();
467
+ await store.init(dataDir);
468
+ return store;
469
+ }, label);
470
+ }
471
+ var SQLITE_BUSY_RETRY_DELAYS_MS, SqliteUnavailableError;
472
+ var init_sqlite_reliability = __esm({
473
+ "src/store/sqlite-reliability.ts"() {
474
+ "use strict";
475
+ init_esm_shims();
476
+ init_sqlite_db();
477
+ SQLITE_BUSY_RETRY_DELAYS_MS = [50, 150, 400, 1e3, 2500];
478
+ SqliteUnavailableError = class extends Error {
479
+ code = "MEMORIX_SQLITE_UNAVAILABLE";
480
+ constructor(cause) {
481
+ super(
482
+ cause instanceof Error && cause.message ? cause.message : "[memorix] SQLite is unavailable (install a supported SQLite runtime)"
483
+ );
484
+ this.name = "SqliteUnavailableError";
485
+ }
486
+ };
487
+ }
488
+ });
489
+
422
490
  // src/store/sqlite-fts.ts
423
491
  function normalizeFtsToken(token) {
424
492
  return token.replace(/"/g, '""');
@@ -432,22 +500,27 @@ function buildFtsQuery(query) {
432
500
  function initializeObservationLexicalIndex(db2) {
433
501
  const known = ftsAvailability.get(db2);
434
502
  if (known !== void 0) return known;
435
- try {
436
- db2.exec(CREATE_OBSERVATION_FTS);
437
- const observationCount = Number(db2.prepare("SELECT COUNT(*) AS count FROM observations").get()?.count ?? 0);
438
- const indexedCount = Number(db2.prepare(`SELECT COUNT(*) AS count FROM ${FTS_TABLE}`).get()?.count ?? 0);
439
- if (observationCount !== indexedCount) {
440
- db2.exec(`INSERT INTO ${FTS_TABLE}(${FTS_TABLE}) VALUES ('rebuild')`);
503
+ let lastError;
504
+ for (let attempt = 1; attempt <= FTS_INIT_MAX_ATTEMPTS; attempt++) {
505
+ try {
506
+ db2.exec(CREATE_OBSERVATION_FTS);
507
+ const observationCount = Number(db2.prepare("SELECT COUNT(*) AS count FROM observations").get()?.count ?? 0);
508
+ const indexedCount = Number(db2.prepare(`SELECT COUNT(*) AS count FROM ${FTS_TABLE}`).get()?.count ?? 0);
509
+ if (observationCount !== indexedCount) {
510
+ db2.exec(`INSERT INTO ${FTS_TABLE}(${FTS_TABLE}) VALUES ('rebuild')`);
511
+ }
512
+ ftsAvailability.set(db2, true);
513
+ return true;
514
+ } catch (error) {
515
+ lastError = error;
516
+ if (!isTransientSqliteError(error) || attempt === FTS_INIT_MAX_ATTEMPTS) break;
441
517
  }
442
- ftsAvailability.set(db2, true);
443
- return true;
444
- } catch (error) {
445
- ftsAvailability.set(db2, false);
446
- console.warn(
447
- `[memorix] SQLite FTS5 unavailable; using the existing search fallback: ${error instanceof Error ? error.message : String(error)}`
448
- );
449
- return false;
450
518
  }
519
+ ftsAvailability.set(db2, false);
520
+ console.warn(
521
+ `[memorix] SQLite FTS5 unavailable; using the existing search fallback: ${lastError instanceof Error ? lastError.message : String(lastError)}`
522
+ );
523
+ return false;
451
524
  }
452
525
  function isObservationLexicalIndexEnabled(db2) {
453
526
  return ftsAvailability.get(db2) === true;
@@ -501,11 +574,12 @@ function searchObservationLexically(db2, options) {
501
574
  score: Math.max(0, Number(row.lexical_score ?? 0))
502
575
  }));
503
576
  }
504
- var ftsAvailability, FTS_TABLE, CREATE_OBSERVATION_FTS;
577
+ var ftsAvailability, FTS_TABLE, CREATE_OBSERVATION_FTS, FTS_INIT_MAX_ATTEMPTS;
505
578
  var init_sqlite_fts = __esm({
506
579
  "src/store/sqlite-fts.ts"() {
507
580
  "use strict";
508
581
  init_esm_shims();
582
+ init_sqlite_reliability();
509
583
  ftsAvailability = /* @__PURE__ */ new WeakMap();
510
584
  FTS_TABLE = "observations_fts";
511
585
  CREATE_OBSERVATION_FTS = `
@@ -539,6 +613,7 @@ CREATE TRIGGER IF NOT EXISTS observations_fts_au AFTER UPDATE ON observations BE
539
613
  VALUES (new.id, new.entityName, new.title, new.narrative, new.facts, new.filesModified, new.concepts, new.attachments);
540
614
  END;
541
615
  `;
616
+ FTS_INIT_MAX_ATTEMPTS = 3;
542
617
  }
543
618
  });
544
619
 
@@ -1726,74 +1801,6 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1726
1801
  }
1727
1802
  });
1728
1803
 
1729
- // src/store/sqlite-reliability.ts
1730
- function isTransientSqliteError(error) {
1731
- const code = error?.code;
1732
- if (typeof code === "string") {
1733
- return /^SQLITE_BUSY(?:_|$)/i.test(code);
1734
- }
1735
- return error instanceof Error && /\bdatabase is locked\b|\bdatabase is busy\b/i.test(error.message);
1736
- }
1737
- function isSqliteUnavailableError(error) {
1738
- return error instanceof SqliteUnavailableError || error instanceof Error && /SQLite is not available|better-sqlite3.*failed|node:sqlite.*failed|bun:sqlite.*failed/i.test(error.message);
1739
- }
1740
- function degradedReadError(storeName) {
1741
- return new Error(`[memorix] Cannot read ${storeName}: SQLite backend unavailable (memory is not loaded)`);
1742
- }
1743
- function degradedWriteError(storeName) {
1744
- return new Error(`[memorix] Cannot write ${storeName}: SQLite backend unavailable (degraded mode; read-only)`);
1745
- }
1746
- function formatSqliteFailure(error) {
1747
- return error instanceof Error && error.message ? error.message : String(error);
1748
- }
1749
- function delay(ms) {
1750
- return new Promise((resolve2) => setTimeout(resolve2, ms));
1751
- }
1752
- async function retrySqliteBusy(operation, label) {
1753
- for (let attempt = 0; ; attempt++) {
1754
- try {
1755
- return await operation();
1756
- } catch (error) {
1757
- if (!isTransientSqliteError(error) || attempt >= SQLITE_BUSY_RETRY_DELAYS_MS.length) throw error;
1758
- const waitMs = SQLITE_BUSY_RETRY_DELAYS_MS[attempt];
1759
- console.error(
1760
- `[memorix] ${label} SQLite busy (attempt ${attempt + 1}/${SQLITE_BUSY_RETRY_DELAYS_MS.length + 1}), retrying in ${waitMs}ms`
1761
- );
1762
- await delay(waitMs);
1763
- }
1764
- }
1765
- }
1766
- async function initializeSqliteStore(factory, dataDir, label) {
1767
- try {
1768
- loadBetterSqlite3();
1769
- } catch (error) {
1770
- throw new SqliteUnavailableError(error);
1771
- }
1772
- return retrySqliteBusy(async () => {
1773
- const store = factory();
1774
- await store.init(dataDir);
1775
- return store;
1776
- }, label);
1777
- }
1778
- var SQLITE_BUSY_RETRY_DELAYS_MS, SqliteUnavailableError;
1779
- var init_sqlite_reliability = __esm({
1780
- "src/store/sqlite-reliability.ts"() {
1781
- "use strict";
1782
- init_esm_shims();
1783
- init_sqlite_db();
1784
- SQLITE_BUSY_RETRY_DELAYS_MS = [50, 150, 400, 1e3, 2500];
1785
- SqliteUnavailableError = class extends Error {
1786
- code = "MEMORIX_SQLITE_UNAVAILABLE";
1787
- constructor(cause) {
1788
- super(
1789
- cause instanceof Error && cause.message ? cause.message : "[memorix] SQLite is unavailable (install a supported SQLite runtime)"
1790
- );
1791
- this.name = "SqliteUnavailableError";
1792
- }
1793
- };
1794
- }
1795
- });
1796
-
1797
1804
  // src/store/file-lock.ts
1798
1805
  import { promises as fs2 } from "fs";
1799
1806
  import { randomUUID } from "crypto";
@@ -7686,6 +7693,7 @@ async function searchObservations(options) {
7686
7693
  };
7687
7694
  let queryVector = null;
7688
7695
  let embeddingProviderForSearch = null;
7696
+ let embeddingUnavailable = false;
7689
7697
  if (quality !== "fast" && embeddingEnabled && hasQuery && tier !== "fast") {
7690
7698
  try {
7691
7699
  const provider2 = await getEmbeddingProvider();
@@ -7693,6 +7701,7 @@ async function searchObservations(options) {
7693
7701
  embeddingProviderForSearch = provider2;
7694
7702
  const activeVectorDimensions = getVectorDimensions();
7695
7703
  if (activeVectorDimensions !== null && provider2.dimensions !== activeVectorDimensions) {
7704
+ embeddingUnavailable = true;
7696
7705
  rememberSearchMode(
7697
7706
  modeKey,
7698
7707
  `fulltext (embedding dimension mismatch: provider ${provider2.dimensions}d vs index ${activeVectorDimensions}d)`
@@ -7732,8 +7741,11 @@ async function searchObservations(options) {
7732
7741
  hybridWeights: isCJKHeavy ? { text: 0.2, vector: 0.8 } : { text: 0.6, vector: 0.4 }
7733
7742
  };
7734
7743
  }
7744
+ } else {
7745
+ embeddingUnavailable = true;
7735
7746
  }
7736
7747
  } catch (error) {
7748
+ embeddingUnavailable = true;
7737
7749
  rememberSearchMode(modeKey, "fulltext (embedding unavailable)");
7738
7750
  console.error("[memorix] Embedding failed or timed out, falling back to fulltext search");
7739
7751
  }
@@ -7741,7 +7753,7 @@ async function searchObservations(options) {
7741
7753
  mark("preSearch");
7742
7754
  let results;
7743
7755
  const persistentCorpusEligible = await shouldUsePersistentSearch(projectIds, options.projectId);
7744
- const canUsePersistentLexical = persistentCorpusEligible && Boolean(hasQuery) && !queryVector && (quality === "fast" || tier === "fast" || !embeddingEnabled);
7756
+ const canUsePersistentLexical = persistentCorpusEligible && Boolean(hasQuery) && !queryVector && (quality === "fast" || tier === "fast" || !embeddingEnabled || embeddingUnavailable);
7745
7757
  let persistent = persistentCorpusEligible && queryVector && embeddingProviderForSearch ? await searchPersistentSemantically(options, projectIds, requestLimit, queryVector, embeddingProviderForSearch) : canUsePersistentLexical ? await searchPersistentLexically(options, projectIds, requestLimit) : null;
7746
7758
  const durableStore = getOptionalObservationStore();
7747
7759
  if (!persistent && queryVector && durableStore?.hasLexicalIndex?.() && count(database) === 0) {
@@ -6,6 +6,17 @@ All notable changes to this project will be documented in this file.
6
6
 
7
7
  No unreleased changes.
8
8
 
9
+ ## [1.9.7] - 2026-09-28
10
+
11
+ ### Fixed
12
+ - **SQLite FTS5 startup resilience** -- transient `SQLITE_BUSY` contention during
13
+ lexical-index initialization is retried before FTS5 is marked unavailable.
14
+ - **Large-store search fallback** -- runtime embedding failure, provider
15
+ disappearance, and vector-dimension mismatch now all fall back to the durable
16
+ SQLite lexical index instead of returning a silent empty result.
17
+ - **Release metadata** -- synchronized the npm, MCP Registry, and packaged
18
+ integration metadata for the 1.9.7 patch release.
19
+
9
20
  ## [1.9.6] - 2026-09-22
10
21
 
11
22
  ### Added
package/dist/sdk.js CHANGED
@@ -294,6 +294,74 @@ var init_launch_root = __esm({
294
294
  }
295
295
  });
296
296
 
297
+ // src/store/sqlite-reliability.ts
298
+ function isTransientSqliteError(error) {
299
+ const code = error?.code;
300
+ if (typeof code === "string") {
301
+ return /^SQLITE_BUSY(?:_|$)/i.test(code);
302
+ }
303
+ return error instanceof Error && /\bdatabase is locked\b|\bdatabase is busy\b/i.test(error.message);
304
+ }
305
+ function isSqliteUnavailableError(error) {
306
+ return error instanceof SqliteUnavailableError || error instanceof Error && /SQLite is not available|better-sqlite3.*failed|node:sqlite.*failed|bun:sqlite.*failed/i.test(error.message);
307
+ }
308
+ function degradedReadError(storeName) {
309
+ return new Error(`[memorix] Cannot read ${storeName}: SQLite backend unavailable (memory is not loaded)`);
310
+ }
311
+ function degradedWriteError(storeName) {
312
+ return new Error(`[memorix] Cannot write ${storeName}: SQLite backend unavailable (degraded mode; read-only)`);
313
+ }
314
+ function formatSqliteFailure(error) {
315
+ return error instanceof Error && error.message ? error.message : String(error);
316
+ }
317
+ function delay(ms) {
318
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
319
+ }
320
+ async function retrySqliteBusy(operation, label) {
321
+ for (let attempt = 0; ; attempt++) {
322
+ try {
323
+ return await operation();
324
+ } catch (error) {
325
+ if (!isTransientSqliteError(error) || attempt >= SQLITE_BUSY_RETRY_DELAYS_MS.length) throw error;
326
+ const waitMs = SQLITE_BUSY_RETRY_DELAYS_MS[attempt];
327
+ console.error(
328
+ `[memorix] ${label} SQLite busy (attempt ${attempt + 1}/${SQLITE_BUSY_RETRY_DELAYS_MS.length + 1}), retrying in ${waitMs}ms`
329
+ );
330
+ await delay(waitMs);
331
+ }
332
+ }
333
+ }
334
+ async function initializeSqliteStore(factory, dataDir, label) {
335
+ try {
336
+ loadBetterSqlite3();
337
+ } catch (error) {
338
+ throw new SqliteUnavailableError(error);
339
+ }
340
+ return retrySqliteBusy(async () => {
341
+ const store = factory();
342
+ await store.init(dataDir);
343
+ return store;
344
+ }, label);
345
+ }
346
+ var SQLITE_BUSY_RETRY_DELAYS_MS, SqliteUnavailableError;
347
+ var init_sqlite_reliability = __esm({
348
+ "src/store/sqlite-reliability.ts"() {
349
+ "use strict";
350
+ init_esm_shims();
351
+ init_sqlite_db();
352
+ SQLITE_BUSY_RETRY_DELAYS_MS = [50, 150, 400, 1e3, 2500];
353
+ SqliteUnavailableError = class extends Error {
354
+ code = "MEMORIX_SQLITE_UNAVAILABLE";
355
+ constructor(cause) {
356
+ super(
357
+ cause instanceof Error && cause.message ? cause.message : "[memorix] SQLite is unavailable (install a supported SQLite runtime)"
358
+ );
359
+ this.name = "SqliteUnavailableError";
360
+ }
361
+ };
362
+ }
363
+ });
364
+
297
365
  // src/store/sqlite-fts.ts
298
366
  function normalizeFtsToken(token) {
299
367
  return token.replace(/"/g, '""');
@@ -307,22 +375,27 @@ function buildFtsQuery(query) {
307
375
  function initializeObservationLexicalIndex(db2) {
308
376
  const known = ftsAvailability.get(db2);
309
377
  if (known !== void 0) return known;
310
- try {
311
- db2.exec(CREATE_OBSERVATION_FTS);
312
- const observationCount = Number(db2.prepare("SELECT COUNT(*) AS count FROM observations").get()?.count ?? 0);
313
- const indexedCount = Number(db2.prepare(`SELECT COUNT(*) AS count FROM ${FTS_TABLE}`).get()?.count ?? 0);
314
- if (observationCount !== indexedCount) {
315
- db2.exec(`INSERT INTO ${FTS_TABLE}(${FTS_TABLE}) VALUES ('rebuild')`);
378
+ let lastError;
379
+ for (let attempt = 1; attempt <= FTS_INIT_MAX_ATTEMPTS; attempt++) {
380
+ try {
381
+ db2.exec(CREATE_OBSERVATION_FTS);
382
+ const observationCount = Number(db2.prepare("SELECT COUNT(*) AS count FROM observations").get()?.count ?? 0);
383
+ const indexedCount = Number(db2.prepare(`SELECT COUNT(*) AS count FROM ${FTS_TABLE}`).get()?.count ?? 0);
384
+ if (observationCount !== indexedCount) {
385
+ db2.exec(`INSERT INTO ${FTS_TABLE}(${FTS_TABLE}) VALUES ('rebuild')`);
386
+ }
387
+ ftsAvailability.set(db2, true);
388
+ return true;
389
+ } catch (error) {
390
+ lastError = error;
391
+ if (!isTransientSqliteError(error) || attempt === FTS_INIT_MAX_ATTEMPTS) break;
316
392
  }
317
- ftsAvailability.set(db2, true);
318
- return true;
319
- } catch (error) {
320
- ftsAvailability.set(db2, false);
321
- console.warn(
322
- `[memorix] SQLite FTS5 unavailable; using the existing search fallback: ${error instanceof Error ? error.message : String(error)}`
323
- );
324
- return false;
325
393
  }
394
+ ftsAvailability.set(db2, false);
395
+ console.warn(
396
+ `[memorix] SQLite FTS5 unavailable; using the existing search fallback: ${lastError instanceof Error ? lastError.message : String(lastError)}`
397
+ );
398
+ return false;
326
399
  }
327
400
  function isObservationLexicalIndexEnabled(db2) {
328
401
  return ftsAvailability.get(db2) === true;
@@ -376,11 +449,12 @@ function searchObservationLexically(db2, options) {
376
449
  score: Math.max(0, Number(row.lexical_score ?? 0))
377
450
  }));
378
451
  }
379
- var ftsAvailability, FTS_TABLE, CREATE_OBSERVATION_FTS;
452
+ var ftsAvailability, FTS_TABLE, CREATE_OBSERVATION_FTS, FTS_INIT_MAX_ATTEMPTS;
380
453
  var init_sqlite_fts = __esm({
381
454
  "src/store/sqlite-fts.ts"() {
382
455
  "use strict";
383
456
  init_esm_shims();
457
+ init_sqlite_reliability();
384
458
  ftsAvailability = /* @__PURE__ */ new WeakMap();
385
459
  FTS_TABLE = "observations_fts";
386
460
  CREATE_OBSERVATION_FTS = `
@@ -414,6 +488,7 @@ CREATE TRIGGER IF NOT EXISTS observations_fts_au AFTER UPDATE ON observations BE
414
488
  VALUES (new.id, new.entityName, new.title, new.narrative, new.facts, new.filesModified, new.concepts, new.attachments);
415
489
  END;
416
490
  `;
491
+ FTS_INIT_MAX_ATTEMPTS = 3;
417
492
  }
418
493
  });
419
494
 
@@ -2638,74 +2713,6 @@ var init_types = __esm({
2638
2713
  }
2639
2714
  });
2640
2715
 
2641
- // src/store/sqlite-reliability.ts
2642
- function isTransientSqliteError(error) {
2643
- const code = error?.code;
2644
- if (typeof code === "string") {
2645
- return /^SQLITE_BUSY(?:_|$)/i.test(code);
2646
- }
2647
- return error instanceof Error && /\bdatabase is locked\b|\bdatabase is busy\b/i.test(error.message);
2648
- }
2649
- function isSqliteUnavailableError(error) {
2650
- return error instanceof SqliteUnavailableError || error instanceof Error && /SQLite is not available|better-sqlite3.*failed|node:sqlite.*failed|bun:sqlite.*failed/i.test(error.message);
2651
- }
2652
- function degradedReadError(storeName) {
2653
- return new Error(`[memorix] Cannot read ${storeName}: SQLite backend unavailable (memory is not loaded)`);
2654
- }
2655
- function degradedWriteError(storeName) {
2656
- return new Error(`[memorix] Cannot write ${storeName}: SQLite backend unavailable (degraded mode; read-only)`);
2657
- }
2658
- function formatSqliteFailure(error) {
2659
- return error instanceof Error && error.message ? error.message : String(error);
2660
- }
2661
- function delay(ms) {
2662
- return new Promise((resolve5) => setTimeout(resolve5, ms));
2663
- }
2664
- async function retrySqliteBusy(operation, label) {
2665
- for (let attempt = 0; ; attempt++) {
2666
- try {
2667
- return await operation();
2668
- } catch (error) {
2669
- if (!isTransientSqliteError(error) || attempt >= SQLITE_BUSY_RETRY_DELAYS_MS.length) throw error;
2670
- const waitMs = SQLITE_BUSY_RETRY_DELAYS_MS[attempt];
2671
- console.error(
2672
- `[memorix] ${label} SQLite busy (attempt ${attempt + 1}/${SQLITE_BUSY_RETRY_DELAYS_MS.length + 1}), retrying in ${waitMs}ms`
2673
- );
2674
- await delay(waitMs);
2675
- }
2676
- }
2677
- }
2678
- async function initializeSqliteStore(factory, dataDir, label) {
2679
- try {
2680
- loadBetterSqlite3();
2681
- } catch (error) {
2682
- throw new SqliteUnavailableError(error);
2683
- }
2684
- return retrySqliteBusy(async () => {
2685
- const store = factory();
2686
- await store.init(dataDir);
2687
- return store;
2688
- }, label);
2689
- }
2690
- var SQLITE_BUSY_RETRY_DELAYS_MS, SqliteUnavailableError;
2691
- var init_sqlite_reliability = __esm({
2692
- "src/store/sqlite-reliability.ts"() {
2693
- "use strict";
2694
- init_esm_shims();
2695
- init_sqlite_db();
2696
- SQLITE_BUSY_RETRY_DELAYS_MS = [50, 150, 400, 1e3, 2500];
2697
- SqliteUnavailableError = class extends Error {
2698
- code = "MEMORIX_SQLITE_UNAVAILABLE";
2699
- constructor(cause) {
2700
- super(
2701
- cause instanceof Error && cause.message ? cause.message : "[memorix] SQLite is unavailable (install a supported SQLite runtime)"
2702
- );
2703
- this.name = "SqliteUnavailableError";
2704
- }
2705
- };
2706
- }
2707
- });
2708
-
2709
2716
  // src/store/mini-skill-store.ts
2710
2717
  var mini_skill_store_exports = {};
2711
2718
  __export(mini_skill_store_exports, {
@@ -9207,6 +9214,7 @@ async function searchObservations(options) {
9207
9214
  };
9208
9215
  let queryVector = null;
9209
9216
  let embeddingProviderForSearch = null;
9217
+ let embeddingUnavailable = false;
9210
9218
  if (quality !== "fast" && embeddingEnabled && hasQuery && tier !== "fast") {
9211
9219
  try {
9212
9220
  const provider2 = await getEmbeddingProvider();
@@ -9214,6 +9222,7 @@ async function searchObservations(options) {
9214
9222
  embeddingProviderForSearch = provider2;
9215
9223
  const activeVectorDimensions = getVectorDimensions();
9216
9224
  if (activeVectorDimensions !== null && provider2.dimensions !== activeVectorDimensions) {
9225
+ embeddingUnavailable = true;
9217
9226
  rememberSearchMode(
9218
9227
  modeKey,
9219
9228
  `fulltext (embedding dimension mismatch: provider ${provider2.dimensions}d vs index ${activeVectorDimensions}d)`
@@ -9253,8 +9262,11 @@ async function searchObservations(options) {
9253
9262
  hybridWeights: isCJKHeavy ? { text: 0.2, vector: 0.8 } : { text: 0.6, vector: 0.4 }
9254
9263
  };
9255
9264
  }
9265
+ } else {
9266
+ embeddingUnavailable = true;
9256
9267
  }
9257
9268
  } catch (error) {
9269
+ embeddingUnavailable = true;
9258
9270
  rememberSearchMode(modeKey, "fulltext (embedding unavailable)");
9259
9271
  console.error("[memorix] Embedding failed or timed out, falling back to fulltext search");
9260
9272
  }
@@ -9262,7 +9274,7 @@ async function searchObservations(options) {
9262
9274
  mark("preSearch");
9263
9275
  let results;
9264
9276
  const persistentCorpusEligible = await shouldUsePersistentSearch(projectIds, options.projectId);
9265
- const canUsePersistentLexical = persistentCorpusEligible && Boolean(hasQuery) && !queryVector && (quality === "fast" || tier === "fast" || !embeddingEnabled);
9277
+ const canUsePersistentLexical = persistentCorpusEligible && Boolean(hasQuery) && !queryVector && (quality === "fast" || tier === "fast" || !embeddingEnabled || embeddingUnavailable);
9266
9278
  let persistent = persistentCorpusEligible && queryVector && embeddingProviderForSearch ? await searchPersistentSemantically(options, projectIds, requestLimit, queryVector, embeddingProviderForSearch) : canUsePersistentLexical ? await searchPersistentLexically(options, projectIds, requestLimit) : null;
9267
9279
  const durableStore = getOptionalObservationStore();
9268
9280
  if (!persistent && queryVector && durableStore?.hasLexicalIndex?.() && count(database) === 0) {
@@ -170804,7 +170816,7 @@ var MCP_SERVER_INFO_META_KEY = "io.modelcontextprotocol/serverInfo";
170804
170816
  function getMcpServerInfo() {
170805
170817
  return {
170806
170818
  name: "memorix",
170807
- version: true ? "1.9.6" : "1.0.1"
170819
+ version: true ? "1.9.7" : "1.0.1"
170808
170820
  };
170809
170821
  }
170810
170822
  function createMcpDiscoverResult(capabilities, serverInfo) {