@molroo-io/sdk 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (293) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +251 -0
  3. package/dist/cjs/api-client.d.ts +23 -0
  4. package/dist/cjs/api-client.d.ts.map +1 -0
  5. package/dist/cjs/api-client.js +55 -0
  6. package/dist/cjs/defaults/index.d.ts +8 -0
  7. package/dist/cjs/defaults/index.d.ts.map +1 -0
  8. package/dist/cjs/defaults/index.js +30 -0
  9. package/dist/cjs/defaults/persona.json +17 -0
  10. package/dist/cjs/embedding/cloudflare.d.ts +15 -0
  11. package/dist/cjs/embedding/cloudflare.d.ts.map +1 -0
  12. package/dist/cjs/embedding/cloudflare.js +16 -0
  13. package/dist/cjs/embedding/cohere.d.ts +8 -0
  14. package/dist/cjs/embedding/cohere.d.ts.map +1 -0
  15. package/dist/cjs/embedding/cohere.js +31 -0
  16. package/dist/cjs/embedding/index.d.ts +9 -0
  17. package/dist/cjs/embedding/index.d.ts.map +1 -0
  18. package/dist/cjs/embedding/index.js +11 -0
  19. package/dist/cjs/embedding/local.d.ts +6 -0
  20. package/dist/cjs/embedding/local.d.ts.map +1 -0
  21. package/dist/cjs/embedding/local.js +28 -0
  22. package/dist/cjs/embedding/openai.d.ts +9 -0
  23. package/dist/cjs/embedding/openai.d.ts.map +1 -0
  24. package/dist/cjs/embedding/openai.js +26 -0
  25. package/dist/cjs/errors.d.ts +17 -0
  26. package/dist/cjs/errors.d.ts.map +1 -0
  27. package/dist/cjs/errors.js +21 -0
  28. package/dist/cjs/events/console.d.ts +25 -0
  29. package/dist/cjs/events/console.d.ts.map +1 -0
  30. package/dist/cjs/events/console.js +41 -0
  31. package/dist/cjs/events/types.d.ts +28 -0
  32. package/dist/cjs/events/types.d.ts.map +1 -0
  33. package/dist/cjs/events/types.js +13 -0
  34. package/dist/cjs/events/webhook.d.ts +30 -0
  35. package/dist/cjs/events/webhook.d.ts.map +1 -0
  36. package/dist/cjs/events/webhook.js +79 -0
  37. package/dist/cjs/generate/persona.d.ts +16 -0
  38. package/dist/cjs/generate/persona.d.ts.map +1 -0
  39. package/dist/cjs/generate/persona.js +42 -0
  40. package/dist/cjs/generate/prompt.d.ts +7 -0
  41. package/dist/cjs/generate/prompt.d.ts.map +1 -0
  42. package/dist/cjs/generate/prompt.js +41 -0
  43. package/dist/cjs/generate/schema.d.ts +32 -0
  44. package/dist/cjs/generate/schema.d.ts.map +1 -0
  45. package/dist/cjs/generate/schema.js +54 -0
  46. package/dist/cjs/generated/index.d.ts +2 -0
  47. package/dist/cjs/generated/index.d.ts.map +1 -0
  48. package/dist/cjs/generated/index.js +2 -0
  49. package/dist/cjs/index.d.ts +66 -0
  50. package/dist/cjs/index.d.ts.map +1 -0
  51. package/dist/cjs/index.js +69 -0
  52. package/dist/cjs/llm/adapter.d.ts +61 -0
  53. package/dist/cjs/llm/adapter.d.ts.map +1 -0
  54. package/dist/cjs/llm/adapter.js +2 -0
  55. package/dist/cjs/llm/resolve.d.ts +28 -0
  56. package/dist/cjs/llm/resolve.d.ts.map +1 -0
  57. package/dist/cjs/llm/resolve.js +20 -0
  58. package/dist/cjs/llm/schema.d.ts +60 -0
  59. package/dist/cjs/llm/schema.d.ts.map +1 -0
  60. package/dist/cjs/llm/schema.js +72 -0
  61. package/dist/cjs/llm/types.d.ts +24 -0
  62. package/dist/cjs/llm/types.d.ts.map +1 -0
  63. package/dist/cjs/llm/types.js +2 -0
  64. package/dist/cjs/llm/vercel-ai/adapter.d.ts +29 -0
  65. package/dist/cjs/llm/vercel-ai/adapter.d.ts.map +1 -0
  66. package/dist/cjs/llm/vercel-ai/adapter.js +234 -0
  67. package/dist/cjs/llm/vercel-ai/config.d.ts +9 -0
  68. package/dist/cjs/llm/vercel-ai/config.d.ts.map +1 -0
  69. package/dist/cjs/llm/vercel-ai/config.js +2 -0
  70. package/dist/cjs/llm/vercel-ai/index.d.ts +9 -0
  71. package/dist/cjs/llm/vercel-ai/index.d.ts.map +1 -0
  72. package/dist/cjs/llm/vercel-ai/index.js +13 -0
  73. package/dist/cjs/memory/cloudflare/index.d.ts +3 -0
  74. package/dist/cjs/memory/cloudflare/index.d.ts.map +1 -0
  75. package/dist/cjs/memory/cloudflare/index.js +5 -0
  76. package/dist/cjs/memory/cloudflare/vectorize.d.ts +62 -0
  77. package/dist/cjs/memory/cloudflare/vectorize.d.ts.map +1 -0
  78. package/dist/cjs/memory/cloudflare/vectorize.js +55 -0
  79. package/dist/cjs/memory/in-memory-semantic.d.ts +16 -0
  80. package/dist/cjs/memory/in-memory-semantic.d.ts.map +1 -0
  81. package/dist/cjs/memory/in-memory-semantic.js +57 -0
  82. package/dist/cjs/memory/in-memory.d.ts +46 -0
  83. package/dist/cjs/memory/in-memory.d.ts.map +1 -0
  84. package/dist/cjs/memory/in-memory.js +115 -0
  85. package/dist/cjs/memory/pinecone/index.d.ts +7 -0
  86. package/dist/cjs/memory/pinecone/index.d.ts.map +1 -0
  87. package/dist/cjs/memory/pinecone/index.js +8 -0
  88. package/dist/cjs/memory/pinecone/memory-adapter.d.ts +62 -0
  89. package/dist/cjs/memory/pinecone/memory-adapter.d.ts.map +1 -0
  90. package/dist/cjs/memory/pinecone/memory-adapter.js +220 -0
  91. package/dist/cjs/memory/pinecone/semantic.d.ts +44 -0
  92. package/dist/cjs/memory/pinecone/semantic.d.ts.map +1 -0
  93. package/dist/cjs/memory/pinecone/semantic.js +90 -0
  94. package/dist/cjs/memory/recall.d.ts +58 -0
  95. package/dist/cjs/memory/recall.d.ts.map +1 -0
  96. package/dist/cjs/memory/recall.js +220 -0
  97. package/dist/cjs/memory/semantic.d.ts +24 -0
  98. package/dist/cjs/memory/semantic.d.ts.map +1 -0
  99. package/dist/cjs/memory/semantic.js +2 -0
  100. package/dist/cjs/memory/sqlite/index.d.ts +3 -0
  101. package/dist/cjs/memory/sqlite/index.d.ts.map +1 -0
  102. package/dist/cjs/memory/sqlite/index.js +5 -0
  103. package/dist/cjs/memory/sqlite/memory-adapter.d.ts +58 -0
  104. package/dist/cjs/memory/sqlite/memory-adapter.d.ts.map +1 -0
  105. package/dist/cjs/memory/sqlite/memory-adapter.js +336 -0
  106. package/dist/cjs/memory/sqlite/schema.d.ts +4 -0
  107. package/dist/cjs/memory/sqlite/schema.d.ts.map +1 -0
  108. package/dist/cjs/memory/sqlite/schema.js +91 -0
  109. package/dist/cjs/memory/supabase/index.d.ts +7 -0
  110. package/dist/cjs/memory/supabase/index.d.ts.map +1 -0
  111. package/dist/cjs/memory/supabase/index.js +8 -0
  112. package/dist/cjs/memory/supabase/memory-adapter.d.ts +67 -0
  113. package/dist/cjs/memory/supabase/memory-adapter.d.ts.map +1 -0
  114. package/dist/cjs/memory/supabase/memory-adapter.js +335 -0
  115. package/dist/cjs/memory/supabase/semantic.d.ts +44 -0
  116. package/dist/cjs/memory/supabase/semantic.d.ts.map +1 -0
  117. package/dist/cjs/memory/supabase/semantic.js +72 -0
  118. package/dist/cjs/memory/types.d.ts +231 -0
  119. package/dist/cjs/memory/types.d.ts.map +1 -0
  120. package/dist/cjs/memory/types.js +12 -0
  121. package/dist/cjs/persona.d.ts +326 -0
  122. package/dist/cjs/persona.d.ts.map +1 -0
  123. package/dist/cjs/persona.js +824 -0
  124. package/dist/cjs/types.d.ts +263 -0
  125. package/dist/cjs/types.d.ts.map +1 -0
  126. package/dist/cjs/types.js +15 -0
  127. package/dist/cjs/world/client.d.ts +36 -0
  128. package/dist/cjs/world/client.d.ts.map +1 -0
  129. package/dist/cjs/world/client.js +59 -0
  130. package/dist/cjs/world/errors.d.ts +9 -0
  131. package/dist/cjs/world/errors.d.ts.map +1 -0
  132. package/dist/cjs/world/errors.js +15 -0
  133. package/dist/cjs/world/index.d.ts +10 -0
  134. package/dist/cjs/world/index.d.ts.map +1 -0
  135. package/dist/cjs/world/index.js +16 -0
  136. package/dist/cjs/world/types.d.ts +101 -0
  137. package/dist/cjs/world/types.d.ts.map +1 -0
  138. package/dist/cjs/world/types.js +8 -0
  139. package/dist/cjs/world/village.d.ts +75 -0
  140. package/dist/cjs/world/village.d.ts.map +1 -0
  141. package/dist/cjs/world/village.js +278 -0
  142. package/dist/cjs/world/world-persona.d.ts +182 -0
  143. package/dist/cjs/world/world-persona.d.ts.map +1 -0
  144. package/dist/cjs/world/world-persona.js +192 -0
  145. package/dist/cjs/world/world.d.ts +41 -0
  146. package/dist/cjs/world/world.d.ts.map +1 -0
  147. package/dist/cjs/world/world.js +91 -0
  148. package/dist/esm/api-client.d.ts +23 -0
  149. package/dist/esm/api-client.d.ts.map +1 -0
  150. package/dist/esm/api-client.js +48 -0
  151. package/dist/esm/defaults/index.d.ts +8 -0
  152. package/dist/esm/defaults/index.d.ts.map +1 -0
  153. package/dist/esm/defaults/index.js +23 -0
  154. package/dist/esm/defaults/persona.json +17 -0
  155. package/dist/esm/embedding/cloudflare.d.ts +15 -0
  156. package/dist/esm/embedding/cloudflare.d.ts.map +1 -0
  157. package/dist/esm/embedding/cloudflare.js +13 -0
  158. package/dist/esm/embedding/cohere.d.ts +8 -0
  159. package/dist/esm/embedding/cohere.d.ts.map +1 -0
  160. package/dist/esm/embedding/cohere.js +28 -0
  161. package/dist/esm/embedding/index.d.ts +9 -0
  162. package/dist/esm/embedding/index.d.ts.map +1 -0
  163. package/dist/esm/embedding/index.js +4 -0
  164. package/dist/esm/embedding/local.d.ts +6 -0
  165. package/dist/esm/embedding/local.d.ts.map +1 -0
  166. package/dist/esm/embedding/local.js +25 -0
  167. package/dist/esm/embedding/openai.d.ts +9 -0
  168. package/dist/esm/embedding/openai.d.ts.map +1 -0
  169. package/dist/esm/embedding/openai.js +23 -0
  170. package/dist/esm/errors.d.ts +17 -0
  171. package/dist/esm/errors.d.ts.map +1 -0
  172. package/dist/esm/errors.js +17 -0
  173. package/dist/esm/events/console.d.ts +25 -0
  174. package/dist/esm/events/console.d.ts.map +1 -0
  175. package/dist/esm/events/console.js +37 -0
  176. package/dist/esm/events/types.d.ts +28 -0
  177. package/dist/esm/events/types.d.ts.map +1 -0
  178. package/dist/esm/events/types.js +12 -0
  179. package/dist/esm/events/webhook.d.ts +30 -0
  180. package/dist/esm/events/webhook.d.ts.map +1 -0
  181. package/dist/esm/events/webhook.js +75 -0
  182. package/dist/esm/generate/persona.d.ts +16 -0
  183. package/dist/esm/generate/persona.d.ts.map +1 -0
  184. package/dist/esm/generate/persona.js +39 -0
  185. package/dist/esm/generate/prompt.d.ts +7 -0
  186. package/dist/esm/generate/prompt.d.ts.map +1 -0
  187. package/dist/esm/generate/prompt.js +38 -0
  188. package/dist/esm/generate/schema.d.ts +32 -0
  189. package/dist/esm/generate/schema.d.ts.map +1 -0
  190. package/dist/esm/generate/schema.js +51 -0
  191. package/dist/esm/generated/index.d.ts +2 -0
  192. package/dist/esm/generated/index.d.ts.map +1 -0
  193. package/dist/esm/generated/index.js +1 -0
  194. package/dist/esm/index.d.ts +66 -0
  195. package/dist/esm/index.d.ts.map +1 -0
  196. package/dist/esm/index.js +49 -0
  197. package/dist/esm/llm/adapter.d.ts +61 -0
  198. package/dist/esm/llm/adapter.d.ts.map +1 -0
  199. package/dist/esm/llm/adapter.js +1 -0
  200. package/dist/esm/llm/resolve.d.ts +28 -0
  201. package/dist/esm/llm/resolve.d.ts.map +1 -0
  202. package/dist/esm/llm/resolve.js +17 -0
  203. package/dist/esm/llm/schema.d.ts +60 -0
  204. package/dist/esm/llm/schema.d.ts.map +1 -0
  205. package/dist/esm/llm/schema.js +69 -0
  206. package/dist/esm/llm/types.d.ts +24 -0
  207. package/dist/esm/llm/types.d.ts.map +1 -0
  208. package/dist/esm/llm/types.js +1 -0
  209. package/dist/esm/llm/vercel-ai/adapter.d.ts +29 -0
  210. package/dist/esm/llm/vercel-ai/adapter.d.ts.map +1 -0
  211. package/dist/esm/llm/vercel-ai/adapter.js +196 -0
  212. package/dist/esm/llm/vercel-ai/config.d.ts +9 -0
  213. package/dist/esm/llm/vercel-ai/config.d.ts.map +1 -0
  214. package/dist/esm/llm/vercel-ai/config.js +1 -0
  215. package/dist/esm/llm/vercel-ai/index.d.ts +9 -0
  216. package/dist/esm/llm/vercel-ai/index.d.ts.map +1 -0
  217. package/dist/esm/llm/vercel-ai/index.js +8 -0
  218. package/dist/esm/memory/cloudflare/index.d.ts +3 -0
  219. package/dist/esm/memory/cloudflare/index.d.ts.map +1 -0
  220. package/dist/esm/memory/cloudflare/index.js +1 -0
  221. package/dist/esm/memory/cloudflare/vectorize.d.ts +62 -0
  222. package/dist/esm/memory/cloudflare/vectorize.d.ts.map +1 -0
  223. package/dist/esm/memory/cloudflare/vectorize.js +51 -0
  224. package/dist/esm/memory/in-memory-semantic.d.ts +16 -0
  225. package/dist/esm/memory/in-memory-semantic.d.ts.map +1 -0
  226. package/dist/esm/memory/in-memory-semantic.js +53 -0
  227. package/dist/esm/memory/in-memory.d.ts +46 -0
  228. package/dist/esm/memory/in-memory.d.ts.map +1 -0
  229. package/dist/esm/memory/in-memory.js +111 -0
  230. package/dist/esm/memory/pinecone/index.d.ts +7 -0
  231. package/dist/esm/memory/pinecone/index.d.ts.map +1 -0
  232. package/dist/esm/memory/pinecone/index.js +3 -0
  233. package/dist/esm/memory/pinecone/memory-adapter.d.ts +62 -0
  234. package/dist/esm/memory/pinecone/memory-adapter.d.ts.map +1 -0
  235. package/dist/esm/memory/pinecone/memory-adapter.js +216 -0
  236. package/dist/esm/memory/pinecone/semantic.d.ts +44 -0
  237. package/dist/esm/memory/pinecone/semantic.d.ts.map +1 -0
  238. package/dist/esm/memory/pinecone/semantic.js +86 -0
  239. package/dist/esm/memory/recall.d.ts +58 -0
  240. package/dist/esm/memory/recall.d.ts.map +1 -0
  241. package/dist/esm/memory/recall.js +215 -0
  242. package/dist/esm/memory/semantic.d.ts +24 -0
  243. package/dist/esm/memory/semantic.d.ts.map +1 -0
  244. package/dist/esm/memory/semantic.js +1 -0
  245. package/dist/esm/memory/sqlite/index.d.ts +3 -0
  246. package/dist/esm/memory/sqlite/index.d.ts.map +1 -0
  247. package/dist/esm/memory/sqlite/index.js +1 -0
  248. package/dist/esm/memory/sqlite/memory-adapter.d.ts +58 -0
  249. package/dist/esm/memory/sqlite/memory-adapter.d.ts.map +1 -0
  250. package/dist/esm/memory/sqlite/memory-adapter.js +296 -0
  251. package/dist/esm/memory/sqlite/schema.d.ts +4 -0
  252. package/dist/esm/memory/sqlite/schema.d.ts.map +1 -0
  253. package/dist/esm/memory/sqlite/schema.js +86 -0
  254. package/dist/esm/memory/supabase/index.d.ts +7 -0
  255. package/dist/esm/memory/supabase/index.d.ts.map +1 -0
  256. package/dist/esm/memory/supabase/index.js +3 -0
  257. package/dist/esm/memory/supabase/memory-adapter.d.ts +67 -0
  258. package/dist/esm/memory/supabase/memory-adapter.d.ts.map +1 -0
  259. package/dist/esm/memory/supabase/memory-adapter.js +331 -0
  260. package/dist/esm/memory/supabase/semantic.d.ts +44 -0
  261. package/dist/esm/memory/supabase/semantic.d.ts.map +1 -0
  262. package/dist/esm/memory/supabase/semantic.js +68 -0
  263. package/dist/esm/memory/types.d.ts +231 -0
  264. package/dist/esm/memory/types.d.ts.map +1 -0
  265. package/dist/esm/memory/types.js +9 -0
  266. package/dist/esm/persona.d.ts +326 -0
  267. package/dist/esm/persona.d.ts.map +1 -0
  268. package/dist/esm/persona.js +787 -0
  269. package/dist/esm/types.d.ts +263 -0
  270. package/dist/esm/types.d.ts.map +1 -0
  271. package/dist/esm/types.js +11 -0
  272. package/dist/esm/world/client.d.ts +36 -0
  273. package/dist/esm/world/client.d.ts.map +1 -0
  274. package/dist/esm/world/client.js +52 -0
  275. package/dist/esm/world/errors.d.ts +9 -0
  276. package/dist/esm/world/errors.d.ts.map +1 -0
  277. package/dist/esm/world/errors.js +11 -0
  278. package/dist/esm/world/index.d.ts +10 -0
  279. package/dist/esm/world/index.d.ts.map +1 -0
  280. package/dist/esm/world/index.js +8 -0
  281. package/dist/esm/world/types.d.ts +101 -0
  282. package/dist/esm/world/types.d.ts.map +1 -0
  283. package/dist/esm/world/types.js +7 -0
  284. package/dist/esm/world/village.d.ts +75 -0
  285. package/dist/esm/world/village.d.ts.map +1 -0
  286. package/dist/esm/world/village.js +274 -0
  287. package/dist/esm/world/world-persona.d.ts +182 -0
  288. package/dist/esm/world/world-persona.d.ts.map +1 -0
  289. package/dist/esm/world/world-persona.js +188 -0
  290. package/dist/esm/world/world.d.ts +41 -0
  291. package/dist/esm/world/world.d.ts.map +1 -0
  292. package/dist/esm/world/world.js +87 -0
  293. package/package.json +207 -0
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PineconeMemoryAdapter = void 0;
4
+ const pinecone_1 = require("@pinecone-database/pinecone");
5
+ /**
6
+ * Pinecone-backed MemoryAdapter combining in-memory arrays (RDB) with
7
+ * Pinecone vector search (semanticRecall).
8
+ *
9
+ * RDB operations (saveEpisode, recall, saveReflection, getReflections,
10
+ * getByIds, countEpisodes, updateEpisode, deleteEpisode, expireEpisodes)
11
+ * all operate on in-memory arrays, identical to InMemoryAdapter.
12
+ *
13
+ * Vector search (semanticRecall) delegates to Pinecone after embedding
14
+ * the query text via the provided EmbeddingAdapter.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const memory = new PineconeMemoryAdapter({
19
+ * apiKey: process.env.PINECONE_API_KEY!,
20
+ * indexName: 'molroo-memory',
21
+ * namespace: 'world-123',
22
+ * embedding: openaiEmbedding({ apiKey: '...' }),
23
+ * });
24
+ * await memory.init();
25
+ * ```
26
+ */
27
+ class PineconeMemoryAdapter {
28
+ constructor(options) {
29
+ this.initialized = false;
30
+ this.episodes = [];
31
+ this.reflections = [];
32
+ this.client = new pinecone_1.Pinecone({ apiKey: options.apiKey });
33
+ this.indexName = options.indexName;
34
+ this.namespace = options.namespace ?? 'default';
35
+ this.embedding = options.embedding;
36
+ }
37
+ /**
38
+ * Initialize the adapter. Must be called before use.
39
+ * Validates embedding dimension against Pinecone index.
40
+ */
41
+ async init() {
42
+ this.pcIndex = this.client.index(this.indexName);
43
+ const stats = await this.pcIndex.describeIndexStats();
44
+ if (stats.dimension && stats.dimension !== this.embedding.dimension) {
45
+ throw new Error(`Dimension mismatch: Pinecone index expects ${stats.dimension}d, ` +
46
+ `but embedding provider has ${this.embedding.dimension}d`);
47
+ }
48
+ this.initialized = true;
49
+ }
50
+ ensureInitialized() {
51
+ if (!this.initialized) {
52
+ throw new Error('PineconeMemoryAdapter not initialized. Call init() first.');
53
+ }
54
+ }
55
+ ns() {
56
+ return this.pcIndex.namespace(this.namespace);
57
+ }
58
+ // ── Required methods (in-memory, identical to InMemoryAdapter) ──
59
+ async saveEpisode(episode) {
60
+ this.ensureInitialized();
61
+ this.episodes.push(episode);
62
+ // Auto-upsert embedding to Pinecone (best-effort)
63
+ const text = episode.context ?? episode.sourceEntity ?? '';
64
+ if (text) {
65
+ try {
66
+ const embedding = await this.embedding.embed(text);
67
+ await this.ns().upsert([{
68
+ id: episode.id,
69
+ values: embedding,
70
+ metadata: {
71
+ type: 'episode',
72
+ sourceEntity: episode.sourceEntity ?? '',
73
+ timestamp: episode.timestamp,
74
+ importance: episode.importance,
75
+ },
76
+ }]);
77
+ }
78
+ catch {
79
+ // Best-effort: vector indexing failure doesn't block episode save.
80
+ }
81
+ }
82
+ }
83
+ async recall(query) {
84
+ this.ensureInitialized();
85
+ let results = this.episodes;
86
+ if (query.sourceEntity) {
87
+ results = results.filter((e) => e.sourceEntity === query.sourceEntity);
88
+ }
89
+ if (query.context) {
90
+ const ctx = query.context.toLowerCase();
91
+ results = results.filter((e) => e.context && e.context.toLowerCase().includes(ctx));
92
+ }
93
+ if (query.valenceRange) {
94
+ const [min, max] = query.valenceRange;
95
+ results = results.filter((e) => e.emotionSnapshot.V >= min && e.emotionSnapshot.V <= max);
96
+ }
97
+ if (query.minImportance !== undefined) {
98
+ results = results.filter((e) => e.importance >= query.minImportance);
99
+ }
100
+ if (query.timeRange) {
101
+ const [start, end] = query.timeRange;
102
+ results = results.filter((e) => e.timestamp >= start && e.timestamp <= end);
103
+ }
104
+ // Return most recent first
105
+ results = results.slice().sort((a, b) => b.timestamp - a.timestamp);
106
+ if (query.limit && query.limit > 0) {
107
+ results = results.slice(0, query.limit);
108
+ }
109
+ return results;
110
+ }
111
+ async saveReflection(reflection) {
112
+ this.ensureInitialized();
113
+ this.reflections.push(reflection);
114
+ }
115
+ async getReflections(sourceEntity) {
116
+ this.ensureInitialized();
117
+ if (sourceEntity) {
118
+ return this.reflections.filter((r) => r.sourceEntity === sourceEntity);
119
+ }
120
+ return [...this.reflections];
121
+ }
122
+ // ── Optional methods ──
123
+ async semanticRecall(query, options) {
124
+ this.ensureInitialized();
125
+ const embedding = await this.embedding.embed(query);
126
+ const topK = options?.topK ?? 5;
127
+ // Build Pinecone filter
128
+ const filter = {};
129
+ if (options?.filter?.sourceEntity) {
130
+ filter.sourceEntity = { $eq: options.filter.sourceEntity };
131
+ }
132
+ if (options?.filter?.minImportance !== undefined) {
133
+ filter.importance = { $gte: options.filter.minImportance };
134
+ }
135
+ // Over-fetch to account for in-memory-only episodes that may not be in Pinecone
136
+ const hasFilter = Object.keys(filter).length > 0;
137
+ const fetchK = hasFilter ? topK * 4 : topK;
138
+ const results = await this.ns().query({
139
+ vector: embedding,
140
+ topK: fetchK,
141
+ filter: hasFilter ? filter : undefined,
142
+ includeMetadata: true,
143
+ });
144
+ // Map Pinecone results to episodes via in-memory lookup
145
+ const matches = results.matches ?? [];
146
+ const idSet = new Set(matches.map((m) => m.id));
147
+ const matched = this.episodes.filter((e) => idSet.has(e.id));
148
+ // Sort by Pinecone score order (highest first), limit to topK
149
+ const scoreMap = new Map(matches.map((m) => [m.id, m.score ?? 0]));
150
+ return matched
151
+ .sort((a, b) => (scoreMap.get(b.id) ?? 0) - (scoreMap.get(a.id) ?? 0))
152
+ .slice(0, topK);
153
+ }
154
+ async getByIds(ids) {
155
+ this.ensureInitialized();
156
+ const idSet = new Set(ids);
157
+ return this.episodes.filter((e) => idSet.has(e.id));
158
+ }
159
+ async countEpisodes(query) {
160
+ this.ensureInitialized();
161
+ let results = this.episodes;
162
+ if (query.sourceEntity) {
163
+ results = results.filter((e) => e.sourceEntity === query.sourceEntity);
164
+ }
165
+ if (query.context) {
166
+ const ctx = query.context.toLowerCase();
167
+ results = results.filter((e) => e.context && e.context.toLowerCase().includes(ctx));
168
+ }
169
+ if (query.timeRange) {
170
+ const [start, end] = query.timeRange;
171
+ results = results.filter((e) => e.timestamp >= start && e.timestamp <= end);
172
+ }
173
+ return results.length;
174
+ }
175
+ async updateEpisode(id, patch) {
176
+ this.ensureInitialized();
177
+ const episode = this.episodes.find((e) => e.id === id);
178
+ if (!episode)
179
+ return;
180
+ if (patch.importance !== undefined)
181
+ episode.importance = patch.importance;
182
+ if (patch.intensity !== undefined)
183
+ episode.intensity = patch.intensity;
184
+ if (patch.emotionSnapshot !== undefined)
185
+ episode.emotionSnapshot = patch.emotionSnapshot;
186
+ }
187
+ async deleteEpisode(id) {
188
+ this.ensureInitialized();
189
+ this.episodes = this.episodes.filter((e) => e.id !== id);
190
+ // Best-effort Pinecone cleanup
191
+ try {
192
+ await this.ns().deleteOne(id);
193
+ }
194
+ catch {
195
+ // Non-fatal: Pinecone cleanup failure doesn't affect in-memory state.
196
+ }
197
+ }
198
+ async expireEpisodes(before, minImportance) {
199
+ this.ensureInitialized();
200
+ const threshold = minImportance ?? 0;
201
+ const original = this.episodes.length;
202
+ // Collect IDs of episodes to expire for Pinecone cleanup
203
+ const expiredIds = this.episodes
204
+ .filter((e) => e.timestamp < before && e.importance < threshold)
205
+ .map((e) => e.id);
206
+ this.episodes = this.episodes.filter((e) => e.timestamp >= before || e.importance >= threshold);
207
+ const count = original - this.episodes.length;
208
+ // Best-effort Pinecone cleanup
209
+ if (expiredIds.length > 0) {
210
+ try {
211
+ await this.ns().deleteMany({ ids: expiredIds });
212
+ }
213
+ catch {
214
+ // Non-fatal: Pinecone cleanup failure doesn't affect in-memory state.
215
+ }
216
+ }
217
+ return count;
218
+ }
219
+ }
220
+ exports.PineconeMemoryAdapter = PineconeMemoryAdapter;
@@ -0,0 +1,44 @@
1
+ import type { EmbeddingAdapter } from '../types';
2
+ import type { SemanticMemory, SearchOptions, SearchResult } from '../semantic';
3
+ export interface PineconeSemanticMemoryOptions {
4
+ /** Pinecone API key. */
5
+ apiKey: string;
6
+ /** Pinecone index name. */
7
+ indexName: string;
8
+ /** Pinecone namespace. Default: 'default'. */
9
+ namespace?: string;
10
+ /** Embedding provider (embed function + dimension). */
11
+ embedding: EmbeddingAdapter;
12
+ }
13
+ /**
14
+ * Pinecone-backed SemanticMemory.
15
+ *
16
+ * Call `init()` before use to validate embedding dimension against Pinecone index.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const memory = new PineconeSemanticMemory({
21
+ * apiKey: process.env.PINECONE_API_KEY!,
22
+ * indexName: 'my-index',
23
+ * embedding: openaiEmbedding({ apiKey: '...' }),
24
+ * });
25
+ * await memory.init();
26
+ * await memory.store('user likes coffee');
27
+ * ```
28
+ */
29
+ export declare class PineconeSemanticMemory implements SemanticMemory {
30
+ private client;
31
+ private pcIndex;
32
+ private namespace;
33
+ private indexName;
34
+ private embedding;
35
+ private initialized;
36
+ constructor(options: PineconeSemanticMemoryOptions);
37
+ init(): Promise<void>;
38
+ private ensureInit;
39
+ private ns;
40
+ store(text: string, metadata?: Record<string, unknown>): Promise<string>;
41
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
42
+ delete(ids: string[]): Promise<void>;
43
+ }
44
+ //# sourceMappingURL=semantic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic.d.ts","sourceRoot":"","sources":["../../../../src/memory/pinecone/semantic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/E,MAAM,WAAW,6BAA6B;IAC5C,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,SAAS,EAAE,gBAAgB,CAAC;CAC7B;AAOD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,sBAAuB,YAAW,cAAc;IAC3D,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE,6BAA6B;IAO5C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,EAAE;IAIJ,KAAK,CACT,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACrC,OAAO,CAAC,MAAM,CAAC;IAqBZ,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,EAAE,CAAC;IA4BpB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAM3C"}
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PineconeSemanticMemory = void 0;
4
+ const pinecone_1 = require("@pinecone-database/pinecone");
5
+ /**
6
+ * Pinecone-backed SemanticMemory.
7
+ *
8
+ * Call `init()` before use to validate embedding dimension against Pinecone index.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const memory = new PineconeSemanticMemory({
13
+ * apiKey: process.env.PINECONE_API_KEY!,
14
+ * indexName: 'my-index',
15
+ * embedding: openaiEmbedding({ apiKey: '...' }),
16
+ * });
17
+ * await memory.init();
18
+ * await memory.store('user likes coffee');
19
+ * ```
20
+ */
21
+ class PineconeSemanticMemory {
22
+ constructor(options) {
23
+ this.initialized = false;
24
+ this.client = new pinecone_1.Pinecone({ apiKey: options.apiKey });
25
+ this.indexName = options.indexName;
26
+ this.namespace = options.namespace ?? 'default';
27
+ this.embedding = options.embedding;
28
+ }
29
+ async init() {
30
+ this.pcIndex = this.client.index(this.indexName);
31
+ const stats = await this.pcIndex.describeIndexStats();
32
+ if (stats.dimension && stats.dimension !== this.embedding.dimension) {
33
+ throw new Error(`Dimension mismatch: Pinecone index expects ${stats.dimension}d, ` +
34
+ `but embedding provider has ${this.embedding.dimension}d`);
35
+ }
36
+ this.initialized = true;
37
+ }
38
+ ensureInit() {
39
+ if (!this.initialized) {
40
+ throw new Error('PineconeSemanticMemory not initialized. Call init() first.');
41
+ }
42
+ }
43
+ ns() {
44
+ return this.pcIndex.namespace(this.namespace);
45
+ }
46
+ async store(text, metadata = {}) {
47
+ this.ensureInit();
48
+ const id = crypto.randomUUID();
49
+ const values = await this.embedding.embed(text);
50
+ const pineconeMetadata = {
51
+ text,
52
+ ...Object.fromEntries(Object.entries(metadata).filter(([, v]) => typeof v === 'string' ||
53
+ typeof v === 'number' ||
54
+ typeof v === 'boolean' ||
55
+ Array.isArray(v))),
56
+ };
57
+ await this.ns().upsert([{ id, values, metadata: pineconeMetadata }]);
58
+ return id;
59
+ }
60
+ async search(query, options = {}) {
61
+ this.ensureInit();
62
+ const topK = options.topK ?? 5;
63
+ const threshold = options.scoreThreshold ?? 0;
64
+ const vector = await this.embedding.embed(query);
65
+ const filter = options.filter;
66
+ const hasFilter = filter && Object.keys(filter).length > 0;
67
+ const results = await this.ns().query({
68
+ vector,
69
+ topK,
70
+ filter: hasFilter ? filter : undefined,
71
+ includeMetadata: true,
72
+ });
73
+ const matchList = results.matches ?? [];
74
+ return matchList
75
+ .filter((m) => (m.score ?? 0) >= threshold)
76
+ .map((m) => ({
77
+ id: m.id,
78
+ text: m.metadata?.text ?? '',
79
+ score: m.score ?? 0,
80
+ metadata: m.metadata ?? {},
81
+ }));
82
+ }
83
+ async delete(ids) {
84
+ this.ensureInit();
85
+ if (ids.length > 0) {
86
+ await this.ns().deleteMany({ ids });
87
+ }
88
+ }
89
+ }
90
+ exports.PineconeSemanticMemory = PineconeSemanticMemory;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Shared memory recall and prompt-building utilities.
3
+ *
4
+ * Used by MolrooPersona to recall episodic/semantic memories and
5
+ * format them for LLM system prompts. Supports both:
6
+ * - Single MemoryAdapter (new, preferred)
7
+ * - Split EpisodeAdapter + SemanticAdapter + EmbeddingAdapter (backward compat)
8
+ */
9
+ import type { Episode } from '../types';
10
+ import type { EpisodeAdapter, SemanticAdapter, EmbeddingAdapter, MemoryAdapter, Reflection } from './types';
11
+ /**
12
+ * Strip leading `[...]` metadata tags from text before embedding.
13
+ * These tags (channel info, scene hints, timestamps) add noise to
14
+ * semantic similarity and should not influence vector search.
15
+ */
16
+ export declare function stripMetaTags(text: string): string;
17
+ /** Recall tuning parameters. */
18
+ export interface RecallConfig {
19
+ episodicLimit?: number;
20
+ semanticLimit?: number;
21
+ reflectionLimit?: number;
22
+ minImportance?: number;
23
+ /** Filter episodic recall to these episode types. Undefined = all types. */
24
+ types?: string[];
25
+ }
26
+ /** Result of a memory recall operation. */
27
+ export interface RecallResult {
28
+ episodic: Episode[];
29
+ semantic: Episode[];
30
+ reflections: Reflection[];
31
+ }
32
+ /**
33
+ * Recall episodic + semantic + reflection memories in parallel.
34
+ *
35
+ * Supports two paths:
36
+ * 1. Single MemoryAdapter (`memoryAdapter` param) — adapter handles everything
37
+ * 2. Split stores (`episodeStore` + `semanticStore` + `embeddingProvider`) — legacy
38
+ *
39
+ * @param message - Current user message (used for semantic embedding).
40
+ * @param opts - Stores, provider, config, and entity filter.
41
+ * @returns Recalled memories grouped by type.
42
+ */
43
+ export declare function recallMemories(message: string, opts: {
44
+ memoryAdapter?: MemoryAdapter | null;
45
+ episodeStore: EpisodeAdapter | null;
46
+ semanticStore: SemanticAdapter | null;
47
+ embeddingProvider: EmbeddingAdapter | null;
48
+ config?: RecallConfig;
49
+ sourceEntity?: string;
50
+ reflectionEntity?: string;
51
+ }): Promise<RecallResult>;
52
+ /**
53
+ * Format recalled memories into a text block for LLM system prompt injection.
54
+ * Groups episodic memories by type: conversations vs events.
55
+ * Deduplicates semantic results that overlap with episodic results.
56
+ */
57
+ export declare function buildMemoryBlock(episodicMemories?: Episode[], semanticMemories?: Episode[], reflections?: Reflection[]): string;
58
+ //# sourceMappingURL=recall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall.d.ts","sourceRoot":"","sources":["../../../src/memory/recall.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,UAAU,EAEX,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,gCAAgC;AAChC,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAgFD;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;IACJ,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,YAAY,EAAE,cAAc,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,eAAe,GAAG,IAAI,CAAC;IACtC,iBAAiB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC3C,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GACA,OAAO,CAAC,YAAY,CAAC,CA2FvB;AAcD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAC5B,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAC5B,WAAW,CAAC,EAAE,UAAU,EAAE,GACzB,MAAM,CAwCR"}
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ /**
3
+ * Shared memory recall and prompt-building utilities.
4
+ *
5
+ * Used by MolrooPersona to recall episodic/semantic memories and
6
+ * format them for LLM system prompts. Supports both:
7
+ * - Single MemoryAdapter (new, preferred)
8
+ * - Split EpisodeAdapter + SemanticAdapter + EmbeddingAdapter (backward compat)
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.stripMetaTags = stripMetaTags;
12
+ exports.recallMemories = recallMemories;
13
+ exports.buildMemoryBlock = buildMemoryBlock;
14
+ /**
15
+ * Strip leading `[...]` metadata tags from text before embedding.
16
+ * These tags (channel info, scene hints, timestamps) add noise to
17
+ * semantic similarity and should not influence vector search.
18
+ */
19
+ function stripMetaTags(text) {
20
+ return text.replace(/^\s*(\[.*?\]\s*)+/s, '').trim();
21
+ }
22
+ /**
23
+ * Recall from a single MemoryAdapter. The adapter handles all storage
24
+ * and vector search internally.
25
+ */
26
+ async function recallFromAdapter(message, adapter, config, sourceEntity, reflectionEntity) {
27
+ const episodicLimit = config.episodicLimit ?? 5;
28
+ const semanticLimit = config.semanticLimit ?? 3;
29
+ const reflectionLimit = config.reflectionLimit ?? 3;
30
+ const minImportance = config.minImportance ?? 0;
31
+ // Episodic recall — conversations (filtered by sourceEntity)
32
+ const conversationP = adapter
33
+ .recall({
34
+ sourceEntity,
35
+ limit: episodicLimit,
36
+ minImportance,
37
+ ...(config.types ? { type: config.types } : {}),
38
+ })
39
+ .catch(() => []);
40
+ // Episodic recall — non-chat events (no sourceEntity filter)
41
+ const hasTypeFilter = config.types && config.types.length > 0;
42
+ const eventP = !hasTypeFilter
43
+ ? adapter
44
+ .recall({
45
+ limit: episodicLimit,
46
+ minImportance,
47
+ })
48
+ .then((all) => all.filter((ep) => ep.type && ep.type !== 'chat_message'))
49
+ .catch(() => [])
50
+ : Promise.resolve([]);
51
+ // Semantic recall (vector) — adapter handles embedding internally
52
+ const semanticP = adapter.semanticRecall
53
+ ? adapter
54
+ .semanticRecall(stripMetaTags(message), {
55
+ topK: semanticLimit,
56
+ filter: { minImportance },
57
+ })
58
+ .catch(() => [])
59
+ : Promise.resolve([]);
60
+ // Reflection recall
61
+ const reflectionP = adapter.getReflections
62
+ ? adapter
63
+ .getReflections(reflectionEntity)
64
+ .then((refs) => refs.slice(0, reflectionLimit))
65
+ .catch(() => [])
66
+ : Promise.resolve([]);
67
+ const [conversations, events, semantic, reflections] = await Promise.all([
68
+ conversationP,
69
+ eventP,
70
+ semanticP,
71
+ reflectionP,
72
+ ]);
73
+ // Merge conversations + events, deduplicate, and re-sort by recency
74
+ const seenIds = new Set();
75
+ const episodic = [];
76
+ for (const ep of [...conversations, ...events]) {
77
+ if (!seenIds.has(ep.id)) {
78
+ seenIds.add(ep.id);
79
+ episodic.push(ep);
80
+ }
81
+ }
82
+ episodic.sort((a, b) => b.timestamp - a.timestamp);
83
+ episodic.splice(episodicLimit);
84
+ return { episodic, semantic, reflections };
85
+ }
86
+ /**
87
+ * Recall episodic + semantic + reflection memories in parallel.
88
+ *
89
+ * Supports two paths:
90
+ * 1. Single MemoryAdapter (`memoryAdapter` param) — adapter handles everything
91
+ * 2. Split stores (`episodeStore` + `semanticStore` + `embeddingProvider`) — legacy
92
+ *
93
+ * @param message - Current user message (used for semantic embedding).
94
+ * @param opts - Stores, provider, config, and entity filter.
95
+ * @returns Recalled memories grouped by type.
96
+ */
97
+ async function recallMemories(message, opts) {
98
+ const config = opts.config ?? {};
99
+ // Path 1: Single MemoryAdapter
100
+ if (opts.memoryAdapter) {
101
+ return recallFromAdapter(message, opts.memoryAdapter, config, opts.sourceEntity, opts.reflectionEntity);
102
+ }
103
+ // Path 2: Split stores (backward compat)
104
+ const { episodeStore, semanticStore, embeddingProvider } = opts;
105
+ const episodicLimit = config.episodicLimit ?? 5;
106
+ const semanticLimit = config.semanticLimit ?? 3;
107
+ const reflectionLimit = config.reflectionLimit ?? 3;
108
+ const minImportance = config.minImportance ?? 0;
109
+ // Episodic recall — conversations (filtered by sourceEntity)
110
+ const conversationP = episodeStore
111
+ ? episodeStore
112
+ .recall({
113
+ sourceEntity: opts.sourceEntity,
114
+ limit: episodicLimit,
115
+ minImportance,
116
+ ...(config.types ? { type: config.types } : {}),
117
+ })
118
+ .catch(() => [])
119
+ : Promise.resolve([]);
120
+ // Episodic recall — non-chat events (no sourceEntity filter).
121
+ // Events like attacks/gifts come from various entities and must be
122
+ // recalled regardless of who the persona is currently talking to.
123
+ const hasTypeFilter = config.types && config.types.length > 0;
124
+ const eventP = (episodeStore && !hasTypeFilter)
125
+ ? episodeStore
126
+ .recall({
127
+ // No sourceEntity — recall events from all sources
128
+ limit: episodicLimit,
129
+ minImportance,
130
+ })
131
+ .then((all) => all.filter((ep) => ep.type && ep.type !== 'chat_message'))
132
+ .catch(() => [])
133
+ : Promise.resolve([]);
134
+ // Semantic recall (vector)
135
+ const semanticP = semanticStore && embeddingProvider && episodeStore?.getByIds
136
+ ? embeddingProvider
137
+ .embed(stripMetaTags(message))
138
+ .then((embedding) => semanticStore.search({ embedding, topK: semanticLimit, filter: { minImportance } }))
139
+ .then((results) => results.length > 0
140
+ ? episodeStore.getByIds(results.map((r) => r.id))
141
+ : [])
142
+ .catch(() => [])
143
+ : Promise.resolve([]);
144
+ // Reflection recall (RDB)
145
+ const reflectionP = episodeStore
146
+ ? episodeStore
147
+ .getReflections(opts.reflectionEntity, reflectionLimit)
148
+ .catch(() => [])
149
+ : Promise.resolve([]);
150
+ const [conversations, events, semantic, reflections] = await Promise.all([
151
+ conversationP,
152
+ eventP,
153
+ semanticP,
154
+ reflectionP,
155
+ ]);
156
+ // Merge conversations + events, deduplicate, and re-sort by recency
157
+ const seenIds = new Set();
158
+ const episodic = [];
159
+ for (const ep of [...conversations, ...events]) {
160
+ if (!seenIds.has(ep.id)) {
161
+ seenIds.add(ep.id);
162
+ episodic.push(ep);
163
+ }
164
+ }
165
+ episodic.sort((a, b) => b.timestamp - a.timestamp);
166
+ episodic.splice(episodicLimit);
167
+ return { episodic, semantic, reflections };
168
+ }
169
+ /** Format a single episode into a display line. */
170
+ function formatEpisodeLine(ep) {
171
+ const v = ep.emotionSnapshot;
172
+ const isEvent = ep.type && ep.type !== 'chat_message';
173
+ const prefix = isEvent ? `[${ep.type}] ` : '';
174
+ return (`- [${new Date(ep.timestamp).toISOString()}] `
175
+ + `${prefix}${ep.sourceEntity ?? 'unknown'}: ${ep.context ?? 'no context'} `
176
+ + `(V:${v.V.toFixed(2)} A:${v.A.toFixed(2)} importance:${ep.importance.toFixed(2)})`);
177
+ }
178
+ /**
179
+ * Format recalled memories into a text block for LLM system prompt injection.
180
+ * Groups episodic memories by type: conversations vs events.
181
+ * Deduplicates semantic results that overlap with episodic results.
182
+ */
183
+ function buildMemoryBlock(episodicMemories, semanticMemories, reflections) {
184
+ const parts = [];
185
+ if (episodicMemories && episodicMemories.length > 0) {
186
+ const conversations = episodicMemories.filter((ep) => !ep.type || ep.type === 'chat_message');
187
+ const events = episodicMemories.filter((ep) => ep.type && ep.type !== 'chat_message');
188
+ if (conversations.length > 0) {
189
+ parts.push('Recent conversations:');
190
+ for (const ep of conversations)
191
+ parts.push(formatEpisodeLine(ep));
192
+ }
193
+ if (events.length > 0) {
194
+ if (parts.length > 0)
195
+ parts.push('');
196
+ parts.push('Recent events:');
197
+ for (const ep of events)
198
+ parts.push(formatEpisodeLine(ep));
199
+ }
200
+ }
201
+ if (semanticMemories && semanticMemories.length > 0) {
202
+ const episodicIds = new Set(episodicMemories?.map((e) => e.id) ?? []);
203
+ const unique = semanticMemories.filter((e) => !episodicIds.has(e.id));
204
+ if (unique.length > 0) {
205
+ if (parts.length > 0)
206
+ parts.push('');
207
+ parts.push('Related past experiences:');
208
+ for (const ep of unique)
209
+ parts.push(formatEpisodeLine(ep));
210
+ }
211
+ }
212
+ if (reflections && reflections.length > 0) {
213
+ if (parts.length > 0)
214
+ parts.push('');
215
+ parts.push('Your recent self-reflections:');
216
+ for (const ref of reflections)
217
+ parts.push(`- ${ref.content}`);
218
+ }
219
+ return parts.join('\n');
220
+ }
@@ -0,0 +1,24 @@
1
+ /** Semantic (vector-based) memory interface. */
2
+ export interface SemanticMemory {
3
+ /** Embed and store text. Returns the stored entry ID. */
4
+ store(text: string, metadata?: Record<string, unknown>): Promise<string>;
5
+ /** Embed query and return similar entries by cosine similarity. */
6
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
7
+ /** Delete entries by ID. */
8
+ delete?(ids: string[]): Promise<void>;
9
+ }
10
+ export interface SearchOptions {
11
+ /** Maximum number of results. Default: 5. */
12
+ topK?: number;
13
+ /** Minimum similarity score threshold (0–1). */
14
+ scoreThreshold?: number;
15
+ /** Backend-specific metadata filter. */
16
+ filter?: Record<string, unknown>;
17
+ }
18
+ export interface SearchResult {
19
+ id: string;
20
+ text: string;
21
+ score: number;
22
+ metadata: Record<string, unknown>;
23
+ }
24
+ //# sourceMappingURL=semantic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic.d.ts","sourceRoot":"","sources":["../../../src/memory/semantic.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzE,mEAAmE;IACnE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACxE,4BAA4B;IAC5B,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export { SqliteMemoryAdapter } from './memory-adapter';
2
+ export type { SqliteMemoryAdapterOptions } from './memory-adapter';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/memory/sqlite/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,YAAY,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC"}