@agentmemory/agentmemory 0.7.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 (259) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/.github/workflows/ci.yml +22 -0
  3. package/.github/workflows/publish.yml +28 -0
  4. package/AGENTS.md +113 -0
  5. package/LICENSE +190 -0
  6. package/README.md +828 -0
  7. package/assets/banner.png +0 -0
  8. package/assets/demo.gif +0 -0
  9. package/assets/demo.mp4 +0 -0
  10. package/benchmark/QUALITY.md +73 -0
  11. package/benchmark/REAL-EMBEDDINGS.md +67 -0
  12. package/benchmark/SCALE.md +110 -0
  13. package/benchmark/dataset.ts +293 -0
  14. package/benchmark/quality-eval.ts +643 -0
  15. package/benchmark/real-embeddings-eval.ts +405 -0
  16. package/benchmark/scale-eval.ts +398 -0
  17. package/dist/cli.d.mts +1 -0
  18. package/dist/cli.mjs +137 -0
  19. package/dist/cli.mjs.map +1 -0
  20. package/dist/docker-compose.yml +14 -0
  21. package/dist/hooks/notification.d.mts +1 -0
  22. package/dist/hooks/notification.mjs +45 -0
  23. package/dist/hooks/notification.mjs.map +1 -0
  24. package/dist/hooks/post-tool-failure.d.mts +1 -0
  25. package/dist/hooks/post-tool-failure.mjs +45 -0
  26. package/dist/hooks/post-tool-failure.mjs.map +1 -0
  27. package/dist/hooks/post-tool-use.d.mts +1 -0
  28. package/dist/hooks/post-tool-use.mjs +53 -0
  29. package/dist/hooks/post-tool-use.mjs.map +1 -0
  30. package/dist/hooks/pre-compact.d.mts +1 -0
  31. package/dist/hooks/pre-compact.mjs +50 -0
  32. package/dist/hooks/pre-compact.mjs.map +1 -0
  33. package/dist/hooks/pre-tool-use.d.mts +1 -0
  34. package/dist/hooks/pre-tool-use.mjs +69 -0
  35. package/dist/hooks/pre-tool-use.mjs.map +1 -0
  36. package/dist/hooks/prompt-submit.d.mts +1 -0
  37. package/dist/hooks/prompt-submit.mjs +40 -0
  38. package/dist/hooks/prompt-submit.mjs.map +1 -0
  39. package/dist/hooks/session-end.d.mts +1 -0
  40. package/dist/hooks/session-end.mjs +61 -0
  41. package/dist/hooks/session-end.mjs.map +1 -0
  42. package/dist/hooks/session-start.d.mts +1 -0
  43. package/dist/hooks/session-start.mjs +42 -0
  44. package/dist/hooks/session-start.mjs.map +1 -0
  45. package/dist/hooks/stop.d.mts +1 -0
  46. package/dist/hooks/stop.mjs +33 -0
  47. package/dist/hooks/stop.mjs.map +1 -0
  48. package/dist/hooks/subagent-start.d.mts +1 -0
  49. package/dist/hooks/subagent-start.mjs +43 -0
  50. package/dist/hooks/subagent-start.mjs.map +1 -0
  51. package/dist/hooks/subagent-stop.d.mts +1 -0
  52. package/dist/hooks/subagent-stop.mjs +45 -0
  53. package/dist/hooks/subagent-stop.mjs.map +1 -0
  54. package/dist/hooks/task-completed.d.mts +1 -0
  55. package/dist/hooks/task-completed.mjs +46 -0
  56. package/dist/hooks/task-completed.mjs.map +1 -0
  57. package/dist/iii-config.yaml +51 -0
  58. package/dist/index.d.mts +2 -0
  59. package/dist/index.mjs +13776 -0
  60. package/dist/index.mjs.map +1 -0
  61. package/dist/src-QxitMPfJ.mjs +13775 -0
  62. package/dist/src-QxitMPfJ.mjs.map +1 -0
  63. package/dist/standalone.d.mts +1 -0
  64. package/dist/standalone.mjs +1155 -0
  65. package/dist/standalone.mjs.map +1 -0
  66. package/dist/transformers-BX_tgxdO.mjs +38684 -0
  67. package/dist/transformers-BX_tgxdO.mjs.map +1 -0
  68. package/dist/transformers-KMm1i9no.mjs +38683 -0
  69. package/dist/transformers-KMm1i9no.mjs.map +1 -0
  70. package/docker-compose.yml +14 -0
  71. package/iii-config.yaml +51 -0
  72. package/package.json +59 -0
  73. package/plugin/.claude-plugin/plugin.json +10 -0
  74. package/plugin/hooks/hooks.json +77 -0
  75. package/plugin/scripts/diagnostics.mjs +551 -0
  76. package/plugin/scripts/notification.mjs +45 -0
  77. package/plugin/scripts/post-tool-failure.mjs +45 -0
  78. package/plugin/scripts/post-tool-use.mjs +53 -0
  79. package/plugin/scripts/pre-compact.mjs +50 -0
  80. package/plugin/scripts/pre-tool-use.mjs +69 -0
  81. package/plugin/scripts/prompt-submit.mjs +40 -0
  82. package/plugin/scripts/session-end.mjs +61 -0
  83. package/plugin/scripts/session-start.mjs +42 -0
  84. package/plugin/scripts/stop.mjs +33 -0
  85. package/plugin/scripts/subagent-start.mjs +43 -0
  86. package/plugin/scripts/subagent-stop.mjs +45 -0
  87. package/plugin/scripts/task-completed.mjs +46 -0
  88. package/plugin/skills/forget/SKILL.md +32 -0
  89. package/plugin/skills/recall/SKILL.md +18 -0
  90. package/plugin/skills/remember/SKILL.md +25 -0
  91. package/plugin/skills/session-history/SKILL.md +17 -0
  92. package/src/auth.ts +12 -0
  93. package/src/cli.ts +159 -0
  94. package/src/config.ts +221 -0
  95. package/src/eval/metrics-store.ts +65 -0
  96. package/src/eval/quality.ts +51 -0
  97. package/src/eval/schemas.ts +124 -0
  98. package/src/eval/self-correct.ts +28 -0
  99. package/src/eval/validator.ts +31 -0
  100. package/src/functions/actions.ts +288 -0
  101. package/src/functions/audit.ts +61 -0
  102. package/src/functions/auto-forget.ts +169 -0
  103. package/src/functions/branch-aware.ts +169 -0
  104. package/src/functions/cascade.ts +80 -0
  105. package/src/functions/checkpoints.ts +209 -0
  106. package/src/functions/claude-bridge.ts +161 -0
  107. package/src/functions/compress.ts +194 -0
  108. package/src/functions/consolidate.ts +212 -0
  109. package/src/functions/consolidation-pipeline.ts +258 -0
  110. package/src/functions/context.ts +169 -0
  111. package/src/functions/crystallize.ts +293 -0
  112. package/src/functions/dedup.ts +57 -0
  113. package/src/functions/diagnostics.ts +785 -0
  114. package/src/functions/enrich.ts +132 -0
  115. package/src/functions/evict.ts +163 -0
  116. package/src/functions/export-import.ts +508 -0
  117. package/src/functions/facets.ts +248 -0
  118. package/src/functions/file-index.ts +106 -0
  119. package/src/functions/flow-compress.ts +214 -0
  120. package/src/functions/frontier.ts +196 -0
  121. package/src/functions/governance.ts +131 -0
  122. package/src/functions/graph-retrieval.ts +277 -0
  123. package/src/functions/graph.ts +275 -0
  124. package/src/functions/leases.ts +216 -0
  125. package/src/functions/lessons.ts +253 -0
  126. package/src/functions/mesh.ts +434 -0
  127. package/src/functions/migrate.ts +165 -0
  128. package/src/functions/observe.ts +144 -0
  129. package/src/functions/obsidian-export.ts +310 -0
  130. package/src/functions/patterns.ts +138 -0
  131. package/src/functions/privacy.ts +39 -0
  132. package/src/functions/profile.ts +155 -0
  133. package/src/functions/query-expansion.ts +186 -0
  134. package/src/functions/relations.ts +237 -0
  135. package/src/functions/remember.ts +162 -0
  136. package/src/functions/retention.ts +235 -0
  137. package/src/functions/routines.ts +289 -0
  138. package/src/functions/search.ts +80 -0
  139. package/src/functions/sentinels.ts +417 -0
  140. package/src/functions/signals.ts +186 -0
  141. package/src/functions/sketches.ts +274 -0
  142. package/src/functions/sliding-window.ts +257 -0
  143. package/src/functions/smart-search.ts +115 -0
  144. package/src/functions/snapshot.ts +219 -0
  145. package/src/functions/summarize.ts +155 -0
  146. package/src/functions/team.ts +147 -0
  147. package/src/functions/temporal-graph.ts +476 -0
  148. package/src/functions/timeline.ts +138 -0
  149. package/src/functions/verify.ts +117 -0
  150. package/src/health/monitor.ts +110 -0
  151. package/src/health/thresholds.ts +73 -0
  152. package/src/hooks/notification.ts +52 -0
  153. package/src/hooks/post-tool-failure.ts +58 -0
  154. package/src/hooks/post-tool-use.ts +62 -0
  155. package/src/hooks/pre-compact.ts +60 -0
  156. package/src/hooks/pre-tool-use.ts +72 -0
  157. package/src/hooks/prompt-submit.ts +46 -0
  158. package/src/hooks/session-end.ts +71 -0
  159. package/src/hooks/session-start.ts +48 -0
  160. package/src/hooks/stop.ts +39 -0
  161. package/src/hooks/subagent-start.ts +49 -0
  162. package/src/hooks/subagent-stop.ts +54 -0
  163. package/src/hooks/task-completed.ts +54 -0
  164. package/src/index.ts +342 -0
  165. package/src/mcp/in-memory-kv.ts +61 -0
  166. package/src/mcp/server.ts +1455 -0
  167. package/src/mcp/standalone.ts +177 -0
  168. package/src/mcp/tools-registry.ts +769 -0
  169. package/src/mcp/transport.ts +91 -0
  170. package/src/prompts/compression.ts +67 -0
  171. package/src/prompts/consolidation.ts +48 -0
  172. package/src/prompts/graph-extraction.ts +35 -0
  173. package/src/prompts/summary.ts +38 -0
  174. package/src/prompts/xml.ts +26 -0
  175. package/src/providers/agent-sdk.ts +34 -0
  176. package/src/providers/anthropic.ts +35 -0
  177. package/src/providers/circuit-breaker.ts +82 -0
  178. package/src/providers/embedding/cohere.ts +46 -0
  179. package/src/providers/embedding/gemini.ts +54 -0
  180. package/src/providers/embedding/index.ts +39 -0
  181. package/src/providers/embedding/local.ts +52 -0
  182. package/src/providers/embedding/openai.ts +45 -0
  183. package/src/providers/embedding/openrouter.ts +51 -0
  184. package/src/providers/embedding/voyage.ts +46 -0
  185. package/src/providers/fallback-chain.ts +31 -0
  186. package/src/providers/index.ts +84 -0
  187. package/src/providers/openrouter.ts +71 -0
  188. package/src/providers/resilient.ts +37 -0
  189. package/src/state/hybrid-search.ts +295 -0
  190. package/src/state/index-persistence.ts +63 -0
  191. package/src/state/keyed-mutex.ts +18 -0
  192. package/src/state/kv.ts +33 -0
  193. package/src/state/schema.ts +71 -0
  194. package/src/state/search-index.ts +245 -0
  195. package/src/state/stemmer.ts +104 -0
  196. package/src/state/synonyms.ts +63 -0
  197. package/src/state/vector-index.ts +130 -0
  198. package/src/telemetry/setup.ts +116 -0
  199. package/src/triggers/api.ts +1904 -0
  200. package/src/triggers/events.ts +71 -0
  201. package/src/types.ts +769 -0
  202. package/src/version.ts +1 -0
  203. package/src/viewer/index.html +2497 -0
  204. package/src/viewer/server.ts +207 -0
  205. package/src/xenova.d.ts +3 -0
  206. package/test/actions.test.ts +490 -0
  207. package/test/audit.test.ts +108 -0
  208. package/test/auto-forget.test.ts +188 -0
  209. package/test/cascade.test.ts +277 -0
  210. package/test/checkpoints.test.ts +493 -0
  211. package/test/circuit-breaker.test.ts +107 -0
  212. package/test/claude-bridge.test.ts +178 -0
  213. package/test/confidence.test.ts +247 -0
  214. package/test/consistency.test.ts +61 -0
  215. package/test/consolidation-pipeline.test.ts +251 -0
  216. package/test/crystallize.test.ts +521 -0
  217. package/test/diagnostics.test.ts +638 -0
  218. package/test/embedding-provider.test.ts +49 -0
  219. package/test/enrich.test.ts +209 -0
  220. package/test/eval.test.ts +300 -0
  221. package/test/export-import.test.ts +251 -0
  222. package/test/facets.test.ts +448 -0
  223. package/test/fallback-chain.test.ts +93 -0
  224. package/test/frontier.test.ts +485 -0
  225. package/test/governance.test.ts +147 -0
  226. package/test/graph-retrieval.test.ts +186 -0
  227. package/test/graph.test.ts +160 -0
  228. package/test/helpers/mocks.ts +40 -0
  229. package/test/hybrid-search.test.ts +145 -0
  230. package/test/index-persistence.test.ts +124 -0
  231. package/test/integration.test.ts +265 -0
  232. package/test/leases.test.ts +399 -0
  233. package/test/mcp-prompts.test.ts +218 -0
  234. package/test/mcp-resources.test.ts +286 -0
  235. package/test/mcp-standalone.test.ts +113 -0
  236. package/test/mesh.test.ts +700 -0
  237. package/test/privacy.test.ts +87 -0
  238. package/test/profile.test.ts +161 -0
  239. package/test/query-expansion.test.ts +154 -0
  240. package/test/relations.test.ts +198 -0
  241. package/test/retention.test.ts +245 -0
  242. package/test/routines.test.ts +497 -0
  243. package/test/schema-fingerprint.test.ts +81 -0
  244. package/test/schema.test.ts +42 -0
  245. package/test/search-index.test.ts +128 -0
  246. package/test/sentinels.test.ts +626 -0
  247. package/test/signals.test.ts +410 -0
  248. package/test/sketches.test.ts +549 -0
  249. package/test/sliding-window.test.ts +199 -0
  250. package/test/smart-search.test.ts +169 -0
  251. package/test/snapshot.test.ts +165 -0
  252. package/test/team.test.ts +156 -0
  253. package/test/temporal-graph.test.ts +378 -0
  254. package/test/timeline.test.ts +148 -0
  255. package/test/vector-index.test.ts +79 -0
  256. package/test/verify.test.ts +209 -0
  257. package/test/xml.test.ts +65 -0
  258. package/tsconfig.json +22 -0
  259. package/tsdown.config.ts +62 -0
@@ -0,0 +1,1904 @@
1
+ import type { ISdk, ApiRequest } from "iii-sdk";
2
+ import type { Session, CompressedObservation, HookPayload } from "../types.js";
3
+ import { KV } from "../state/schema.js";
4
+ import { StateKV } from "../state/kv.js";
5
+ import { readFileSync } from "node:fs";
6
+ import { join, dirname } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ import { getLatestHealth } from "../health/monitor.js";
9
+ import type { MetricsStore } from "../eval/metrics-store.js";
10
+ import type { ResilientProvider } from "../providers/resilient.js";
11
+ import { VERSION } from "../version.js";
12
+ import { timingSafeCompare, VIEWER_CSP } from "../auth.js";
13
+
14
+ type Response = {
15
+ status_code: number;
16
+ headers?: Record<string, string>;
17
+ body: unknown;
18
+ };
19
+
20
+ function checkAuth(
21
+ req: ApiRequest,
22
+ secret: string | undefined,
23
+ ): Response | null {
24
+ if (!secret) return null;
25
+ const auth = req.headers?.["authorization"] || req.headers?.["Authorization"];
26
+ if (
27
+ typeof auth !== "string" ||
28
+ !timingSafeCompare(auth, `Bearer ${secret}`)
29
+ ) {
30
+ return { status_code: 401, body: { error: "unauthorized" } };
31
+ }
32
+ return null;
33
+ }
34
+
35
+ export function registerApiTriggers(
36
+ sdk: ISdk,
37
+ kv: StateKV,
38
+ secret?: string,
39
+ metricsStore?: MetricsStore,
40
+ provider?: ResilientProvider | { circuitState?: unknown },
41
+ ): void {
42
+ sdk.registerFunction(
43
+ { id: "api::liveness" },
44
+ async (): Promise<Response> => ({
45
+ status_code: 200,
46
+ body: { status: "ok", service: "agentmemory" },
47
+ }),
48
+ );
49
+ sdk.registerTrigger({
50
+ type: "http",
51
+ function_id: "api::liveness",
52
+ config: { api_path: "/agentmemory/livez", http_method: "GET" },
53
+ });
54
+
55
+ sdk.registerFunction(
56
+ { id: "api::health" },
57
+ async (req: ApiRequest): Promise<Response> => {
58
+ const authErr = checkAuth(req, secret);
59
+ if (authErr) return authErr;
60
+
61
+ const health = await getLatestHealth(kv);
62
+ const functionMetrics = metricsStore ? await metricsStore.getAll() : [];
63
+ const circuitBreaker =
64
+ provider && "circuitState" in provider ? provider.circuitState : null;
65
+
66
+ const status = health?.status || "healthy";
67
+ const statusCode = status === "critical" ? 503 : 200;
68
+
69
+ return {
70
+ status_code: statusCode,
71
+ body: {
72
+ status,
73
+ service: "agentmemory",
74
+ version: VERSION,
75
+ health: health || null,
76
+ functionMetrics,
77
+ circuitBreaker,
78
+ },
79
+ };
80
+ },
81
+ );
82
+ sdk.registerTrigger({
83
+ type: "http",
84
+ function_id: "api::health",
85
+ config: { api_path: "/agentmemory/health", http_method: "GET" },
86
+ });
87
+
88
+ sdk.registerFunction(
89
+ { id: "api::observe" },
90
+ async (req: ApiRequest<HookPayload>): Promise<Response> => {
91
+ const authErr = checkAuth(req, secret);
92
+ if (authErr) return authErr;
93
+ const result = await sdk.trigger("mem::observe", req.body);
94
+ return { status_code: 201, body: result };
95
+ },
96
+ );
97
+ sdk.registerTrigger({
98
+ type: "http",
99
+ function_id: "api::observe",
100
+ config: { api_path: "/agentmemory/observe", http_method: "POST" },
101
+ });
102
+
103
+ sdk.registerFunction(
104
+ { id: "api::context" },
105
+ async (
106
+ req: ApiRequest<{ sessionId: string; project: string; budget?: number }>,
107
+ ): Promise<Response> => {
108
+ const authErr = checkAuth(req, secret);
109
+ if (authErr) return authErr;
110
+ const result = await sdk.trigger("mem::context", req.body);
111
+ return { status_code: 200, body: result };
112
+ },
113
+ );
114
+ sdk.registerTrigger({
115
+ type: "http",
116
+ function_id: "api::context",
117
+ config: { api_path: "/agentmemory/context", http_method: "POST" },
118
+ });
119
+
120
+ sdk.registerFunction(
121
+ { id: "api::search" },
122
+ async (
123
+ req: ApiRequest<{ query: string; limit?: number }>,
124
+ ): Promise<Response> => {
125
+ const authErr = checkAuth(req, secret);
126
+ if (authErr) return authErr;
127
+ const result = await sdk.trigger("mem::search", req.body);
128
+ return { status_code: 200, body: result };
129
+ },
130
+ );
131
+ sdk.registerTrigger({
132
+ type: "http",
133
+ function_id: "api::search",
134
+ config: { api_path: "/agentmemory/search", http_method: "POST" },
135
+ });
136
+
137
+ sdk.registerFunction(
138
+ { id: "api::session::start" },
139
+ async (
140
+ req: ApiRequest<{ sessionId: string; project: string; cwd: string }>,
141
+ ): Promise<Response> => {
142
+ const authErr = checkAuth(req, secret);
143
+ if (authErr) return authErr;
144
+ const { sessionId, project, cwd } = req.body;
145
+ const session: Session = {
146
+ id: sessionId,
147
+ project,
148
+ cwd,
149
+ startedAt: new Date().toISOString(),
150
+ status: "active",
151
+ observationCount: 0,
152
+ };
153
+ await kv.set(KV.sessions, sessionId, session);
154
+ const contextResult = await sdk.trigger<
155
+ { sessionId: string; project: string },
156
+ { context: string }
157
+ >("mem::context", { sessionId, project });
158
+ return {
159
+ status_code: 200,
160
+ body: { session, context: contextResult.context },
161
+ };
162
+ },
163
+ );
164
+ sdk.registerTrigger({
165
+ type: "http",
166
+ function_id: "api::session::start",
167
+ config: { api_path: "/agentmemory/session/start", http_method: "POST" },
168
+ });
169
+
170
+ sdk.registerFunction(
171
+ { id: "api::session::end" },
172
+ async (req: ApiRequest<{ sessionId: string }>): Promise<Response> => {
173
+ const authErr = checkAuth(req, secret);
174
+ if (authErr) return authErr;
175
+ const session = await kv.get<Session>(KV.sessions, req.body.sessionId);
176
+ if (session) {
177
+ await kv.set(KV.sessions, req.body.sessionId, {
178
+ ...session,
179
+ endedAt: new Date().toISOString(),
180
+ status: "completed",
181
+ });
182
+ }
183
+ return { status_code: 200, body: { success: true } };
184
+ },
185
+ );
186
+ sdk.registerTrigger({
187
+ type: "http",
188
+ function_id: "api::session::end",
189
+ config: { api_path: "/agentmemory/session/end", http_method: "POST" },
190
+ });
191
+
192
+ sdk.registerFunction(
193
+ { id: "api::summarize" },
194
+ async (req: ApiRequest<{ sessionId: string }>): Promise<Response> => {
195
+ const authErr = checkAuth(req, secret);
196
+ if (authErr) return authErr;
197
+ const result = await sdk.trigger("mem::summarize", req.body);
198
+ return { status_code: 200, body: result };
199
+ },
200
+ );
201
+ sdk.registerTrigger({
202
+ type: "http",
203
+ function_id: "api::summarize",
204
+ config: { api_path: "/agentmemory/summarize", http_method: "POST" },
205
+ });
206
+
207
+ sdk.registerFunction(
208
+ { id: "api::sessions" },
209
+ async (req: ApiRequest): Promise<Response> => {
210
+ const authErr = checkAuth(req, secret);
211
+ if (authErr) return authErr;
212
+ const sessions = await kv.list<Session>(KV.sessions);
213
+ return { status_code: 200, body: { sessions } };
214
+ },
215
+ );
216
+ sdk.registerTrigger({
217
+ type: "http",
218
+ function_id: "api::sessions",
219
+ config: { api_path: "/agentmemory/sessions", http_method: "GET" },
220
+ });
221
+
222
+ sdk.registerFunction(
223
+ { id: "api::observations" },
224
+ async (req: ApiRequest): Promise<Response> => {
225
+ const authErr = checkAuth(req, secret);
226
+ if (authErr) return authErr;
227
+ const sessionId = req.query_params["sessionId"] as string;
228
+ if (!sessionId)
229
+ return { status_code: 400, body: { error: "sessionId required" } };
230
+ const observations = await kv.list<CompressedObservation>(
231
+ KV.observations(sessionId),
232
+ );
233
+ return { status_code: 200, body: { observations } };
234
+ },
235
+ );
236
+ sdk.registerTrigger({
237
+ type: "http",
238
+ function_id: "api::observations",
239
+ config: { api_path: "/agentmemory/observations", http_method: "GET" },
240
+ });
241
+
242
+ sdk.registerFunction(
243
+ { id: "api::file-context" },
244
+ async (
245
+ req: ApiRequest<{ sessionId: string; files: string[] }>,
246
+ ): Promise<Response> => {
247
+ const authErr = checkAuth(req, secret);
248
+ if (authErr) return authErr;
249
+ const result = await sdk.trigger("mem::file-context", req.body);
250
+ return { status_code: 200, body: result };
251
+ },
252
+ );
253
+ sdk.registerTrigger({
254
+ type: "http",
255
+ function_id: "api::file-context",
256
+ config: { api_path: "/agentmemory/file-context", http_method: "POST" },
257
+ });
258
+
259
+ sdk.registerFunction(
260
+ { id: "api::enrich" },
261
+ async (
262
+ req: ApiRequest<{
263
+ sessionId: string;
264
+ files: string[];
265
+ terms?: string[];
266
+ toolName?: string;
267
+ }>,
268
+ ): Promise<Response> => {
269
+ const authErr = checkAuth(req, secret);
270
+ if (authErr) return authErr;
271
+ if (
272
+ !req.body?.sessionId ||
273
+ typeof req.body.sessionId !== "string" ||
274
+ !Array.isArray(req.body?.files) ||
275
+ req.body.files.length === 0 ||
276
+ !req.body.files.every((f: unknown) => typeof f === "string")
277
+ ) {
278
+ return {
279
+ status_code: 400,
280
+ body: {
281
+ error: "sessionId (string) and files (string[]) are required",
282
+ },
283
+ };
284
+ }
285
+ if (
286
+ req.body.terms !== undefined &&
287
+ (!Array.isArray(req.body.terms) ||
288
+ !req.body.terms.every((t: unknown) => typeof t === "string"))
289
+ ) {
290
+ return {
291
+ status_code: 400,
292
+ body: { error: "terms must be an array of strings" },
293
+ };
294
+ }
295
+ const result = await sdk.trigger("mem::enrich", req.body);
296
+ return { status_code: 200, body: result };
297
+ },
298
+ );
299
+ sdk.registerTrigger({
300
+ type: "http",
301
+ function_id: "api::enrich",
302
+ config: { api_path: "/agentmemory/enrich", http_method: "POST" },
303
+ });
304
+
305
+ sdk.registerFunction(
306
+ { id: "api::remember" },
307
+ async (
308
+ req: ApiRequest<{
309
+ content: string;
310
+ type?: string;
311
+ concepts?: string[];
312
+ files?: string[];
313
+ }>,
314
+ ): Promise<Response> => {
315
+ const authErr = checkAuth(req, secret);
316
+ if (authErr) return authErr;
317
+ if (
318
+ !req.body?.content ||
319
+ typeof req.body.content !== "string" ||
320
+ !req.body.content.trim()
321
+ ) {
322
+ return { status_code: 400, body: { error: "content is required" } };
323
+ }
324
+ const result = await sdk.trigger("mem::remember", req.body);
325
+ return { status_code: 201, body: result };
326
+ },
327
+ );
328
+ sdk.registerTrigger({
329
+ type: "http",
330
+ function_id: "api::remember",
331
+ config: { api_path: "/agentmemory/remember", http_method: "POST" },
332
+ });
333
+
334
+ sdk.registerFunction(
335
+ { id: "api::forget" },
336
+ async (
337
+ req: ApiRequest<{
338
+ sessionId?: string;
339
+ observationIds?: string[];
340
+ memoryId?: string;
341
+ }>,
342
+ ): Promise<Response> => {
343
+ const authErr = checkAuth(req, secret);
344
+ if (authErr) return authErr;
345
+ if (!req.body?.sessionId && !req.body?.memoryId) {
346
+ return {
347
+ status_code: 400,
348
+ body: { error: "sessionId or memoryId is required" },
349
+ };
350
+ }
351
+ const result = await sdk.trigger("mem::forget", req.body);
352
+ return { status_code: 200, body: result };
353
+ },
354
+ );
355
+ sdk.registerTrigger({
356
+ type: "http",
357
+ function_id: "api::forget",
358
+ config: { api_path: "/agentmemory/forget", http_method: "POST" },
359
+ });
360
+
361
+ sdk.registerFunction(
362
+ { id: "api::consolidate" },
363
+ async (
364
+ req: ApiRequest<{ project?: string; minObservations?: number }>,
365
+ ): Promise<Response> => {
366
+ const authErr = checkAuth(req, secret);
367
+ if (authErr) return authErr;
368
+ const result = await sdk.trigger("mem::consolidate", req.body);
369
+ return { status_code: 200, body: result };
370
+ },
371
+ );
372
+ sdk.registerTrigger({
373
+ type: "http",
374
+ function_id: "api::consolidate",
375
+ config: { api_path: "/agentmemory/consolidate", http_method: "POST" },
376
+ });
377
+
378
+ sdk.registerFunction(
379
+ { id: "api::patterns" },
380
+ async (req: ApiRequest<{ project?: string }>): Promise<Response> => {
381
+ const authErr = checkAuth(req, secret);
382
+ if (authErr) return authErr;
383
+ const result = await sdk.trigger("mem::patterns", req.body);
384
+ return { status_code: 200, body: result };
385
+ },
386
+ );
387
+ sdk.registerTrigger({
388
+ type: "http",
389
+ function_id: "api::patterns",
390
+ config: { api_path: "/agentmemory/patterns", http_method: "POST" },
391
+ });
392
+
393
+ sdk.registerFunction(
394
+ { id: "api::generate-rules" },
395
+ async (req: ApiRequest<{ project?: string }>): Promise<Response> => {
396
+ const authErr = checkAuth(req, secret);
397
+ if (authErr) return authErr;
398
+ const result = await sdk.trigger("mem::generate-rules", req.body);
399
+ return { status_code: 200, body: result };
400
+ },
401
+ );
402
+ sdk.registerTrigger({
403
+ type: "http",
404
+ function_id: "api::generate-rules",
405
+ config: { api_path: "/agentmemory/generate-rules", http_method: "POST" },
406
+ });
407
+
408
+ sdk.registerFunction(
409
+ { id: "api::migrate" },
410
+ async (req: ApiRequest<{ dbPath: string }>): Promise<Response> => {
411
+ const authErr = checkAuth(req, secret);
412
+ if (authErr) return authErr;
413
+ if (!req.body?.dbPath || typeof req.body.dbPath !== "string") {
414
+ return { status_code: 400, body: { error: "dbPath is required" } };
415
+ }
416
+ const result = await sdk.trigger("mem::migrate", req.body);
417
+ return { status_code: 200, body: result };
418
+ },
419
+ );
420
+ sdk.registerTrigger({
421
+ type: "http",
422
+ function_id: "api::migrate",
423
+ config: { api_path: "/agentmemory/migrate", http_method: "POST" },
424
+ });
425
+
426
+ sdk.registerFunction(
427
+ { id: "api::evict" },
428
+ async (req: ApiRequest<{ dryRun?: boolean }>): Promise<Response> => {
429
+ const authErr = checkAuth(req, secret);
430
+ if (authErr) return authErr;
431
+ const dryRun =
432
+ req.query_params?.["dryRun"] === "true" || req.body?.dryRun === true;
433
+ const result = await sdk.trigger("mem::evict", { dryRun });
434
+ return { status_code: 200, body: result };
435
+ },
436
+ );
437
+ sdk.registerTrigger({
438
+ type: "http",
439
+ function_id: "api::evict",
440
+ config: { api_path: "/agentmemory/evict", http_method: "POST" },
441
+ });
442
+
443
+ sdk.registerFunction(
444
+ { id: "api::smart-search" },
445
+ async (
446
+ req: ApiRequest<{ query?: string; expandIds?: string[]; limit?: number }>,
447
+ ): Promise<Response> => {
448
+ const authErr = checkAuth(req, secret);
449
+ if (authErr) return authErr;
450
+ if (
451
+ !req.body?.query &&
452
+ (!req.body?.expandIds || req.body.expandIds.length === 0)
453
+ ) {
454
+ return {
455
+ status_code: 400,
456
+ body: { error: "query or expandIds is required" },
457
+ };
458
+ }
459
+ const result = await sdk.trigger("mem::smart-search", req.body);
460
+ return { status_code: 200, body: result };
461
+ },
462
+ );
463
+ sdk.registerTrigger({
464
+ type: "http",
465
+ function_id: "api::smart-search",
466
+ config: { api_path: "/agentmemory/smart-search", http_method: "POST" },
467
+ });
468
+
469
+ sdk.registerFunction(
470
+ { id: "api::timeline" },
471
+ async (
472
+ req: ApiRequest<{
473
+ anchor: string;
474
+ project?: string;
475
+ before?: number;
476
+ after?: number;
477
+ }>,
478
+ ): Promise<Response> => {
479
+ const authErr = checkAuth(req, secret);
480
+ if (authErr) return authErr;
481
+ if (!req.body?.anchor) {
482
+ return { status_code: 400, body: { error: "anchor is required" } };
483
+ }
484
+ const result = await sdk.trigger("mem::timeline", req.body);
485
+ return { status_code: 200, body: result };
486
+ },
487
+ );
488
+ sdk.registerTrigger({
489
+ type: "http",
490
+ function_id: "api::timeline",
491
+ config: { api_path: "/agentmemory/timeline", http_method: "POST" },
492
+ });
493
+
494
+ sdk.registerFunction(
495
+ { id: "api::profile" },
496
+ async (req: ApiRequest): Promise<Response> => {
497
+ const authErr = checkAuth(req, secret);
498
+ if (authErr) return authErr;
499
+ const project = req.query_params["project"] as string;
500
+ if (!project) {
501
+ return {
502
+ status_code: 400,
503
+ body: { error: "project query param is required" },
504
+ };
505
+ }
506
+ const result = await sdk.trigger("mem::profile", { project });
507
+ return { status_code: 200, body: result };
508
+ },
509
+ );
510
+ sdk.registerTrigger({
511
+ type: "http",
512
+ function_id: "api::profile",
513
+ config: { api_path: "/agentmemory/profile", http_method: "GET" },
514
+ });
515
+
516
+ sdk.registerFunction(
517
+ { id: "api::export" },
518
+ async (req: ApiRequest): Promise<Response> => {
519
+ const authErr = checkAuth(req, secret);
520
+ if (authErr) return authErr;
521
+ const result = await sdk.trigger("mem::export", {});
522
+ return { status_code: 200, body: result };
523
+ },
524
+ );
525
+ sdk.registerTrigger({
526
+ type: "http",
527
+ function_id: "api::export",
528
+ config: { api_path: "/agentmemory/export", http_method: "GET" },
529
+ });
530
+
531
+ sdk.registerFunction(
532
+ { id: "api::import" },
533
+ async (
534
+ req: ApiRequest<{
535
+ exportData: unknown;
536
+ strategy?: "merge" | "replace" | "skip";
537
+ }>,
538
+ ): Promise<Response> => {
539
+ const authErr = checkAuth(req, secret);
540
+ if (authErr) return authErr;
541
+ if (!req.body?.exportData) {
542
+ return { status_code: 400, body: { error: "exportData is required" } };
543
+ }
544
+ const result = await sdk.trigger("mem::import", req.body);
545
+ return { status_code: 200, body: result };
546
+ },
547
+ );
548
+ sdk.registerTrigger({
549
+ type: "http",
550
+ function_id: "api::import",
551
+ config: { api_path: "/agentmemory/import", http_method: "POST" },
552
+ });
553
+
554
+ sdk.registerFunction(
555
+ { id: "api::relations" },
556
+ async (
557
+ req: ApiRequest<{ sourceId: string; targetId: string; type: string }>,
558
+ ): Promise<Response> => {
559
+ const authErr = checkAuth(req, secret);
560
+ if (authErr) return authErr;
561
+ if (!req.body?.sourceId || !req.body?.targetId || !req.body?.type) {
562
+ return {
563
+ status_code: 400,
564
+ body: { error: "sourceId, targetId, and type are required" },
565
+ };
566
+ }
567
+ const result = await sdk.trigger("mem::relate", req.body);
568
+ return { status_code: 201, body: result };
569
+ },
570
+ );
571
+ sdk.registerTrigger({
572
+ type: "http",
573
+ function_id: "api::relations",
574
+ config: { api_path: "/agentmemory/relations", http_method: "POST" },
575
+ });
576
+
577
+ sdk.registerFunction(
578
+ { id: "api::evolve" },
579
+ async (
580
+ req: ApiRequest<{
581
+ memoryId: string;
582
+ newContent: string;
583
+ newTitle?: string;
584
+ }>,
585
+ ): Promise<Response> => {
586
+ const authErr = checkAuth(req, secret);
587
+ if (authErr) return authErr;
588
+ if (!req.body?.memoryId || !req.body?.newContent) {
589
+ return {
590
+ status_code: 400,
591
+ body: { error: "memoryId and newContent are required" },
592
+ };
593
+ }
594
+ const result = await sdk.trigger("mem::evolve", req.body);
595
+ return { status_code: 200, body: result };
596
+ },
597
+ );
598
+ sdk.registerTrigger({
599
+ type: "http",
600
+ function_id: "api::evolve",
601
+ config: { api_path: "/agentmemory/evolve", http_method: "POST" },
602
+ });
603
+
604
+ sdk.registerFunction(
605
+ { id: "api::auto-forget" },
606
+ async (req: ApiRequest<{ dryRun?: boolean }>): Promise<Response> => {
607
+ const authErr = checkAuth(req, secret);
608
+ if (authErr) return authErr;
609
+ const dryRun =
610
+ req.query_params?.["dryRun"] === "true" || req.body?.dryRun === true;
611
+ const result = await sdk.trigger("mem::auto-forget", { dryRun });
612
+ return { status_code: 200, body: result };
613
+ },
614
+ );
615
+ sdk.registerTrigger({
616
+ type: "http",
617
+ function_id: "api::auto-forget",
618
+ config: { api_path: "/agentmemory/auto-forget", http_method: "POST" },
619
+ });
620
+
621
+ sdk.registerFunction(
622
+ { id: "api::claude-bridge-read" },
623
+ async (req: ApiRequest): Promise<Response> => {
624
+ const authErr = checkAuth(req, secret);
625
+ if (authErr) return authErr;
626
+ try {
627
+ const result = await sdk.trigger("mem::claude-bridge-read", {});
628
+ return { status_code: 200, body: result };
629
+ } catch {
630
+ return {
631
+ status_code: 404,
632
+ body: { error: "Claude bridge not enabled" },
633
+ };
634
+ }
635
+ },
636
+ );
637
+ sdk.registerTrigger({
638
+ type: "http",
639
+ function_id: "api::claude-bridge-read",
640
+ config: { api_path: "/agentmemory/claude-bridge/read", http_method: "GET" },
641
+ });
642
+
643
+ sdk.registerFunction(
644
+ { id: "api::claude-bridge-sync" },
645
+ async (req: ApiRequest): Promise<Response> => {
646
+ const authErr = checkAuth(req, secret);
647
+ if (authErr) return authErr;
648
+ try {
649
+ const result = await sdk.trigger("mem::claude-bridge-sync", {});
650
+ return { status_code: 200, body: result };
651
+ } catch {
652
+ return {
653
+ status_code: 404,
654
+ body: { error: "Claude bridge not enabled" },
655
+ };
656
+ }
657
+ },
658
+ );
659
+ sdk.registerTrigger({
660
+ type: "http",
661
+ function_id: "api::claude-bridge-sync",
662
+ config: {
663
+ api_path: "/agentmemory/claude-bridge/sync",
664
+ http_method: "POST",
665
+ },
666
+ });
667
+
668
+ sdk.registerFunction(
669
+ { id: "api::graph-query" },
670
+ async (
671
+ req: ApiRequest<{
672
+ startNodeId?: string;
673
+ nodeType?: string;
674
+ maxDepth?: number;
675
+ query?: string;
676
+ }>,
677
+ ): Promise<Response> => {
678
+ const authErr = checkAuth(req, secret);
679
+ if (authErr) return authErr;
680
+ try {
681
+ const result = await sdk.trigger("mem::graph-query", req.body || {});
682
+ return { status_code: 200, body: result };
683
+ } catch {
684
+ return {
685
+ status_code: 404,
686
+ body: { error: "Knowledge graph not enabled" },
687
+ };
688
+ }
689
+ },
690
+ );
691
+ sdk.registerTrigger({
692
+ type: "http",
693
+ function_id: "api::graph-query",
694
+ config: { api_path: "/agentmemory/graph/query", http_method: "POST" },
695
+ });
696
+
697
+ sdk.registerFunction(
698
+ { id: "api::graph-stats" },
699
+ async (req: ApiRequest): Promise<Response> => {
700
+ const authErr = checkAuth(req, secret);
701
+ if (authErr) return authErr;
702
+ try {
703
+ const result = await sdk.trigger("mem::graph-stats", {});
704
+ return { status_code: 200, body: result };
705
+ } catch {
706
+ return {
707
+ status_code: 404,
708
+ body: { error: "Knowledge graph not enabled" },
709
+ };
710
+ }
711
+ },
712
+ );
713
+ sdk.registerTrigger({
714
+ type: "http",
715
+ function_id: "api::graph-stats",
716
+ config: { api_path: "/agentmemory/graph/stats", http_method: "GET" },
717
+ });
718
+
719
+ sdk.registerFunction(
720
+ { id: "api::graph-extract" },
721
+ async (req: ApiRequest<{ observations: unknown[] }>): Promise<Response> => {
722
+ const authErr = checkAuth(req, secret);
723
+ if (authErr) return authErr;
724
+ if (
725
+ !Array.isArray(req.body?.observations) ||
726
+ req.body.observations.length === 0
727
+ ) {
728
+ return {
729
+ status_code: 400,
730
+ body: { error: "observations array is required" },
731
+ };
732
+ }
733
+ try {
734
+ const result = await sdk.trigger("mem::graph-extract", req.body);
735
+ return { status_code: 200, body: result };
736
+ } catch {
737
+ return {
738
+ status_code: 404,
739
+ body: { error: "Knowledge graph not enabled" },
740
+ };
741
+ }
742
+ },
743
+ );
744
+ sdk.registerTrigger({
745
+ type: "http",
746
+ function_id: "api::graph-extract",
747
+ config: { api_path: "/agentmemory/graph/extract", http_method: "POST" },
748
+ });
749
+
750
+ sdk.registerFunction(
751
+ { id: "api::consolidate-pipeline" },
752
+ async (req: ApiRequest<{ tier?: string }>): Promise<Response> => {
753
+ const authErr = checkAuth(req, secret);
754
+ if (authErr) return authErr;
755
+ try {
756
+ const result = await sdk.trigger(
757
+ "mem::consolidate-pipeline",
758
+ req.body || {},
759
+ );
760
+ return { status_code: 200, body: result };
761
+ } catch {
762
+ return {
763
+ status_code: 404,
764
+ body: { error: "Consolidation pipeline not enabled" },
765
+ };
766
+ }
767
+ },
768
+ );
769
+ sdk.registerTrigger({
770
+ type: "http",
771
+ function_id: "api::consolidate-pipeline",
772
+ config: {
773
+ api_path: "/agentmemory/consolidate-pipeline",
774
+ http_method: "POST",
775
+ },
776
+ });
777
+
778
+ sdk.registerFunction(
779
+ { id: "api::team-share" },
780
+ async (
781
+ req: ApiRequest<{ itemId: string; itemType: string; project?: string }>,
782
+ ): Promise<Response> => {
783
+ const authErr = checkAuth(req, secret);
784
+ if (authErr) return authErr;
785
+ if (!req.body?.itemId || !req.body?.itemType) {
786
+ return {
787
+ status_code: 400,
788
+ body: { error: "itemId and itemType are required" },
789
+ };
790
+ }
791
+ try {
792
+ const result = await sdk.trigger("mem::team-share", req.body);
793
+ return { status_code: 201, body: result };
794
+ } catch {
795
+ return { status_code: 404, body: { error: "Team memory not enabled" } };
796
+ }
797
+ },
798
+ );
799
+ sdk.registerTrigger({
800
+ type: "http",
801
+ function_id: "api::team-share",
802
+ config: { api_path: "/agentmemory/team/share", http_method: "POST" },
803
+ });
804
+
805
+ sdk.registerFunction(
806
+ { id: "api::team-feed" },
807
+ async (req: ApiRequest): Promise<Response> => {
808
+ const authErr = checkAuth(req, secret);
809
+ if (authErr) return authErr;
810
+ try {
811
+ const limit = parseInt(req.query_params?.["limit"] as string) || 20;
812
+ const result = await sdk.trigger("mem::team-feed", { limit });
813
+ return { status_code: 200, body: result };
814
+ } catch {
815
+ return { status_code: 404, body: { error: "Team memory not enabled" } };
816
+ }
817
+ },
818
+ );
819
+ sdk.registerTrigger({
820
+ type: "http",
821
+ function_id: "api::team-feed",
822
+ config: { api_path: "/agentmemory/team/feed", http_method: "GET" },
823
+ });
824
+
825
+ sdk.registerFunction(
826
+ { id: "api::team-profile" },
827
+ async (req: ApiRequest): Promise<Response> => {
828
+ const authErr = checkAuth(req, secret);
829
+ if (authErr) return authErr;
830
+ try {
831
+ const result = await sdk.trigger("mem::team-profile", {});
832
+ return { status_code: 200, body: result };
833
+ } catch {
834
+ return { status_code: 404, body: { error: "Team memory not enabled" } };
835
+ }
836
+ },
837
+ );
838
+ sdk.registerTrigger({
839
+ type: "http",
840
+ function_id: "api::team-profile",
841
+ config: { api_path: "/agentmemory/team/profile", http_method: "GET" },
842
+ });
843
+
844
+ sdk.registerFunction(
845
+ { id: "api::audit" },
846
+ async (req: ApiRequest): Promise<Response> => {
847
+ const authErr = checkAuth(req, secret);
848
+ if (authErr) return authErr;
849
+ const result = await sdk.trigger("mem::audit-query", {
850
+ operation: req.query_params?.["operation"],
851
+ limit: parseInt(req.query_params?.["limit"] as string) || 50,
852
+ });
853
+ return { status_code: 200, body: result };
854
+ },
855
+ );
856
+ sdk.registerTrigger({
857
+ type: "http",
858
+ function_id: "api::audit",
859
+ config: { api_path: "/agentmemory/audit", http_method: "GET" },
860
+ });
861
+
862
+ sdk.registerFunction(
863
+ { id: "api::governance-delete" },
864
+ async (
865
+ req: ApiRequest<{ memoryIds: string[]; reason?: string }>,
866
+ ): Promise<Response> => {
867
+ const authErr = checkAuth(req, secret);
868
+ if (authErr) return authErr;
869
+ if (!req.body?.memoryIds || !Array.isArray(req.body.memoryIds)) {
870
+ return {
871
+ status_code: 400,
872
+ body: { error: "memoryIds array is required" },
873
+ };
874
+ }
875
+ const result = await sdk.trigger("mem::governance-delete", req.body);
876
+ return { status_code: 200, body: result };
877
+ },
878
+ );
879
+ sdk.registerTrigger({
880
+ type: "http",
881
+ function_id: "api::governance-delete",
882
+ config: {
883
+ api_path: "/agentmemory/governance/memories",
884
+ http_method: "DELETE",
885
+ },
886
+ });
887
+
888
+ sdk.registerFunction(
889
+ { id: "api::governance-bulk" },
890
+ async (
891
+ req: ApiRequest<{
892
+ type?: string[];
893
+ dateFrom?: string;
894
+ dateTo?: string;
895
+ qualityBelow?: number;
896
+ dryRun?: boolean;
897
+ }>,
898
+ ): Promise<Response> => {
899
+ const authErr = checkAuth(req, secret);
900
+ if (authErr) return authErr;
901
+ const result = await sdk.trigger("mem::governance-bulk", req.body || {});
902
+ return { status_code: 200, body: result };
903
+ },
904
+ );
905
+ sdk.registerTrigger({
906
+ type: "http",
907
+ function_id: "api::governance-bulk",
908
+ config: {
909
+ api_path: "/agentmemory/governance/bulk-delete",
910
+ http_method: "POST",
911
+ },
912
+ });
913
+
914
+ sdk.registerFunction(
915
+ { id: "api::snapshots" },
916
+ async (req: ApiRequest): Promise<Response> => {
917
+ const authErr = checkAuth(req, secret);
918
+ if (authErr) return authErr;
919
+ try {
920
+ const result = await sdk.trigger("mem::snapshot-list", {});
921
+ return { status_code: 200, body: result };
922
+ } catch {
923
+ return { status_code: 404, body: { error: "Snapshots not enabled" } };
924
+ }
925
+ },
926
+ );
927
+ sdk.registerTrigger({
928
+ type: "http",
929
+ function_id: "api::snapshots",
930
+ config: { api_path: "/agentmemory/snapshots", http_method: "GET" },
931
+ });
932
+
933
+ sdk.registerFunction(
934
+ { id: "api::snapshot-create" },
935
+ async (req: ApiRequest<{ message?: string }>): Promise<Response> => {
936
+ const authErr = checkAuth(req, secret);
937
+ if (authErr) return authErr;
938
+ try {
939
+ const result = await sdk.trigger(
940
+ "mem::snapshot-create",
941
+ req.body || {},
942
+ );
943
+ return { status_code: 201, body: result };
944
+ } catch {
945
+ return { status_code: 404, body: { error: "Snapshots not enabled" } };
946
+ }
947
+ },
948
+ );
949
+ sdk.registerTrigger({
950
+ type: "http",
951
+ function_id: "api::snapshot-create",
952
+ config: { api_path: "/agentmemory/snapshot/create", http_method: "POST" },
953
+ });
954
+
955
+ sdk.registerFunction(
956
+ { id: "api::snapshot-restore" },
957
+ async (req: ApiRequest<{ commitHash: string }>): Promise<Response> => {
958
+ const authErr = checkAuth(req, secret);
959
+ if (authErr) return authErr;
960
+ if (!req.body?.commitHash) {
961
+ return { status_code: 400, body: { error: "commitHash is required" } };
962
+ }
963
+ try {
964
+ const result = await sdk.trigger("mem::snapshot-restore", req.body);
965
+ return { status_code: 200, body: result };
966
+ } catch {
967
+ return { status_code: 404, body: { error: "Snapshots not enabled" } };
968
+ }
969
+ },
970
+ );
971
+ sdk.registerTrigger({
972
+ type: "http",
973
+ function_id: "api::snapshot-restore",
974
+ config: { api_path: "/agentmemory/snapshot/restore", http_method: "POST" },
975
+ });
976
+
977
+ sdk.registerFunction(
978
+ { id: "api::memories" },
979
+ async (req: ApiRequest): Promise<Response> => {
980
+ const authErr = checkAuth(req, secret);
981
+ if (authErr) return authErr;
982
+ const memories = await kv.list<import("../types.js").Memory>(KV.memories);
983
+ const latest = req.query_params?.["latest"] === "true";
984
+ const filtered = latest ? memories.filter((m) => m.isLatest) : memories;
985
+ return { status_code: 200, body: { memories: filtered } };
986
+ },
987
+ );
988
+ sdk.registerTrigger({
989
+ type: "http",
990
+ function_id: "api::memories",
991
+ config: { api_path: "/agentmemory/memories", http_method: "GET" },
992
+ });
993
+
994
+ sdk.registerFunction(
995
+ { id: "api::action-create" },
996
+ async (
997
+ req: ApiRequest<{
998
+ title: string;
999
+ description?: string;
1000
+ priority?: number;
1001
+ createdBy?: string;
1002
+ project?: string;
1003
+ tags?: string[];
1004
+ parentId?: string;
1005
+ edges?: Array<{ type: string; targetActionId: string }>;
1006
+ }>,
1007
+ ): Promise<Response> => {
1008
+ const authErr = checkAuth(req, secret);
1009
+ if (authErr) return authErr;
1010
+ if (!req.body?.title) {
1011
+ return { status_code: 400, body: { error: "title is required" } };
1012
+ }
1013
+ const result = await sdk.trigger("mem::action-create", req.body);
1014
+ return { status_code: 201, body: result };
1015
+ },
1016
+ );
1017
+ sdk.registerTrigger({
1018
+ type: "http",
1019
+ function_id: "api::action-create",
1020
+ config: { api_path: "/agentmemory/actions", http_method: "POST" },
1021
+ });
1022
+
1023
+ sdk.registerFunction(
1024
+ { id: "api::action-update" },
1025
+ async (
1026
+ req: ApiRequest<{
1027
+ actionId: string;
1028
+ status?: string;
1029
+ title?: string;
1030
+ description?: string;
1031
+ priority?: number;
1032
+ result?: string;
1033
+ }>,
1034
+ ): Promise<Response> => {
1035
+ const authErr = checkAuth(req, secret);
1036
+ if (authErr) return authErr;
1037
+ if (!req.body?.actionId) {
1038
+ return { status_code: 400, body: { error: "actionId is required" } };
1039
+ }
1040
+ const result = await sdk.trigger("mem::action-update", req.body);
1041
+ return { status_code: 200, body: result };
1042
+ },
1043
+ );
1044
+ sdk.registerTrigger({
1045
+ type: "http",
1046
+ function_id: "api::action-update",
1047
+ config: { api_path: "/agentmemory/actions/update", http_method: "POST" },
1048
+ });
1049
+
1050
+ sdk.registerFunction(
1051
+ { id: "api::action-list" },
1052
+ async (req: ApiRequest): Promise<Response> => {
1053
+ const authErr = checkAuth(req, secret);
1054
+ if (authErr) return authErr;
1055
+ const result = await sdk.trigger("mem::action-list", {
1056
+ status: req.query_params?.["status"],
1057
+ project: req.query_params?.["project"],
1058
+ parentId: req.query_params?.["parentId"],
1059
+ });
1060
+ return { status_code: 200, body: result };
1061
+ },
1062
+ );
1063
+ sdk.registerTrigger({
1064
+ type: "http",
1065
+ function_id: "api::action-list",
1066
+ config: { api_path: "/agentmemory/actions", http_method: "GET" },
1067
+ });
1068
+
1069
+ sdk.registerFunction(
1070
+ { id: "api::action-get" },
1071
+ async (req: ApiRequest<{ actionId: string }>): Promise<Response> => {
1072
+ const authErr = checkAuth(req, secret);
1073
+ if (authErr) return authErr;
1074
+ const actionId = req.query_params?.["actionId"] as string;
1075
+ if (!actionId) {
1076
+ return { status_code: 400, body: { error: "actionId required" } };
1077
+ }
1078
+ const result = await sdk.trigger("mem::action-get", { actionId });
1079
+ return { status_code: 200, body: result };
1080
+ },
1081
+ );
1082
+ sdk.registerTrigger({
1083
+ type: "http",
1084
+ function_id: "api::action-get",
1085
+ config: { api_path: "/agentmemory/actions/get", http_method: "GET" },
1086
+ });
1087
+
1088
+ sdk.registerFunction(
1089
+ { id: "api::action-edge" },
1090
+ async (
1091
+ req: ApiRequest<{
1092
+ sourceActionId: string;
1093
+ targetActionId: string;
1094
+ type: string;
1095
+ }>,
1096
+ ): Promise<Response> => {
1097
+ const authErr = checkAuth(req, secret);
1098
+ if (authErr) return authErr;
1099
+ if (!req.body?.sourceActionId || !req.body?.targetActionId || !req.body?.type) {
1100
+ return { status_code: 400, body: { error: "sourceActionId, targetActionId, and type are required" } };
1101
+ }
1102
+ const result = await sdk.trigger("mem::action-edge-create", req.body);
1103
+ return { status_code: 201, body: result };
1104
+ },
1105
+ );
1106
+ sdk.registerTrigger({
1107
+ type: "http",
1108
+ function_id: "api::action-edge",
1109
+ config: { api_path: "/agentmemory/actions/edges", http_method: "POST" },
1110
+ });
1111
+
1112
+ sdk.registerFunction(
1113
+ { id: "api::frontier" },
1114
+ async (req: ApiRequest): Promise<Response> => {
1115
+ const authErr = checkAuth(req, secret);
1116
+ if (authErr) return authErr;
1117
+ const result = await sdk.trigger("mem::frontier", {
1118
+ project: req.query_params?.["project"],
1119
+ agentId: req.query_params?.["agentId"],
1120
+ limit: parseInt(req.query_params?.["limit"] as string) || undefined,
1121
+ });
1122
+ return { status_code: 200, body: result };
1123
+ },
1124
+ );
1125
+ sdk.registerTrigger({
1126
+ type: "http",
1127
+ function_id: "api::frontier",
1128
+ config: { api_path: "/agentmemory/frontier", http_method: "GET" },
1129
+ });
1130
+
1131
+ sdk.registerFunction(
1132
+ { id: "api::next" },
1133
+ async (req: ApiRequest): Promise<Response> => {
1134
+ const authErr = checkAuth(req, secret);
1135
+ if (authErr) return authErr;
1136
+ const result = await sdk.trigger("mem::next", {
1137
+ project: req.query_params?.["project"],
1138
+ agentId: req.query_params?.["agentId"],
1139
+ });
1140
+ return { status_code: 200, body: result };
1141
+ },
1142
+ );
1143
+ sdk.registerTrigger({
1144
+ type: "http",
1145
+ function_id: "api::next",
1146
+ config: { api_path: "/agentmemory/next", http_method: "GET" },
1147
+ });
1148
+
1149
+ sdk.registerFunction(
1150
+ { id: "api::lease-acquire" },
1151
+ async (
1152
+ req: ApiRequest<{ actionId: string; agentId: string; ttlMs?: number }>,
1153
+ ): Promise<Response> => {
1154
+ const authErr = checkAuth(req, secret);
1155
+ if (authErr) return authErr;
1156
+ if (!req.body?.actionId || !req.body?.agentId) {
1157
+ return { status_code: 400, body: { error: "actionId and agentId are required" } };
1158
+ }
1159
+ const result = await sdk.trigger("mem::lease-acquire", req.body);
1160
+ return { status_code: 200, body: result };
1161
+ },
1162
+ );
1163
+ sdk.registerTrigger({
1164
+ type: "http",
1165
+ function_id: "api::lease-acquire",
1166
+ config: { api_path: "/agentmemory/leases/acquire", http_method: "POST" },
1167
+ });
1168
+
1169
+ sdk.registerFunction(
1170
+ { id: "api::lease-release" },
1171
+ async (
1172
+ req: ApiRequest<{ actionId: string; agentId: string; result?: string }>,
1173
+ ): Promise<Response> => {
1174
+ const authErr = checkAuth(req, secret);
1175
+ if (authErr) return authErr;
1176
+ if (!req.body?.actionId || !req.body?.agentId) {
1177
+ return { status_code: 400, body: { error: "actionId and agentId are required" } };
1178
+ }
1179
+ const result = await sdk.trigger("mem::lease-release", req.body);
1180
+ return { status_code: 200, body: result };
1181
+ },
1182
+ );
1183
+ sdk.registerTrigger({
1184
+ type: "http",
1185
+ function_id: "api::lease-release",
1186
+ config: { api_path: "/agentmemory/leases/release", http_method: "POST" },
1187
+ });
1188
+
1189
+ sdk.registerFunction(
1190
+ { id: "api::lease-renew" },
1191
+ async (
1192
+ req: ApiRequest<{ actionId: string; agentId: string; ttlMs?: number }>,
1193
+ ): Promise<Response> => {
1194
+ const authErr = checkAuth(req, secret);
1195
+ if (authErr) return authErr;
1196
+ if (!req.body?.actionId || !req.body?.agentId) {
1197
+ return { status_code: 400, body: { error: "actionId and agentId are required" } };
1198
+ }
1199
+ const result = await sdk.trigger("mem::lease-renew", req.body);
1200
+ return { status_code: 200, body: result };
1201
+ },
1202
+ );
1203
+ sdk.registerTrigger({
1204
+ type: "http",
1205
+ function_id: "api::lease-renew",
1206
+ config: { api_path: "/agentmemory/leases/renew", http_method: "POST" },
1207
+ });
1208
+
1209
+ sdk.registerFunction(
1210
+ { id: "api::routine-create" },
1211
+ async (req: ApiRequest): Promise<Response> => {
1212
+ const authErr = checkAuth(req, secret);
1213
+ if (authErr) return authErr;
1214
+ if (!req.body?.name) {
1215
+ return { status_code: 400, body: { error: "name is required" } };
1216
+ }
1217
+ const result = await sdk.trigger("mem::routine-create", req.body);
1218
+ return { status_code: 201, body: result };
1219
+ },
1220
+ );
1221
+ sdk.registerTrigger({
1222
+ type: "http",
1223
+ function_id: "api::routine-create",
1224
+ config: { api_path: "/agentmemory/routines", http_method: "POST" },
1225
+ });
1226
+
1227
+ sdk.registerFunction(
1228
+ { id: "api::routine-list" },
1229
+ async (req: ApiRequest): Promise<Response> => {
1230
+ const authErr = checkAuth(req, secret);
1231
+ if (authErr) return authErr;
1232
+ const result = await sdk.trigger("mem::routine-list", {
1233
+ frozen: req.query_params?.["frozen"] === "true" ? true : undefined,
1234
+ });
1235
+ return { status_code: 200, body: result };
1236
+ },
1237
+ );
1238
+ sdk.registerTrigger({
1239
+ type: "http",
1240
+ function_id: "api::routine-list",
1241
+ config: { api_path: "/agentmemory/routines", http_method: "GET" },
1242
+ });
1243
+
1244
+ sdk.registerFunction(
1245
+ { id: "api::routine-run" },
1246
+ async (
1247
+ req: ApiRequest<{ routineId: string; project?: string; initiatedBy?: string }>,
1248
+ ): Promise<Response> => {
1249
+ const authErr = checkAuth(req, secret);
1250
+ if (authErr) return authErr;
1251
+ if (!req.body?.routineId) {
1252
+ return { status_code: 400, body: { error: "routineId is required" } };
1253
+ }
1254
+ const result = await sdk.trigger("mem::routine-run", req.body);
1255
+ return { status_code: 201, body: result };
1256
+ },
1257
+ );
1258
+ sdk.registerTrigger({
1259
+ type: "http",
1260
+ function_id: "api::routine-run",
1261
+ config: { api_path: "/agentmemory/routines/run", http_method: "POST" },
1262
+ });
1263
+
1264
+ sdk.registerFunction(
1265
+ { id: "api::routine-status" },
1266
+ async (req: ApiRequest): Promise<Response> => {
1267
+ const authErr = checkAuth(req, secret);
1268
+ if (authErr) return authErr;
1269
+ const runId = req.query_params?.["runId"] as string;
1270
+ if (!runId) {
1271
+ return { status_code: 400, body: { error: "runId query param required" } };
1272
+ }
1273
+ const result = await sdk.trigger("mem::routine-status", { runId });
1274
+ return { status_code: 200, body: result };
1275
+ },
1276
+ );
1277
+ sdk.registerTrigger({
1278
+ type: "http",
1279
+ function_id: "api::routine-status",
1280
+ config: { api_path: "/agentmemory/routines/status", http_method: "GET" },
1281
+ });
1282
+
1283
+ sdk.registerFunction(
1284
+ { id: "api::signal-send" },
1285
+ async (
1286
+ req: ApiRequest<{
1287
+ from: string;
1288
+ to?: string;
1289
+ content: string;
1290
+ type?: string;
1291
+ replyTo?: string;
1292
+ }>,
1293
+ ): Promise<Response> => {
1294
+ const authErr = checkAuth(req, secret);
1295
+ if (authErr) return authErr;
1296
+ if (!req.body?.from || !req.body?.content) {
1297
+ return { status_code: 400, body: { error: "from and content are required" } };
1298
+ }
1299
+ const result = await sdk.trigger("mem::signal-send", req.body);
1300
+ return { status_code: 201, body: result };
1301
+ },
1302
+ );
1303
+ sdk.registerTrigger({
1304
+ type: "http",
1305
+ function_id: "api::signal-send",
1306
+ config: { api_path: "/agentmemory/signals/send", http_method: "POST" },
1307
+ });
1308
+
1309
+ sdk.registerFunction(
1310
+ { id: "api::signal-read" },
1311
+ async (req: ApiRequest): Promise<Response> => {
1312
+ const authErr = checkAuth(req, secret);
1313
+ if (authErr) return authErr;
1314
+ const agentId = req.query_params?.["agentId"] as string;
1315
+ if (!agentId) {
1316
+ return { status_code: 400, body: { error: "agentId query param required" } };
1317
+ }
1318
+ const result = await sdk.trigger("mem::signal-read", {
1319
+ agentId,
1320
+ unreadOnly: req.query_params?.["unreadOnly"] === "true",
1321
+ threadId: req.query_params?.["threadId"],
1322
+ limit: parseInt(req.query_params?.["limit"] as string) || undefined,
1323
+ });
1324
+ return { status_code: 200, body: result };
1325
+ },
1326
+ );
1327
+ sdk.registerTrigger({
1328
+ type: "http",
1329
+ function_id: "api::signal-read",
1330
+ config: { api_path: "/agentmemory/signals", http_method: "GET" },
1331
+ });
1332
+
1333
+ sdk.registerFunction(
1334
+ { id: "api::checkpoint-create" },
1335
+ async (
1336
+ req: ApiRequest<{
1337
+ name: string;
1338
+ description?: string;
1339
+ type?: string;
1340
+ linkedActionIds?: string[];
1341
+ expiresInMs?: number;
1342
+ }>,
1343
+ ): Promise<Response> => {
1344
+ const authErr = checkAuth(req, secret);
1345
+ if (authErr) return authErr;
1346
+ if (!req.body?.name) {
1347
+ return { status_code: 400, body: { error: "name is required" } };
1348
+ }
1349
+ const result = await sdk.trigger("mem::checkpoint-create", req.body);
1350
+ return { status_code: 201, body: result };
1351
+ },
1352
+ );
1353
+ sdk.registerTrigger({
1354
+ type: "http",
1355
+ function_id: "api::checkpoint-create",
1356
+ config: { api_path: "/agentmemory/checkpoints", http_method: "POST" },
1357
+ });
1358
+
1359
+ sdk.registerFunction(
1360
+ { id: "api::checkpoint-resolve" },
1361
+ async (
1362
+ req: ApiRequest<{
1363
+ checkpointId: string;
1364
+ status: string;
1365
+ resolvedBy?: string;
1366
+ result?: unknown;
1367
+ }>,
1368
+ ): Promise<Response> => {
1369
+ const authErr = checkAuth(req, secret);
1370
+ if (authErr) return authErr;
1371
+ if (!req.body?.checkpointId || !req.body?.status) {
1372
+ return { status_code: 400, body: { error: "checkpointId and status are required" } };
1373
+ }
1374
+ const result = await sdk.trigger("mem::checkpoint-resolve", req.body);
1375
+ return { status_code: 200, body: result };
1376
+ },
1377
+ );
1378
+ sdk.registerTrigger({
1379
+ type: "http",
1380
+ function_id: "api::checkpoint-resolve",
1381
+ config: { api_path: "/agentmemory/checkpoints/resolve", http_method: "POST" },
1382
+ });
1383
+
1384
+ sdk.registerFunction(
1385
+ { id: "api::checkpoint-list" },
1386
+ async (req: ApiRequest): Promise<Response> => {
1387
+ const authErr = checkAuth(req, secret);
1388
+ if (authErr) return authErr;
1389
+ const result = await sdk.trigger("mem::checkpoint-list", {
1390
+ status: req.query_params?.["status"],
1391
+ type: req.query_params?.["type"],
1392
+ });
1393
+ return { status_code: 200, body: result };
1394
+ },
1395
+ );
1396
+ sdk.registerTrigger({
1397
+ type: "http",
1398
+ function_id: "api::checkpoint-list",
1399
+ config: { api_path: "/agentmemory/checkpoints", http_method: "GET" },
1400
+ });
1401
+
1402
+ sdk.registerFunction(
1403
+ { id: "api::mesh-register" },
1404
+ async (
1405
+ req: ApiRequest<{ url: string; name: string; sharedScopes?: string[] }>,
1406
+ ): Promise<Response> => {
1407
+ const authErr = checkAuth(req, secret);
1408
+ if (authErr) return authErr;
1409
+ if (!req.body?.url || !req.body?.name) {
1410
+ return { status_code: 400, body: { error: "url and name are required" } };
1411
+ }
1412
+ const result = await sdk.trigger("mem::mesh-register", req.body);
1413
+ return { status_code: 201, body: result };
1414
+ },
1415
+ );
1416
+ sdk.registerTrigger({
1417
+ type: "http",
1418
+ function_id: "api::mesh-register",
1419
+ config: { api_path: "/agentmemory/mesh/peers", http_method: "POST" },
1420
+ });
1421
+
1422
+ sdk.registerFunction(
1423
+ { id: "api::mesh-list" },
1424
+ async (req: ApiRequest): Promise<Response> => {
1425
+ const authErr = checkAuth(req, secret);
1426
+ if (authErr) return authErr;
1427
+ const result = await sdk.trigger("mem::mesh-list", {});
1428
+ return { status_code: 200, body: result };
1429
+ },
1430
+ );
1431
+ sdk.registerTrigger({
1432
+ type: "http",
1433
+ function_id: "api::mesh-list",
1434
+ config: { api_path: "/agentmemory/mesh/peers", http_method: "GET" },
1435
+ });
1436
+
1437
+ sdk.registerFunction(
1438
+ { id: "api::mesh-sync" },
1439
+ async (
1440
+ req: ApiRequest<{ peerId?: string; direction?: string }>,
1441
+ ): Promise<Response> => {
1442
+ const authErr = checkAuth(req, secret);
1443
+ if (authErr) return authErr;
1444
+ const result = await sdk.trigger("mem::mesh-sync", req.body || {});
1445
+ return { status_code: 200, body: result };
1446
+ },
1447
+ );
1448
+ sdk.registerTrigger({
1449
+ type: "http",
1450
+ function_id: "api::mesh-sync",
1451
+ config: { api_path: "/agentmemory/mesh/sync", http_method: "POST" },
1452
+ });
1453
+
1454
+ sdk.registerFunction(
1455
+ { id: "api::mesh-receive" },
1456
+ async (req: ApiRequest): Promise<Response> => {
1457
+ const authErr = checkAuth(req, secret);
1458
+ if (authErr) return authErr;
1459
+ const result = await sdk.trigger("mem::mesh-receive", req.body || {});
1460
+ return { status_code: 200, body: result };
1461
+ },
1462
+ );
1463
+ sdk.registerTrigger({
1464
+ type: "http",
1465
+ function_id: "api::mesh-receive",
1466
+ config: { api_path: "/agentmemory/mesh/receive", http_method: "POST" },
1467
+ });
1468
+
1469
+ sdk.registerFunction(
1470
+ { id: "api::mesh-export" },
1471
+ async (req: ApiRequest): Promise<Response> => {
1472
+ const authErr = checkAuth(req, secret);
1473
+ if (authErr) return authErr;
1474
+ const since = req.query_params?.["since"] as string;
1475
+ if (since) {
1476
+ const parsed = new Date(since).getTime();
1477
+ if (Number.isNaN(parsed)) {
1478
+ return { status_code: 400, body: { error: "Invalid 'since' date format" } };
1479
+ }
1480
+ }
1481
+ const project = req.query_params?.["project"] as string | undefined;
1482
+ const sinceTime = since ? new Date(since).getTime() : 0;
1483
+ const df = <T>(items: T[], field: "updatedAt" | "createdAt") =>
1484
+ items.filter((i) => new Date((i as Record<string, unknown>)[field] as string).getTime() > sinceTime);
1485
+ const memories = await kv.list<import("../types.js").Memory>(KV.memories);
1486
+ let actions = await kv.list<import("../types.js").Action>(KV.actions);
1487
+ if (project) {
1488
+ actions = actions.filter((a) => a.project === project);
1489
+ }
1490
+ const body: Record<string, unknown> = {
1491
+ memories: df(memories, "updatedAt"),
1492
+ actions: df(actions, "updatedAt"),
1493
+ };
1494
+ if (!project) {
1495
+ const semantic = await kv.list<import("../types.js").SemanticMemory>(KV.semantic);
1496
+ const procedural = await kv.list<import("../types.js").ProceduralMemory>(KV.procedural);
1497
+ const relations = await kv.list<import("../types.js").MemoryRelation>(KV.relations);
1498
+ const graphNodes = await kv.list<import("../types.js").GraphNode>(KV.graphNodes);
1499
+ const graphEdges = await kv.list<import("../types.js").GraphEdge>(KV.graphEdges);
1500
+ body.semantic = df(semantic, "updatedAt");
1501
+ body.procedural = df(procedural, "updatedAt");
1502
+ body.relations = df(relations, "createdAt");
1503
+ body.graphNodes = graphNodes.filter(
1504
+ (n) => new Date(n.updatedAt || n.createdAt).getTime() > sinceTime,
1505
+ );
1506
+ body.graphEdges = df(graphEdges, "createdAt");
1507
+ }
1508
+ return { status_code: 200, body };
1509
+ },
1510
+ );
1511
+ sdk.registerTrigger({
1512
+ type: "http",
1513
+ function_id: "api::mesh-export",
1514
+ config: { api_path: "/agentmemory/mesh/export", http_method: "GET" },
1515
+ });
1516
+
1517
+ sdk.registerFunction(
1518
+ { id: "api::flow-compress" },
1519
+ async (
1520
+ req: ApiRequest<{
1521
+ runId?: string;
1522
+ actionIds?: string[];
1523
+ project?: string;
1524
+ }>,
1525
+ ): Promise<Response> => {
1526
+ const authErr = checkAuth(req, secret);
1527
+ if (authErr) return authErr;
1528
+ try {
1529
+ const result = await sdk.trigger("mem::flow-compress", req.body || {});
1530
+ return { status_code: 200, body: result };
1531
+ } catch {
1532
+ return {
1533
+ status_code: 404,
1534
+ body: { error: "Flow compression requires a provider" },
1535
+ };
1536
+ }
1537
+ },
1538
+ );
1539
+ sdk.registerTrigger({
1540
+ type: "http",
1541
+ function_id: "api::flow-compress",
1542
+ config: { api_path: "/agentmemory/flow/compress", http_method: "POST" },
1543
+ });
1544
+
1545
+ sdk.registerFunction(
1546
+ { id: "api::branch-detect" },
1547
+ async (req: ApiRequest): Promise<Response> => {
1548
+ const authErr = checkAuth(req, secret);
1549
+ if (authErr) return authErr;
1550
+ const cwd = (req.query_params?.["cwd"] as string) || process.cwd();
1551
+ const result = await sdk.trigger("mem::detect-worktree", { cwd });
1552
+ return { status_code: 200, body: result };
1553
+ },
1554
+ );
1555
+ sdk.registerTrigger({
1556
+ type: "http",
1557
+ function_id: "api::branch-detect",
1558
+ config: { api_path: "/agentmemory/branch/detect", http_method: "GET" },
1559
+ });
1560
+
1561
+ sdk.registerFunction(
1562
+ { id: "api::branch-worktrees" },
1563
+ async (req: ApiRequest): Promise<Response> => {
1564
+ const authErr = checkAuth(req, secret);
1565
+ if (authErr) return authErr;
1566
+ const cwd = (req.query_params?.["cwd"] as string) || process.cwd();
1567
+ const result = await sdk.trigger("mem::list-worktrees", { cwd });
1568
+ return { status_code: 200, body: result };
1569
+ },
1570
+ );
1571
+ sdk.registerTrigger({
1572
+ type: "http",
1573
+ function_id: "api::branch-worktrees",
1574
+ config: { api_path: "/agentmemory/branch/worktrees", http_method: "GET" },
1575
+ });
1576
+
1577
+ sdk.registerFunction(
1578
+ { id: "api::branch-sessions" },
1579
+ async (req: ApiRequest): Promise<Response> => {
1580
+ const authErr = checkAuth(req, secret);
1581
+ if (authErr) return authErr;
1582
+ const cwd = (req.query_params?.["cwd"] as string) || process.cwd();
1583
+ const result = await sdk.trigger("mem::branch-sessions", { cwd });
1584
+ return { status_code: 200, body: result };
1585
+ },
1586
+ );
1587
+ sdk.registerTrigger({
1588
+ type: "http",
1589
+ function_id: "api::branch-sessions",
1590
+ config: { api_path: "/agentmemory/branch/sessions", http_method: "GET" },
1591
+ });
1592
+
1593
+ sdk.registerFunction({ id: "api::viewer" }, async (): Promise<Response> => {
1594
+ const headers = {
1595
+ "Content-Type": "text/html",
1596
+ "Content-Security-Policy": VIEWER_CSP,
1597
+ };
1598
+ const base = dirname(fileURLToPath(import.meta.url));
1599
+ const candidates = [
1600
+ join(base, "..", "viewer", "index.html"),
1601
+ join(base, "..", "src", "viewer", "index.html"),
1602
+ join(base, "viewer", "index.html"),
1603
+ ];
1604
+ for (const p of candidates) {
1605
+ try {
1606
+ const html = readFileSync(p, "utf-8");
1607
+ return { status_code: 200, headers, body: html };
1608
+ } catch {}
1609
+ }
1610
+ return {
1611
+ status_code: 404,
1612
+ headers,
1613
+ body: "<!DOCTYPE html><html><body><h1>agentmemory</h1><p>viewer not found</p></body></html>",
1614
+ };
1615
+ });
1616
+ sdk.registerTrigger({
1617
+ type: "http",
1618
+ function_id: "api::viewer",
1619
+ config: { api_path: "/agentmemory/viewer", http_method: "GET" },
1620
+ });
1621
+
1622
+ sdk.registerFunction({ id: "api::sentinel-create" }, async (req: ApiRequest) => {
1623
+ const denied = checkAuth(req, secret);
1624
+ if (denied) return denied;
1625
+ const body = req.body as Record<string, unknown>;
1626
+ if (!body?.name) return { status_code: 400, body: { error: "name is required" } };
1627
+ const result = await sdk.trigger("mem::sentinel-create", body);
1628
+ return { status_code: 200, body: result };
1629
+ });
1630
+ sdk.registerTrigger({ type: "http", function_id: "api::sentinel-create", config: { api_path: "/agentmemory/sentinels", http_method: "POST" } });
1631
+
1632
+ sdk.registerFunction({ id: "api::sentinel-trigger" }, async (req: ApiRequest) => {
1633
+ const denied = checkAuth(req, secret);
1634
+ if (denied) return denied;
1635
+ const body = req.body as Record<string, unknown>;
1636
+ if (!body?.sentinelId) return { status_code: 400, body: { error: "sentinelId is required" } };
1637
+ const result = await sdk.trigger("mem::sentinel-trigger", body);
1638
+ return { status_code: 200, body: result };
1639
+ });
1640
+ sdk.registerTrigger({ type: "http", function_id: "api::sentinel-trigger", config: { api_path: "/agentmemory/sentinels/trigger", http_method: "POST" } });
1641
+
1642
+ sdk.registerFunction({ id: "api::sentinel-check" }, async (req: ApiRequest) => {
1643
+ const denied = checkAuth(req, secret);
1644
+ if (denied) return denied;
1645
+ const result = await sdk.trigger("mem::sentinel-check", {});
1646
+ return { status_code: 200, body: result };
1647
+ });
1648
+ sdk.registerTrigger({ type: "http", function_id: "api::sentinel-check", config: { api_path: "/agentmemory/sentinels/check", http_method: "POST" } });
1649
+
1650
+ sdk.registerFunction({ id: "api::sentinel-cancel" }, async (req: ApiRequest) => {
1651
+ const denied = checkAuth(req, secret);
1652
+ if (denied) return denied;
1653
+ const body = req.body as Record<string, unknown>;
1654
+ if (!body?.sentinelId) return { status_code: 400, body: { error: "sentinelId is required" } };
1655
+ const result = await sdk.trigger("mem::sentinel-cancel", body);
1656
+ return { status_code: 200, body: result };
1657
+ });
1658
+ sdk.registerTrigger({ type: "http", function_id: "api::sentinel-cancel", config: { api_path: "/agentmemory/sentinels/cancel", http_method: "POST" } });
1659
+
1660
+ sdk.registerFunction({ id: "api::sentinel-list" }, async (req: ApiRequest) => {
1661
+ const denied = checkAuth(req, secret);
1662
+ if (denied) return denied;
1663
+ const params = req.query_params || {};
1664
+ const result = await sdk.trigger("mem::sentinel-list", { status: params.status, type: params.type });
1665
+ return { status_code: 200, body: result };
1666
+ });
1667
+ sdk.registerTrigger({ type: "http", function_id: "api::sentinel-list", config: { api_path: "/agentmemory/sentinels", http_method: "GET" } });
1668
+
1669
+ sdk.registerFunction({ id: "api::sketch-create" }, async (req: ApiRequest) => {
1670
+ const denied = checkAuth(req, secret);
1671
+ if (denied) return denied;
1672
+ const body = req.body as Record<string, unknown>;
1673
+ if (!body?.title) return { status_code: 400, body: { error: "title is required" } };
1674
+ const result = await sdk.trigger("mem::sketch-create", body);
1675
+ return { status_code: 200, body: result };
1676
+ });
1677
+ sdk.registerTrigger({ type: "http", function_id: "api::sketch-create", config: { api_path: "/agentmemory/sketches", http_method: "POST" } });
1678
+
1679
+ sdk.registerFunction({ id: "api::sketch-add" }, async (req: ApiRequest) => {
1680
+ const denied = checkAuth(req, secret);
1681
+ if (denied) return denied;
1682
+ const body = req.body as Record<string, unknown>;
1683
+ if (!body?.sketchId || !body?.title) return { status_code: 400, body: { error: "sketchId and title are required" } };
1684
+ const result = await sdk.trigger("mem::sketch-add", body);
1685
+ return { status_code: 200, body: result };
1686
+ });
1687
+ sdk.registerTrigger({ type: "http", function_id: "api::sketch-add", config: { api_path: "/agentmemory/sketches/add", http_method: "POST" } });
1688
+
1689
+ sdk.registerFunction({ id: "api::sketch-promote" }, async (req: ApiRequest) => {
1690
+ const denied = checkAuth(req, secret);
1691
+ if (denied) return denied;
1692
+ const body = req.body as Record<string, unknown>;
1693
+ if (!body?.sketchId) return { status_code: 400, body: { error: "sketchId is required" } };
1694
+ const result = await sdk.trigger("mem::sketch-promote", body);
1695
+ return { status_code: 200, body: result };
1696
+ });
1697
+ sdk.registerTrigger({ type: "http", function_id: "api::sketch-promote", config: { api_path: "/agentmemory/sketches/promote", http_method: "POST" } });
1698
+
1699
+ sdk.registerFunction({ id: "api::sketch-discard" }, async (req: ApiRequest) => {
1700
+ const denied = checkAuth(req, secret);
1701
+ if (denied) return denied;
1702
+ const body = req.body as Record<string, unknown>;
1703
+ if (!body?.sketchId) return { status_code: 400, body: { error: "sketchId is required" } };
1704
+ const result = await sdk.trigger("mem::sketch-discard", body);
1705
+ return { status_code: 200, body: result };
1706
+ });
1707
+ sdk.registerTrigger({ type: "http", function_id: "api::sketch-discard", config: { api_path: "/agentmemory/sketches/discard", http_method: "POST" } });
1708
+
1709
+ sdk.registerFunction({ id: "api::sketch-list" }, async (req: ApiRequest) => {
1710
+ const denied = checkAuth(req, secret);
1711
+ if (denied) return denied;
1712
+ const params = req.query_params || {};
1713
+ const result = await sdk.trigger("mem::sketch-list", { status: params.status, project: params.project });
1714
+ return { status_code: 200, body: result };
1715
+ });
1716
+ sdk.registerTrigger({ type: "http", function_id: "api::sketch-list", config: { api_path: "/agentmemory/sketches", http_method: "GET" } });
1717
+
1718
+ sdk.registerFunction({ id: "api::sketch-gc" }, async (req: ApiRequest) => {
1719
+ const denied = checkAuth(req, secret);
1720
+ if (denied) return denied;
1721
+ const result = await sdk.trigger("mem::sketch-gc", {});
1722
+ return { status_code: 200, body: result };
1723
+ });
1724
+ sdk.registerTrigger({ type: "http", function_id: "api::sketch-gc", config: { api_path: "/agentmemory/sketches/gc", http_method: "POST" } });
1725
+
1726
+ sdk.registerFunction({ id: "api::crystallize" }, async (req: ApiRequest) => {
1727
+ const denied = checkAuth(req, secret);
1728
+ if (denied) return denied;
1729
+ const body = req.body as Record<string, unknown>;
1730
+ if (!body?.actionIds) return { status_code: 400, body: { error: "actionIds is required" } };
1731
+ const result = await sdk.trigger("mem::crystallize", body);
1732
+ return { status_code: 200, body: result };
1733
+ });
1734
+ sdk.registerTrigger({ type: "http", function_id: "api::crystallize", config: { api_path: "/agentmemory/crystals/create", http_method: "POST" } });
1735
+
1736
+ sdk.registerFunction({ id: "api::crystal-list" }, async (req: ApiRequest) => {
1737
+ const denied = checkAuth(req, secret);
1738
+ if (denied) return denied;
1739
+ const params = req.query_params || {};
1740
+ const result = await sdk.trigger("mem::crystal-list", { project: params.project, sessionId: params.sessionId, limit: params.limit ? parseInt(params.limit as string) : undefined });
1741
+ return { status_code: 200, body: result };
1742
+ });
1743
+ sdk.registerTrigger({ type: "http", function_id: "api::crystal-list", config: { api_path: "/agentmemory/crystals", http_method: "GET" } });
1744
+
1745
+ sdk.registerFunction({ id: "api::auto-crystallize" }, async (req: ApiRequest) => {
1746
+ const denied = checkAuth(req, secret);
1747
+ if (denied) return denied;
1748
+ const body = req.body as Record<string, unknown>;
1749
+ const result = await sdk.trigger("mem::auto-crystallize", body || {});
1750
+ return { status_code: 200, body: result };
1751
+ });
1752
+ sdk.registerTrigger({ type: "http", function_id: "api::auto-crystallize", config: { api_path: "/agentmemory/crystals/auto", http_method: "POST" } });
1753
+
1754
+ sdk.registerFunction({ id: "api::diagnose" }, async (req: ApiRequest) => {
1755
+ const denied = checkAuth(req, secret);
1756
+ if (denied) return denied;
1757
+ const body = req.body as Record<string, unknown>;
1758
+ const result = await sdk.trigger("mem::diagnose", body || {});
1759
+ return { status_code: 200, body: result };
1760
+ });
1761
+ sdk.registerTrigger({ type: "http", function_id: "api::diagnose", config: { api_path: "/agentmemory/diagnostics", http_method: "POST" } });
1762
+
1763
+ sdk.registerFunction({ id: "api::heal" }, async (req: ApiRequest) => {
1764
+ const denied = checkAuth(req, secret);
1765
+ if (denied) return denied;
1766
+ const body = req.body as Record<string, unknown>;
1767
+ const result = await sdk.trigger("mem::heal", body || {});
1768
+ return { status_code: 200, body: result };
1769
+ });
1770
+ sdk.registerTrigger({ type: "http", function_id: "api::heal", config: { api_path: "/agentmemory/diagnostics/heal", http_method: "POST" } });
1771
+
1772
+ sdk.registerFunction({ id: "api::facet-tag" }, async (req: ApiRequest) => {
1773
+ const denied = checkAuth(req, secret);
1774
+ if (denied) return denied;
1775
+ const body = req.body as Record<string, unknown>;
1776
+ if (!body?.targetId || !body?.dimension || !body?.value) return { status_code: 400, body: { error: "targetId, dimension, and value are required" } };
1777
+ const result = await sdk.trigger("mem::facet-tag", body);
1778
+ return { status_code: 200, body: result };
1779
+ });
1780
+ sdk.registerTrigger({ type: "http", function_id: "api::facet-tag", config: { api_path: "/agentmemory/facets", http_method: "POST" } });
1781
+
1782
+ sdk.registerFunction({ id: "api::facet-untag" }, async (req: ApiRequest) => {
1783
+ const denied = checkAuth(req, secret);
1784
+ if (denied) return denied;
1785
+ const body = req.body as Record<string, unknown>;
1786
+ if (!body?.targetId || !body?.dimension) return { status_code: 400, body: { error: "targetId and dimension are required" } };
1787
+ const result = await sdk.trigger("mem::facet-untag", body);
1788
+ return { status_code: 200, body: result };
1789
+ });
1790
+ sdk.registerTrigger({ type: "http", function_id: "api::facet-untag", config: { api_path: "/agentmemory/facets/remove", http_method: "POST" } });
1791
+
1792
+ sdk.registerFunction({ id: "api::facet-query" }, async (req: ApiRequest) => {
1793
+ const denied = checkAuth(req, secret);
1794
+ if (denied) return denied;
1795
+ const body = req.body as Record<string, unknown>;
1796
+ const result = await sdk.trigger("mem::facet-query", body || {});
1797
+ return { status_code: 200, body: result };
1798
+ });
1799
+ sdk.registerTrigger({ type: "http", function_id: "api::facet-query", config: { api_path: "/agentmemory/facets/query", http_method: "POST" } });
1800
+
1801
+ sdk.registerFunction({ id: "api::facet-get" }, async (req: ApiRequest) => {
1802
+ const denied = checkAuth(req, secret);
1803
+ if (denied) return denied;
1804
+ const params = req.query_params || {};
1805
+ if (!params.targetId) return { status_code: 400, body: { error: "targetId query param is required" } };
1806
+ const result = await sdk.trigger("mem::facet-get", { targetId: params.targetId });
1807
+ return { status_code: 200, body: result };
1808
+ });
1809
+ sdk.registerTrigger({ type: "http", function_id: "api::facet-get", config: { api_path: "/agentmemory/facets", http_method: "GET" } });
1810
+
1811
+ sdk.registerFunction({ id: "api::facet-stats" }, async (req: ApiRequest) => {
1812
+ const denied = checkAuth(req, secret);
1813
+ if (denied) return denied;
1814
+ const params = req.query_params || {};
1815
+ const result = await sdk.trigger("mem::facet-stats", { targetType: params.targetType });
1816
+ return { status_code: 200, body: result };
1817
+ });
1818
+ sdk.registerTrigger({ type: "http", function_id: "api::facet-stats", config: { api_path: "/agentmemory/facets/stats", http_method: "GET" } });
1819
+
1820
+ sdk.registerFunction({ id: "api::verify" }, async (req: ApiRequest) => {
1821
+ const denied = checkAuth(req, secret);
1822
+ if (denied) return denied;
1823
+ const body = req.body as Record<string, unknown>;
1824
+ if (!body?.id || typeof body.id !== "string") return { status_code: 400, body: { error: "id is required" } };
1825
+ const result = await sdk.trigger("mem::verify", { id: body.id });
1826
+ return { status_code: 200, body: result };
1827
+ });
1828
+ sdk.registerTrigger({ type: "http", function_id: "api::verify", config: { api_path: "/agentmemory/verify", http_method: "POST" } });
1829
+
1830
+ sdk.registerFunction({ id: "api::cascade-update" }, async (req: ApiRequest) => {
1831
+ const denied = checkAuth(req, secret);
1832
+ if (denied) return denied;
1833
+ const body = req.body as Record<string, unknown>;
1834
+ if (!body?.supersededMemoryId || typeof body.supersededMemoryId !== "string") {
1835
+ return { status_code: 400, body: { error: "supersededMemoryId is required" } };
1836
+ }
1837
+ const result = await sdk.trigger("mem::cascade-update", { supersededMemoryId: body.supersededMemoryId });
1838
+ return { status_code: 200, body: result };
1839
+ });
1840
+ sdk.registerTrigger({ type: "http", function_id: "api::cascade-update", config: { api_path: "/agentmemory/cascade-update", http_method: "POST" } });
1841
+
1842
+ sdk.registerFunction({ id: "api::lesson-save" }, async (req: ApiRequest) => {
1843
+ const denied = checkAuth(req, secret);
1844
+ if (denied) return denied;
1845
+ const body = req.body as Record<string, unknown>;
1846
+ if (!body?.content || typeof body.content !== "string") return { status_code: 400, body: { error: "content is required" } };
1847
+ const tags = typeof body.tags === "string" ? (body.tags as string).split(",").map((t: string) => t.trim()).filter(Boolean) : Array.isArray(body.tags) ? body.tags : [];
1848
+ const result = await sdk.trigger("mem::lesson-save", {
1849
+ content: body.content,
1850
+ context: body.context || "",
1851
+ confidence: typeof body.confidence === "number" ? body.confidence : undefined,
1852
+ project: typeof body.project === "string" ? body.project : undefined,
1853
+ tags,
1854
+ source: "manual",
1855
+ }) as { action?: string };
1856
+ const statusCode = result?.action === "created" ? 201 : 200;
1857
+ return { status_code: statusCode, body: result };
1858
+ });
1859
+ sdk.registerTrigger({ type: "http", function_id: "api::lesson-save", config: { api_path: "/agentmemory/lessons", http_method: "POST" } });
1860
+
1861
+ sdk.registerFunction({ id: "api::lesson-list" }, async (req: ApiRequest) => {
1862
+ const denied = checkAuth(req, secret);
1863
+ if (denied) return denied;
1864
+ const params = req.query_params || {};
1865
+ const result = await sdk.trigger("mem::lesson-list", {
1866
+ project: params.project,
1867
+ source: params.source,
1868
+ minConfidence: params.minConfidence ? parseFloat(params.minConfidence as string) : undefined,
1869
+ limit: params.limit ? parseInt(params.limit as string, 10) : undefined,
1870
+ });
1871
+ return { status_code: 200, body: result };
1872
+ });
1873
+ sdk.registerTrigger({ type: "http", function_id: "api::lesson-list", config: { api_path: "/agentmemory/lessons", http_method: "GET" } });
1874
+
1875
+ sdk.registerFunction({ id: "api::lesson-search" }, async (req: ApiRequest) => {
1876
+ const denied = checkAuth(req, secret);
1877
+ if (denied) return denied;
1878
+ const body = req.body as Record<string, unknown>;
1879
+ if (!body?.query || typeof body.query !== "string") return { status_code: 400, body: { error: "query is required" } };
1880
+ const result = await sdk.trigger("mem::lesson-recall", body);
1881
+ return { status_code: 200, body: result };
1882
+ });
1883
+ sdk.registerTrigger({ type: "http", function_id: "api::lesson-search", config: { api_path: "/agentmemory/lessons/search", http_method: "POST" } });
1884
+
1885
+ sdk.registerFunction({ id: "api::lesson-strengthen" }, async (req: ApiRequest) => {
1886
+ const denied = checkAuth(req, secret);
1887
+ if (denied) return denied;
1888
+ const body = req.body as Record<string, unknown>;
1889
+ if (!body?.lessonId || typeof body.lessonId !== "string") return { status_code: 400, body: { error: "lessonId is required" } };
1890
+ const result = await sdk.trigger("mem::lesson-strengthen", { lessonId: body.lessonId });
1891
+ return { status_code: 200, body: result };
1892
+ });
1893
+ sdk.registerTrigger({ type: "http", function_id: "api::lesson-strengthen", config: { api_path: "/agentmemory/lessons/strengthen", http_method: "POST" } });
1894
+
1895
+ sdk.registerFunction({ id: "api::obsidian-export" }, async (req: ApiRequest) => {
1896
+ const denied = checkAuth(req, secret);
1897
+ if (denied) return denied;
1898
+ const body = (req.body as Record<string, unknown>) || {};
1899
+ const types = typeof body.types === "string" ? body.types.split(",").map((t: string) => t.trim()).filter(Boolean) : undefined;
1900
+ const result = await sdk.trigger("mem::obsidian-export", { vaultDir: body.vaultDir, types });
1901
+ return { status_code: 200, body: result };
1902
+ });
1903
+ sdk.registerTrigger({ type: "http", function_id: "api::obsidian-export", config: { api_path: "/agentmemory/obsidian/export", http_method: "POST" } });
1904
+ }