@bip-krishna/agentmind 0.1.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.
Files changed (169) hide show
  1. package/.agentmind/memory.db +0 -0
  2. package/.context-memory/memory.db +0 -0
  3. package/README.md +176 -0
  4. package/apps/dashboard/src/server.ts +369 -0
  5. package/cli/src/index.ts +163 -0
  6. package/dist/apps/dashboard/src/server.d.ts +6 -0
  7. package/dist/apps/dashboard/src/server.d.ts.map +1 -0
  8. package/dist/apps/dashboard/src/server.js +360 -0
  9. package/dist/apps/dashboard/src/server.js.map +1 -0
  10. package/dist/cli/src/index.d.ts +3 -0
  11. package/dist/cli/src/index.d.ts.map +1 -0
  12. package/dist/cli/src/index.js +162 -0
  13. package/dist/cli/src/index.js.map +1 -0
  14. package/dist/examples/advanced.d.ts +2 -0
  15. package/dist/examples/advanced.d.ts.map +1 -0
  16. package/dist/examples/advanced.js +41 -0
  17. package/dist/examples/advanced.js.map +1 -0
  18. package/dist/examples/basic.d.ts +2 -0
  19. package/dist/examples/basic.d.ts.map +1 -0
  20. package/dist/examples/basic.js +22 -0
  21. package/dist/examples/basic.js.map +1 -0
  22. package/dist/packages/core/src/consolidation.d.ts +27 -0
  23. package/dist/packages/core/src/consolidation.d.ts.map +1 -0
  24. package/dist/packages/core/src/consolidation.js +97 -0
  25. package/dist/packages/core/src/consolidation.js.map +1 -0
  26. package/dist/packages/core/src/events.d.ts +18 -0
  27. package/dist/packages/core/src/events.d.ts.map +1 -0
  28. package/dist/packages/core/src/events.js +13 -0
  29. package/dist/packages/core/src/events.js.map +1 -0
  30. package/dist/packages/core/src/extraction.d.ts +32 -0
  31. package/dist/packages/core/src/extraction.d.ts.map +1 -0
  32. package/dist/packages/core/src/extraction.js +65 -0
  33. package/dist/packages/core/src/extraction.js.map +1 -0
  34. package/dist/packages/core/src/index.d.ts +10 -0
  35. package/dist/packages/core/src/index.d.ts.map +1 -0
  36. package/dist/packages/core/src/index.js +7 -0
  37. package/dist/packages/core/src/index.js.map +1 -0
  38. package/dist/packages/core/src/memory-store.d.ts +36 -0
  39. package/dist/packages/core/src/memory-store.d.ts.map +1 -0
  40. package/dist/packages/core/src/memory-store.js +2 -0
  41. package/dist/packages/core/src/memory-store.js.map +1 -0
  42. package/dist/packages/core/src/memory.d.ts +75 -0
  43. package/dist/packages/core/src/memory.d.ts.map +1 -0
  44. package/dist/packages/core/src/memory.js +402 -0
  45. package/dist/packages/core/src/memory.js.map +1 -0
  46. package/dist/packages/core/src/policy.d.ts +17 -0
  47. package/dist/packages/core/src/policy.d.ts.map +1 -0
  48. package/dist/packages/core/src/policy.js +22 -0
  49. package/dist/packages/core/src/policy.js.map +1 -0
  50. package/dist/packages/core/src/types.d.ts +102 -0
  51. package/dist/packages/core/src/types.d.ts.map +1 -0
  52. package/dist/packages/core/src/types.js +23 -0
  53. package/dist/packages/core/src/types.js.map +1 -0
  54. package/dist/packages/embeddings/src/index.d.ts +4 -0
  55. package/dist/packages/embeddings/src/index.d.ts.map +1 -0
  56. package/dist/packages/embeddings/src/index.js +4 -0
  57. package/dist/packages/embeddings/src/index.js.map +1 -0
  58. package/dist/packages/embeddings/src/local.d.ts +15 -0
  59. package/dist/packages/embeddings/src/local.d.ts.map +1 -0
  60. package/dist/packages/embeddings/src/local.js +45 -0
  61. package/dist/packages/embeddings/src/local.js.map +1 -0
  62. package/dist/packages/embeddings/src/openai.d.ts +17 -0
  63. package/dist/packages/embeddings/src/openai.d.ts.map +1 -0
  64. package/dist/packages/embeddings/src/openai.js +41 -0
  65. package/dist/packages/embeddings/src/openai.js.map +1 -0
  66. package/dist/packages/embeddings/src/provider.d.ts +8 -0
  67. package/dist/packages/embeddings/src/provider.d.ts.map +1 -0
  68. package/dist/packages/embeddings/src/provider.js +12 -0
  69. package/dist/packages/embeddings/src/provider.js.map +1 -0
  70. package/dist/packages/integrations/src/anthropic.d.ts +15 -0
  71. package/dist/packages/integrations/src/anthropic.d.ts.map +1 -0
  72. package/dist/packages/integrations/src/anthropic.js +25 -0
  73. package/dist/packages/integrations/src/anthropic.js.map +1 -0
  74. package/dist/packages/integrations/src/index.d.ts +4 -0
  75. package/dist/packages/integrations/src/index.d.ts.map +1 -0
  76. package/dist/packages/integrations/src/index.js +4 -0
  77. package/dist/packages/integrations/src/index.js.map +1 -0
  78. package/dist/packages/integrations/src/openai.d.ts +27 -0
  79. package/dist/packages/integrations/src/openai.d.ts.map +1 -0
  80. package/dist/packages/integrations/src/openai.js +26 -0
  81. package/dist/packages/integrations/src/openai.js.map +1 -0
  82. package/dist/packages/integrations/src/vercel.d.ts +24 -0
  83. package/dist/packages/integrations/src/vercel.d.ts.map +1 -0
  84. package/dist/packages/integrations/src/vercel.js +20 -0
  85. package/dist/packages/integrations/src/vercel.js.map +1 -0
  86. package/dist/packages/retrieval/src/index.d.ts +3 -0
  87. package/dist/packages/retrieval/src/index.d.ts.map +1 -0
  88. package/dist/packages/retrieval/src/index.js +3 -0
  89. package/dist/packages/retrieval/src/index.js.map +1 -0
  90. package/dist/packages/retrieval/src/ranker.d.ts +21 -0
  91. package/dist/packages/retrieval/src/ranker.d.ts.map +1 -0
  92. package/dist/packages/retrieval/src/ranker.js +54 -0
  93. package/dist/packages/retrieval/src/ranker.js.map +1 -0
  94. package/dist/packages/retrieval/src/token.d.ts +3 -0
  95. package/dist/packages/retrieval/src/token.d.ts.map +1 -0
  96. package/dist/packages/retrieval/src/token.js +7 -0
  97. package/dist/packages/retrieval/src/token.js.map +1 -0
  98. package/dist/packages/storage/src/config.d.ts +14 -0
  99. package/dist/packages/storage/src/config.d.ts.map +1 -0
  100. package/dist/packages/storage/src/config.js +41 -0
  101. package/dist/packages/storage/src/config.js.map +1 -0
  102. package/dist/packages/storage/src/index.d.ts +4 -0
  103. package/dist/packages/storage/src/index.d.ts.map +1 -0
  104. package/dist/packages/storage/src/index.js +4 -0
  105. package/dist/packages/storage/src/index.js.map +1 -0
  106. package/dist/packages/storage/src/memory-store.d.ts +37 -0
  107. package/dist/packages/storage/src/memory-store.d.ts.map +1 -0
  108. package/dist/packages/storage/src/memory-store.js +107 -0
  109. package/dist/packages/storage/src/memory-store.js.map +1 -0
  110. package/dist/packages/storage/src/migrations.d.ts +12 -0
  111. package/dist/packages/storage/src/migrations.d.ts.map +1 -0
  112. package/dist/packages/storage/src/migrations.js +89 -0
  113. package/dist/packages/storage/src/migrations.js.map +1 -0
  114. package/dist/packages/storage/src/postgres-store.d.ts +45 -0
  115. package/dist/packages/storage/src/postgres-store.d.ts.map +1 -0
  116. package/dist/packages/storage/src/postgres-store.js +282 -0
  117. package/dist/packages/storage/src/postgres-store.js.map +1 -0
  118. package/dist/packages/storage/src/sqlite-store.d.ts +36 -0
  119. package/dist/packages/storage/src/sqlite-store.d.ts.map +1 -0
  120. package/dist/packages/storage/src/sqlite-store.js +243 -0
  121. package/dist/packages/storage/src/sqlite-store.js.map +1 -0
  122. package/examples/advanced.ts +46 -0
  123. package/examples/basic.ts +25 -0
  124. package/package.json +52 -0
  125. package/packages/core/package.json +13 -0
  126. package/packages/core/src/consolidation.ts +104 -0
  127. package/packages/core/src/events.ts +25 -0
  128. package/packages/core/src/extraction.ts +81 -0
  129. package/packages/core/src/index.ts +22 -0
  130. package/packages/core/src/memory-store.ts +50 -0
  131. package/packages/core/src/memory.ts +447 -0
  132. package/packages/core/src/policy.ts +36 -0
  133. package/packages/core/src/types.ts +119 -0
  134. package/packages/core/tsconfig.json +6 -0
  135. package/packages/embeddings/package.json +9 -0
  136. package/packages/embeddings/src/index.ts +3 -0
  137. package/packages/embeddings/src/local.ts +47 -0
  138. package/packages/embeddings/src/openai.ts +50 -0
  139. package/packages/embeddings/src/provider.d.ts.map +1 -0
  140. package/packages/embeddings/src/provider.js.map +1 -0
  141. package/packages/embeddings/src/provider.ts +17 -0
  142. package/packages/embeddings/tsconfig.json +6 -0
  143. package/packages/integrations/package.json +7 -0
  144. package/packages/integrations/src/anthropic.ts +34 -0
  145. package/packages/integrations/src/index.ts +3 -0
  146. package/packages/integrations/src/openai.ts +52 -0
  147. package/packages/integrations/src/vercel.ts +26 -0
  148. package/packages/retrieval/package.json +8 -0
  149. package/packages/retrieval/src/index.ts +2 -0
  150. package/packages/retrieval/src/ranker.d.ts.map +1 -0
  151. package/packages/retrieval/src/ranker.js.map +1 -0
  152. package/packages/retrieval/src/ranker.ts +77 -0
  153. package/packages/retrieval/src/token.d.ts.map +1 -0
  154. package/packages/retrieval/src/token.js.map +1 -0
  155. package/packages/retrieval/src/token.ts +5 -0
  156. package/packages/retrieval/tsconfig.json +6 -0
  157. package/packages/storage/package.json +11 -0
  158. package/packages/storage/src/config.ts +44 -0
  159. package/packages/storage/src/index.ts +3 -0
  160. package/packages/storage/src/memory-store.ts +100 -0
  161. package/packages/storage/src/migrations.ts +96 -0
  162. package/packages/storage/src/postgres-store.ts +299 -0
  163. package/packages/storage/src/sqlite-store.ts +298 -0
  164. package/packages/storage/tsconfig.json +6 -0
  165. package/test-mvp.mjs +82 -0
  166. package/tests/consolidation.test.ts +45 -0
  167. package/tests/eval.test.ts +102 -0
  168. package/tsconfig.json +21 -0
  169. package/vitest.config.ts +8 -0
@@ -0,0 +1,50 @@
1
+ import type { EmbeddingProvider } from "./provider.js";
2
+
3
+ export interface OpenAIEmbeddingOptions {
4
+ apiKey: string;
5
+ model?: string; // default text-embedding-3-small
6
+ dimensions?: number;
7
+ baseURL?: string;
8
+ }
9
+
10
+ export class OpenAIEmbeddingProvider implements EmbeddingProvider {
11
+ readonly model: string;
12
+ readonly dimensions: number;
13
+ private apiKey: string;
14
+ private baseURL: string;
15
+
16
+ constructor(opts: OpenAIEmbeddingOptions) {
17
+ this.apiKey = opts.apiKey;
18
+ this.model = opts.model ?? "text-embedding-3-small";
19
+ this.dimensions = opts.dimensions ?? 1536;
20
+ this.baseURL = opts.baseURL ?? "https://api.openai.com/v1";
21
+ }
22
+
23
+ async embed(text: string): Promise<number[]> {
24
+ const res = await fetch(`${this.baseURL}/embeddings`, {
25
+ method: "POST",
26
+ headers: {
27
+ "Content-Type": "application/json",
28
+ Authorization: `Bearer ${this.apiKey}`,
29
+ },
30
+ body: JSON.stringify({ model: this.model, input: text }),
31
+ });
32
+ if (!res.ok) throw new Error(`OpenAI embed failed: ${res.status} ${await res.text()}`);
33
+ const data = (await res.json()) as any;
34
+ return data.data[0].embedding as number[];
35
+ }
36
+
37
+ async embedBatch(texts: string[]): Promise<number[][]> {
38
+ const res = await fetch(`${this.baseURL}/embeddings`, {
39
+ method: "POST",
40
+ headers: {
41
+ "Content-Type": "application/json",
42
+ Authorization: `Bearer ${this.apiKey}`,
43
+ },
44
+ body: JSON.stringify({ model: this.model, input: texts }),
45
+ });
46
+ if (!res.ok) throw new Error(`OpenAI embedBatch failed: ${res.status} ${await res.text()}`);
47
+ const data = (await res.json()) as any;
48
+ return data.data.sort((a: any, b: any) => a.index - b.index).map((d: any) => d.embedding);
49
+ }
50
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["provider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;CAClD;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CASjE"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["provider.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,gBAAgB,CAAC,CAAW,EAAE,CAAW;IACvD,IAAI,GAAG,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAClB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IACD,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACnC,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface EmbeddingProvider {
2
+ readonly model: string;
3
+ readonly dimensions: number;
4
+ embed(text: string): Promise<number[]>;
5
+ embedBatch(texts: string[]): Promise<number[][]>;
6
+ }
7
+
8
+ export function cosineSimilarity(a: number[], b: number[]): number {
9
+ let dot = 0, na = 0, nb = 0;
10
+ for (let i = 0; i < a.length; i++) {
11
+ dot += a[i] * b[i];
12
+ na += a[i] * a[i];
13
+ nb += b[i] * b[i];
14
+ }
15
+ if (na === 0 || nb === 0) return 0;
16
+ return dot / (Math.sqrt(na) * Math.sqrt(nb));
17
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "composite": false
5
+ }
6
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@agentmind/integrations",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/src/index.js",
6
+ "types": "./dist/src/index.d.ts"
7
+ }
@@ -0,0 +1,34 @@
1
+ import type { MemoryEngine } from "../../core/src/memory.js";
2
+ import type { ChatMessage } from "./openai.js";
3
+
4
+ export interface AnthropicWithMemoryOptions {
5
+ memory: MemoryEngine;
6
+ messages: ChatMessage[];
7
+ callLLM: (messages: ChatMessage[]) => Promise<string>;
8
+ extract?: boolean;
9
+ }
10
+
11
+ export async function withAnthropicMemory(opts: AnthropicWithMemoryOptions) {
12
+ const lastUser = [...opts.messages].reverse().find((m) => m.role === "user");
13
+ const query = lastUser?.content ?? opts.messages.map((m) => m.content).join("\n").slice(-500);
14
+ const ctx = await opts.memory.context({ query, maxTokens: 4000 });
15
+ const system = ctx.text ? ctx.text : undefined;
16
+ // Anthropic separates system; we prepend as system if provided
17
+ const augmented = system ? [{ role: "system" as const, content: system }, ...opts.messages.filter((m) => m.role !== "system")] : opts.messages;
18
+ const response = await opts.callLLM(augmented);
19
+ let memories: any[] = [];
20
+ if (opts.extract !== false) {
21
+ const ingested = await opts.memory.ingest({ role: "assistant", content: response });
22
+ if (ingested.extracted) memories = ingested.extracted;
23
+ }
24
+ return { response, context: ctx.text, memories };
25
+ }
26
+
27
+ export function createAnthropicCaller(anthropic: any, model: string) {
28
+ return async (messages: ChatMessage[]) => {
29
+ const system = messages.find((m) => m.role === "system")?.content;
30
+ const rest = messages.filter((m) => m.role !== "system").map((m) => ({ role: m.role, content: m.content }));
31
+ const res = await anthropic.messages.create({ model, max_tokens: 1024, system, messages: rest });
32
+ return res.content[0].text as string;
33
+ };
34
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./openai.js";
2
+ export * from "./anthropic.js";
3
+ export * from "./vercel.js";
@@ -0,0 +1,52 @@
1
+ import type { MemoryEngine } from "../../core/src/memory.js";
2
+
3
+ /**
4
+ * OpenAI integration — automates retrieve -> context -> LLM -> extract -> store
5
+ * Usage:
6
+ * import { withMemory } from "@agentmind/integrations/openai";
7
+ * const res = await withMemory({ memory, messages, openai, model: "gpt-4o" });
8
+ */
9
+
10
+ export interface ChatMessage {
11
+ role: "system" | "user" | "assistant" | "tool";
12
+ content: string;
13
+ }
14
+
15
+ export interface WithMemoryOptions {
16
+ memory: MemoryEngine;
17
+ messages: ChatMessage[];
18
+ // Provide a function that calls OpenAI — keeps this package dependency-free
19
+ callLLM: (messages: ChatMessage[]) => Promise<string>;
20
+ // Optional: extract memories from assistant response
21
+ extract?: boolean;
22
+ }
23
+
24
+ export async function withMemory(opts: WithMemoryOptions): Promise<{ response: string; context: string; memories: any[] }> {
25
+ const lastUser = [...opts.messages].reverse().find((m) => m.role === "user");
26
+ const query = lastUser?.content ?? opts.messages.map((m) => m.content).join("\n").slice(-500);
27
+
28
+ const ctx = await opts.memory.context({ query, maxTokens: 4000 });
29
+ const augmented: ChatMessage[] = ctx.text
30
+ ? [{ role: "system", content: ctx.text }, ...opts.messages]
31
+ : [...opts.messages];
32
+
33
+ const response = await opts.callLLM(augmented);
34
+
35
+ let memories: any[] = [];
36
+ if (opts.extract !== false) {
37
+ // Use memory's extractor if available via ingest
38
+ const ingested = await opts.memory.ingest({ role: "assistant", content: response });
39
+ // If autoExtract is enabled, ingest already extracted; otherwise manually remember key facts via heuristic
40
+ if (ingested.extracted) memories = ingested.extracted;
41
+ }
42
+
43
+ return { response, context: ctx.text, memories };
44
+ }
45
+
46
+ /** Helper for OpenAI SDK users */
47
+ export function createOpenAICaller(openai: any, model: string, opts?: { temperature?: number }) {
48
+ return async (messages: ChatMessage[]) => {
49
+ const res = await openai.chat.completions.create({ model, messages, temperature: opts?.temperature ?? 0.7 });
50
+ return res.choices[0].message.content as string;
51
+ };
52
+ }
@@ -0,0 +1,26 @@
1
+ import type { MemoryEngine } from "../../core/src/memory.js";
2
+
3
+ /**
4
+ * Vercel AI SDK integration
5
+ * Example:
6
+ * import { withMemoryAISDK } from "@agentmind/integrations/vercel";
7
+ * const { text } = await withMemoryAISDK({ memory, prompt, generateText });
8
+ */
9
+ export async function withMemoryAISDK(opts: {
10
+ memory: MemoryEngine;
11
+ prompt: string;
12
+ generateText: (prompt: string, system?: string) => Promise<string>;
13
+ }): Promise<{ text: string; context: string }> {
14
+ const ctx = await opts.memory.context({ query: opts.prompt, maxTokens: 4000 });
15
+ const text = await opts.generateText(opts.prompt, ctx.text || undefined);
16
+ await opts.memory.ingest({ role: "assistant", content: text });
17
+ return { text, context: ctx.text };
18
+ }
19
+
20
+ // LangChain adapter stub
21
+ export async function withLangChainMemory(opts: { memory: MemoryEngine; input: string; callChain: (input: string, context: string) => Promise<string> }) {
22
+ const ctx = await opts.memory.context({ query: opts.input });
23
+ const output = await opts.callChain(opts.input, ctx.text);
24
+ await opts.memory.ingest({ role: "assistant", content: output });
25
+ return { output, context: ctx.text };
26
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "@agentmind/retrieval",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/src/index.js",
6
+ "types": "./dist/src/index.d.ts",
7
+ "scripts": { "build": "tsc -b" }
8
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./ranker.js";
2
+ export * from "./token.js";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ranker.d.ts","sourceRoot":"","sources":["ranker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAqBD,qBAAa,YAAY;IACvB,OAAO,EAAE,aAAa,CAAC;gBAEX,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAS5C,IAAI,CACF,QAAQ,EAAE,KAAK,CAAC,MAAM,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,EAC7C,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,UAAU,EAAE;CAwBhB"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ranker.js","sourceRoot":"","sources":["ranker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import { cosineSimilarity } from "../../embeddings/src/provider.js";
2
+ import type { Memory } from "../../core/src/types.js";
3
+
4
+ export interface RankerWeights {
5
+ semantic: number; // 0.6
6
+ keyword: number; // 0.2
7
+ importance: number; // 0.1
8
+ recency: number; // 0.1
9
+ }
10
+
11
+ export interface RankedItem {
12
+ memory: Memory;
13
+ score: number;
14
+ semanticScore: number;
15
+ keywordScore: number;
16
+ }
17
+
18
+ function keywordScore(query: string, content: string): number {
19
+ const qTokens = new Set(query.toLowerCase().split(/\W+/).filter(Boolean));
20
+ const cTokens = content.toLowerCase().split(/\W+/).filter(Boolean);
21
+ if (qTokens.size === 0) return 0;
22
+ let hits = 0;
23
+ for (const t of cTokens) if (qTokens.has(t)) hits++;
24
+ // exact phrase boost
25
+ const phrase = query.toLowerCase().trim();
26
+ const phraseBoost = content.toLowerCase().includes(phrase) ? 0.3 : 0;
27
+ return Math.min(1, hits / qTokens.size + phraseBoost);
28
+ }
29
+
30
+ function recencyScore(mem: Memory): number {
31
+ const ageMs = Date.now() - new Date(mem.updatedAt).getTime();
32
+ const days = ageMs / (1000 * 60 * 60 * 24);
33
+ // exponential decay, half-life ~30 days
34
+ return Math.exp(-days / 30);
35
+ }
36
+
37
+ export class HybridRanker {
38
+ weights: RankerWeights;
39
+
40
+ constructor(weights?: Partial<RankerWeights>) {
41
+ this.weights = {
42
+ semantic: weights?.semantic ?? 0.6,
43
+ keyword: weights?.keyword ?? 0.2,
44
+ importance: weights?.importance ?? 0.1,
45
+ recency: weights?.recency ?? 0.1,
46
+ };
47
+ }
48
+
49
+ rank(
50
+ memories: Array<Memory & { _vec?: number[] }>,
51
+ query: string,
52
+ queryVec?: number[]
53
+ ): RankedItem[] {
54
+ const scored = memories.map((m) => {
55
+ const semantic = queryVec && m._vec ? (cosineSimilarity(queryVec, m._vec) + 1) / 2 : 0; // normalize -1..1 -> 0..1
56
+ const kw = keywordScore(query, m.content);
57
+ const imp = m.importance;
58
+ const rec = recencyScore(m);
59
+ const finalScore =
60
+ semantic * this.weights.semantic +
61
+ kw * this.weights.keyword +
62
+ imp * this.weights.importance +
63
+ rec * this.weights.recency;
64
+
65
+ return {
66
+ memory: m,
67
+ score: finalScore,
68
+ semanticScore: semantic,
69
+ keywordScore: kw,
70
+ } as RankedItem;
71
+ });
72
+
73
+ // If no query vectors, keyword+importance+recency still ranks
74
+ scored.sort((a, b) => b.score - a.score);
75
+ return scored;
76
+ }
77
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["token.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["token.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC;IACpB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** Very rough token estimator: ~4 chars per token */
2
+ export function estimateTokens(text: string): number {
3
+ if (!text) return 0;
4
+ return Math.ceil(text.length / 4);
5
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "composite": false
5
+ }
6
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "@agentmind/storage",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/src/index.js",
6
+ "types": "./dist/src/index.d.ts",
7
+ "scripts": { "build": "tsc -b" },
8
+ "dependencies": {
9
+ "zod": "^3.23.0"
10
+ }
11
+ }
@@ -0,0 +1,44 @@
1
+ import { SqliteMemoryStore } from "./sqlite-store.js";
2
+ import { PostgresMemoryStore } from "./postgres-store.js";
3
+ import type { MemoryStore } from "../../core/src/memory-store.js";
4
+
5
+ export interface StorageConfig {
6
+ provider: "sqlite" | "postgres" | "memory";
7
+ sqlite?: { path?: string };
8
+ postgres?: { connectionString: string };
9
+ }
10
+
11
+ export function resolveStorageConfig(): StorageConfig {
12
+ const pgUrl = process.env.DATABASE_URL ?? process.env.POSTGRES_URL;
13
+ if (pgUrl) return { provider: "postgres", postgres: { connectionString: pgUrl } };
14
+ const sqlitePath = process.env.AGENTMIND_DB ?? process.env.CTX_MEMORY_DB ?? "./.agentmind/memory.db";
15
+ if (sqlitePath === ":memory:") return { provider: "memory" };
16
+ return { provider: "sqlite", sqlite: { path: sqlitePath } };
17
+ }
18
+
19
+ export function createStoreFromConfig(config: StorageConfig): MemoryStore {
20
+ switch (config.provider) {
21
+ case "postgres":
22
+ return new PostgresMemoryStore(config.postgres!.connectionString);
23
+ case "sqlite":
24
+ return new SqliteMemoryStore({ path: config.sqlite?.path });
25
+ case "memory":
26
+ return new SqliteMemoryStore({ path: ":memory:" });
27
+ default:
28
+ return new SqliteMemoryStore({ path: "./.agentmind/memory.db" });
29
+ }
30
+ }
31
+
32
+ export function autoDetectProject(): string {
33
+ if (process.env.AGENTMIND_PROJECT ?? process.env.CTX_MEMORY_PROJECT) return (process.env.AGENTMIND_PROJECT ?? process.env.CTX_MEMORY_PROJECT) as string;
34
+ try {
35
+ const pkg = JSON.parse(require("node:fs").readFileSync("package.json", "utf-8"));
36
+ if (pkg.name) return String(pkg.name).replace(/^@.*\//, "");
37
+ } catch {}
38
+ try {
39
+ const cwd = process.cwd().split("/").pop() ?? "default";
40
+ return cwd;
41
+ } catch {
42
+ return "default";
43
+ }
44
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./sqlite-store.js";
2
+ export * from "./memory-store.js";
3
+ export * from "./postgres-store.js";
@@ -0,0 +1,100 @@
1
+ import type { MemoryStore } from "../../core/src/memory-store.js";
2
+ import type { Memory, Project, Source, SearchQuery, SearchResult, RetrievalEvent } from "../../core/src/types.js";
3
+
4
+ /**
5
+ * Pure in-memory store — zero dependencies, ideal for tests.
6
+ */
7
+ export class InMemoryStore implements MemoryStore {
8
+ private projects = new Map<string, Project>();
9
+ private projectsByName = new Map<string, Project>();
10
+ private sources = new Map<string, Source>();
11
+ private memories = new Map<string, Memory>();
12
+ private embeddings = new Map<string, { vector: number[]; model: string }>();
13
+ private retrievals: RetrievalEvent[] = [];
14
+
15
+ async createProject(project: Project): Promise<Project> {
16
+ this.projects.set(project.id, project);
17
+ this.projectsByName.set(project.name, project);
18
+ return project;
19
+ }
20
+ async getProject(id: string): Promise<Project | null> {
21
+ return this.projects.get(id) ?? null;
22
+ }
23
+ async getProjectByName(name: string): Promise<Project | null> {
24
+ return this.projectsByName.get(name) ?? null;
25
+ }
26
+ async listProjects(): Promise<Project[]> {
27
+ return [...this.projects.values()];
28
+ }
29
+ async deleteProject(projectId: string): Promise<void> {
30
+ const p = this.projects.get(projectId);
31
+ if (p) this.projectsByName.delete(p.name);
32
+ this.projects.delete(projectId);
33
+ for (const [id, m] of this.memories) if (m.projectId === projectId) this.memories.delete(id);
34
+ }
35
+ async createSource(source: Source): Promise<Source> {
36
+ this.sources.set(source.id, source);
37
+ return source;
38
+ }
39
+ async getSource(id: string): Promise<Source | null> {
40
+ return this.sources.get(id) ?? null;
41
+ }
42
+ async createMemory(memory: Memory): Promise<void> {
43
+ this.memories.set(memory.id, memory);
44
+ }
45
+ async getMemory(id: string): Promise<Memory | null> {
46
+ return this.memories.get(id) ?? null;
47
+ }
48
+ async updateMemory(id: string, update: Partial<Memory>): Promise<void> {
49
+ const existing = this.memories.get(id);
50
+ if (!existing) return;
51
+ this.memories.set(id, { ...existing, ...update, id, updatedAt: update.updatedAt ?? new Date() } as Memory);
52
+ }
53
+ async deleteMemory(id: string): Promise<void> {
54
+ this.memories.delete(id);
55
+ }
56
+ async archiveMemory(id: string): Promise<void> {
57
+ const m = this.memories.get(id);
58
+ if (m) this.memories.set(id, { ...m, archived: true, status: "archived", updatedAt: new Date() });
59
+ }
60
+ async listMemories(projectId: string): Promise<Memory[]> {
61
+ return [...this.memories.values()].filter((m) => m.projectId === projectId).sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
62
+ }
63
+ async search(query: SearchQuery): Promise<SearchResult[]> {
64
+ let candidates = [...this.memories.values()].filter((m) => m.projectId === query.projectId);
65
+ if (query.types?.length) candidates = candidates.filter((m) => query.types!.includes(m.type));
66
+ if (query.minImportance !== undefined) candidates = candidates.filter((m) => m.importance >= query.minImportance!);
67
+ if (!query.includeArchived) candidates = candidates.filter((m) => !m.archived && m.status !== "archived");
68
+ const qLower = query.query.toLowerCase();
69
+ const qTokens = new Set(qLower.split(/\W+/).filter(Boolean));
70
+ const scored = candidates.map((m) => {
71
+ const cLower = m.content.toLowerCase();
72
+ const cTokens = cLower.split(/\W+/).filter(Boolean);
73
+ let hits = 0;
74
+ for (const t of cTokens) if (qTokens.has(t)) hits++;
75
+ const phraseBoost = cLower.includes(qLower) ? 0.5 : 0;
76
+ const keywordScore = qTokens.size ? Math.min(1, hits / qTokens.size + phraseBoost) : 0;
77
+ const recency = Math.exp(-(Date.now() - m.updatedAt.getTime()) / (1000 * 60 * 60 * 24 * 30));
78
+ const final = keywordScore * 0.7 + m.importance * 0.15 + recency * 0.15;
79
+ return { memory: m, score: final, semanticScore: 0, keywordScore };
80
+ });
81
+ scored.sort((a, b) => b.score - a.score);
82
+ return scored.slice(0, query.limit ?? 5);
83
+ }
84
+ async upsertEmbedding(memoryId: string, vector: number[], model: string): Promise<void> {
85
+ this.embeddings.set(memoryId, { vector, model });
86
+ }
87
+ async getEmbedding(memoryId: string): Promise<{ vector: number[]; model: string } | null> {
88
+ return this.embeddings.get(memoryId) ?? null;
89
+ }
90
+ async deleteEmbedding(memoryId: string): Promise<void> {
91
+ this.embeddings.delete(memoryId);
92
+ }
93
+ async logRetrieval(event: RetrievalEvent): Promise<void> {
94
+ this.retrievals.push(event);
95
+ }
96
+ async listRetrievals(projectId: string, limit = 20): Promise<RetrievalEvent[]> {
97
+ return this.retrievals.filter((r) => r.projectId === projectId).slice(-limit).reverse();
98
+ }
99
+ async close(): Promise<void> {}
100
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Migration system for both SQLite (node:sqlite) and Postgres.
3
+ * Versioned, idempotent — tracks `schema_migrations` table.
4
+ */
5
+
6
+ export interface Migration {
7
+ version: number;
8
+ name: string;
9
+ up: string; // SQL
10
+ }
11
+
12
+ export const MIGRATIONS: Migration[] = [
13
+ {
14
+ version: 1,
15
+ name: "initial",
16
+ up: `
17
+ CREATE TABLE IF NOT EXISTS schema_migrations (
18
+ version INTEGER PRIMARY KEY,
19
+ name TEXT NOT NULL,
20
+ applied_at TEXT NOT NULL
21
+ );
22
+ CREATE TABLE IF NOT EXISTS projects (
23
+ id TEXT PRIMARY KEY,
24
+ name TEXT UNIQUE NOT NULL,
25
+ description TEXT,
26
+ created_at TEXT NOT NULL,
27
+ updated_at TEXT NOT NULL
28
+ );
29
+ CREATE TABLE IF NOT EXISTS sources (
30
+ id TEXT PRIMARY KEY,
31
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
32
+ type TEXT NOT NULL,
33
+ content TEXT,
34
+ created_at TEXT NOT NULL,
35
+ metadata TEXT NOT NULL
36
+ );
37
+ CREATE TABLE IF NOT EXISTS memories (
38
+ id TEXT PRIMARY KEY,
39
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
40
+ type TEXT NOT NULL,
41
+ content TEXT NOT NULL,
42
+ importance REAL NOT NULL,
43
+ confidence REAL NOT NULL,
44
+ status TEXT NOT NULL,
45
+ created_at TEXT NOT NULL,
46
+ updated_at TEXT NOT NULL,
47
+ last_accessed_at TEXT,
48
+ access_count INTEGER NOT NULL,
49
+ source_id TEXT REFERENCES sources(id) ON DELETE SET NULL,
50
+ metadata TEXT NOT NULL,
51
+ archived INTEGER NOT NULL DEFAULT 0
52
+ );
53
+ CREATE TABLE IF NOT EXISTS embeddings (
54
+ memory_id TEXT PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
55
+ vector TEXT NOT NULL,
56
+ model TEXT NOT NULL,
57
+ dimensions INTEGER NOT NULL
58
+ );
59
+ CREATE TABLE IF NOT EXISTS retrieval_events (
60
+ id TEXT PRIMARY KEY,
61
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
62
+ query TEXT NOT NULL,
63
+ retrieved_memory_ids TEXT NOT NULL,
64
+ scores TEXT NOT NULL,
65
+ final_context_tokens INTEGER NOT NULL,
66
+ created_at TEXT NOT NULL
67
+ );
68
+ CREATE TABLE IF NOT EXISTS consolidations (
69
+ id TEXT PRIMARY KEY,
70
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
71
+ summary_memory_id TEXT REFERENCES memories(id) ON DELETE SET NULL,
72
+ source_memory_ids TEXT NOT NULL,
73
+ created_at TEXT NOT NULL
74
+ );
75
+ CREATE INDEX IF NOT EXISTS idx_memories_project ON memories(project_id);
76
+ CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(type);
77
+ CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status);
78
+ `,
79
+ },
80
+ {
81
+ version: 2,
82
+ name: "pgvector",
83
+ up: `
84
+ -- Postgres only: enable pgvector
85
+ -- CREATE EXTENSION IF NOT EXISTS vector;
86
+ -- ALTER TABLE embeddings ADD COLUMN IF NOT EXISTS vec vector(1536);
87
+ -- CREATE INDEX IF NOT EXISTS idx_embeddings_vec ON embeddings USING hnsw (vec vector_cosine_ops);
88
+ -- For SQLite, this migration is a no-op (vector stored as JSON text)
89
+ SELECT 1;
90
+ `,
91
+ },
92
+ ];
93
+
94
+ export function getPendingMigrations(applied: number[]): Migration[] {
95
+ return MIGRATIONS.filter((m) => !applied.includes(m.version));
96
+ }