@melandlabs/memory-store 0.2.0 → 0.2.1

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/http.js CHANGED
@@ -1,13 +1,21 @@
1
- import { serve } from '@hono/node-server';
2
- import { Hono } from 'hono';
3
1
  import { buildMemoryRecordEmbeddingDocument } from '@melandlabs/ai/memory';
4
2
  import { ChromaVectorStore } from '@melandlabs/rag';
5
3
  import { mkdirSync } from 'fs';
6
4
  import { homedir } from 'os';
7
- import { join, dirname } from 'path';
5
+ import { dirname, join } from 'path';
8
6
  import { SQLiteRawMessageManager } from '@melandlabs/sqlite';
7
+ import { serve } from '@hono/node-server';
8
+ import { Hono } from 'hono';
9
9
 
10
- // src/http.ts
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropNames = Object.getOwnPropertyNames;
12
+ var __esm = (fn, res) => function __init() {
13
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
14
+ };
15
+ var __export = (target, all) => {
16
+ for (var name in all)
17
+ __defProp(target, name, { get: all[name], enumerable: true });
18
+ };
11
19
 
12
20
  // src/contracts.ts
13
21
  function normalizeTimestampToMs(value) {
@@ -31,14 +39,10 @@ function rawMessageToMemoryRecord(message) {
31
39
  embeddingContentHash: message.embeddingContentHash
32
40
  };
33
41
  }
34
-
35
- // src/storage/chroma-memory-index.ts
36
- var DEFAULT_RAW_MESSAGES_COLLECTION = "opencontext_raw_messages";
37
- var RAW_VECTOR_BACKEND_ENV_KEYS = [
38
- "RAW_MESSAGE_VECTOR_STORE_BACKEND",
39
- "MEMORY_VECTOR_STORE_BACKEND",
40
- "VECTOR_STORE_BACKEND"
41
- ];
42
+ var init_contracts = __esm({
43
+ "src/contracts.ts"() {
44
+ }
45
+ });
42
46
  function getBackend(keys) {
43
47
  for (const key of keys) {
44
48
  const value = process.env[key]?.trim().toLowerCase();
@@ -141,21 +145,51 @@ async function searchRawMessagesWithChroma(input) {
141
145
  metadata: result.metadata ?? {}
142
146
  })).slice(0, input.limit);
143
147
  }
148
+ var DEFAULT_RAW_MESSAGES_COLLECTION, RAW_VECTOR_BACKEND_ENV_KEYS;
149
+ var init_chroma_memory_index = __esm({
150
+ "src/storage/chroma-memory-index.ts"() {
151
+ init_contracts();
152
+ DEFAULT_RAW_MESSAGES_COLLECTION = "opencontext_raw_messages";
153
+ RAW_VECTOR_BACKEND_ENV_KEYS = [
154
+ "RAW_MESSAGE_VECTOR_STORE_BACKEND",
155
+ "MEMORY_VECTOR_STORE_BACKEND",
156
+ "VECTOR_STORE_BACKEND"
157
+ ];
158
+ }
159
+ });
144
160
 
145
161
  // src/storage/postgres-raw-message-factory.ts
146
- var factory = null;
147
162
  async function resolvePostgresFactory(env) {
148
- return null;
163
+ if (!factory) return null;
164
+ return await factory(env);
149
165
  }
150
166
  function hasPostgresFactory() {
151
167
  return factory !== null;
152
168
  }
153
- var manager = null;
154
- var DEFAULT_SQLITE_PATH = join(homedir(), ".opencontext", "memory", "store.db");
169
+ var factory;
170
+ var init_postgres_raw_message_factory = __esm({
171
+ "src/storage/postgres-raw-message-factory.ts"() {
172
+ factory = null;
173
+ }
174
+ });
175
+
176
+ // src/storage/sqlite-raw-message-store.ts
177
+ var sqlite_raw_message_store_exports = {};
178
+ __export(sqlite_raw_message_store_exports, {
179
+ __resetSQLiteRawMessageManagerForTests: () => __resetSQLiteRawMessageManagerForTests,
180
+ closeSQLiteRawMessageManager: () => closeSQLiteRawMessageManager,
181
+ getSQLiteRawMessageManager: () => getSQLiteRawMessageManager,
182
+ isSQLiteRawMessageStorageAvailable: () => isSQLiteRawMessageStorageAvailable,
183
+ lexicalSearchRawMessages: () => lexicalSearchRawMessages,
184
+ resolveSQLiteRawMessageDbPath: () => resolveSQLiteRawMessageDbPath
185
+ });
155
186
  function resolveSQLiteRawMessageDbPath() {
156
187
  const fromEnv = process.env.MEMORY_STORE_DB_PATH?.trim();
157
188
  return fromEnv && fromEnv.length > 0 ? fromEnv : DEFAULT_SQLITE_PATH;
158
189
  }
190
+ function isSQLiteRawMessageStorageAvailable(_env) {
191
+ return true;
192
+ }
159
193
  async function getSQLiteRawMessageManager(_env) {
160
194
  if (!manager) {
161
195
  const dbPath = resolveSQLiteRawMessageDbPath();
@@ -175,8 +209,35 @@ async function closeSQLiteRawMessageManager() {
175
209
  await manager.close();
176
210
  manager = null;
177
211
  }
212
+ function __resetSQLiteRawMessageManagerForTests() {
213
+ manager = null;
214
+ }
215
+ async function lexicalSearchRawMessages(input) {
216
+ const mgr = await getSQLiteRawMessageManager();
217
+ if (typeof mgr.lexicalSearchMessages !== "function") {
218
+ return [];
219
+ }
220
+ return mgr.lexicalSearchMessages(input);
221
+ }
222
+ var manager, DEFAULT_SQLITE_PATH;
223
+ var init_sqlite_raw_message_store = __esm({
224
+ "src/storage/sqlite-raw-message-store.ts"() {
225
+ init_chroma_memory_index();
226
+ manager = null;
227
+ DEFAULT_SQLITE_PATH = join(homedir(), ".opencontext", "memory", "store.db");
228
+ }
229
+ });
178
230
 
179
231
  // src/storage/raw-message-store.ts
232
+ var raw_message_store_exports = {};
233
+ __export(raw_message_store_exports, {
234
+ closeRawMessageStore: () => closeRawMessageStore,
235
+ configureRawMessageStore: () => configureRawMessageStore,
236
+ createRawMessageStore: () => createRawMessageStore,
237
+ getRawMessageManager: () => getRawMessageManager,
238
+ getRawMessageStorageBackend: () => getRawMessageStorageBackend,
239
+ isRawMessageStorageAvailable: () => isRawMessageStorageAvailable
240
+ });
180
241
  function resolveBackend(env) {
181
242
  const explicit = process.env.OPENCONTEXT_MEMORY_STORE_BACKEND?.trim().toLowerCase();
182
243
  if (explicit === "postgres") return "postgres";
@@ -186,7 +247,7 @@ function resolveEnv(_env) {
186
247
  return {};
187
248
  }
188
249
  function createRawMessageStore(options = {}) {
189
- resolveEnv(options.env);
250
+ const env = resolveEnv(options.env);
190
251
  return {
191
252
  getBackend() {
192
253
  return resolveBackend();
@@ -196,7 +257,7 @@ function createRawMessageStore(options = {}) {
196
257
  },
197
258
  async getManager() {
198
259
  if (resolveBackend() === "postgres") {
199
- const pg = await resolvePostgresFactory();
260
+ const pg = await resolvePostgresFactory(env);
200
261
  if (!pg) {
201
262
  throw new Error(
202
263
  "OPENCONTEXT_MEMORY_STORE_BACKEND=postgres but no Postgres factory is registered. Call registerPostgresFactory() at startup, or unset the env var to use the default SQLite backend."
@@ -211,14 +272,47 @@ function createRawMessageStore(options = {}) {
211
272
  }
212
273
  };
213
274
  }
214
- var moduleStore = null;
215
- var moduleConfig = null;
275
+ function configureRawMessageStore(config) {
276
+ moduleConfig = config;
277
+ moduleStore = createRawMessageStore({ env: config.env });
278
+ return moduleStore;
279
+ }
280
+ function getRawMessageStorageBackend() {
281
+ if (!moduleStore) {
282
+ moduleStore = createRawMessageStore({ env: moduleConfig?.env });
283
+ }
284
+ return moduleStore.getBackend();
285
+ }
216
286
  function isRawMessageStorageAvailable() {
217
287
  if (!moduleStore) {
218
288
  moduleStore = createRawMessageStore({ env: moduleConfig?.env });
219
289
  }
220
290
  return moduleStore.isAvailable();
221
291
  }
292
+ async function getRawMessageManager() {
293
+ if (!moduleStore) {
294
+ moduleStore = createRawMessageStore({ env: moduleConfig?.env });
295
+ }
296
+ return moduleStore.getManager();
297
+ }
298
+ async function closeRawMessageStore() {
299
+ if (!moduleStore) return;
300
+ await moduleStore.close();
301
+ moduleStore = null;
302
+ }
303
+ var moduleStore, moduleConfig;
304
+ var init_raw_message_store = __esm({
305
+ "src/storage/raw-message-store.ts"() {
306
+ init_postgres_raw_message_factory();
307
+ init_sqlite_raw_message_store();
308
+ moduleStore = null;
309
+ moduleConfig = null;
310
+ }
311
+ });
312
+
313
+ // src/search/unified-search.ts
314
+ init_chroma_memory_index();
315
+ init_raw_message_store();
222
316
 
223
317
  // src/search/utilities.ts
224
318
  var DEFAULT_LIMIT = 10;
@@ -362,7 +456,7 @@ function createUnifiedSearch(deps = {}) {
362
456
  warnings.push({
363
457
  source: "memory",
364
458
  code: "memory_search_failed",
365
- message: error.message ?? "memory_search_failed"
459
+ message: `Memory search failed: ${error.message ?? "Unknown error"}. Using keyword search fallback.`
366
460
  });
367
461
  }
368
462
  } else {
@@ -402,13 +496,7 @@ function createUnifiedSearch(deps = {}) {
402
496
  message: error.message ?? "insights_search_failed"
403
497
  });
404
498
  }
405
- } else if (sources.includes("insights")) {
406
- warnings.push({
407
- source: "insights",
408
- code: "insights_search_not_configured",
409
- message: "Insights search is not configured for this host."
410
- });
411
- }
499
+ } else if (sources.includes("insights")) ;
412
500
  const knowledgeHits = [];
413
501
  if (sources.includes("knowledge") && typeof deps.searchKnowledge === "function") {
414
502
  try {
@@ -433,13 +521,7 @@ function createUnifiedSearch(deps = {}) {
433
521
  message: error.message ?? "knowledge_search_failed"
434
522
  });
435
523
  }
436
- } else if (sources.includes("knowledge")) {
437
- warnings.push({
438
- source: "knowledge",
439
- code: "knowledge_search_not_configured",
440
- message: "Knowledge search is not configured for this host."
441
- });
442
- }
524
+ } else if (sources.includes("knowledge")) ;
443
525
  const merged = mergeAcrossSources({
444
526
  memorySubs,
445
527
  insightHits,
@@ -457,7 +539,33 @@ function createUnifiedSearch(deps = {}) {
457
539
  }
458
540
  async function runMemorySource(input, limit, threshold, warnings) {
459
541
  if (typeof deps.embedQuery !== "function") {
460
- throw new Error("embedQuery is not configured");
542
+ warnings.push({
543
+ source: "memory",
544
+ code: "memory_lexical_search_fallback",
545
+ message: "Semantic search not configured, using keyword search as fallback"
546
+ });
547
+ const { lexicalSearchRawMessages: lexicalSearchRawMessages2 } = await Promise.resolve().then(() => (init_sqlite_raw_message_store(), sqlite_raw_message_store_exports));
548
+ const keywords = deriveLexicalKeywords(input.query);
549
+ let lexical2 = [];
550
+ if (keywords.length > 0) {
551
+ try {
552
+ const filters2 = input.botIds && input.botIds.length > 0 ? input.botIds : [void 0];
553
+ const results = await Promise.all(
554
+ filters2.map(
555
+ (botId) => lexicalSearchRawMessages2({
556
+ userId: input.userId,
557
+ keywords,
558
+ limit: Math.ceil(limit / filters2.length),
559
+ botId
560
+ })
561
+ )
562
+ );
563
+ lexical2 = results.flat().filter(Boolean).map(toMemoryResult);
564
+ } catch (error) {
565
+ logger.warn?.("[memory-store] Default lexical search failed:", error);
566
+ }
567
+ }
568
+ return { semantic: [], lexical: lexical2 };
461
569
  }
462
570
  const queryEmbedding = await deps.embedQuery({
463
571
  userId: input.userId,
@@ -504,6 +612,28 @@ function createUnifiedSearch(deps = {}) {
504
612
  )
505
613
  )).flat().filter(isRawMemorySemanticResult).map(toMemoryResult);
506
614
  }
615
+ if (semantic.length === 0) {
616
+ try {
617
+ const { getRawMessageManager: getRawMessageManager2 } = await Promise.resolve().then(() => (init_raw_message_store(), raw_message_store_exports));
618
+ const manager2 = await getRawMessageManager2();
619
+ if (typeof manager2.searchMessagesSemantically === "function") {
620
+ const results = await manager2.searchMessagesSemantically({
621
+ userId: input.userId,
622
+ queryEmbedding,
623
+ limit
624
+ });
625
+ semantic = results.map((r) => ({
626
+ type: "memory",
627
+ id: r.id,
628
+ content: r.content,
629
+ similarity: r.similarity,
630
+ metadata: r.metadata ?? {}
631
+ }));
632
+ }
633
+ } catch (error) {
634
+ logger.warn?.("[memory-store] SQLite semantic search failed:", error);
635
+ }
636
+ }
507
637
  let lexical = [];
508
638
  if (typeof deps.searchRawMessagesLexical === "function") {
509
639
  const keywords = deriveLexicalKeywords(input.query);
@@ -586,6 +716,8 @@ function mergeAcrossSources(input) {
586
716
  }
587
717
 
588
718
  // src/http.ts
719
+ init_chroma_memory_index();
720
+ init_raw_message_store();
589
721
  async function embedMissingMessages(messages, deps) {
590
722
  if (typeof deps.embedQuery !== "function") {
591
723
  return messages;
@@ -620,7 +752,23 @@ async function startHttpServer(options = {}) {
620
752
  const rawStore = createRawMessageStore({
621
753
  env: options.env
622
754
  });
623
- const search = createUnifiedSearch(options.unified);
755
+ const manager2 = await rawStore.getManager();
756
+ const search = createUnifiedSearch({
757
+ ...options.unified,
758
+ searchRawMessagesLexical: async (input) => {
759
+ if (typeof manager2.lexicalSearchMessages === "function") {
760
+ const results = await manager2.lexicalSearchMessages(input);
761
+ return results.filter(Boolean).map((r) => ({
762
+ type: "memory",
763
+ id: r.id,
764
+ content: r.content,
765
+ similarity: r.similarity,
766
+ metadata: r.metadata ?? {}
767
+ }));
768
+ }
769
+ return [];
770
+ }
771
+ });
624
772
  const app = new Hono();
625
773
  app.get("/health", (c) => c.json({ ok: true, store: "memory", ts: Date.now() }));
626
774
  app.post("/v1/search", async (c) => {
@@ -648,20 +796,20 @@ async function startHttpServer(options = {}) {
648
796
  if (!Array.isArray(body.messages) || !body.userId) {
649
797
  return c.json({ error: "userId and messages[] required" }, 400);
650
798
  }
651
- const manager2 = await rawStore.getManager();
799
+ const manager3 = await rawStore.getManager();
652
800
  const incoming = body.messages;
653
801
  const messages = body.embedOnInsert === true ? await embedMissingMessages(
654
802
  incoming.map((m) => ({ ...m, userId: m.userId ?? body.userId })),
655
803
  options.unified ?? {}
656
804
  ) : incoming.map((m) => ({ ...m, userId: m.userId ?? body.userId }));
657
805
  let result;
658
- if (typeof manager2.upsertRawMessages === "function") {
659
- result = await manager2.upsertRawMessages({
806
+ if (typeof manager3.upsertRawMessages === "function") {
807
+ result = await manager3.upsertRawMessages({
660
808
  userId: body.userId,
661
809
  messages
662
810
  });
663
- } else if (typeof manager2.storeMessages === "function") {
664
- const ids = await manager2.storeMessages(messages);
811
+ } else if (typeof manager3.storeMessages === "function") {
812
+ const ids = await manager3.storeMessages(messages);
665
813
  result = { inserted: ids.length, ids };
666
814
  } else {
667
815
  return c.json(
@@ -676,14 +824,33 @@ async function startHttpServer(options = {}) {
676
824
  } catch (error) {
677
825
  console.warn("[memory-store/http] chroma upsert failed:", error);
678
826
  }
827
+ try {
828
+ const messagesWithEmbeddings = messages.filter(
829
+ (m) => Array.isArray(m.embedding) && m.embedding.length > 0
830
+ );
831
+ if (messagesWithEmbeddings.length > 0) {
832
+ for (const message of messagesWithEmbeddings) {
833
+ if (typeof manager3.upsertVectorForMessage === "function") {
834
+ manager3.upsertVectorForMessage(message.messageId, message.embedding);
835
+ }
836
+ }
837
+ console.log(
838
+ "[memory-store/http] Updated sqlite-vec vector table for",
839
+ messagesWithEmbeddings.length,
840
+ "message(s)"
841
+ );
842
+ }
843
+ } catch (error) {
844
+ console.warn("[memory-store/http] sqlite-vec vector update failed:", error);
845
+ }
679
846
  return c.json({ ok: true, count: messages.length, result });
680
847
  });
681
848
  app.get("/v1/raw-messages/:id", async (c) => {
682
849
  const id = c.req.param("id");
683
850
  const userId = c.req.query("userId");
684
851
  if (!userId) return c.json({ error: "userId query param required" }, 400);
685
- const manager2 = await rawStore.getManager();
686
- const row = await manager2.getMessageById?.(id);
852
+ const manager3 = await rawStore.getManager();
853
+ const row = await manager3.getMessageById?.(id);
687
854
  if (!row) return c.json({ error: "not found" }, 404);
688
855
  return c.json({ message: row });
689
856
  });
package/dist/index.js CHANGED
@@ -2,16 +2,24 @@ import '@melandlabs/ai/memory';
2
2
  import { ChromaVectorStore } from '@melandlabs/rag';
3
3
  import { mkdirSync } from 'fs';
4
4
  import { homedir } from 'os';
5
- import { join, dirname } from 'path';
5
+ import { dirname, join } from 'path';
6
6
  import { SQLiteRawMessageManager } from '@melandlabs/sqlite';
7
7
 
8
- // src/storage/chroma-memory-index.ts
9
- var DEFAULT_RAW_MESSAGES_COLLECTION = "opencontext_raw_messages";
10
- var RAW_VECTOR_BACKEND_ENV_KEYS = [
11
- "RAW_MESSAGE_VECTOR_STORE_BACKEND",
12
- "MEMORY_VECTOR_STORE_BACKEND",
13
- "VECTOR_STORE_BACKEND"
14
- ];
8
+ var __defProp = Object.defineProperty;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __esm = (fn, res) => function __init() {
11
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
+ };
13
+ var __export = (target, all) => {
14
+ for (var name in all)
15
+ __defProp(target, name, { get: all[name], enumerable: true });
16
+ };
17
+
18
+ // src/contracts.ts
19
+ var init_contracts = __esm({
20
+ "src/contracts.ts"() {
21
+ }
22
+ });
15
23
  function getBackend(keys) {
16
24
  for (const key of keys) {
17
25
  const value = process.env[key]?.trim().toLowerCase();
@@ -62,9 +70,20 @@ async function searchRawMessagesWithChroma(input) {
62
70
  metadata: result.metadata ?? {}
63
71
  })).slice(0, input.limit);
64
72
  }
73
+ var DEFAULT_RAW_MESSAGES_COLLECTION, RAW_VECTOR_BACKEND_ENV_KEYS;
74
+ var init_chroma_memory_index = __esm({
75
+ "src/storage/chroma-memory-index.ts"() {
76
+ init_contracts();
77
+ DEFAULT_RAW_MESSAGES_COLLECTION = "opencontext_raw_messages";
78
+ RAW_VECTOR_BACKEND_ENV_KEYS = [
79
+ "RAW_MESSAGE_VECTOR_STORE_BACKEND",
80
+ "MEMORY_VECTOR_STORE_BACKEND",
81
+ "VECTOR_STORE_BACKEND"
82
+ ];
83
+ }
84
+ });
65
85
 
66
86
  // src/storage/postgres-raw-message-factory.ts
67
- var factory = null;
68
87
  function registerPostgresFactory(fn) {
69
88
  factory = fn;
70
89
  }
@@ -78,12 +97,30 @@ async function resolvePostgresFactory(env) {
78
97
  function hasPostgresFactory() {
79
98
  return factory !== null;
80
99
  }
81
- var manager = null;
82
- var DEFAULT_SQLITE_PATH = join(homedir(), ".opencontext", "memory", "store.db");
100
+ var factory;
101
+ var init_postgres_raw_message_factory = __esm({
102
+ "src/storage/postgres-raw-message-factory.ts"() {
103
+ factory = null;
104
+ }
105
+ });
106
+
107
+ // src/storage/sqlite-raw-message-store.ts
108
+ var sqlite_raw_message_store_exports = {};
109
+ __export(sqlite_raw_message_store_exports, {
110
+ __resetSQLiteRawMessageManagerForTests: () => __resetSQLiteRawMessageManagerForTests,
111
+ closeSQLiteRawMessageManager: () => closeSQLiteRawMessageManager,
112
+ getSQLiteRawMessageManager: () => getSQLiteRawMessageManager,
113
+ isSQLiteRawMessageStorageAvailable: () => isSQLiteRawMessageStorageAvailable,
114
+ lexicalSearchRawMessages: () => lexicalSearchRawMessages,
115
+ resolveSQLiteRawMessageDbPath: () => resolveSQLiteRawMessageDbPath
116
+ });
83
117
  function resolveSQLiteRawMessageDbPath() {
84
118
  const fromEnv = process.env.MEMORY_STORE_DB_PATH?.trim();
85
119
  return fromEnv && fromEnv.length > 0 ? fromEnv : DEFAULT_SQLITE_PATH;
86
120
  }
121
+ function isSQLiteRawMessageStorageAvailable(_env) {
122
+ return true;
123
+ }
87
124
  async function getSQLiteRawMessageManager(_env) {
88
125
  if (!manager) {
89
126
  const dbPath = resolveSQLiteRawMessageDbPath();
@@ -103,8 +140,35 @@ async function closeSQLiteRawMessageManager() {
103
140
  await manager.close();
104
141
  manager = null;
105
142
  }
143
+ function __resetSQLiteRawMessageManagerForTests() {
144
+ manager = null;
145
+ }
146
+ async function lexicalSearchRawMessages(input) {
147
+ const mgr = await getSQLiteRawMessageManager();
148
+ if (typeof mgr.lexicalSearchMessages !== "function") {
149
+ return [];
150
+ }
151
+ return mgr.lexicalSearchMessages(input);
152
+ }
153
+ var manager, DEFAULT_SQLITE_PATH;
154
+ var init_sqlite_raw_message_store = __esm({
155
+ "src/storage/sqlite-raw-message-store.ts"() {
156
+ init_chroma_memory_index();
157
+ manager = null;
158
+ DEFAULT_SQLITE_PATH = join(homedir(), ".opencontext", "memory", "store.db");
159
+ }
160
+ });
106
161
 
107
162
  // src/storage/raw-message-store.ts
163
+ var raw_message_store_exports = {};
164
+ __export(raw_message_store_exports, {
165
+ closeRawMessageStore: () => closeRawMessageStore,
166
+ configureRawMessageStore: () => configureRawMessageStore,
167
+ createRawMessageStore: () => createRawMessageStore,
168
+ getRawMessageManager: () => getRawMessageManager,
169
+ getRawMessageStorageBackend: () => getRawMessageStorageBackend,
170
+ isRawMessageStorageAvailable: () => isRawMessageStorageAvailable
171
+ });
108
172
  function resolveBackend(env) {
109
173
  const explicit = process.env.OPENCONTEXT_MEMORY_STORE_BACKEND?.trim().toLowerCase();
110
174
  if (explicit === "postgres") return "postgres";
@@ -139,8 +203,6 @@ function createRawMessageStore(options = {}) {
139
203
  }
140
204
  };
141
205
  }
142
- var moduleStore = null;
143
- var moduleConfig = null;
144
206
  function configureRawMessageStore(config) {
145
207
  moduleConfig = config;
146
208
  moduleStore = createRawMessageStore({ env: config.env });
@@ -169,6 +231,19 @@ async function closeRawMessageStore() {
169
231
  await moduleStore.close();
170
232
  moduleStore = null;
171
233
  }
234
+ var moduleStore, moduleConfig;
235
+ var init_raw_message_store = __esm({
236
+ "src/storage/raw-message-store.ts"() {
237
+ init_postgres_raw_message_factory();
238
+ init_sqlite_raw_message_store();
239
+ moduleStore = null;
240
+ moduleConfig = null;
241
+ }
242
+ });
243
+
244
+ // src/search/unified-search.ts
245
+ init_chroma_memory_index();
246
+ init_raw_message_store();
172
247
 
173
248
  // src/search/utilities.ts
174
249
  var DEFAULT_LIMIT = 10;
@@ -312,7 +387,7 @@ function createUnifiedSearch(deps = {}) {
312
387
  warnings.push({
313
388
  source: "memory",
314
389
  code: "memory_search_failed",
315
- message: error.message ?? "memory_search_failed"
390
+ message: `Memory search failed: ${error.message ?? "Unknown error"}. Using keyword search fallback.`
316
391
  });
317
392
  }
318
393
  } else {
@@ -352,13 +427,7 @@ function createUnifiedSearch(deps = {}) {
352
427
  message: error.message ?? "insights_search_failed"
353
428
  });
354
429
  }
355
- } else if (sources.includes("insights")) {
356
- warnings.push({
357
- source: "insights",
358
- code: "insights_search_not_configured",
359
- message: "Insights search is not configured for this host."
360
- });
361
- }
430
+ } else if (sources.includes("insights")) ;
362
431
  const knowledgeHits = [];
363
432
  if (sources.includes("knowledge") && typeof deps.searchKnowledge === "function") {
364
433
  try {
@@ -383,13 +452,7 @@ function createUnifiedSearch(deps = {}) {
383
452
  message: error.message ?? "knowledge_search_failed"
384
453
  });
385
454
  }
386
- } else if (sources.includes("knowledge")) {
387
- warnings.push({
388
- source: "knowledge",
389
- code: "knowledge_search_not_configured",
390
- message: "Knowledge search is not configured for this host."
391
- });
392
- }
455
+ } else if (sources.includes("knowledge")) ;
393
456
  const merged = mergeAcrossSources({
394
457
  memorySubs,
395
458
  insightHits,
@@ -407,7 +470,33 @@ function createUnifiedSearch(deps = {}) {
407
470
  }
408
471
  async function runMemorySource(input, limit, threshold, warnings) {
409
472
  if (typeof deps.embedQuery !== "function") {
410
- throw new Error("embedQuery is not configured");
473
+ warnings.push({
474
+ source: "memory",
475
+ code: "memory_lexical_search_fallback",
476
+ message: "Semantic search not configured, using keyword search as fallback"
477
+ });
478
+ const { lexicalSearchRawMessages: lexicalSearchRawMessages2 } = await Promise.resolve().then(() => (init_sqlite_raw_message_store(), sqlite_raw_message_store_exports));
479
+ const keywords = deriveLexicalKeywords(input.query);
480
+ let lexical2 = [];
481
+ if (keywords.length > 0) {
482
+ try {
483
+ const filters2 = input.botIds && input.botIds.length > 0 ? input.botIds : [void 0];
484
+ const results = await Promise.all(
485
+ filters2.map(
486
+ (botId) => lexicalSearchRawMessages2({
487
+ userId: input.userId,
488
+ keywords,
489
+ limit: Math.ceil(limit / filters2.length),
490
+ botId
491
+ })
492
+ )
493
+ );
494
+ lexical2 = results.flat().filter(Boolean).map(toMemoryResult);
495
+ } catch (error) {
496
+ logger.warn?.("[memory-store] Default lexical search failed:", error);
497
+ }
498
+ }
499
+ return { semantic: [], lexical: lexical2 };
411
500
  }
412
501
  const queryEmbedding = await deps.embedQuery({
413
502
  userId: input.userId,
@@ -454,6 +543,28 @@ function createUnifiedSearch(deps = {}) {
454
543
  )
455
544
  )).flat().filter(isRawMemorySemanticResult).map(toMemoryResult);
456
545
  }
546
+ if (semantic.length === 0) {
547
+ try {
548
+ const { getRawMessageManager: getRawMessageManager2 } = await Promise.resolve().then(() => (init_raw_message_store(), raw_message_store_exports));
549
+ const manager2 = await getRawMessageManager2();
550
+ if (typeof manager2.searchMessagesSemantically === "function") {
551
+ const results = await manager2.searchMessagesSemantically({
552
+ userId: input.userId,
553
+ queryEmbedding,
554
+ limit
555
+ });
556
+ semantic = results.map((r) => ({
557
+ type: "memory",
558
+ id: r.id,
559
+ content: r.content,
560
+ similarity: r.similarity,
561
+ metadata: r.metadata ?? {}
562
+ }));
563
+ }
564
+ } catch (error) {
565
+ logger.warn?.("[memory-store] SQLite semantic search failed:", error);
566
+ }
567
+ }
457
568
  let lexical = [];
458
569
  if (typeof deps.searchRawMessagesLexical === "function") {
459
570
  const keywords = deriveLexicalKeywords(input.query);
@@ -536,6 +647,9 @@ function mergeAcrossSources(input) {
536
647
  }
537
648
 
538
649
  // src/index.ts
650
+ init_raw_message_store();
651
+ init_raw_message_store();
652
+ init_postgres_raw_message_factory();
539
653
  async function createMemoryStore(config = {}) {
540
654
  const raw = createRawMessageStore({ env: config.env });
541
655
  const search = createUnifiedSearch(config.unified);