@avee1234/agent-kit 0.2.0 → 0.3.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/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # agent-kit
2
2
 
3
+ [![CI](https://github.com/abhid1234/agent-kit/actions/workflows/ci.yml/badge.svg)](https://github.com/abhid1234/agent-kit/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/@avee1234/agent-kit)](https://www.npmjs.com/package/@avee1234/agent-kit)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
+
3
7
  TypeScript-first library for building stateful, persistent AI agents.
4
8
 
5
9
  <p align="center">
package/dist/cli.cjs ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/cli.ts
27
+ var import_fs = __toESM(require("fs"), 1);
28
+ var import_path = __toESM(require("path"), 1);
29
+ var args = process.argv.slice(2);
30
+ var command = args[0];
31
+ var projectName = args[1] ?? "my-agent";
32
+ if (command !== "init") {
33
+ console.error(`Unknown command: ${command}`);
34
+ console.error("Usage: agent-kit init [project-name]");
35
+ process.exit(1);
36
+ }
37
+ var targetDir = import_path.default.resolve(process.cwd(), projectName);
38
+ if (import_fs.default.existsSync(targetDir)) {
39
+ console.error(`Directory already exists: ${targetDir}`);
40
+ process.exit(1);
41
+ }
42
+ import_fs.default.mkdirSync(targetDir, { recursive: true });
43
+ var packageJson = {
44
+ name: projectName,
45
+ version: "1.0.0",
46
+ private: true,
47
+ type: "module",
48
+ scripts: {
49
+ start: "npx tsx agent.ts"
50
+ },
51
+ dependencies: {
52
+ "@avee1234/agent-kit": "^0.2.0"
53
+ },
54
+ devDependencies: {
55
+ tsx: "^4.0.0"
56
+ }
57
+ };
58
+ var agentTs = `import { Agent, Tool, Memory } from '@avee1234/agent-kit';
59
+
60
+ const greet = Tool.create({
61
+ name: 'greet',
62
+ description: 'Greet someone by name',
63
+ parameters: {
64
+ name: { type: 'string', description: 'Name to greet' },
65
+ },
66
+ execute: async ({ name }) => \`Hello, \${name}!\`,
67
+ });
68
+
69
+ const agent = new Agent({
70
+ name: 'my-agent',
71
+ memory: new Memory({ store: 'sqlite', path: './memory.db' }),
72
+ tools: [greet],
73
+ system: 'You are a helpful assistant.',
74
+ });
75
+
76
+ const response = await agent.chat(process.argv[2] ?? 'Hello!');
77
+ console.log(response.content);
78
+ `;
79
+ var readmeMd = `# ${projectName}
80
+
81
+ Built with [agent-kit](https://github.com/abhid1234/agent-kit).
82
+
83
+ ## Quick Start
84
+
85
+ \`\`\`bash
86
+ npm install
87
+ npm start "Hello, what can you do?"
88
+ \`\`\`
89
+ `;
90
+ import_fs.default.writeFileSync(import_path.default.join(targetDir, "package.json"), JSON.stringify(packageJson, null, 2) + "\n");
91
+ import_fs.default.writeFileSync(import_path.default.join(targetDir, "agent.ts"), agentTs);
92
+ import_fs.default.writeFileSync(import_path.default.join(targetDir, "README.md"), readmeMd);
93
+ console.log(`
94
+ Scaffolded project: ${projectName}
95
+ `);
96
+ console.log("Next steps:\n");
97
+ console.log(` cd ${projectName}`);
98
+ console.log(" npm install");
99
+ console.log(' npm start "Hello, what can you do?"\n');
100
+ //# sourceMappingURL=cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport fs from 'fs';\nimport path from 'path';\n\nconst args = process.argv.slice(2);\nconst command = args[0];\nconst projectName = args[1] ?? 'my-agent';\n\nif (command !== 'init') {\n console.error(`Unknown command: ${command}`);\n console.error('Usage: agent-kit init [project-name]');\n process.exit(1);\n}\n\nconst targetDir = path.resolve(process.cwd(), projectName);\n\nif (fs.existsSync(targetDir)) {\n console.error(`Directory already exists: ${targetDir}`);\n process.exit(1);\n}\n\nfs.mkdirSync(targetDir, { recursive: true });\n\nconst packageJson = {\n name: projectName,\n version: '1.0.0',\n private: true,\n type: 'module',\n scripts: {\n start: 'npx tsx agent.ts',\n },\n dependencies: {\n '@avee1234/agent-kit': '^0.2.0',\n },\n devDependencies: {\n tsx: '^4.0.0',\n },\n};\n\nconst agentTs = `import { Agent, Tool, Memory } from '@avee1234/agent-kit';\n\nconst greet = Tool.create({\n name: 'greet',\n description: 'Greet someone by name',\n parameters: {\n name: { type: 'string', description: 'Name to greet' },\n },\n execute: async ({ name }) => \\`Hello, \\${name}!\\`,\n});\n\nconst agent = new Agent({\n name: 'my-agent',\n memory: new Memory({ store: 'sqlite', path: './memory.db' }),\n tools: [greet],\n system: 'You are a helpful assistant.',\n});\n\nconst response = await agent.chat(process.argv[2] ?? 'Hello!');\nconsole.log(response.content);\n`;\n\nconst readmeMd = `# ${projectName}\n\nBuilt with [agent-kit](https://github.com/abhid1234/agent-kit).\n\n## Quick Start\n\n\\`\\`\\`bash\nnpm install\nnpm start \"Hello, what can you do?\"\n\\`\\`\\`\n`;\n\nfs.writeFileSync(path.join(targetDir, 'package.json'), JSON.stringify(packageJson, null, 2) + '\\n');\nfs.writeFileSync(path.join(targetDir, 'agent.ts'), agentTs);\nfs.writeFileSync(path.join(targetDir, 'README.md'), readmeMd);\n\nconsole.log(`\\nScaffolded project: ${projectName}\\n`);\nconsole.log('Next steps:\\n');\nconsole.log(` cd ${projectName}`);\nconsole.log(' npm install');\nconsole.log(' npm start \"Hello, what can you do?\"\\n');\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,gBAAe;AACf,kBAAiB;AAEjB,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,IAAM,UAAU,KAAK,CAAC;AACtB,IAAM,cAAc,KAAK,CAAC,KAAK;AAE/B,IAAI,YAAY,QAAQ;AACtB,UAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,UAAQ,MAAM,sCAAsC;AACpD,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,YAAY,YAAAA,QAAK,QAAQ,QAAQ,IAAI,GAAG,WAAW;AAEzD,IAAI,UAAAC,QAAG,WAAW,SAAS,GAAG;AAC5B,UAAQ,MAAM,6BAA6B,SAAS,EAAE;AACtD,UAAQ,KAAK,CAAC;AAChB;AAEA,UAAAA,QAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAE3C,IAAM,cAAc;AAAA,EAClB,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,cAAc;AAAA,IACZ,uBAAuB;AAAA,EACzB;AAAA,EACA,iBAAiB;AAAA,IACf,KAAK;AAAA,EACP;AACF;AAEA,IAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBhB,IAAM,WAAW,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYjC,UAAAA,QAAG,cAAc,YAAAD,QAAK,KAAK,WAAW,cAAc,GAAG,KAAK,UAAU,aAAa,MAAM,CAAC,IAAI,IAAI;AAClG,UAAAC,QAAG,cAAc,YAAAD,QAAK,KAAK,WAAW,UAAU,GAAG,OAAO;AAC1D,UAAAC,QAAG,cAAc,YAAAD,QAAK,KAAK,WAAW,WAAW,GAAG,QAAQ;AAE5D,QAAQ,IAAI;AAAA,sBAAyB,WAAW;AAAA,CAAI;AACpD,QAAQ,IAAI,eAAe;AAC3B,QAAQ,IAAI,QAAQ,WAAW,EAAE;AACjC,QAAQ,IAAI,eAAe;AAC3B,QAAQ,IAAI,yCAAyC;","names":["path","fs"]}
package/dist/cli.d.cts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.js ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.ts
4
+ import fs from "fs";
5
+ import path from "path";
6
+ var args = process.argv.slice(2);
7
+ var command = args[0];
8
+ var projectName = args[1] ?? "my-agent";
9
+ if (command !== "init") {
10
+ console.error(`Unknown command: ${command}`);
11
+ console.error("Usage: agent-kit init [project-name]");
12
+ process.exit(1);
13
+ }
14
+ var targetDir = path.resolve(process.cwd(), projectName);
15
+ if (fs.existsSync(targetDir)) {
16
+ console.error(`Directory already exists: ${targetDir}`);
17
+ process.exit(1);
18
+ }
19
+ fs.mkdirSync(targetDir, { recursive: true });
20
+ var packageJson = {
21
+ name: projectName,
22
+ version: "1.0.0",
23
+ private: true,
24
+ type: "module",
25
+ scripts: {
26
+ start: "npx tsx agent.ts"
27
+ },
28
+ dependencies: {
29
+ "@avee1234/agent-kit": "^0.2.0"
30
+ },
31
+ devDependencies: {
32
+ tsx: "^4.0.0"
33
+ }
34
+ };
35
+ var agentTs = `import { Agent, Tool, Memory } from '@avee1234/agent-kit';
36
+
37
+ const greet = Tool.create({
38
+ name: 'greet',
39
+ description: 'Greet someone by name',
40
+ parameters: {
41
+ name: { type: 'string', description: 'Name to greet' },
42
+ },
43
+ execute: async ({ name }) => \`Hello, \${name}!\`,
44
+ });
45
+
46
+ const agent = new Agent({
47
+ name: 'my-agent',
48
+ memory: new Memory({ store: 'sqlite', path: './memory.db' }),
49
+ tools: [greet],
50
+ system: 'You are a helpful assistant.',
51
+ });
52
+
53
+ const response = await agent.chat(process.argv[2] ?? 'Hello!');
54
+ console.log(response.content);
55
+ `;
56
+ var readmeMd = `# ${projectName}
57
+
58
+ Built with [agent-kit](https://github.com/abhid1234/agent-kit).
59
+
60
+ ## Quick Start
61
+
62
+ \`\`\`bash
63
+ npm install
64
+ npm start "Hello, what can you do?"
65
+ \`\`\`
66
+ `;
67
+ fs.writeFileSync(path.join(targetDir, "package.json"), JSON.stringify(packageJson, null, 2) + "\n");
68
+ fs.writeFileSync(path.join(targetDir, "agent.ts"), agentTs);
69
+ fs.writeFileSync(path.join(targetDir, "README.md"), readmeMd);
70
+ console.log(`
71
+ Scaffolded project: ${projectName}
72
+ `);
73
+ console.log("Next steps:\n");
74
+ console.log(` cd ${projectName}`);
75
+ console.log(" npm install");
76
+ console.log(' npm start "Hello, what can you do?"\n');
77
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport fs from 'fs';\nimport path from 'path';\n\nconst args = process.argv.slice(2);\nconst command = args[0];\nconst projectName = args[1] ?? 'my-agent';\n\nif (command !== 'init') {\n console.error(`Unknown command: ${command}`);\n console.error('Usage: agent-kit init [project-name]');\n process.exit(1);\n}\n\nconst targetDir = path.resolve(process.cwd(), projectName);\n\nif (fs.existsSync(targetDir)) {\n console.error(`Directory already exists: ${targetDir}`);\n process.exit(1);\n}\n\nfs.mkdirSync(targetDir, { recursive: true });\n\nconst packageJson = {\n name: projectName,\n version: '1.0.0',\n private: true,\n type: 'module',\n scripts: {\n start: 'npx tsx agent.ts',\n },\n dependencies: {\n '@avee1234/agent-kit': '^0.2.0',\n },\n devDependencies: {\n tsx: '^4.0.0',\n },\n};\n\nconst agentTs = `import { Agent, Tool, Memory } from '@avee1234/agent-kit';\n\nconst greet = Tool.create({\n name: 'greet',\n description: 'Greet someone by name',\n parameters: {\n name: { type: 'string', description: 'Name to greet' },\n },\n execute: async ({ name }) => \\`Hello, \\${name}!\\`,\n});\n\nconst agent = new Agent({\n name: 'my-agent',\n memory: new Memory({ store: 'sqlite', path: './memory.db' }),\n tools: [greet],\n system: 'You are a helpful assistant.',\n});\n\nconst response = await agent.chat(process.argv[2] ?? 'Hello!');\nconsole.log(response.content);\n`;\n\nconst readmeMd = `# ${projectName}\n\nBuilt with [agent-kit](https://github.com/abhid1234/agent-kit).\n\n## Quick Start\n\n\\`\\`\\`bash\nnpm install\nnpm start \"Hello, what can you do?\"\n\\`\\`\\`\n`;\n\nfs.writeFileSync(path.join(targetDir, 'package.json'), JSON.stringify(packageJson, null, 2) + '\\n');\nfs.writeFileSync(path.join(targetDir, 'agent.ts'), agentTs);\nfs.writeFileSync(path.join(targetDir, 'README.md'), readmeMd);\n\nconsole.log(`\\nScaffolded project: ${projectName}\\n`);\nconsole.log('Next steps:\\n');\nconsole.log(` cd ${projectName}`);\nconsole.log(' npm install');\nconsole.log(' npm start \"Hello, what can you do?\"\\n');\n"],"mappings":";;;AAEA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,IAAM,UAAU,KAAK,CAAC;AACtB,IAAM,cAAc,KAAK,CAAC,KAAK;AAE/B,IAAI,YAAY,QAAQ;AACtB,UAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,UAAQ,MAAM,sCAAsC;AACpD,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,YAAY,KAAK,QAAQ,QAAQ,IAAI,GAAG,WAAW;AAEzD,IAAI,GAAG,WAAW,SAAS,GAAG;AAC5B,UAAQ,MAAM,6BAA6B,SAAS,EAAE;AACtD,UAAQ,KAAK,CAAC;AAChB;AAEA,GAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAE3C,IAAM,cAAc;AAAA,EAClB,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,cAAc;AAAA,IACZ,uBAAuB;AAAA,EACzB;AAAA,EACA,iBAAiB;AAAA,IACf,KAAK;AAAA,EACP;AACF;AAEA,IAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBhB,IAAM,WAAW,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYjC,GAAG,cAAc,KAAK,KAAK,WAAW,cAAc,GAAG,KAAK,UAAU,aAAa,MAAM,CAAC,IAAI,IAAI;AAClG,GAAG,cAAc,KAAK,KAAK,WAAW,UAAU,GAAG,OAAO;AAC1D,GAAG,cAAc,KAAK,KAAK,WAAW,WAAW,GAAG,QAAQ;AAE5D,QAAQ,IAAI;AAAA,sBAAyB,WAAW;AAAA,CAAI;AACpD,QAAQ,IAAI,eAAe;AAC3B,QAAQ,IAAI,QAAQ,WAAW,EAAE;AACjC,QAAQ,IAAI,eAAe;AAC3B,QAAQ,IAAI,yCAAyC;","names":[]}
package/dist/index.cjs CHANGED
@@ -25,7 +25,9 @@ __export(index_exports, {
25
25
  InMemoryStore: () => InMemoryStore,
26
26
  Memory: () => Memory,
27
27
  MockAdapter: () => MockAdapter,
28
+ OllamaEmbeddingAdapter: () => OllamaEmbeddingAdapter,
28
29
  OpenAICompatibleAdapter: () => OpenAICompatibleAdapter,
30
+ PostgresStore: () => PostgresStore,
29
31
  SQLiteStore: () => SQLiteStore,
30
32
  Team: () => Team,
31
33
  Tool: () => Tool,
@@ -101,7 +103,15 @@ var OpenAICompatibleAdapter = class {
101
103
  function: {
102
104
  name: t.name,
103
105
  description: t.description,
104
- parameters: { type: "object", properties: t.parameters }
106
+ parameters: {
107
+ type: "object",
108
+ properties: Object.fromEntries(
109
+ Object.entries(t.parameters).map(([key, val]) => {
110
+ const { required: _req, ...rest } = val;
111
+ return [key, rest];
112
+ })
113
+ )
114
+ }
105
115
  }
106
116
  }));
107
117
  }
@@ -147,7 +157,15 @@ var OpenAICompatibleAdapter = class {
147
157
  function: {
148
158
  name: t.name,
149
159
  description: t.description,
150
- parameters: { type: "object", properties: t.parameters }
160
+ parameters: {
161
+ type: "object",
162
+ properties: Object.fromEntries(
163
+ Object.entries(t.parameters).map(([key, val]) => {
164
+ const { required: _req, ...rest } = val;
165
+ return [key, rest];
166
+ })
167
+ )
168
+ }
151
169
  }
152
170
  }));
153
171
  }
@@ -609,13 +627,11 @@ var HierarchicalStrategy = class {
609
627
  parameters: {
610
628
  agentName: {
611
629
  type: "string",
612
- description: "The name of the agent to delegate to",
613
- required: true
630
+ description: `The name of the agent to delegate to. Available: ${[...agents.map((a) => a.name)].join(", ")}`
614
631
  },
615
632
  task: {
616
633
  type: "string",
617
- description: "The task to assign to the agent",
618
- required: true
634
+ description: "The task to assign to the agent"
619
635
  }
620
636
  },
621
637
  execute: async (params) => {
@@ -724,10 +740,27 @@ var Team = class {
724
740
  }
725
741
  };
726
742
 
743
+ // src/store/cosine.ts
744
+ function cosineSimilarity(a, b) {
745
+ let dot = 0;
746
+ let normA = 0;
747
+ let normB = 0;
748
+ for (let i = 0; i < a.length; i++) {
749
+ dot += a[i] * b[i];
750
+ normA += a[i] * a[i];
751
+ normB += b[i] * b[i];
752
+ }
753
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
754
+ if (denom === 0) return 0;
755
+ return dot / denom;
756
+ }
757
+
727
758
  // src/store/in-memory.ts
728
759
  var InMemoryStore = class {
729
760
  messages = /* @__PURE__ */ new Map();
730
761
  summaries = /* @__PURE__ */ new Map();
762
+ // agentId -> (summaryId -> embedding vector)
763
+ embeddings = /* @__PURE__ */ new Map();
731
764
  async saveMessages(agentId, messages) {
732
765
  const existing = this.messages.get(agentId) ?? [];
733
766
  existing.push(...messages);
@@ -748,6 +781,28 @@ var InMemoryStore = class {
748
781
  const matches = all.filter((s) => s.content.toLowerCase().includes(queryLower)).sort((a, b) => b.timestamp - a.timestamp).slice(0, limit);
749
782
  return matches;
750
783
  }
784
+ async saveEmbedding(agentId, summaryId, embedding) {
785
+ let agentMap = this.embeddings.get(agentId);
786
+ if (!agentMap) {
787
+ agentMap = /* @__PURE__ */ new Map();
788
+ this.embeddings.set(agentId, agentMap);
789
+ }
790
+ agentMap.set(summaryId, embedding);
791
+ }
792
+ async searchByEmbedding(agentId, embedding, limit) {
793
+ const agentMap = this.embeddings.get(agentId);
794
+ if (!agentMap || agentMap.size === 0) return [];
795
+ const summaries = this.summaries.get(agentId) ?? [];
796
+ const summaryById = new Map(summaries.map((s) => [s.id, s]));
797
+ const scored = [];
798
+ for (const [summaryId, storedEmbedding] of agentMap) {
799
+ const summary = summaryById.get(summaryId);
800
+ if (!summary) continue;
801
+ const score = cosineSimilarity(embedding, storedEmbedding);
802
+ scored.push({ summary, score });
803
+ }
804
+ return scored.sort((a, b) => b.score - a.score).slice(0, limit).map((entry) => entry.summary);
805
+ }
751
806
  };
752
807
 
753
808
  // src/store/sqlite.ts
@@ -781,8 +836,14 @@ var SQLiteStore = class {
781
836
  message_range_from INTEGER NOT NULL,
782
837
  message_range_to INTEGER NOT NULL
783
838
  );
839
+ CREATE TABLE IF NOT EXISTS embeddings (
840
+ summary_id TEXT PRIMARY KEY,
841
+ agent_id TEXT NOT NULL,
842
+ embedding BLOB NOT NULL
843
+ );
784
844
  CREATE INDEX IF NOT EXISTS idx_messages_agent ON messages(agent_id);
785
845
  CREATE INDEX IF NOT EXISTS idx_summaries_agent ON summaries(agent_id);
846
+ CREATE INDEX IF NOT EXISTS idx_embeddings_agent ON embeddings(agent_id);
786
847
  `);
787
848
  }
788
849
  async saveMessages(agentId, messages) {
@@ -842,25 +903,209 @@ var SQLiteStore = class {
842
903
  messageRange: { from: row.message_range_from, to: row.message_range_to }
843
904
  }));
844
905
  }
906
+ async saveEmbedding(agentId, summaryId, embedding) {
907
+ this.db.prepare(
908
+ "INSERT OR REPLACE INTO embeddings (summary_id, agent_id, embedding) VALUES (?, ?, ?)"
909
+ ).run(summaryId, agentId, JSON.stringify(embedding));
910
+ }
911
+ async searchByEmbedding(agentId, embedding, limit) {
912
+ const rows = this.db.prepare(
913
+ `SELECT e.summary_id, s.content, s.timestamp, s.message_range_from, s.message_range_to, e.embedding
914
+ FROM embeddings e
915
+ JOIN summaries s ON e.summary_id = s.id
916
+ WHERE e.agent_id = ?`
917
+ ).all(agentId);
918
+ if (rows.length === 0) return [];
919
+ const scored = rows.map((row) => {
920
+ const storedEmbedding = JSON.parse(row.embedding);
921
+ const score = cosineSimilarity(embedding, storedEmbedding);
922
+ return {
923
+ summary: {
924
+ id: row.summary_id,
925
+ content: row.content,
926
+ timestamp: row.timestamp,
927
+ messageRange: { from: row.message_range_from, to: row.message_range_to }
928
+ },
929
+ score
930
+ };
931
+ });
932
+ return scored.sort((a, b) => b.score - a.score).slice(0, limit).map((entry) => entry.summary);
933
+ }
845
934
  close() {
846
935
  this.db.close();
847
936
  }
848
937
  };
849
938
 
939
+ // src/store/postgres.ts
940
+ var import_module2 = require("module");
941
+ var import_meta2 = {};
942
+ var require3 = (0, import_module2.createRequire)(import_meta2.url);
943
+ var SCHEMA_SQL = `
944
+ CREATE EXTENSION IF NOT EXISTS vector;
945
+
946
+ CREATE TABLE IF NOT EXISTS agent_messages (
947
+ id SERIAL PRIMARY KEY,
948
+ agent_id TEXT NOT NULL,
949
+ role TEXT NOT NULL,
950
+ content TEXT NOT NULL,
951
+ timestamp BIGINT NOT NULL,
952
+ tool_calls JSONB,
953
+ tool_call_id TEXT
954
+ );
955
+
956
+ CREATE TABLE IF NOT EXISTS agent_summaries (
957
+ id TEXT PRIMARY KEY,
958
+ agent_id TEXT NOT NULL,
959
+ content TEXT NOT NULL,
960
+ timestamp BIGINT NOT NULL,
961
+ message_range_from BIGINT NOT NULL,
962
+ message_range_to BIGINT NOT NULL,
963
+ embedding vector(768)
964
+ );
965
+
966
+ CREATE INDEX IF NOT EXISTS idx_agent_messages_agent ON agent_messages(agent_id);
967
+ CREATE INDEX IF NOT EXISTS idx_agent_summaries_agent ON agent_summaries(agent_id);
968
+ `;
969
+ var PostgresStore = class _PostgresStore {
970
+ pool;
971
+ constructor(config) {
972
+ const { Pool } = require3("pg");
973
+ this.pool = new Pool({ connectionString: config.connectionString });
974
+ void this.init();
975
+ }
976
+ async init() {
977
+ await this.pool.query(SCHEMA_SQL);
978
+ }
979
+ /** Factory that ensures schema is ready before returning the store. */
980
+ static async create(config) {
981
+ const store = new _PostgresStore(config);
982
+ await store.init();
983
+ return store;
984
+ }
985
+ async saveMessages(agentId, messages) {
986
+ for (const msg of messages) {
987
+ await this.pool.query(
988
+ `INSERT INTO agent_messages (agent_id, role, content, timestamp, tool_calls, tool_call_id)
989
+ VALUES ($1, $2, $3, $4, $5, $6)`,
990
+ [
991
+ agentId,
992
+ msg.role,
993
+ msg.content,
994
+ msg.timestamp,
995
+ msg.toolCalls ? JSON.stringify(msg.toolCalls) : null,
996
+ msg.toolCallId ?? null
997
+ ]
998
+ );
999
+ }
1000
+ }
1001
+ async getRecentMessages(agentId, limit) {
1002
+ const result = await this.pool.query(
1003
+ `SELECT role, content, timestamp, tool_calls, tool_call_id
1004
+ FROM agent_messages
1005
+ WHERE agent_id = $1
1006
+ ORDER BY id DESC
1007
+ LIMIT $2`,
1008
+ [agentId, limit]
1009
+ );
1010
+ return result.rows.reverse().map((row) => ({
1011
+ role: row.role,
1012
+ content: row.content,
1013
+ timestamp: Number(row.timestamp),
1014
+ ...row.tool_calls ? {
1015
+ toolCalls: typeof row.tool_calls === "string" ? JSON.parse(row.tool_calls) : row.tool_calls
1016
+ } : {},
1017
+ ...row.tool_call_id ? { toolCallId: row.tool_call_id } : {}
1018
+ }));
1019
+ }
1020
+ async saveSummary(agentId, summary) {
1021
+ await this.pool.query(
1022
+ `INSERT INTO agent_summaries (id, agent_id, content, timestamp, message_range_from, message_range_to)
1023
+ VALUES ($1, $2, $3, $4, $5, $6)`,
1024
+ [
1025
+ summary.id,
1026
+ agentId,
1027
+ summary.content,
1028
+ summary.timestamp,
1029
+ summary.messageRange.from,
1030
+ summary.messageRange.to
1031
+ ]
1032
+ );
1033
+ }
1034
+ async searchSummaries(agentId, query, limit) {
1035
+ const result = await this.pool.query(
1036
+ `SELECT id, content, timestamp, message_range_from, message_range_to
1037
+ FROM agent_summaries
1038
+ WHERE agent_id = $1 AND content ILIKE $2
1039
+ ORDER BY timestamp DESC
1040
+ LIMIT $3`,
1041
+ [agentId, `%${query}%`, limit]
1042
+ );
1043
+ return result.rows.map((row) => ({
1044
+ id: row.id,
1045
+ content: row.content,
1046
+ timestamp: Number(row.timestamp),
1047
+ messageRange: {
1048
+ from: Number(row.message_range_from),
1049
+ to: Number(row.message_range_to)
1050
+ }
1051
+ }));
1052
+ }
1053
+ async saveEmbedding(agentId, summaryId, embedding) {
1054
+ const vectorLiteral = `[${embedding.join(",")}]`;
1055
+ await this.pool.query(
1056
+ `UPDATE agent_summaries SET embedding = $1 WHERE id = $2 AND agent_id = $3`,
1057
+ [vectorLiteral, summaryId, agentId]
1058
+ );
1059
+ }
1060
+ async searchByEmbedding(agentId, embedding, limit) {
1061
+ const vectorLiteral = `[${embedding.join(",")}]`;
1062
+ const result = await this.pool.query(
1063
+ `SELECT id, content, timestamp, message_range_from, message_range_to
1064
+ FROM agent_summaries
1065
+ WHERE agent_id = $1 AND embedding IS NOT NULL
1066
+ ORDER BY embedding <=> $2
1067
+ LIMIT $3`,
1068
+ [agentId, vectorLiteral, limit]
1069
+ );
1070
+ return result.rows.map((row) => ({
1071
+ id: row.id,
1072
+ content: row.content,
1073
+ timestamp: Number(row.timestamp),
1074
+ messageRange: {
1075
+ from: Number(row.message_range_from),
1076
+ to: Number(row.message_range_to)
1077
+ }
1078
+ }));
1079
+ }
1080
+ async close() {
1081
+ await this.pool.end();
1082
+ }
1083
+ };
1084
+
850
1085
  // src/memory.ts
851
1086
  var Memory = class {
852
1087
  store;
853
1088
  windowSize;
854
1089
  summarizeAfter;
855
1090
  model;
1091
+ embeddingAdapter;
856
1092
  messageCount = /* @__PURE__ */ new Map();
857
1093
  constructor(config = {}) {
858
1094
  this.windowSize = config.windowSize ?? 20;
859
1095
  this.summarizeAfter = config.summarizeAfter ?? 20;
1096
+ this.embeddingAdapter = config.embedding;
860
1097
  if (!config.store || config.store === "memory") {
861
1098
  this.store = new InMemoryStore();
862
1099
  } else if (config.store === "sqlite") {
863
1100
  this.store = new SQLiteStore(config.path ?? "./agent-memory.db");
1101
+ } else if (config.store === "postgres") {
1102
+ const connectionString = config.url ?? config.path;
1103
+ if (!connectionString) {
1104
+ throw new Error(
1105
+ "Memory store 'postgres' requires a connection string via the 'url' config option."
1106
+ );
1107
+ }
1108
+ this.store = new PostgresStore({ connectionString });
864
1109
  } else {
865
1110
  this.store = config.store;
866
1111
  }
@@ -882,7 +1127,13 @@ var Memory = class {
882
1127
  }
883
1128
  async getContext(agentId, query) {
884
1129
  const recentMessages = await this.store.getRecentMessages(agentId, this.windowSize);
885
- const relevantSummaries = await this.store.searchSummaries(agentId, query, 3);
1130
+ let relevantSummaries;
1131
+ if (this.embeddingAdapter && this.store.searchByEmbedding) {
1132
+ const queryEmbedding = await this.embeddingAdapter.embed(query);
1133
+ relevantSummaries = await this.store.searchByEmbedding(agentId, queryEmbedding, 3);
1134
+ } else {
1135
+ relevantSummaries = await this.store.searchSummaries(agentId, query, 3);
1136
+ }
886
1137
  return { recentMessages, relevantSummaries };
887
1138
  }
888
1139
  async summarize(agentId) {
@@ -905,6 +1156,10 @@ var Memory = class {
905
1156
  }
906
1157
  });
907
1158
  await this.store.saveSummary(agentId, summary);
1159
+ if (this.embeddingAdapter && this.store.saveEmbedding) {
1160
+ const embedding = await this.embeddingAdapter.embed(summary.content);
1161
+ await this.store.saveEmbedding(agentId, summary.id, embedding);
1162
+ }
908
1163
  }
909
1164
  close() {
910
1165
  if ("close" in this.store && typeof this.store.close === "function") {
@@ -912,6 +1167,36 @@ var Memory = class {
912
1167
  }
913
1168
  }
914
1169
  };
1170
+
1171
+ // src/model/ollama-embedding.ts
1172
+ var OllamaEmbeddingAdapter = class {
1173
+ baseURL;
1174
+ model;
1175
+ constructor(config = {}) {
1176
+ this.baseURL = config.baseURL ?? "http://localhost:11434";
1177
+ this.model = config.model ?? "nomic-embed-text";
1178
+ }
1179
+ async embed(text) {
1180
+ const [vector] = await this.request(text);
1181
+ return vector;
1182
+ }
1183
+ async embedBatch(texts) {
1184
+ if (texts.length === 0) return [];
1185
+ return this.request(texts);
1186
+ }
1187
+ async request(input) {
1188
+ const response = await fetch(`${this.baseURL}/api/embed`, {
1189
+ method: "POST",
1190
+ headers: { "Content-Type": "application/json" },
1191
+ body: JSON.stringify({ model: this.model, input })
1192
+ });
1193
+ if (!response.ok) {
1194
+ throw new Error(`Ollama embedding request failed: ${response.status} ${response.statusText}`);
1195
+ }
1196
+ const data = await response.json();
1197
+ return data.embeddings;
1198
+ }
1199
+ };
915
1200
  // Annotate the CommonJS export names for ESM import in node:
916
1201
  0 && (module.exports = {
917
1202
  Agent,
@@ -919,7 +1204,9 @@ var Memory = class {
919
1204
  InMemoryStore,
920
1205
  Memory,
921
1206
  MockAdapter,
1207
+ OllamaEmbeddingAdapter,
922
1208
  OpenAICompatibleAdapter,
1209
+ PostgresStore,
923
1210
  SQLiteStore,
924
1211
  Team,
925
1212
  Tool,