@waynesutton/agent-memory 0.0.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.
Files changed (201) hide show
  1. package/.claude/settings.json +9 -0
  2. package/.claude/settings.local.json +7 -0
  3. package/AGENTS.md +113 -0
  4. package/CLAUDE.md +79 -0
  5. package/README.md +1 -0
  6. package/dist/cli/index.d.ts +3 -0
  7. package/dist/cli/index.d.ts.map +1 -0
  8. package/dist/cli/index.js +192 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/cli/parsers/claude-code.d.ts +3 -0
  11. package/dist/cli/parsers/claude-code.d.ts.map +1 -0
  12. package/dist/cli/parsers/claude-code.js +75 -0
  13. package/dist/cli/parsers/claude-code.js.map +1 -0
  14. package/dist/cli/parsers/codex.d.ts +3 -0
  15. package/dist/cli/parsers/codex.d.ts.map +1 -0
  16. package/dist/cli/parsers/codex.js +42 -0
  17. package/dist/cli/parsers/codex.js.map +1 -0
  18. package/dist/cli/parsers/conductor.d.ts +3 -0
  19. package/dist/cli/parsers/conductor.d.ts.map +1 -0
  20. package/dist/cli/parsers/conductor.js +43 -0
  21. package/dist/cli/parsers/conductor.js.map +1 -0
  22. package/dist/cli/parsers/cursor.d.ts +3 -0
  23. package/dist/cli/parsers/cursor.d.ts.map +1 -0
  24. package/dist/cli/parsers/cursor.js +50 -0
  25. package/dist/cli/parsers/cursor.js.map +1 -0
  26. package/dist/cli/parsers/index.d.ts +12 -0
  27. package/dist/cli/parsers/index.d.ts.map +1 -0
  28. package/dist/cli/parsers/index.js +27 -0
  29. package/dist/cli/parsers/index.js.map +1 -0
  30. package/dist/cli/parsers/opencode.d.ts +3 -0
  31. package/dist/cli/parsers/opencode.d.ts.map +1 -0
  32. package/dist/cli/parsers/opencode.js +72 -0
  33. package/dist/cli/parsers/opencode.js.map +1 -0
  34. package/dist/cli/parsers/parsers.test.d.ts +2 -0
  35. package/dist/cli/parsers/parsers.test.d.ts.map +1 -0
  36. package/dist/cli/parsers/parsers.test.js +151 -0
  37. package/dist/cli/parsers/parsers.test.js.map +1 -0
  38. package/dist/cli/parsers/pi.d.ts +3 -0
  39. package/dist/cli/parsers/pi.d.ts.map +1 -0
  40. package/dist/cli/parsers/pi.js +43 -0
  41. package/dist/cli/parsers/pi.js.map +1 -0
  42. package/dist/cli/parsers/types.d.ts +25 -0
  43. package/dist/cli/parsers/types.d.ts.map +1 -0
  44. package/dist/cli/parsers/types.js +2 -0
  45. package/dist/cli/parsers/types.js.map +1 -0
  46. package/dist/cli/parsers/vscode-copilot.d.ts +3 -0
  47. package/dist/cli/parsers/vscode-copilot.d.ts.map +1 -0
  48. package/dist/cli/parsers/vscode-copilot.js +69 -0
  49. package/dist/cli/parsers/vscode-copilot.js.map +1 -0
  50. package/dist/cli/parsers/zed.d.ts +3 -0
  51. package/dist/cli/parsers/zed.d.ts.map +1 -0
  52. package/dist/cli/parsers/zed.js +43 -0
  53. package/dist/cli/parsers/zed.js.map +1 -0
  54. package/dist/cli/sync.d.ts +21 -0
  55. package/dist/cli/sync.d.ts.map +1 -0
  56. package/dist/cli/sync.js +78 -0
  57. package/dist/cli/sync.js.map +1 -0
  58. package/dist/cli/type-extractor.d.ts +25 -0
  59. package/dist/cli/type-extractor.d.ts.map +1 -0
  60. package/dist/cli/type-extractor.js +254 -0
  61. package/dist/cli/type-extractor.js.map +1 -0
  62. package/dist/cli/type-extractor.test.d.ts +2 -0
  63. package/dist/cli/type-extractor.test.d.ts.map +1 -0
  64. package/dist/cli/type-extractor.test.js +173 -0
  65. package/dist/cli/type-extractor.test.js.map +1 -0
  66. package/dist/client/http.d.ts +44 -0
  67. package/dist/client/http.d.ts.map +1 -0
  68. package/dist/client/http.js +311 -0
  69. package/dist/client/http.js.map +1 -0
  70. package/dist/client/index.d.ts +158 -0
  71. package/dist/client/index.d.ts.map +1 -0
  72. package/dist/client/index.js +256 -0
  73. package/dist/client/index.js.map +1 -0
  74. package/dist/component/_generated/api.d.ts +12 -0
  75. package/dist/component/_generated/api.d.ts.map +1 -0
  76. package/dist/component/_generated/api.js +13 -0
  77. package/dist/component/_generated/api.js.map +1 -0
  78. package/dist/component/_generated/dataModel.d.ts +18 -0
  79. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  80. package/dist/component/_generated/dataModel.js +11 -0
  81. package/dist/component/_generated/dataModel.js.map +1 -0
  82. package/dist/component/_generated/server.d.ts +42 -0
  83. package/dist/component/_generated/server.d.ts.map +1 -0
  84. package/dist/component/_generated/server.js +39 -0
  85. package/dist/component/_generated/server.js.map +1 -0
  86. package/dist/component/actions.d.ts +42 -0
  87. package/dist/component/actions.d.ts.map +1 -0
  88. package/dist/component/actions.js +405 -0
  89. package/dist/component/actions.js.map +1 -0
  90. package/dist/component/apiKeyMutations.d.ts +29 -0
  91. package/dist/component/apiKeyMutations.d.ts.map +1 -0
  92. package/dist/component/apiKeyMutations.js +149 -0
  93. package/dist/component/apiKeyMutations.js.map +1 -0
  94. package/dist/component/apiKeyQueries.d.ts +37 -0
  95. package/dist/component/apiKeyQueries.d.ts.map +1 -0
  96. package/dist/component/apiKeyQueries.js +127 -0
  97. package/dist/component/apiKeyQueries.js.map +1 -0
  98. package/dist/component/checksum.d.ts +6 -0
  99. package/dist/component/checksum.d.ts.map +1 -0
  100. package/dist/component/checksum.js +14 -0
  101. package/dist/component/checksum.js.map +1 -0
  102. package/dist/component/checksum.test.d.ts +2 -0
  103. package/dist/component/checksum.test.d.ts.map +1 -0
  104. package/dist/component/checksum.test.js +27 -0
  105. package/dist/component/checksum.test.js.map +1 -0
  106. package/dist/component/convex.config.d.ts +3 -0
  107. package/dist/component/convex.config.d.ts.map +1 -0
  108. package/dist/component/convex.config.js +4 -0
  109. package/dist/component/convex.config.js.map +1 -0
  110. package/dist/component/cronActions.d.ts +3 -0
  111. package/dist/component/cronActions.d.ts.map +1 -0
  112. package/dist/component/cronActions.js +38 -0
  113. package/dist/component/cronActions.js.map +1 -0
  114. package/dist/component/cronQueries.d.ts +6 -0
  115. package/dist/component/cronQueries.d.ts.map +1 -0
  116. package/dist/component/cronQueries.js +38 -0
  117. package/dist/component/cronQueries.js.map +1 -0
  118. package/dist/component/crons.d.ts +3 -0
  119. package/dist/component/crons.d.ts.map +1 -0
  120. package/dist/component/crons.js +18 -0
  121. package/dist/component/crons.js.map +1 -0
  122. package/dist/component/format.d.ts +11 -0
  123. package/dist/component/format.d.ts.map +1 -0
  124. package/dist/component/format.js +175 -0
  125. package/dist/component/format.js.map +1 -0
  126. package/dist/component/format.test.d.ts +2 -0
  127. package/dist/component/format.test.d.ts.map +1 -0
  128. package/dist/component/format.test.js +118 -0
  129. package/dist/component/format.test.js.map +1 -0
  130. package/dist/component/mutations.d.ts +158 -0
  131. package/dist/component/mutations.d.ts.map +1 -0
  132. package/dist/component/mutations.js +745 -0
  133. package/dist/component/mutations.js.map +1 -0
  134. package/dist/component/queries.d.ts +94 -0
  135. package/dist/component/queries.d.ts.map +1 -0
  136. package/dist/component/queries.js +574 -0
  137. package/dist/component/queries.js.map +1 -0
  138. package/dist/component/schema.d.ts +278 -0
  139. package/dist/component/schema.d.ts.map +1 -0
  140. package/dist/component/schema.js +161 -0
  141. package/dist/component/schema.js.map +1 -0
  142. package/dist/mcp/server.d.ts +11 -0
  143. package/dist/mcp/server.d.ts.map +1 -0
  144. package/dist/mcp/server.js +571 -0
  145. package/dist/mcp/server.js.map +1 -0
  146. package/dist/shared.d.ts +126 -0
  147. package/dist/shared.d.ts.map +1 -0
  148. package/dist/shared.js +67 -0
  149. package/dist/shared.js.map +1 -0
  150. package/dist/test.d.ts +23 -0
  151. package/dist/test.d.ts.map +1 -0
  152. package/dist/test.js +21 -0
  153. package/dist/test.js.map +1 -0
  154. package/eslint.config.js +15 -0
  155. package/example/convex/convex.config.ts +7 -0
  156. package/example/convex/memory.ts +129 -0
  157. package/llms.md +175 -0
  158. package/llms.txt +126 -0
  159. package/package.json +72 -0
  160. package/prds/API-REFERENCE.md +935 -0
  161. package/prds/README.md +988 -0
  162. package/prds/SETUP.md +682 -0
  163. package/src/cli/index.ts +254 -0
  164. package/src/cli/parsers/claude-code.ts +80 -0
  165. package/src/cli/parsers/codex.ts +45 -0
  166. package/src/cli/parsers/conductor.ts +47 -0
  167. package/src/cli/parsers/cursor.ts +55 -0
  168. package/src/cli/parsers/index.ts +30 -0
  169. package/src/cli/parsers/opencode.ts +84 -0
  170. package/src/cli/parsers/parsers.test.ts +201 -0
  171. package/src/cli/parsers/pi.ts +47 -0
  172. package/src/cli/parsers/types.ts +26 -0
  173. package/src/cli/parsers/vscode-copilot.ts +78 -0
  174. package/src/cli/parsers/zed.ts +47 -0
  175. package/src/cli/sync.ts +110 -0
  176. package/src/cli/type-extractor.test.ts +241 -0
  177. package/src/cli/type-extractor.ts +331 -0
  178. package/src/client/http.ts +415 -0
  179. package/src/client/index.ts +519 -0
  180. package/src/component/_generated/api.ts +14 -0
  181. package/src/component/_generated/dataModel.ts +20 -0
  182. package/src/component/_generated/server.ts +64 -0
  183. package/src/component/actions.ts +558 -0
  184. package/src/component/apiKeyMutations.ts +175 -0
  185. package/src/component/apiKeyQueries.ts +156 -0
  186. package/src/component/checksum.test.ts +31 -0
  187. package/src/component/checksum.ts +13 -0
  188. package/src/component/convex.config.ts +5 -0
  189. package/src/component/cronActions.ts +52 -0
  190. package/src/component/cronQueries.ts +42 -0
  191. package/src/component/crons.ts +34 -0
  192. package/src/component/format.test.ts +133 -0
  193. package/src/component/format.ts +232 -0
  194. package/src/component/mutations.ts +824 -0
  195. package/src/component/queries.ts +684 -0
  196. package/src/component/schema.ts +207 -0
  197. package/src/mcp/server.ts +695 -0
  198. package/src/shared.ts +251 -0
  199. package/src/test.ts +32 -0
  200. package/tsconfig.json +21 -0
  201. package/vitest.config.ts +8 -0
package/prds/SETUP.md ADDED
@@ -0,0 +1,682 @@
1
+ # Setup Guide — @waynesutton/agent-memory
2
+
3
+ Step-by-step instructions for every integration path.
4
+
5
+ ---
6
+
7
+ ## Prerequisites
8
+
9
+ - Node.js 18+
10
+ - A Convex account and project ([convex.dev](https://convex.dev))
11
+ - `CONVEX_URL` from your Convex dashboard
12
+
13
+ ---
14
+
15
+ ## Path A: Add to an Existing Convex App
16
+
17
+ ### Step 1 — Install
18
+
19
+ ```bash
20
+ npm install @waynesutton/agent-memory
21
+ ```
22
+
23
+ Make sure you already have `convex` and `convex-helpers` installed:
24
+
25
+ ```bash
26
+ npm install convex convex-helpers
27
+ ```
28
+
29
+ ### Step 2 — Register the Component
30
+
31
+ Edit your `convex/convex.config.ts`:
32
+
33
+ ```typescript
34
+ import { defineApp } from "convex/server";
35
+ import agentMemory from "@waynesutton/agent-memory/convex.config.js";
36
+
37
+ const app = defineApp();
38
+ app.use(agentMemory);
39
+ export default app;
40
+ ```
41
+
42
+ ### Step 3 — Create Memory Functions
43
+
44
+ Create `convex/memory.ts`:
45
+
46
+ ```typescript
47
+ import { v } from "convex/values";
48
+ import { query, mutation, action } from "./_generated/server.js";
49
+ import { components } from "./_generated/api.js";
50
+ import { AgentMemory } from "@waynesutton/agent-memory";
51
+
52
+ const memory = new AgentMemory(components.agentMemory, {
53
+ projectId: "my-project",
54
+ agentId: "my-app", // optional: identifies this agent
55
+ llmApiKey: process.env.OPENAI_API_KEY, // optional: enables intelligent ingest
56
+ });
57
+
58
+ // Save a memory
59
+ export const remember = mutation({
60
+ args: {
61
+ title: v.string(),
62
+ content: v.string(),
63
+ memoryType: v.union(
64
+ v.literal("instruction"),
65
+ v.literal("learning"),
66
+ v.literal("reference"),
67
+ v.literal("feedback"),
68
+ v.literal("journal"),
69
+ ),
70
+ tags: v.optional(v.array(v.string())),
71
+ priority: v.optional(v.float64()),
72
+ },
73
+ returns: v.string(),
74
+ handler: async (ctx, args) => memory.remember(ctx, args),
75
+ });
76
+
77
+ // Search memories
78
+ export const recall = query({
79
+ args: { q: v.string() },
80
+ returns: v.any(),
81
+ handler: async (ctx, args) => memory.search(ctx, args.q),
82
+ });
83
+
84
+ // List all memories
85
+ export const listAll = query({
86
+ args: {},
87
+ returns: v.any(),
88
+ handler: async (ctx) => memory.list(ctx),
89
+ });
90
+
91
+ // Archive a memory
92
+ export const forget = mutation({
93
+ args: { memoryId: v.string() },
94
+ returns: v.null(),
95
+ handler: async (ctx, args) => {
96
+ await memory.forget(ctx, args.memoryId);
97
+ return null;
98
+ },
99
+ });
100
+
101
+ // Get context bundle for agent sessions
102
+ export const getContext = query({
103
+ args: {
104
+ activePaths: v.optional(v.array(v.string())),
105
+ },
106
+ returns: v.any(),
107
+ handler: async (ctx, args) =>
108
+ memory.getContextBundle(ctx, { activePaths: args.activePaths }),
109
+ });
110
+
111
+ // View change history
112
+ export const memoryHistory = query({
113
+ args: { memoryId: v.string() },
114
+ returns: v.any(),
115
+ handler: async (ctx, args) => memory.history(ctx, args.memoryId),
116
+ });
117
+
118
+ // Rate a memory
119
+ export const rateFeedback = mutation({
120
+ args: {
121
+ memoryId: v.string(),
122
+ sentiment: v.union(
123
+ v.literal("positive"),
124
+ v.literal("negative"),
125
+ v.literal("very_negative"),
126
+ ),
127
+ comment: v.optional(v.string()),
128
+ },
129
+ returns: v.null(),
130
+ handler: async (ctx, args) => {
131
+ await memory.addFeedback(ctx, args.memoryId, args.sentiment, {
132
+ comment: args.comment,
133
+ });
134
+ return null;
135
+ },
136
+ });
137
+
138
+ // Intelligently ingest raw text
139
+ export const ingest = action({
140
+ args: { content: v.string() },
141
+ returns: v.any(),
142
+ handler: async (ctx, args) => memory.ingest(ctx, args.content),
143
+ });
144
+ ```
145
+
146
+ ### Step 4 — Deploy
147
+
148
+ ```bash
149
+ npx convex dev
150
+ ```
151
+
152
+ Your memories table is now live. Use the Convex dashboard to verify.
153
+
154
+ ---
155
+
156
+ ## Path B: CLI-Only (Sync Local Files)
157
+
158
+ Use the CLI to push/pull memory files without writing any Convex code.
159
+
160
+ ### Step 1 — Install Globally (or use npx)
161
+
162
+ ```bash
163
+ npm install -g @waynesutton/agent-memory
164
+ ```
165
+
166
+ ### Step 2 — Set Your Convex URL
167
+
168
+ ```bash
169
+ export CONVEX_URL="https://your-deployment.convex.cloud"
170
+ ```
171
+
172
+ Get this from your Convex dashboard under "Settings" > "URL & Deploy Key".
173
+
174
+ ### Step 3 — Initialize
175
+
176
+ ```bash
177
+ cd /path/to/your/project
178
+ npx agent-memory init --project my-project --name "My Project"
179
+ ```
180
+
181
+ This detects which tools are present (Claude Code, Cursor, etc.) and registers the project.
182
+
183
+ ### Step 4 — Push Local Memories
184
+
185
+ ```bash
186
+ npx agent-memory push --project my-project
187
+ ```
188
+
189
+ This reads all detected tool files (`.claude/rules/`, `.cursor/rules/`, `AGENTS.md`, etc.) and uploads them to Convex.
190
+
191
+ ### Step 5 — Pull to Another Tool
192
+
193
+ ```bash
194
+ # Pull as Cursor rules
195
+ npx agent-memory pull --project my-project --format cursor
196
+
197
+ # Pull as Claude Code rules
198
+ npx agent-memory pull --project my-project --format claude-code
199
+
200
+ # Pull as AGENTS.md (OpenCode/Codex)
201
+ npx agent-memory pull --project my-project --format opencode
202
+ ```
203
+
204
+ ---
205
+
206
+ ## Path C: MCP Server for AI Agents
207
+
208
+ ### Step 1 — Configure for Claude Code
209
+
210
+ Add to `.claude/settings.json` in your project:
211
+
212
+ ```json
213
+ {
214
+ "mcpServers": {
215
+ "agent-memory": {
216
+ "command": "npx",
217
+ "args": ["agent-memory", "mcp", "--project", "my-project"],
218
+ "env": {
219
+ "CONVEX_URL": "https://your-deployment.convex.cloud"
220
+ }
221
+ }
222
+ }
223
+ }
224
+ ```
225
+
226
+ ### Step 2 — Configure for Cursor
227
+
228
+ Add to `.cursor/mcp.json` in your project:
229
+
230
+ ```json
231
+ {
232
+ "mcpServers": {
233
+ "agent-memory": {
234
+ "command": "npx",
235
+ "args": ["agent-memory", "mcp", "--project", "my-project"],
236
+ "env": {
237
+ "CONVEX_URL": "https://your-deployment.convex.cloud"
238
+ }
239
+ }
240
+ }
241
+ }
242
+ ```
243
+
244
+ ### Step 3 — Verify
245
+
246
+ Once configured, your AI agent will have access to 14 tools:
247
+
248
+ - `memory_remember` — save a new memory (with agent/session scoping)
249
+ - `memory_recall` — search by keyword
250
+ - `memory_semantic_recall` — search by meaning (if embedding key provided)
251
+ - `memory_list` — list memories with filters (agent, session, source, tags)
252
+ - `memory_context` — get context bundle
253
+ - `memory_forget` — archive a memory
254
+ - `memory_restore` — restore an archived memory
255
+ - `memory_update` — update a memory
256
+ - `memory_history` — view change audit trail
257
+ - `memory_feedback` — rate a memory as helpful/unhelpful
258
+ - `memory_relate` — create relationship between memories
259
+ - `memory_relations` — view memory graph connections
260
+ - `memory_batch_archive` — archive multiple memories
261
+ - `memory_ingest` — intelligently extract memories from raw text
262
+
263
+ ### Step 4 (Optional) — Enable Vector Search
264
+
265
+ ```json
266
+ {
267
+ "mcpServers": {
268
+ "agent-memory": {
269
+ "command": "npx",
270
+ "args": [
271
+ "agent-memory", "mcp",
272
+ "--project", "my-project",
273
+ "--embedding-api-key", "${env:OPENAI_API_KEY}"
274
+ ],
275
+ "env": {
276
+ "CONVEX_URL": "${env:CONVEX_URL}",
277
+ "OPENAI_API_KEY": "${env:OPENAI_API_KEY}"
278
+ }
279
+ }
280
+ }
281
+ }
282
+ ```
283
+
284
+ ### Step 5 (Optional) — Enable Intelligent Ingest
285
+
286
+ ```json
287
+ {
288
+ "mcpServers": {
289
+ "agent-memory": {
290
+ "command": "npx",
291
+ "args": [
292
+ "agent-memory", "mcp",
293
+ "--project", "my-project",
294
+ "--llm-api-key", "${env:OPENAI_API_KEY}"
295
+ ],
296
+ "env": {
297
+ "CONVEX_URL": "${env:CONVEX_URL}",
298
+ "OPENAI_API_KEY": "${env:OPENAI_API_KEY}"
299
+ }
300
+ }
301
+ }
302
+ }
303
+ ```
304
+
305
+ ### Step 6 (Optional) — Read-Only Mode
306
+
307
+ For agents that should only read, not write:
308
+
309
+ ```json
310
+ {
311
+ "mcpServers": {
312
+ "agent-memory": {
313
+ "command": "npx",
314
+ "args": ["agent-memory", "mcp", "--project", "my-project", "--read-only"],
315
+ "env": {
316
+ "CONVEX_URL": "${env:CONVEX_URL}"
317
+ }
318
+ }
319
+ }
320
+ }
321
+ ```
322
+
323
+ ---
324
+
325
+ ## Path D: Auto-Sync with Hooks
326
+
327
+ ### Claude Code — Sync on Session Start/End
328
+
329
+ Add to `.claude/settings.json`:
330
+
331
+ ```json
332
+ {
333
+ "hooks": {
334
+ "SessionStart": [{
335
+ "hooks": [{
336
+ "type": "command",
337
+ "command": "CONVEX_URL=https://your-deployment.convex.cloud npx agent-memory pull --format claude-code --project my-project"
338
+ }]
339
+ }],
340
+ "SessionEnd": [{
341
+ "hooks": [{
342
+ "type": "command",
343
+ "command": "CONVEX_URL=https://your-deployment.convex.cloud npx agent-memory push --format claude-code --project my-project"
344
+ }]
345
+ }]
346
+ }
347
+ }
348
+ ```
349
+
350
+ This ensures:
351
+ - Session starts with latest memories from the cloud
352
+ - Session ends by pushing any new learnings back
353
+
354
+ ---
355
+
356
+ ## Path E: Using with @convex-dev/agent
357
+
358
+ If your app uses `@convex-dev/agent` for AI agent threads, you can load memories as system prompts:
359
+
360
+ ```typescript
361
+ // convex/convex.config.ts
362
+ import { defineApp } from "convex/server";
363
+ import agentMemory from "@waynesutton/agent-memory/convex.config.js";
364
+ import agent from "@convex-dev/agent/convex.config.js";
365
+
366
+ const app = defineApp();
367
+ app.use(agentMemory);
368
+ app.use(agent);
369
+ export default app;
370
+ ```
371
+
372
+ ```typescript
373
+ // convex/ai.ts
374
+ import { action } from "./_generated/server.js";
375
+ import { components } from "./_generated/api.js";
376
+ import { AgentMemory } from "@waynesutton/agent-memory";
377
+ import { Agent } from "@convex-dev/agent";
378
+ import { v } from "convex/values";
379
+
380
+ const memory = new AgentMemory(components.agentMemory, {
381
+ projectId: "my-app",
382
+ agentId: "my-ai-agent",
383
+ });
384
+
385
+ const myAgent = new Agent(components.agent, {
386
+ model: "claude-sonnet-4-6",
387
+ });
388
+
389
+ export const chat = action({
390
+ args: { message: v.string(), threadId: v.optional(v.string()) },
391
+ returns: v.any(),
392
+ handler: async (ctx, args) => {
393
+ // Load relevant memories (feedback-boosted priority scoring)
394
+ const bundle = await memory.getContextBundle(ctx, {
395
+ activePaths: [], // or pass relevant file paths
396
+ });
397
+
398
+ // Build system prompt from memories
399
+ const memoryPrompt = bundle.pinned
400
+ .map((m) => `## ${m.title}\n${m.content}`)
401
+ .join("\n\n---\n\n");
402
+
403
+ // Use agent with memory-augmented instructions
404
+ const thread = await myAgent.createThread(ctx, {
405
+ systemPrompt: `You are a helpful coding assistant.\n\n# Project Knowledge\n\n${memoryPrompt}`,
406
+ });
407
+
408
+ const result = await myAgent.chat(ctx, {
409
+ threadId: thread._id,
410
+ message: args.message,
411
+ });
412
+
413
+ return result;
414
+ },
415
+ });
416
+ ```
417
+
418
+ ---
419
+
420
+ ## Path F: Enable Relevance Decay
421
+
422
+ For projects with many memories, enable automatic relevance decay so stale memories don't dominate context bundles.
423
+
424
+ ### Step 1 — Update Project Settings
425
+
426
+ ```typescript
427
+ // In a mutation or action context
428
+ await ctx.runMutation(components.agentMemory.mutations.upsertProject, {
429
+ projectId: "my-app",
430
+ name: "My App",
431
+ settings: {
432
+ autoSync: false,
433
+ syncFormats: [],
434
+ decayEnabled: true,
435
+ decayHalfLifeDays: 30, // priority halves every 30 days of no access
436
+ },
437
+ });
438
+ ```
439
+
440
+ ### Step 2 — That's It
441
+
442
+ The component runs a daily cron job at 3 AM UTC that:
443
+ 1. Finds all non-pinned memories in decay-enabled projects
444
+ 2. Reduces priority for memories with low access and old `lastAccessedAt`
445
+ 3. Pinned memories (priority >= 0.8) are never decayed
446
+
447
+ Access tracking happens automatically when you use `recordAccess()` or when the `getContextBundle` query returns memories.
448
+
449
+ ---
450
+
451
+ ## Path G: Custom Ingest Prompts
452
+
453
+ Customize how the intelligent ingest pipeline extracts and deduplicates memories.
454
+
455
+ ### Per-Project (persistent)
456
+
457
+ ```typescript
458
+ await ctx.runMutation(components.agentMemory.mutations.upsertProject, {
459
+ projectId: "my-app",
460
+ name: "My App",
461
+ settings: {
462
+ autoSync: false,
463
+ syncFormats: [],
464
+ factExtractionPrompt: `Extract only coding conventions, architecture decisions,
465
+ and user preferences. Ignore greetings and ephemeral discussion.`,
466
+ updateDecisionPrompt: `When a new fact contradicts an existing memory,
467
+ always UPDATE the existing memory with the newer information.
468
+ Never create duplicates.`,
469
+ },
470
+ });
471
+ ```
472
+
473
+ ### Per-Call (one-time)
474
+
475
+ ```typescript
476
+ const result = await memory.ingest(ctx, rawText, {
477
+ customExtractionPrompt: "Extract only security-related decisions...",
478
+ customUpdatePrompt: "Be very conservative — only ADD if truly novel...",
479
+ });
480
+ ```
481
+
482
+ ---
483
+
484
+ ## Path H: Read-Only HTTP API
485
+
486
+ Expose memories as REST endpoints for dashboards, CI/CD pipelines, and external integrations.
487
+
488
+ ### Step 1 — Create API Keys
489
+
490
+ Add a mutation to your app that creates API keys behind your own auth:
491
+
492
+ ```typescript
493
+ // convex/memory.ts
494
+ import { AgentMemory } from "@waynesutton/agent-memory";
495
+ import { mutation } from "./_generated/server.js";
496
+ import { components } from "./_generated/api.js";
497
+
498
+ const memory = new AgentMemory(components.agentMemory, {
499
+ projectId: "my-project",
500
+ });
501
+
502
+ export const createApiKey = mutation({
503
+ args: {},
504
+ handler: async (ctx) => {
505
+ const identity = await ctx.auth.getUserIdentity();
506
+ if (!identity) throw new Error("Not authenticated");
507
+
508
+ return await memory.createApiKey(ctx, {
509
+ name: "Dashboard read key",
510
+ permissions: ["list", "search", "context"],
511
+ // Optional: custom rate limit
512
+ // rateLimitOverride: { requestsPerWindow: 200, windowMs: 60000 },
513
+ // Optional: key expiry
514
+ // expiresAt: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 days
515
+ });
516
+ // Returns: { key: "am_<40chars>", keyHash: "..." }
517
+ // ⚠️ The plaintext key is only returned once — store it securely!
518
+ },
519
+ });
520
+ ```
521
+
522
+ ### Step 2 — Mount the HTTP Router
523
+
524
+ ```typescript
525
+ // convex/http.ts
526
+ import { httpRouter } from "convex/server";
527
+ import { MemoryHttpApi } from "@waynesutton/agent-memory/http";
528
+ import { components } from "./_generated/api";
529
+
530
+ const http = httpRouter();
531
+
532
+ const memoryApi = new MemoryHttpApi(components.agentMemory, {
533
+ corsOrigins: ["https://myapp.com"], // optional, defaults to ["*"]
534
+ });
535
+ memoryApi.mount(http, "/api/memory");
536
+
537
+ export default http;
538
+ ```
539
+
540
+ ### Step 3 — Deploy
541
+
542
+ ```bash
543
+ npx convex dev
544
+ ```
545
+
546
+ ### Step 4 — Use the API
547
+
548
+ ```bash
549
+ # List memories
550
+ curl -H "Authorization: Bearer am_<your-key>" \
551
+ https://your-deployment.convex.cloud/api/memory/list
552
+
553
+ # Search
554
+ curl -H "Authorization: Bearer am_<your-key>" \
555
+ "https://your-deployment.convex.cloud/api/memory/search?q=API+conventions"
556
+
557
+ # Get context bundle
558
+ curl -H "Authorization: Bearer am_<your-key>" \
559
+ https://your-deployment.convex.cloud/api/memory/context
560
+
561
+ # Export as Cursor format
562
+ curl -H "Authorization: Bearer am_<your-key>" \
563
+ "https://your-deployment.convex.cloud/api/memory/export?format=cursor"
564
+ ```
565
+
566
+ ### Available Endpoints
567
+
568
+ | Path | Permission | Description |
569
+ |------|------------|-------------|
570
+ | `/list` | `list` | List memories with query param filters |
571
+ | `/get?id=<memoryId>` | `get` | Get a single memory |
572
+ | `/search?q=<query>` | `search` | Full-text search |
573
+ | `/context` | `context` | Progressive context bundle |
574
+ | `/export?format=<format>` | `export` | Export in tool format |
575
+ | `/history?id=<memoryId>` | `history` | Memory audit trail |
576
+ | `/relations?id=<memoryId>` | `relations` | Memory graph connections |
577
+
578
+ ### Available Permissions
579
+
580
+ `list`, `get`, `search`, `context`, `export`, `history`, `relations`
581
+
582
+ ### Rate Limiting
583
+
584
+ - Default: 100 requests per 60 seconds
585
+ - Configurable per-key or per-project
586
+ - Returns `429` with `retryAfterMs` when exceeded
587
+ - Self-contained (no external dependency)
588
+
589
+ ### Managing Keys
590
+
591
+ ```typescript
592
+ // List keys (never exposes plaintext)
593
+ const keys = await memory.listApiKeys(ctx);
594
+
595
+ // Revoke a key
596
+ await memory.revokeApiKey(ctx, keyHash);
597
+ ```
598
+
599
+ ---
600
+
601
+ ## Verifying Your Setup
602
+
603
+ ### Check Convex Dashboard
604
+
605
+ After deploying, go to your Convex dashboard. You should see the component's tables under the `agentMemory` namespace:
606
+ - `agentMemory:memories`
607
+ - `agentMemory:embeddings`
608
+ - `agentMemory:projects`
609
+ - `agentMemory:syncLog`
610
+ - `agentMemory:memoryHistory`
611
+ - `agentMemory:memoryFeedback`
612
+ - `agentMemory:memoryRelations`
613
+
614
+ ### CLI Verification
615
+
616
+ ```bash
617
+ # List memories (should be empty initially)
618
+ npx agent-memory list --project my-project
619
+
620
+ # If you have .claude/rules/ or .cursor/rules/ files, push them
621
+ npx agent-memory push --project my-project
622
+
623
+ # List again to see uploaded memories
624
+ npx agent-memory list --project my-project
625
+
626
+ # Search
627
+ npx agent-memory search "your search term" --project my-project
628
+ ```
629
+
630
+ ### MCP Verification
631
+
632
+ ```bash
633
+ # Start the MCP server manually to test
634
+ CONVEX_URL=https://your-deployment.convex.cloud npx agent-memory mcp --project my-project
635
+ ```
636
+
637
+ If it starts without errors, you'll see:
638
+ ```
639
+ agent-memory MCP server running for project "my-project"
640
+ ```
641
+
642
+ ---
643
+
644
+ ## Troubleshooting
645
+
646
+ ### "CONVEX_URL environment variable is required"
647
+
648
+ Set your deployment URL:
649
+ ```bash
650
+ export CONVEX_URL="https://your-deployment.convex.cloud"
651
+ ```
652
+
653
+ ### "Cannot find module '@waynesutton/agent-memory'"
654
+
655
+ Make sure you installed the package:
656
+ ```bash
657
+ npm install @waynesutton/agent-memory
658
+ ```
659
+
660
+ ### MCP server not showing tools in Claude Code
661
+
662
+ 1. Check `.claude/settings.json` is valid JSON
663
+ 2. Verify `CONVEX_URL` is set in the `env` block
664
+ 3. Restart Claude Code after changing MCP config
665
+
666
+ ### No memories found after push
667
+
668
+ 1. Check the project ID matches between push and list
669
+ 2. Verify the Convex dashboard shows data in `agentMemory:memories`
670
+ 3. Make sure you have actual tool files (`.claude/rules/*.md`, etc.) in your directory
671
+
672
+ ### Ingest not working
673
+
674
+ 1. Ensure `--llm-api-key` is passed to the MCP server or `llmApiKey` is set in config
675
+ 2. Check your API key is valid and has access to the specified model
676
+ 3. The default model is `gpt-4.1-nano` — change with `--llm-model` if needed
677
+
678
+ ### Relevance decay not running
679
+
680
+ 1. Verify decay is enabled in project settings (`decayEnabled: true`)
681
+ 2. The cron runs daily at 3 AM UTC — check the Convex dashboard cron jobs view
682
+ 3. Pinned memories (priority >= 0.8) are intentionally excluded from decay