@melandlabs/memory-store 0.2.7 → 0.3.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.
@@ -241,7 +241,7 @@ __export(raw_message_store_exports, {
241
241
  getRawMessageStorageBackend: () => getRawMessageStorageBackend,
242
242
  isRawMessageStorageAvailable: () => isRawMessageStorageAvailable
243
243
  });
244
- function resolveBackend(env) {
244
+ function resolveBackend(_env) {
245
245
  const explicit = process.env.OPENCONTEXT_MEMORY_STORE_BACKEND?.trim().toLowerCase();
246
246
  if (explicit === "postgres") return "postgres";
247
247
  return "sqlite";
@@ -374,6 +374,12 @@ function mergeUnifiedMemorySearchResults(results, limit, options = {}) {
374
374
  function normalizeUnifiedMemoryMergeStrategy(value) {
375
375
  return value === "rrf" ? "rrf" : "similarity";
376
376
  }
377
+ function normalizeUnifiedMemoryReasoningStrategy(value, defaultStrategy = "none") {
378
+ if (value === "rewrite" || value === "iterative") {
379
+ return value;
380
+ }
381
+ return defaultStrategy;
382
+ }
377
383
  var DEFAULT_RRF_K = 60;
378
384
  function mergeUnifiedMemorySearchResultsRrf(lists, limit, k = DEFAULT_RRF_K) {
379
385
  if (!Array.isArray(lists) || lists.length === 0) {
@@ -396,7 +402,13 @@ function mergeUnifiedMemorySearchResultsRrf(lists, limit, k = DEFAULT_RRF_K) {
396
402
  }
397
403
  }
398
404
  }
399
- const ranked = order.map((key) => scores.get(key)).sort((a, b) => {
405
+ const ranked = order.map((key) => {
406
+ const entry = scores.get(key);
407
+ if (!entry) {
408
+ throw new Error(`Invariant violation: missing RRF score for key "${key}"`);
409
+ }
410
+ return entry;
411
+ }).sort((a, b) => {
400
412
  if (b.rrf !== a.rrf) {
401
413
  return b.rrf - a.rrf;
402
414
  }
@@ -441,14 +453,222 @@ function isRawMemorySemanticResult(result) {
441
453
  function deriveLexicalKeywords(query) {
442
454
  return query.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((token) => token.length >= 2).slice(0, 16);
443
455
  }
456
+ function parseDateBoundary(value, role) {
457
+ const trimmed = value.trim();
458
+ if (!trimmed) {
459
+ return void 0;
460
+ }
461
+ const dateOnlyMatch = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})$/);
462
+ if (dateOnlyMatch) {
463
+ const year = Number.parseInt(dateOnlyMatch[1], 10);
464
+ const month = Number.parseInt(dateOnlyMatch[2], 10) - 1;
465
+ const day = Number.parseInt(dateOnlyMatch[3], 10);
466
+ if (role === "from") {
467
+ return Date.UTC(year, month, day);
468
+ }
469
+ return Date.UTC(year, month, day + 1) - 1;
470
+ }
471
+ const parsed = Date.parse(trimmed);
472
+ if (Number.isNaN(parsed)) {
473
+ return void 0;
474
+ }
475
+ return parsed;
476
+ }
477
+ function getCandidateTimestamp(metadata) {
478
+ for (const key of ["timestamp", "createdAt", "time"]) {
479
+ const value = metadata[key];
480
+ if (typeof value === "number") {
481
+ return value;
482
+ }
483
+ if (typeof value === "string") {
484
+ const parsed = Date.parse(value);
485
+ if (!Number.isNaN(parsed)) {
486
+ return parsed;
487
+ }
488
+ }
489
+ }
490
+ return void 0;
491
+ }
492
+ function filterByDateRange(items, dateFrom, dateTo) {
493
+ if (!dateFrom && !dateTo) {
494
+ return items;
495
+ }
496
+ const fromMs = dateFrom ? parseDateBoundary(dateFrom, "from") : void 0;
497
+ const toMs = dateTo ? parseDateBoundary(dateTo, "to") : void 0;
498
+ if (fromMs === void 0 && toMs === void 0) {
499
+ return items;
500
+ }
501
+ return items.filter((item) => {
502
+ const ts = getCandidateTimestamp(item.metadata);
503
+ if (ts === void 0) {
504
+ return true;
505
+ }
506
+ if (fromMs !== void 0 && ts < fromMs) {
507
+ return false;
508
+ }
509
+ if (toMs !== void 0 && ts > toMs) {
510
+ return false;
511
+ }
512
+ return true;
513
+ });
514
+ }
515
+ async function embedQueryVariant(embedQuery, input, query) {
516
+ return embedQuery({
517
+ userId: input.userId,
518
+ query,
519
+ authToken: input.authToken
520
+ });
521
+ }
522
+ async function runSemanticSearchForEmbedding(deps, input, queryEmbedding, limit, threshold, logger) {
523
+ const filters = input.botIds && input.botIds.length > 0 ? input.botIds.map((botId) => ({ botId })) : [{}];
524
+ let semantic = [];
525
+ if (isRawMessageChromaEnabled()) {
526
+ try {
527
+ semantic = (await Promise.all(
528
+ filters.map((filter) => {
529
+ const botId = "botId" in filter ? filter.botId : void 0;
530
+ return searchRawMessagesWithChroma({
531
+ userId: input.userId,
532
+ queryEmbedding,
533
+ limit,
534
+ threshold,
535
+ botId
536
+ });
537
+ })
538
+ )).flat().map(toMemoryResult);
539
+ logger.log?.("[memory-store] Raw message semantic search completed", {
540
+ backend: "chroma",
541
+ dimensions: queryEmbedding.length,
542
+ count: semantic.length
543
+ });
544
+ } catch (error) {
545
+ logger.warn?.(
546
+ "[memory-store] Chroma raw message search failed; falling back to database search:",
547
+ error
548
+ );
549
+ }
550
+ } else if (typeof deps.searchRawMessagesAnn === "function") {
551
+ const searchRawMessagesAnn = deps.searchRawMessagesAnn;
552
+ semantic = (await Promise.all(
553
+ filters.map(
554
+ (filter) => searchRawMessagesAnn({
555
+ userId: input.userId,
556
+ queryEmbedding,
557
+ limit,
558
+ threshold,
559
+ botId: "botId" in filter ? filter.botId : void 0
560
+ })
561
+ )
562
+ )).flat().filter(isRawMemorySemanticResult).map(toMemoryResult);
563
+ }
564
+ if (semantic.length === 0) {
565
+ try {
566
+ const { getRawMessageManager: getRawMessageManager2 } = await Promise.resolve().then(() => (init_raw_message_store(), raw_message_store_exports));
567
+ const manager2 = await getRawMessageManager2();
568
+ if (typeof manager2.searchMessagesSemantically === "function") {
569
+ const results = await manager2.searchMessagesSemantically({
570
+ userId: input.userId,
571
+ queryEmbedding,
572
+ limit,
573
+ threshold
574
+ });
575
+ semantic = results.map((r) => ({
576
+ type: "memory",
577
+ id: r.id,
578
+ content: r.content,
579
+ similarity: r.similarity,
580
+ metadata: r.metadata ?? {}
581
+ }));
582
+ }
583
+ } catch (error) {
584
+ logger.warn?.("[memory-store] SQLite semantic search failed:", error);
585
+ }
586
+ }
587
+ return semantic;
588
+ }
589
+ function mergeByMaxScore(lists) {
590
+ const best = /* @__PURE__ */ new Map();
591
+ for (const list of lists) {
592
+ for (const hit of list) {
593
+ const existing = best.get(hit.id);
594
+ if (!existing || hit.similarity > existing.similarity) {
595
+ best.set(hit.id, hit);
596
+ }
597
+ }
598
+ }
599
+ return Array.from(best.values()).sort((a, b) => b.similarity - a.similarity);
600
+ }
601
+ function toIterativeRecallCandidate(hit) {
602
+ return {
603
+ id: hit.id,
604
+ content: hit.content,
605
+ similarity: hit.similarity,
606
+ metadata: hit.metadata
607
+ };
608
+ }
609
+ async function runLexicalSearchForKeywords(deps, input, keywords, limit, logger) {
610
+ if (keywords.length === 0) {
611
+ return [];
612
+ }
613
+ if (typeof deps.searchRawMessagesLexical === "function") {
614
+ try {
615
+ const filters = input.botIds && input.botIds.length > 0 ? input.botIds : [void 0];
616
+ const searchRawMessagesLexical = deps.searchRawMessagesLexical;
617
+ return (await Promise.all(
618
+ filters.map(
619
+ (botId) => searchRawMessagesLexical({
620
+ userId: input.userId,
621
+ keywords,
622
+ limit: Math.ceil(limit / filters.length),
623
+ botId
624
+ })
625
+ )
626
+ )).flat().filter(isRawMemorySemanticResult).map((hit) => ({
627
+ ...toMemoryResult(hit),
628
+ metadata: { ...hit.metadata, scoring: "bm25" }
629
+ }));
630
+ } catch (error) {
631
+ logger.warn?.("[memory-store] lexical memory search failed:", error);
632
+ }
633
+ }
634
+ try {
635
+ const { lexicalSearchRawMessages: lexicalSearchRawMessages2 } = await Promise.resolve().then(() => (init_sqlite_raw_message_store(), sqlite_raw_message_store_exports));
636
+ const filters = input.botIds && input.botIds.length > 0 ? input.botIds : [void 0];
637
+ return (await Promise.all(
638
+ filters.map(
639
+ (botId) => lexicalSearchRawMessages2({
640
+ userId: input.userId,
641
+ keywords,
642
+ limit: Math.ceil(limit / filters.length),
643
+ botId
644
+ })
645
+ )
646
+ )).flat().filter(Boolean).map(
647
+ (r) => toMemoryResult(
648
+ r
649
+ )
650
+ );
651
+ } catch (error) {
652
+ logger.warn?.("[memory-store] SQLite lexical search failed:", error);
653
+ }
654
+ return [];
655
+ }
444
656
  function createUnifiedSearch(deps = {}) {
445
657
  const logger = deps.logger ?? console;
658
+ function resolveReasoningStrategy(input) {
659
+ const requested = normalizeUnifiedMemoryReasoningStrategy(input.reasoningStrategy);
660
+ if (requested !== "none") {
661
+ return requested;
662
+ }
663
+ return normalizeUnifiedMemoryReasoningStrategy(deps.reasoning?.defaultStrategy, "none");
664
+ }
446
665
  async function searchUnifiedMemory(input) {
447
666
  const query = input.query.trim();
448
667
  const sources = normalizeUnifiedMemorySearchSources(input.sources);
449
668
  const limit = clampUnifiedMemorySearchLimit(input.limit);
450
669
  const threshold = clampUnifiedMemorySearchThreshold(input.threshold);
451
670
  const mergeStrategy = normalizeUnifiedMemoryMergeStrategy(input.mergeStrategy);
671
+ const reasoningStrategy = resolveReasoningStrategy(input);
452
672
  const warnings = [];
453
673
  if (!query) {
454
674
  return {
@@ -460,10 +680,21 @@ function createUnifiedSearch(deps = {}) {
460
680
  };
461
681
  }
462
682
  let memorySubs;
683
+ const reasoningInfo = { strategy: reasoningStrategy };
684
+ if (input.dateFrom || input.dateTo) {
685
+ reasoningInfo.dateRange = { from: input.dateFrom, to: input.dateTo };
686
+ }
463
687
  if (sources.includes("memory")) {
464
688
  if (isRawMessageStorageAvailable()) {
465
689
  try {
466
- memorySubs = await runMemorySource(input, limit, threshold, warnings);
690
+ memorySubs = await runMemorySource(
691
+ input,
692
+ limit,
693
+ threshold,
694
+ warnings,
695
+ reasoningStrategy,
696
+ reasoningInfo
697
+ );
467
698
  } catch (error) {
468
699
  logger.warn?.("[memory-store] memory source failed:", error);
469
700
  warnings.push({
@@ -542,121 +773,155 @@ function createUnifiedSearch(deps = {}) {
542
773
  limit,
543
774
  strategy: mergeStrategy
544
775
  });
545
- return {
776
+ const output = {
546
777
  query: input.query,
547
778
  sources,
548
779
  results: merged,
549
780
  count: merged.length,
550
781
  warnings
551
782
  };
783
+ if (reasoningInfo && (reasoningInfo.strategy !== "none" || reasoningInfo.dateRange !== void 0)) {
784
+ output.reasoning = reasoningInfo;
785
+ }
786
+ return output;
552
787
  }
553
- async function runMemorySource(input, limit, threshold, warnings) {
788
+ async function runMemorySource(input, limit, threshold, warnings, reasoningStrategy = "none", reasoningInfo) {
789
+ if (reasoningStrategy === "iterative" && !deps.reasoning?.iterativePlanner) {
790
+ warnings.push({
791
+ source: "memory",
792
+ code: "memory_iterative_planner_not_configured",
793
+ message: "Iterative reasoning requested but no iterativePlanner is configured; falling back to default search."
794
+ });
795
+ if (reasoningInfo) reasoningInfo.degraded = true;
796
+ }
797
+ if (reasoningStrategy === "rewrite" && !deps.reasoning?.queryRewriter) {
798
+ warnings.push({
799
+ source: "memory",
800
+ code: "memory_query_rewrite_not_configured",
801
+ message: "Rewrite reasoning requested but no queryRewriter is configured; falling back to default search."
802
+ });
803
+ if (reasoningInfo) reasoningInfo.degraded = true;
804
+ }
805
+ if (reasoningStrategy === "iterative" && deps.reasoning?.iterativePlanner) {
806
+ const planner = deps.reasoning.iterativePlanner;
807
+ const result = await planner.plan({
808
+ query: input.query,
809
+ dateFrom: input.dateFrom,
810
+ dateTo: input.dateTo,
811
+ executor: {
812
+ search: async (request) => {
813
+ const keywords2 = request.keywords.length > 0 ? request.keywords : deriveLexicalKeywords(input.query);
814
+ const lexicalHits = await runLexicalSearchForKeywords(deps, input, keywords2, limit, logger);
815
+ let semanticHits = [];
816
+ if (typeof deps.embedQuery === "function") {
817
+ try {
818
+ const semanticQuery = keywords2.join(" ");
819
+ const queryEmbedding = await embedQueryVariant(deps.embedQuery, input, semanticQuery);
820
+ semanticHits = await runSemanticSearchForEmbedding(
821
+ deps,
822
+ input,
823
+ queryEmbedding,
824
+ limit,
825
+ threshold,
826
+ logger
827
+ );
828
+ } catch (error) {
829
+ logger.warn?.(
830
+ "[memory-store] Iterative semantic search failed; using lexical results only:",
831
+ error
832
+ );
833
+ }
834
+ }
835
+ const candidates = filterByDateRange(
836
+ mergeByMaxScore([
837
+ lexicalHits.map(toIterativeRecallCandidate),
838
+ semanticHits.map(toIterativeRecallCandidate)
839
+ ]),
840
+ request.dateFrom,
841
+ request.dateTo
842
+ );
843
+ return { candidates };
844
+ }
845
+ }
846
+ });
847
+ if (reasoningInfo) {
848
+ reasoningInfo.iterations = result.stats.iterations;
849
+ reasoningInfo.evidenceCount = result.evidence.length;
850
+ if (planner.lastDegraded?.()) {
851
+ reasoningInfo.degraded = true;
852
+ }
853
+ }
854
+ const semantic2 = result.evidence.map((candidate) => ({
855
+ type: "memory",
856
+ id: candidate.id,
857
+ content: candidate.content,
858
+ similarity: candidate.similarity,
859
+ metadata: { ...candidate.metadata, reasoning: "iterative" }
860
+ }));
861
+ return { semantic: semantic2, lexical: [] };
862
+ }
554
863
  if (typeof deps.embedQuery !== "function") {
555
864
  warnings.push({
556
865
  source: "memory",
557
866
  code: "memory_lexical_search_fallback",
558
867
  message: "Semantic search not configured, using keyword search as fallback"
559
868
  });
560
- const { lexicalSearchRawMessages: lexicalSearchRawMessages2 } = await Promise.resolve().then(() => (init_sqlite_raw_message_store(), sqlite_raw_message_store_exports));
561
- const keywords = deriveLexicalKeywords(input.query);
562
- let lexical2 = [];
563
- if (keywords.length > 0) {
564
- try {
565
- const filters2 = input.botIds && input.botIds.length > 0 ? input.botIds : [void 0];
566
- const results = await Promise.all(
567
- filters2.map(
568
- (botId) => lexicalSearchRawMessages2({
569
- userId: input.userId,
570
- keywords,
571
- limit: Math.ceil(limit / filters2.length),
572
- botId
573
- })
574
- )
575
- );
576
- lexical2 = results.flat().filter(Boolean).map(toMemoryResult);
577
- } catch (error) {
578
- logger.warn?.("[memory-store] Default lexical search failed:", error);
579
- }
580
- }
869
+ const keywords2 = deriveLexicalKeywords(input.query);
870
+ const lexical2 = filterByDateRange(
871
+ await runLexicalSearchForKeywords(deps, input, keywords2, limit, logger),
872
+ input.dateFrom,
873
+ input.dateTo
874
+ );
581
875
  return { semantic: [], lexical: lexical2 };
582
876
  }
583
- const queryEmbedding = await deps.embedQuery({
584
- userId: input.userId,
585
- query: input.query,
586
- authToken: input.authToken
587
- });
588
- const filters = input.botIds && input.botIds.length > 0 ? input.botIds.map((botId) => ({ botId })) : [{}];
589
877
  let semantic = [];
590
- if (isRawMessageChromaEnabled()) {
878
+ const embedQuery = deps.embedQuery;
879
+ if (reasoningStrategy === "rewrite" && deps.reasoning?.queryRewriter) {
591
880
  try {
592
- semantic = (await Promise.all(
593
- filters.map((filter) => {
594
- const botId = "botId" in filter ? filter.botId : void 0;
595
- return searchRawMessagesWithChroma({
596
- userId: input.userId,
597
- queryEmbedding,
598
- limit,
599
- threshold,
600
- botId
601
- });
602
- })
603
- )).flat().map(toMemoryResult);
604
- logger.log?.("[memory-store] Raw message semantic search completed", {
605
- backend: "chroma",
606
- dimensions: queryEmbedding.length,
607
- count: semantic.length
881
+ const variants = await deps.reasoning.queryRewriter.rewrite({
882
+ query: input.query,
883
+ userId: input.userId,
884
+ authToken: input.authToken
608
885
  });
609
- } catch (error) {
610
- logger.warn?.(
611
- "[memory-store] Chroma raw message search failed; falling back to database search:",
612
- error
886
+ if (reasoningInfo) {
887
+ reasoningInfo.rewrittenQueries = variants;
888
+ if (deps.reasoning.queryRewriter.lastDegraded?.()) {
889
+ reasoningInfo.degraded = true;
890
+ }
891
+ }
892
+ const embeddings = await Promise.all(
893
+ variants.map((variant) => embedQueryVariant(embedQuery, input, variant))
894
+ );
895
+ const lists = await Promise.all(
896
+ embeddings.map(
897
+ (embedding) => runSemanticSearchForEmbedding(deps, input, embedding, limit, threshold, logger)
898
+ )
613
899
  );
900
+ semantic = mergeByMaxScore(lists);
901
+ } catch (error) {
902
+ logger.warn?.("[memory-store] Query rewriting failed; falling back to original query:", error);
903
+ warnings.push({
904
+ source: "memory",
905
+ code: "memory_query_rewrite_failed",
906
+ message: `Query rewriting failed: ${error.message ?? "Unknown error"}. Using original query.`
907
+ });
908
+ if (reasoningInfo) reasoningInfo.degraded = true;
614
909
  }
615
- } else if (typeof deps.searchRawMessagesAnn === "function") {
616
- semantic = (await Promise.all(
617
- filters.map(
618
- (filter) => deps.searchRawMessagesAnn({
619
- userId: input.userId,
620
- queryEmbedding,
621
- limit,
622
- threshold,
623
- botId: "botId" in filter ? filter.botId : void 0
624
- })
625
- )
626
- )).flat().filter(isRawMemorySemanticResult).map(toMemoryResult);
627
910
  }
628
911
  if (semantic.length === 0) {
629
- try {
630
- const { getRawMessageManager: getRawMessageManager2 } = await Promise.resolve().then(() => (init_raw_message_store(), raw_message_store_exports));
631
- const manager2 = await getRawMessageManager2();
632
- if (typeof manager2.searchMessagesSemantically === "function") {
633
- const results = await manager2.searchMessagesSemantically({
634
- userId: input.userId,
635
- queryEmbedding,
636
- limit,
637
- threshold
638
- });
639
- semantic = results.map((r) => ({
640
- type: "memory",
641
- id: r.id,
642
- content: r.content,
643
- similarity: r.similarity,
644
- metadata: r.metadata ?? {}
645
- }));
646
- }
647
- } catch (error) {
648
- logger.warn?.("[memory-store] SQLite semantic search failed:", error);
649
- }
912
+ const queryEmbedding = await embedQueryVariant(embedQuery, input, input.query);
913
+ semantic = await runSemanticSearchForEmbedding(deps, input, queryEmbedding, limit, threshold, logger);
650
914
  }
651
915
  let lexical = [];
652
- if (typeof deps.searchRawMessagesLexical === "function") {
653
- const keywords = deriveLexicalKeywords(input.query);
654
- if (keywords.length > 0) {
916
+ const keywords = deriveLexicalKeywords(input.query);
917
+ if (keywords.length > 0) {
918
+ if (typeof deps.searchRawMessagesLexical === "function") {
655
919
  try {
656
920
  const lexFilters = input.botIds && input.botIds.length > 0 ? input.botIds : [void 0];
921
+ const searchRawMessagesLexical = deps.searchRawMessagesLexical;
657
922
  lexical = (await Promise.all(
658
923
  lexFilters.map(
659
- (botId) => deps.searchRawMessagesLexical({
924
+ (botId) => searchRawMessagesLexical({
660
925
  userId: input.userId,
661
926
  keywords,
662
927
  limit,
@@ -675,20 +940,24 @@ function createUnifiedSearch(deps = {}) {
675
940
  message: error.message ?? "memory_lexical_search_failed"
676
941
  });
677
942
  }
943
+ } else if (input.mergeStrategy === "rrf") {
944
+ warnings.push({
945
+ source: "memory",
946
+ code: "memory_lexical_search_not_configured",
947
+ message: "RRF merge requested but lexical search is not configured; falling back to semantic-only RRF."
948
+ });
678
949
  }
679
- } else if (input.mergeStrategy === "rrf") {
680
- warnings.push({
681
- source: "memory",
682
- code: "memory_lexical_search_not_configured",
683
- message: "RRF merge requested but lexical search is not configured; falling back to semantic-only RRF."
684
- });
685
950
  }
686
- return { semantic, lexical };
951
+ return {
952
+ semantic: filterByDateRange(semantic, input.dateFrom, input.dateTo),
953
+ lexical: filterByDateRange(lexical, input.dateFrom, input.dateTo)
954
+ };
687
955
  }
688
956
  async function searchRawMemorySemantically(input) {
689
957
  const limit = clampUnifiedMemorySearchLimit(input.limit);
690
958
  const threshold = clampUnifiedMemorySearchThreshold(input.threshold);
691
- const sub = await runMemorySource(input, limit, threshold, []);
959
+ const reasoningStrategy = resolveReasoningStrategy(input);
960
+ const sub = await runMemorySource(input, limit, threshold, [], reasoningStrategy);
692
961
  return mergeAcrossSources({
693
962
  memorySubs: sub,
694
963
  insightHits: [],
@@ -815,6 +1084,7 @@ async function startMcpServer(options = {}) {
815
1084
  {
816
1085
  title: "Search Unified Memory",
817
1086
  description: "Semantic search across raw messages (always), and optionally insights and uploaded knowledge.",
1087
+ // biome-ignore lint/suspicious/noExplicitAny: MCP SDK expects Zod schema type
818
1088
  inputSchema: searchSchema
819
1089
  },
820
1090
  async (args) => {
@@ -830,6 +1100,7 @@ async function startMcpServer(options = {}) {
830
1100
  {
831
1101
  title: "Write Raw Message",
832
1102
  description: "Persist a single raw message to the user's memory store.",
1103
+ // biome-ignore lint/suspicious/noExplicitAny: MCP SDK expects Zod schema type
833
1104
  inputSchema: writeSchema
834
1105
  },
835
1106
  async (args) => {
@@ -869,6 +1140,7 @@ async function startMcpServer(options = {}) {
869
1140
  {
870
1141
  title: "Get Raw Message",
871
1142
  description: "Fetch a single raw message by its message id.",
1143
+ // biome-ignore lint/suspicious/noExplicitAny: MCP SDK expects Zod schema type
872
1144
  inputSchema: getSchema
873
1145
  },
874
1146
  async (args) => {
@@ -1077,6 +1349,9 @@ async function buildUnified(args) {
1077
1349
  } else if (args.memoryBackend === "chroma") {
1078
1350
  if (!args.chromaUrl)
1079
1351
  throw new Error("--memory-backend=chroma requires --chroma-url <url> (or CHROMA_URL env)");
1352
+ if (!aiRag) {
1353
+ throw new Error("ai-rag modules not loaded");
1354
+ }
1080
1355
  const store = new aiRag.ChromaVectorStore({
1081
1356
  url: args.chromaUrl,
1082
1357
  collectionName: "opencontext_raw_messages"
@@ -1115,6 +1390,9 @@ async function buildUnified(args) {
1115
1390
  throw new Error("--insights-backend=chroma requires --chroma-url <url> (or CHROMA_URL env)");
1116
1391
  if (!unified.embedQuery)
1117
1392
  throw new Error("--insights-backend=chroma requires --embedding-provider local|openrouter");
1393
+ if (!aiRag) {
1394
+ throw new Error("ai-rag modules not loaded");
1395
+ }
1118
1396
  const store = new aiRag.ChromaVectorStore({
1119
1397
  url: args.chromaUrl,
1120
1398
  collectionName: args.insightsCollection
@@ -1132,6 +1410,9 @@ async function buildUnified(args) {
1132
1410
  throw new Error("--knowledge-backend=chroma requires --chroma-url <url> (or CHROMA_URL env)");
1133
1411
  if (!unified.embedQuery)
1134
1412
  throw new Error("--knowledge-backend=chroma requires --embedding-provider local|openrouter");
1413
+ if (!aiRag) {
1414
+ throw new Error("ai-rag modules not loaded");
1415
+ }
1135
1416
  const store = new aiRag.ChromaVectorStore({
1136
1417
  url: args.chromaUrl,
1137
1418
  collectionName: args.knowledgeCollection
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { d as UnifiedSearchDeps } from '../config-Ll6ktm4D.js';
2
+ import { H as UnifiedSearchDeps } from '../config-2Q092MUz.js';
3
3
 
4
4
  /**
5
5
  * Shared argv parsing + `unified.*` wiring for the memory-store CLI bins.
@@ -61,7 +61,7 @@ async function closeSQLiteRawMessageManager() {
61
61
  }
62
62
 
63
63
  // src/storage/raw-message-store.ts
64
- function resolveBackend(env) {
64
+ function resolveBackend(_env) {
65
65
  const explicit = process.env.OPENCONTEXT_MEMORY_STORE_BACKEND?.trim().toLowerCase();
66
66
  if (explicit === "postgres") return "postgres";
67
67
  return "sqlite";
@@ -281,6 +281,9 @@ async function buildUnified(args) {
281
281
  } else if (args.memoryBackend === "chroma") {
282
282
  if (!args.chromaUrl)
283
283
  throw new Error("--memory-backend=chroma requires --chroma-url <url> (or CHROMA_URL env)");
284
+ if (!aiRag) {
285
+ throw new Error("ai-rag modules not loaded");
286
+ }
284
287
  const store = new aiRag.ChromaVectorStore({
285
288
  url: args.chromaUrl,
286
289
  collectionName: "opencontext_raw_messages"
@@ -319,6 +322,9 @@ async function buildUnified(args) {
319
322
  throw new Error("--insights-backend=chroma requires --chroma-url <url> (or CHROMA_URL env)");
320
323
  if (!unified.embedQuery)
321
324
  throw new Error("--insights-backend=chroma requires --embedding-provider local|openrouter");
325
+ if (!aiRag) {
326
+ throw new Error("ai-rag modules not loaded");
327
+ }
322
328
  const store = new aiRag.ChromaVectorStore({
323
329
  url: args.chromaUrl,
324
330
  collectionName: args.insightsCollection
@@ -336,6 +342,9 @@ async function buildUnified(args) {
336
342
  throw new Error("--knowledge-backend=chroma requires --chroma-url <url> (or CHROMA_URL env)");
337
343
  if (!unified.embedQuery)
338
344
  throw new Error("--knowledge-backend=chroma requires --embedding-provider local|openrouter");
345
+ if (!aiRag) {
346
+ throw new Error("ai-rag modules not loaded");
347
+ }
339
348
  const store = new aiRag.ChromaVectorStore({
340
349
  url: args.chromaUrl,
341
350
  collectionName: args.knowledgeCollection
@@ -1,4 +1,4 @@
1
- import { b as MemoryStoreEnv } from '../config-Ll6ktm4D.js';
1
+ import { i as MemoryStoreEnv } from '../config-2Q092MUz.js';
2
2
 
3
3
  /**
4
4
  * Lazy registration slot for the host's Postgres-backed raw message
@@ -1,5 +1,5 @@
1
1
  import { RawMessageStorageManager } from '@melandlabs/indexeddb/storage';
2
- import { b as MemoryStoreEnv, M as MemoryStoreConfig } from '../config-Ll6ktm4D.js';
2
+ import { i as MemoryStoreEnv, M as MemoryStoreConfig } from '../config-2Q092MUz.js';
3
3
 
4
4
  /**
5
5
  * Top-level raw-message store facade.
@@ -60,7 +60,7 @@ async function closeSQLiteRawMessageManager() {
60
60
  }
61
61
 
62
62
  // src/storage/raw-message-store.ts
63
- function resolveBackend(env) {
63
+ function resolveBackend(_env) {
64
64
  const explicit = process.env.OPENCONTEXT_MEMORY_STORE_BACKEND?.trim().toLowerCase();
65
65
  if (explicit === "postgres") return "postgres";
66
66
  return "sqlite";
@@ -1,5 +1,5 @@
1
1
  import { SQLiteRawMessageManager } from '@melandlabs/sqlite';
2
- import { b as MemoryStoreEnv } from '../config-Ll6ktm4D.js';
2
+ import { i as MemoryStoreEnv } from '../config-2Q092MUz.js';
3
3
 
4
4
  /**
5
5
  * SQLite-backed raw message store.