@agentmemory/agentmemory 0.9.18 → 0.9.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -2
- package/README.md +4 -4
- package/dist/cli.mjs +12 -8
- package/dist/cli.mjs.map +1 -1
- package/dist/hooks/post-commit.d.mts +1 -0
- package/dist/hooks/post-commit.mjs +102 -0
- package/dist/hooks/post-commit.mjs.map +1 -0
- package/dist/index.mjs +354 -66
- package/dist/index.mjs.map +1 -1
- package/dist/{src-C7vygXCj.mjs → src-2wwYDPGA.mjs} +320 -66
- package/dist/src-2wwYDPGA.mjs.map +1 -0
- package/dist/{standalone-kg2TedgD.mjs → standalone-DMLk7YxP.mjs} +2 -2
- package/dist/{standalone-kg2TedgD.mjs.map → standalone-DMLk7YxP.mjs.map} +1 -1
- package/dist/standalone.mjs +34 -1
- package/dist/standalone.mjs.map +1 -1
- package/dist/{tools-registry-BFKFKmYh.mjs → tools-registry-Dz8ssuMf.mjs} +34 -1
- package/dist/tools-registry-Dz8ssuMf.mjs.map +1 -0
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.mcp.json +5 -1
- package/plugin/hooks/hooks.codex.json +4 -0
- package/plugin/scripts/post-commit.d.mts +1 -0
- package/plugin/scripts/post-commit.mjs +102 -0
- package/plugin/scripts/post-commit.mjs.map +1 -0
- package/plugin/skills/commit-context/SKILL.md +19 -0
- package/plugin/skills/commit-history/SKILL.md +20 -0
- package/plugin/skills/handoff/SKILL.md +21 -0
- package/plugin/skills/recap/SKILL.md +25 -0
- package/dist/src-C7vygXCj.mjs.map +0 -1
- package/dist/tools-registry-BFKFKmYh.mjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as STREAM, c as jaccardSimilarity, i as KV, n as bootLog, o as fingerprintId, r as logger, s as generateId, t as VERSION } from "./cli.mjs";
|
|
2
2
|
import { a as isManagedImagePath, getImageRefCount, i as getMaxBytes, n as IMAGES_DIR, r as deleteImage, t as withKeyedLock } from "./image-refs-R3tin9MR.mjs";
|
|
3
|
-
import { _ as loadTeamConfig, a as getConsolidationDecayDays, c as isAutoCompressEnabled, d as isGraphExtractionEnabled, f as loadClaudeBridgeConfig, g as loadSnapshotConfig, h as loadFallbackConfig, i as detectLlmProviderKind, l as isConsolidationEnabled, m as loadEmbeddingConfig, n as getVisibleTools, o as getEnvVar, p as loadConfig, r as detectEmbeddingProvider, t as getAllTools, u as isContextInjectionEnabled } from "./tools-registry-
|
|
3
|
+
import { _ as loadTeamConfig, a as getConsolidationDecayDays, c as isAutoCompressEnabled, d as isGraphExtractionEnabled, f as loadClaudeBridgeConfig, g as loadSnapshotConfig, h as loadFallbackConfig, i as detectLlmProviderKind, l as isConsolidationEnabled, m as loadEmbeddingConfig, n as getVisibleTools, o as getEnvVar, p as loadConfig, r as detectEmbeddingProvider, t as getAllTools, u as isContextInjectionEnabled } from "./tools-registry-Dz8ssuMf.mjs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { execFile } from "node:child_process";
|
|
6
6
|
import { constants, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
@@ -197,11 +197,63 @@ var NoopProvider = class {
|
|
|
197
197
|
}
|
|
198
198
|
};
|
|
199
199
|
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region src/providers/_openai-shared.ts
|
|
202
|
+
const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com";
|
|
203
|
+
const DEFAULT_AZURE_API_VERSION = "2024-08-01-preview";
|
|
204
|
+
function detectAzure(baseUrl) {
|
|
205
|
+
try {
|
|
206
|
+
return new URL(baseUrl).hostname.endsWith(".openai.azure.com");
|
|
207
|
+
} catch {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function azureStyleOf(baseUrl) {
|
|
212
|
+
try {
|
|
213
|
+
const u = new URL(baseUrl);
|
|
214
|
+
if (/\/openai\/deployments\//.test(u.pathname)) return "legacy";
|
|
215
|
+
return "v1";
|
|
216
|
+
} catch {
|
|
217
|
+
return "v1";
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function legacyAzureUrl(baseUrl, path, apiVersion) {
|
|
221
|
+
const url = new URL(baseUrl);
|
|
222
|
+
url.pathname = `${url.pathname.replace(/\/+$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
223
|
+
url.searchParams.set("api-version", apiVersion);
|
|
224
|
+
return url.toString();
|
|
225
|
+
}
|
|
226
|
+
function v1AzureUrl(baseUrl, path) {
|
|
227
|
+
const url = new URL(baseUrl);
|
|
228
|
+
const route = path.startsWith("/") ? path.slice(1) : path;
|
|
229
|
+
url.pathname = `${url.pathname.replace(/\/?openai(?:\/v1)?\/?$/, "").replace(/\/+$/, "")}/openai/v1/${route}`;
|
|
230
|
+
return url.toString();
|
|
231
|
+
}
|
|
232
|
+
function buildChatUrl(baseUrl, isAzure, azureApiVersion) {
|
|
233
|
+
if (isAzure) return azureStyleOf(baseUrl) === "legacy" ? legacyAzureUrl(baseUrl, "/chat/completions", azureApiVersion) : v1AzureUrl(baseUrl, "/chat/completions");
|
|
234
|
+
return `${baseUrl}/v1/chat/completions`;
|
|
235
|
+
}
|
|
236
|
+
function buildEmbeddingUrl(baseUrl, isAzure, azureApiVersion) {
|
|
237
|
+
if (isAzure) return azureStyleOf(baseUrl) === "legacy" ? legacyAzureUrl(baseUrl, "/embeddings", azureApiVersion) : v1AzureUrl(baseUrl, "/embeddings");
|
|
238
|
+
return `${baseUrl}/v1/embeddings`;
|
|
239
|
+
}
|
|
240
|
+
function buildAuthHeaders(apiKey, isAzure) {
|
|
241
|
+
if (isAzure) return {
|
|
242
|
+
"Content-Type": "application/json",
|
|
243
|
+
"api-key": apiKey
|
|
244
|
+
};
|
|
245
|
+
return {
|
|
246
|
+
"Content-Type": "application/json",
|
|
247
|
+
Authorization: `Bearer ${apiKey}`
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function normalizeBaseUrl(raw) {
|
|
251
|
+
return (raw || DEFAULT_OPENAI_BASE_URL).replace(/\/+$/, "");
|
|
252
|
+
}
|
|
253
|
+
|
|
200
254
|
//#endregion
|
|
201
255
|
//#region src/providers/openai.ts
|
|
202
|
-
const DEFAULT_BASE_URL$1 = "https://api.openai.com";
|
|
203
256
|
const DEFAULT_TIMEOUT_MS = 6e4;
|
|
204
|
-
const DEFAULT_AZURE_API_VERSION = "2024-08-01-preview";
|
|
205
257
|
/**
|
|
206
258
|
* OpenAI-compatible LLM provider.
|
|
207
259
|
*
|
|
@@ -248,7 +300,7 @@ var OpenAIProvider = class {
|
|
|
248
300
|
this.apiKey = apiKey;
|
|
249
301
|
this.model = model;
|
|
250
302
|
this.maxTokens = maxTokens;
|
|
251
|
-
this.baseUrl = (baseURL || getEnvVar("OPENAI_BASE_URL")
|
|
303
|
+
this.baseUrl = normalizeBaseUrl(baseURL || getEnvVar("OPENAI_BASE_URL"));
|
|
252
304
|
this.reasoningEffort = getEnvVar("OPENAI_REASONING_EFFORT") || void 0;
|
|
253
305
|
this.timeoutMs = resolveTimeout();
|
|
254
306
|
this.azureApiVersion = getEnvVar("OPENAI_API_VERSION") || DEFAULT_AZURE_API_VERSION;
|
|
@@ -260,25 +312,8 @@ var OpenAIProvider = class {
|
|
|
260
312
|
async summarize(systemPrompt, userPrompt) {
|
|
261
313
|
return this.call(systemPrompt, userPrompt);
|
|
262
314
|
}
|
|
263
|
-
buildUrl() {
|
|
264
|
-
if (this.isAzure) {
|
|
265
|
-
const sep = this.baseUrl.includes("?") ? "&" : "?";
|
|
266
|
-
return `${this.baseUrl}/chat/completions${sep}api-version=${encodeURIComponent(this.azureApiVersion)}`;
|
|
267
|
-
}
|
|
268
|
-
return `${this.baseUrl}/v1/chat/completions`;
|
|
269
|
-
}
|
|
270
|
-
buildHeaders() {
|
|
271
|
-
if (this.isAzure) return {
|
|
272
|
-
"Content-Type": "application/json",
|
|
273
|
-
"api-key": this.apiKey
|
|
274
|
-
};
|
|
275
|
-
return {
|
|
276
|
-
"Content-Type": "application/json",
|
|
277
|
-
Authorization: `Bearer ${this.apiKey}`
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
315
|
async call(systemPrompt, userPrompt) {
|
|
281
|
-
const url = this.
|
|
316
|
+
const url = buildChatUrl(this.baseUrl, this.isAzure, this.azureApiVersion);
|
|
282
317
|
const body = {
|
|
283
318
|
model: this.model,
|
|
284
319
|
max_tokens: this.maxTokens,
|
|
@@ -295,7 +330,7 @@ var OpenAIProvider = class {
|
|
|
295
330
|
try {
|
|
296
331
|
response = await fetchWithTimeout(url, {
|
|
297
332
|
method: "POST",
|
|
298
|
-
headers: this.
|
|
333
|
+
headers: buildAuthHeaders(this.apiKey, this.isAzure),
|
|
299
334
|
body: JSON.stringify(body)
|
|
300
335
|
}, this.timeoutMs);
|
|
301
336
|
} catch (err) {
|
|
@@ -329,13 +364,6 @@ function parsePositiveInt(raw) {
|
|
|
329
364
|
const n = Number(trimmed);
|
|
330
365
|
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
331
366
|
}
|
|
332
|
-
function detectAzure(baseUrl) {
|
|
333
|
-
try {
|
|
334
|
-
return new URL(baseUrl).hostname.endsWith(".openai.azure.com");
|
|
335
|
-
} catch {
|
|
336
|
-
return false;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
367
|
|
|
340
368
|
//#endregion
|
|
341
369
|
//#region src/providers/openrouter.ts
|
|
@@ -565,7 +593,6 @@ function l2Normalize(vec) {
|
|
|
565
593
|
|
|
566
594
|
//#endregion
|
|
567
595
|
//#region src/providers/embedding/openai.ts
|
|
568
|
-
const DEFAULT_BASE_URL = "https://api.openai.com";
|
|
569
596
|
const DEFAULT_MODEL$1 = "text-embedding-3-small";
|
|
570
597
|
/**
|
|
571
598
|
* Known OpenAI embedding model dimensions. Extend as new models ship.
|
|
@@ -589,11 +616,20 @@ function resolveDimensions(model, override) {
|
|
|
589
616
|
/**
|
|
590
617
|
* OpenAI-compatible embedding provider.
|
|
591
618
|
*
|
|
619
|
+
* Shares transport (URL builder, auth header, Azure detection) with
|
|
620
|
+
* the OpenAI LLM provider via `_openai-shared` (#371). Same env knobs
|
|
621
|
+
* pick up automatically: when `OPENAI_BASE_URL` points at an Azure
|
|
622
|
+
* resource (`.openai.azure.com` hostname) the embedding request uses
|
|
623
|
+
* Azure's `/embeddings` path with the `api-version` query param and
|
|
624
|
+
* `api-key` header instead of `Authorization: Bearer`.
|
|
625
|
+
*
|
|
592
626
|
* Required env vars:
|
|
593
627
|
* OPENAI_API_KEY — API key
|
|
594
628
|
*
|
|
595
629
|
* Optional:
|
|
596
|
-
* OPENAI_BASE_URL — base URL without path (default: https://api.openai.com)
|
|
630
|
+
* OPENAI_BASE_URL — base URL without path (default: https://api.openai.com).
|
|
631
|
+
* Azure: https://<resource>.openai.azure.com/openai/deployments/<deployment>
|
|
632
|
+
* OPENAI_API_VERSION — Azure api-version query param (default: 2024-08-01-preview)
|
|
597
633
|
* OPENAI_EMBEDDING_MODEL — model name (default: text-embedding-3-small)
|
|
598
634
|
* OPENAI_EMBEDDING_DIMENSIONS — override reported dimensions (required for
|
|
599
635
|
* custom / self-hosted models not in the
|
|
@@ -605,24 +641,25 @@ var OpenAIEmbeddingProvider = class {
|
|
|
605
641
|
apiKey;
|
|
606
642
|
baseUrl;
|
|
607
643
|
model;
|
|
644
|
+
isAzure;
|
|
645
|
+
azureApiVersion;
|
|
608
646
|
constructor(apiKey) {
|
|
609
647
|
this.apiKey = apiKey || getEnvVar("OPENAI_API_KEY") || "";
|
|
610
648
|
if (!this.apiKey) throw new Error("OPENAI_API_KEY is required");
|
|
611
|
-
this.baseUrl = getEnvVar("OPENAI_BASE_URL")
|
|
649
|
+
this.baseUrl = normalizeBaseUrl(getEnvVar("OPENAI_BASE_URL"));
|
|
612
650
|
this.model = getEnvVar("OPENAI_EMBEDDING_MODEL") || DEFAULT_MODEL$1;
|
|
613
651
|
this.dimensions = resolveDimensions(this.model, getEnvVar("OPENAI_EMBEDDING_DIMENSIONS"));
|
|
652
|
+
this.isAzure = detectAzure(this.baseUrl);
|
|
653
|
+
this.azureApiVersion = getEnvVar("OPENAI_API_VERSION") || DEFAULT_AZURE_API_VERSION;
|
|
614
654
|
}
|
|
615
655
|
async embed(text) {
|
|
616
656
|
const [result] = await this.embedBatch([text]);
|
|
617
657
|
return result;
|
|
618
658
|
}
|
|
619
659
|
async embedBatch(texts) {
|
|
620
|
-
const response = await fetchWithTimeout(
|
|
660
|
+
const response = await fetchWithTimeout(buildEmbeddingUrl(this.baseUrl, this.isAzure, this.azureApiVersion), {
|
|
621
661
|
method: "POST",
|
|
622
|
-
headers:
|
|
623
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
624
|
-
"Content-Type": "application/json"
|
|
625
|
-
},
|
|
662
|
+
headers: buildAuthHeaders(this.apiKey, this.isAzure),
|
|
626
663
|
body: JSON.stringify({
|
|
627
664
|
model: this.model,
|
|
628
665
|
input: texts
|
|
@@ -1154,7 +1191,7 @@ var GraphRetrieval = class {
|
|
|
1154
1191
|
const results = [];
|
|
1155
1192
|
const visitedObs = /* @__PURE__ */ new Set();
|
|
1156
1193
|
for (const startNode of matchingNodes) {
|
|
1157
|
-
const paths = this.
|
|
1194
|
+
const paths = this.dijkstraTraversal(startNode, allNodes, allEdges, maxDepth);
|
|
1158
1195
|
for (const path of paths) {
|
|
1159
1196
|
const lastNode = path[path.length - 1].node;
|
|
1160
1197
|
for (const obsId of lastNode.sourceObservationIds) {
|
|
@@ -1194,7 +1231,7 @@ var GraphRetrieval = class {
|
|
|
1194
1231
|
const results = [];
|
|
1195
1232
|
const visitedObs = new Set(obsIds);
|
|
1196
1233
|
for (const node of linkedNodes) {
|
|
1197
|
-
const paths = this.
|
|
1234
|
+
const paths = this.dijkstraTraversal(node, allNodes, allEdges, maxDepth);
|
|
1198
1235
|
for (const path of paths) {
|
|
1199
1236
|
const lastNode = path[path.length - 1].node;
|
|
1200
1237
|
for (const obsId of lastNode.sourceObservationIds) {
|
|
@@ -1266,37 +1303,104 @@ var GraphRetrieval = class {
|
|
|
1266
1303
|
}
|
|
1267
1304
|
return latest;
|
|
1268
1305
|
}
|
|
1269
|
-
|
|
1270
|
-
const
|
|
1271
|
-
const
|
|
1272
|
-
const
|
|
1306
|
+
dijkstraTraversal(startNode, allNodes, allEdges, maxDepth) {
|
|
1307
|
+
const nodeIndex = /* @__PURE__ */ new Map();
|
|
1308
|
+
for (const n of allNodes) nodeIndex.set(n.id, n);
|
|
1309
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
1310
|
+
for (const edge of allEdges) {
|
|
1311
|
+
const a = edge.sourceNodeId;
|
|
1312
|
+
const b = edge.targetNodeId;
|
|
1313
|
+
if (!adjacency.has(a)) adjacency.set(a, []);
|
|
1314
|
+
if (!adjacency.has(b)) adjacency.set(b, []);
|
|
1315
|
+
adjacency.get(a).push({
|
|
1316
|
+
neighborId: b,
|
|
1317
|
+
edge
|
|
1318
|
+
});
|
|
1319
|
+
adjacency.get(b).push({
|
|
1320
|
+
neighborId: a,
|
|
1321
|
+
edge
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
const dist = /* @__PURE__ */ new Map();
|
|
1325
|
+
const pathTo = /* @__PURE__ */ new Map();
|
|
1326
|
+
dist.set(startNode.id, 0);
|
|
1327
|
+
pathTo.set(startNode.id, [{ node: startNode }]);
|
|
1328
|
+
const heap = new MinHeap((a, b) => a.cost - b.cost);
|
|
1329
|
+
heap.push({
|
|
1273
1330
|
nodeId: startNode.id,
|
|
1274
1331
|
depth: 0,
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
paths.push(path);
|
|
1332
|
+
cost: 0
|
|
1333
|
+
});
|
|
1334
|
+
while (heap.size() > 0) {
|
|
1335
|
+
const { nodeId, depth, cost } = heap.pop();
|
|
1336
|
+
if (cost > (dist.get(nodeId) ?? Infinity)) continue;
|
|
1281
1337
|
if (depth >= maxDepth) continue;
|
|
1282
|
-
const
|
|
1283
|
-
for (const edge of
|
|
1284
|
-
const
|
|
1285
|
-
if (visited.has(nextId)) continue;
|
|
1286
|
-
visited.add(nextId);
|
|
1287
|
-
const nextNode = allNodes.find((n) => n.id === nextId);
|
|
1338
|
+
const neighbors = adjacency.get(nodeId) ?? [];
|
|
1339
|
+
for (const { neighborId, edge } of neighbors) {
|
|
1340
|
+
const nextNode = nodeIndex.get(neighborId);
|
|
1288
1341
|
if (!nextNode) continue;
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1342
|
+
const newCost = cost + 1 / Math.max(edge.weight, .01);
|
|
1343
|
+
if (newCost < (dist.get(neighborId) ?? Infinity)) {
|
|
1344
|
+
dist.set(neighborId, newCost);
|
|
1345
|
+
pathTo.set(neighborId, [...pathTo.get(nodeId), {
|
|
1293
1346
|
node: nextNode,
|
|
1294
1347
|
edge
|
|
1295
|
-
}]
|
|
1296
|
-
|
|
1348
|
+
}]);
|
|
1349
|
+
heap.push({
|
|
1350
|
+
nodeId: neighborId,
|
|
1351
|
+
depth: depth + 1,
|
|
1352
|
+
cost: newCost
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1297
1355
|
}
|
|
1298
1356
|
}
|
|
1299
|
-
|
|
1357
|
+
pathTo.delete(startNode.id);
|
|
1358
|
+
return Array.from(pathTo.values());
|
|
1359
|
+
}
|
|
1360
|
+
};
|
|
1361
|
+
var MinHeap = class {
|
|
1362
|
+
heap = [];
|
|
1363
|
+
constructor(compare) {
|
|
1364
|
+
this.compare = compare;
|
|
1365
|
+
}
|
|
1366
|
+
size() {
|
|
1367
|
+
return this.heap.length;
|
|
1368
|
+
}
|
|
1369
|
+
push(value) {
|
|
1370
|
+
this.heap.push(value);
|
|
1371
|
+
this.bubbleUp(this.heap.length - 1);
|
|
1372
|
+
}
|
|
1373
|
+
pop() {
|
|
1374
|
+
if (this.heap.length === 0) return void 0;
|
|
1375
|
+
const top = this.heap[0];
|
|
1376
|
+
const last = this.heap.pop();
|
|
1377
|
+
if (this.heap.length > 0) {
|
|
1378
|
+
this.heap[0] = last;
|
|
1379
|
+
this.sinkDown(0);
|
|
1380
|
+
}
|
|
1381
|
+
return top;
|
|
1382
|
+
}
|
|
1383
|
+
bubbleUp(i) {
|
|
1384
|
+
while (i > 0) {
|
|
1385
|
+
const parent = i - 1 >> 1;
|
|
1386
|
+
if (this.compare(this.heap[i], this.heap[parent]) < 0) {
|
|
1387
|
+
[this.heap[i], this.heap[parent]] = [this.heap[parent], this.heap[i]];
|
|
1388
|
+
i = parent;
|
|
1389
|
+
} else break;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
sinkDown(i) {
|
|
1393
|
+
const n = this.heap.length;
|
|
1394
|
+
while (true) {
|
|
1395
|
+
const left = 2 * i + 1;
|
|
1396
|
+
const right = 2 * i + 2;
|
|
1397
|
+
let smallest = i;
|
|
1398
|
+
if (left < n && this.compare(this.heap[left], this.heap[smallest]) < 0) smallest = left;
|
|
1399
|
+
if (right < n && this.compare(this.heap[right], this.heap[smallest]) < 0) smallest = right;
|
|
1400
|
+
if (smallest === i) break;
|
|
1401
|
+
[this.heap[i], this.heap[smallest]] = [this.heap[smallest], this.heap[i]];
|
|
1402
|
+
i = smallest;
|
|
1403
|
+
}
|
|
1300
1404
|
}
|
|
1301
1405
|
};
|
|
1302
1406
|
|
|
@@ -5896,7 +6000,8 @@ function registerExportImportFunction(sdk, kv) {
|
|
|
5896
6000
|
"0.9.15",
|
|
5897
6001
|
"0.9.16",
|
|
5898
6002
|
"0.9.17",
|
|
5899
|
-
"0.9.18"
|
|
6003
|
+
"0.9.18",
|
|
6004
|
+
"0.9.19"
|
|
5900
6005
|
]).has(importData.version)) return {
|
|
5901
6006
|
success: false,
|
|
5902
6007
|
error: `Unsupported export version: ${importData.version}`
|
|
@@ -13724,6 +13829,112 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
13724
13829
|
middleware_function_ids: ["middleware::api-auth"]
|
|
13725
13830
|
}
|
|
13726
13831
|
});
|
|
13832
|
+
sdk.registerFunction("api::session::commit", async (req) => {
|
|
13833
|
+
const body = req.body ?? {};
|
|
13834
|
+
const sha = asNonEmptyString$1(body.sha);
|
|
13835
|
+
if (!sha) return {
|
|
13836
|
+
status_code: 400,
|
|
13837
|
+
body: { error: "sha is required and must be a non-empty string" }
|
|
13838
|
+
};
|
|
13839
|
+
const sessionId = asNonEmptyString$1(body.sessionId) ?? void 0;
|
|
13840
|
+
const branch = asNonEmptyString$1(body.branch) ?? void 0;
|
|
13841
|
+
const repo = asNonEmptyString$1(body.repo) ?? void 0;
|
|
13842
|
+
const message = asNonEmptyString$1(body.message) ?? void 0;
|
|
13843
|
+
const author = asNonEmptyString$1(body.author) ?? void 0;
|
|
13844
|
+
const authoredAt = asNonEmptyString$1(body.authoredAt) ?? void 0;
|
|
13845
|
+
const files = Array.isArray(body.files) ? body.files.filter((f) => typeof f === "string" && f.length > 0) : void 0;
|
|
13846
|
+
const link = await withKeyedLock(`commit:${sha}`, async () => {
|
|
13847
|
+
const existing = await kv.get(KV.commits, sha);
|
|
13848
|
+
const sessionSet = new Set(existing?.sessionIds ?? []);
|
|
13849
|
+
if (sessionId) sessionSet.add(sessionId);
|
|
13850
|
+
const merged = {
|
|
13851
|
+
sha,
|
|
13852
|
+
shortSha: existing?.shortSha ?? sha.slice(0, 7),
|
|
13853
|
+
branch: branch ?? existing?.branch,
|
|
13854
|
+
repo: repo ?? existing?.repo,
|
|
13855
|
+
message: message ?? existing?.message,
|
|
13856
|
+
author: author ?? existing?.author,
|
|
13857
|
+
authoredAt: authoredAt ?? existing?.authoredAt,
|
|
13858
|
+
files: files ?? existing?.files,
|
|
13859
|
+
sessionIds: Array.from(sessionSet),
|
|
13860
|
+
linkedAt: existing?.linkedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
13861
|
+
};
|
|
13862
|
+
await kv.set(KV.commits, sha, merged);
|
|
13863
|
+
return merged;
|
|
13864
|
+
});
|
|
13865
|
+
if (sessionId) await withKeyedLock(`session:${sessionId}`, async () => {
|
|
13866
|
+
const session = await kv.get(KV.sessions, sessionId);
|
|
13867
|
+
if (!session) return;
|
|
13868
|
+
const shaSet = new Set(session.commitShas ?? []);
|
|
13869
|
+
shaSet.add(sha);
|
|
13870
|
+
session.commitShas = Array.from(shaSet);
|
|
13871
|
+
await kv.set(KV.sessions, sessionId, session);
|
|
13872
|
+
});
|
|
13873
|
+
return {
|
|
13874
|
+
status_code: 200,
|
|
13875
|
+
body: { commit: link }
|
|
13876
|
+
};
|
|
13877
|
+
});
|
|
13878
|
+
sdk.registerTrigger({
|
|
13879
|
+
type: "http",
|
|
13880
|
+
function_id: "api::session::commit",
|
|
13881
|
+
config: {
|
|
13882
|
+
api_path: "/agentmemory/session/commit",
|
|
13883
|
+
http_method: "POST",
|
|
13884
|
+
middleware_function_ids: ["middleware::api-auth"]
|
|
13885
|
+
}
|
|
13886
|
+
});
|
|
13887
|
+
sdk.registerFunction("api::session::by-commit", async (req) => {
|
|
13888
|
+
const authErr = checkAuth(req, secret);
|
|
13889
|
+
if (authErr) return authErr;
|
|
13890
|
+
const sha = asNonEmptyString$1(req.query_params?.["sha"]);
|
|
13891
|
+
if (!sha) return {
|
|
13892
|
+
status_code: 400,
|
|
13893
|
+
body: { error: "sha is required and must be a non-empty string" }
|
|
13894
|
+
};
|
|
13895
|
+
const link = await kv.get(KV.commits, sha);
|
|
13896
|
+
if (!link) return {
|
|
13897
|
+
status_code: 404,
|
|
13898
|
+
body: { error: "no sessions linked to this commit" }
|
|
13899
|
+
};
|
|
13900
|
+
return {
|
|
13901
|
+
status_code: 200,
|
|
13902
|
+
body: {
|
|
13903
|
+
commit: link,
|
|
13904
|
+
sessions: (await Promise.all((link.sessionIds ?? []).map((sid) => kv.get(KV.sessions, sid)))).filter((s) => s !== null)
|
|
13905
|
+
}
|
|
13906
|
+
};
|
|
13907
|
+
});
|
|
13908
|
+
sdk.registerTrigger({
|
|
13909
|
+
type: "http",
|
|
13910
|
+
function_id: "api::session::by-commit",
|
|
13911
|
+
config: {
|
|
13912
|
+
api_path: "/agentmemory/session/by-commit",
|
|
13913
|
+
http_method: "GET",
|
|
13914
|
+
middleware_function_ids: ["middleware::api-auth"]
|
|
13915
|
+
}
|
|
13916
|
+
});
|
|
13917
|
+
sdk.registerFunction("api::commits", async (req) => {
|
|
13918
|
+
const authErr = checkAuth(req, secret);
|
|
13919
|
+
if (authErr) return authErr;
|
|
13920
|
+
const branch = asNonEmptyString$1(req.query_params?.["branch"]);
|
|
13921
|
+
const repo = asNonEmptyString$1(req.query_params?.["repo"]);
|
|
13922
|
+
const rawLimit = parseOptionalInt(req.query_params?.["limit"]);
|
|
13923
|
+
const limit = Math.max(1, Math.min(500, rawLimit ?? 100));
|
|
13924
|
+
return {
|
|
13925
|
+
status_code: 200,
|
|
13926
|
+
body: { commits: (await kv.list(KV.commits)).filter((c) => !branch || c.branch === branch).filter((c) => !repo || c.repo === repo).sort((a, b) => (a.linkedAt ?? "") < (b.linkedAt ?? "") ? 1 : -1).slice(0, limit) }
|
|
13927
|
+
};
|
|
13928
|
+
});
|
|
13929
|
+
sdk.registerTrigger({
|
|
13930
|
+
type: "http",
|
|
13931
|
+
function_id: "api::commits",
|
|
13932
|
+
config: {
|
|
13933
|
+
api_path: "/agentmemory/commits",
|
|
13934
|
+
http_method: "GET",
|
|
13935
|
+
middleware_function_ids: ["middleware::api-auth"]
|
|
13936
|
+
}
|
|
13937
|
+
});
|
|
13727
13938
|
sdk.registerFunction("api::sessions", async (req) => {
|
|
13728
13939
|
const authErr = checkAuth(req, secret);
|
|
13729
13940
|
if (authErr) return authErr;
|
|
@@ -17705,6 +17916,49 @@ function registerMcpEndpoints(sdk, kv, secret) {
|
|
|
17705
17916
|
}] }
|
|
17706
17917
|
};
|
|
17707
17918
|
}
|
|
17919
|
+
case "memory_commit_lookup": {
|
|
17920
|
+
const sha = asNonEmptyString(args.sha);
|
|
17921
|
+
if (!sha) return {
|
|
17922
|
+
status_code: 400,
|
|
17923
|
+
body: { error: "sha required" }
|
|
17924
|
+
};
|
|
17925
|
+
const link = await kv.get(KV.commits, sha);
|
|
17926
|
+
if (!link) return {
|
|
17927
|
+
status_code: 200,
|
|
17928
|
+
body: { content: [{
|
|
17929
|
+
type: "text",
|
|
17930
|
+
text: JSON.stringify({
|
|
17931
|
+
commit: null,
|
|
17932
|
+
sessions: []
|
|
17933
|
+
}, null, 2)
|
|
17934
|
+
}] }
|
|
17935
|
+
};
|
|
17936
|
+
const linkRecord = link;
|
|
17937
|
+
const sessions = (await Promise.all((linkRecord.sessionIds ?? []).map((sid) => kv.get(KV.sessions, sid)))).filter((s) => s !== null);
|
|
17938
|
+
return {
|
|
17939
|
+
status_code: 200,
|
|
17940
|
+
body: { content: [{
|
|
17941
|
+
type: "text",
|
|
17942
|
+
text: JSON.stringify({
|
|
17943
|
+
commit: link,
|
|
17944
|
+
sessions
|
|
17945
|
+
}, null, 2)
|
|
17946
|
+
}] }
|
|
17947
|
+
};
|
|
17948
|
+
}
|
|
17949
|
+
case "memory_commits": {
|
|
17950
|
+
const branch = typeof args.branch === "string" ? args.branch : void 0;
|
|
17951
|
+
const repo = typeof args.repo === "string" ? args.repo : void 0;
|
|
17952
|
+
const limit = Math.max(1, Math.min(500, asNumber(args.limit, 100) ?? 100));
|
|
17953
|
+
const filtered = (await kv.list(KV.commits)).filter((c) => !branch || c.branch === branch).filter((c) => !repo || c.repo === repo).sort((a, b) => (a.linkedAt ?? "") < (b.linkedAt ?? "") ? 1 : -1).slice(0, limit);
|
|
17954
|
+
return {
|
|
17955
|
+
status_code: 200,
|
|
17956
|
+
body: { content: [{
|
|
17957
|
+
type: "text",
|
|
17958
|
+
text: JSON.stringify({ commits: filtered }, null, 2)
|
|
17959
|
+
}] }
|
|
17960
|
+
};
|
|
17961
|
+
}
|
|
17708
17962
|
default: return {
|
|
17709
17963
|
status_code: 400,
|
|
17710
17964
|
body: { error: `Unknown tool: ${name}` }
|
|
@@ -18617,7 +18871,7 @@ async function main() {
|
|
|
18617
18871
|
console.warn(`[agentmemory] Failed to backfill memories into BM25:`, err);
|
|
18618
18872
|
}
|
|
18619
18873
|
bootLog(`Ready. ${embeddingProvider ? "Triple-stream (BM25+Vector+Graph)" : "BM25+Graph"} search active.`);
|
|
18620
|
-
bootLog(`REST API:
|
|
18874
|
+
bootLog(`REST API: 124 endpoints at http://localhost:${config.restPort}/agentmemory/*`);
|
|
18621
18875
|
bootLog(`MCP surface (opt-in via \`npx @agentmemory/mcp\`): ${getAllTools().length} tools · 6 resources · 3 prompts`);
|
|
18622
18876
|
const viewerServer = startViewerServer(config.restPort + 2, kv, sdk, secret, config.restPort);
|
|
18623
18877
|
const autoForgetIntervalMs = parseInt(process.env.AUTO_FORGET_INTERVAL_MS || "3600000", 10);
|
|
@@ -18685,4 +18939,4 @@ main().catch((err) => {
|
|
|
18685
18939
|
|
|
18686
18940
|
//#endregion
|
|
18687
18941
|
export { };
|
|
18688
|
-
//# sourceMappingURL=src-
|
|
18942
|
+
//# sourceMappingURL=src-2wwYDPGA.mjs.map
|