@agentmemory/agentmemory 0.9.25 → 0.9.27
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 +1 -1
- package/README.md +10 -8
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +41 -24
- package/dist/cli.mjs.map +1 -1
- package/dist/{image-refs-C7h9L5wx.mjs → image-refs-B5Zf_Djo.mjs} +2 -2
- package/dist/{image-refs-C7h9L5wx.mjs.map → image-refs-B5Zf_Djo.mjs.map} +1 -1
- package/dist/index.mjs +445 -58
- package/dist/index.mjs.map +1 -1
- package/dist/{schema-Dsr_V2Wp.mjs → schema-CNiCWzV9.mjs} +5 -1
- package/dist/schema-CNiCWzV9.mjs.map +1 -0
- package/dist/{src-fQOMXeCp.mjs → src-MOg2zKJs.mjs} +445 -64
- package/dist/src-MOg2zKJs.mjs.map +1 -0
- package/dist/{standalone-BzfA1zu8.mjs → standalone-BORXC71-.mjs} +4 -4
- package/dist/{standalone-BzfA1zu8.mjs.map → standalone-BORXC71-.mjs.map} +1 -1
- package/dist/standalone.mjs +1 -1
- package/dist/standalone.mjs.map +1 -1
- package/dist/{tools-registry-Dzxv9iUu.mjs → tools-registry-D8XVVPbJ.mjs} +6 -4
- package/dist/tools-registry-D8XVVPbJ.mjs.map +1 -0
- package/dist/version-9DNrRyph.mjs +6 -0
- package/dist/version-9DNrRyph.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/plugin.json +1 -1
- package/dist/schema-Dsr_V2Wp.mjs.map +0 -1
- package/dist/src-fQOMXeCp.mjs.map +0 -1
- package/dist/tools-registry-Dzxv9iUu.mjs.map +0 -1
- package/dist/version-C3hZKw8n.mjs +0 -6
- package/dist/version-C3hZKw8n.mjs.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as jaccardSimilarity, i as generateId, n as STREAM, r as fingerprintId, t as KV } from "./schema-
|
|
1
|
+
import { a as jaccardSimilarity, i as generateId, n as STREAM, r as fingerprintId, t as KV } from "./schema-CNiCWzV9.mjs";
|
|
2
2
|
import { n as logger, t as bootLog } from "./logger-yHTcEBAI.mjs";
|
|
3
|
-
import { t as VERSION } from "./version-
|
|
3
|
+
import { t as VERSION } from "./version-9DNrRyph.mjs";
|
|
4
4
|
import { a as isManagedImagePath, n as deleteImage, r as getMaxBytes, t as IMAGES_DIR } from "./image-store-Gpo2mgM9.mjs";
|
|
5
|
-
import { r as withKeyedLock, t as getImageRefCount } from "./image-refs-
|
|
6
|
-
import { _ as loadConfig, a as getAgentId, b as loadSnapshotConfig, c as getFollowupWindowSeconds, d as isAutoCompressEnabled, f as isConsolidationEnabled, g as loadClaudeBridgeConfig, h as isGraphExtractionEnabled, i as detectLlmProviderKind, m as isDropStaleIndexEnabled, n as getVisibleTools, o as getConsolidationDecayDays, p as isContextInjectionEnabled, r as detectEmbeddingProvider, s as getEnvVar, t as getAllTools, u as isAgentScopeIsolated, v as loadEmbeddingConfig, x as loadTeamConfig, y as loadFallbackConfig } from "./tools-registry-
|
|
5
|
+
import { r as withKeyedLock, t as getImageRefCount } from "./image-refs-B5Zf_Djo.mjs";
|
|
6
|
+
import { _ as loadConfig, a as getAgentId, b as loadSnapshotConfig, c as getFollowupWindowSeconds, d as isAutoCompressEnabled, f as isConsolidationEnabled, g as loadClaudeBridgeConfig, h as isGraphExtractionEnabled, i as detectLlmProviderKind, m as isDropStaleIndexEnabled, n as getVisibleTools, o as getConsolidationDecayDays, p as isContextInjectionEnabled, r as detectEmbeddingProvider, s as getEnvVar, t as getAllTools, u as isAgentScopeIsolated, v as loadEmbeddingConfig, x as loadTeamConfig, y as loadFallbackConfig } from "./tools-registry-D8XVVPbJ.mjs";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { execFile } from "node:child_process";
|
|
9
9
|
import { constants, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
@@ -2627,7 +2627,7 @@ var IndexPersistence = class {
|
|
|
2627
2627
|
async loadShardedData(legacyKey, manifestKey, label) {
|
|
2628
2628
|
const manifest = await this.readIndexValue(KV.bm25Index, manifestKey, label, "manifest");
|
|
2629
2629
|
if (!manifest.ok) return null;
|
|
2630
|
-
if (manifest.value
|
|
2630
|
+
if (manifest.value != null && typeof manifest.value === "object") return this.loadManifestData(manifest.value, label);
|
|
2631
2631
|
const legacy = await this.readIndexValue(KV.bm25Index, legacyKey, label, "legacy");
|
|
2632
2632
|
if (!legacy.ok) return null;
|
|
2633
2633
|
if (legacy.value && typeof legacy.value === "string") return legacy.value;
|
|
@@ -3109,6 +3109,12 @@ function registerSearchFunction(sdk, kv) {
|
|
|
3109
3109
|
}
|
|
3110
3110
|
const projectFilter = typeof data.project === "string" && data.project.trim().length > 0 ? data.project.trim() : void 0;
|
|
3111
3111
|
const cwdFilter = typeof data.cwd === "string" && data.cwd.trim().length > 0 ? data.cwd.trim() : void 0;
|
|
3112
|
+
const isolated = isAgentScopeIsolated();
|
|
3113
|
+
const explicitAgentId = typeof data.agentId === "string" && data.agentId.trim().length > 0 ? data.agentId.trim() : void 0;
|
|
3114
|
+
const wildcardAgent = explicitAgentId === "*";
|
|
3115
|
+
const envAgentId = isolated ? getAgentId() : void 0;
|
|
3116
|
+
const filterAgentId = wildcardAgent ? void 0 : explicitAgentId ?? envAgentId;
|
|
3117
|
+
if (isolated && !wildcardAgent && !explicitAgentId && !envAgentId) throw new Error("mem::search: AGENTMEMORY_AGENT_SCOPE=isolated is set but no agent id is available (env AGENT_ID unset and no explicit agentId in the call). Refusing to read cross-agent rows. Pass agentId: \"*\" to opt in to a wildcard read.");
|
|
3112
3118
|
const format = typeof data.format === "string" ? data.format : "full";
|
|
3113
3119
|
if (![
|
|
3114
3120
|
"full",
|
|
@@ -3124,7 +3130,7 @@ function registerSearchFunction(sdk, kv) {
|
|
|
3124
3130
|
const count = await rebuildIndex(kv);
|
|
3125
3131
|
logger.info("Search index rebuilt", { entries: count });
|
|
3126
3132
|
}
|
|
3127
|
-
const filtering = !!(projectFilter || cwdFilter);
|
|
3133
|
+
const filtering = !!(projectFilter || cwdFilter || filterAgentId);
|
|
3128
3134
|
const fetchLimit = filtering ? Math.max(effectiveLimit * 10, 100) : effectiveLimit;
|
|
3129
3135
|
const results = idx.search(query, fetchLimit);
|
|
3130
3136
|
const sessionCache = /* @__PURE__ */ new Map();
|
|
@@ -3141,9 +3147,10 @@ function registerSearchFunction(sdk, kv) {
|
|
|
3141
3147
|
memoryProjectCache.set(obsId, proj);
|
|
3142
3148
|
return proj;
|
|
3143
3149
|
};
|
|
3150
|
+
const earlyCap = filterAgentId ? fetchLimit : effectiveLimit;
|
|
3144
3151
|
const candidates = [];
|
|
3145
3152
|
for (const r of results) {
|
|
3146
|
-
if (candidates.length >=
|
|
3153
|
+
if (candidates.length >= earlyCap) break;
|
|
3147
3154
|
if (filtering) {
|
|
3148
3155
|
const s = await loadSession(r.sessionId);
|
|
3149
3156
|
if (s) {
|
|
@@ -3165,7 +3172,10 @@ function registerSearchFunction(sdk, kv) {
|
|
|
3165
3172
|
const enriched = [];
|
|
3166
3173
|
for (let i = 0; i < candidates.length; i++) {
|
|
3167
3174
|
const obs = obsResults[i];
|
|
3168
|
-
if (obs)
|
|
3175
|
+
if (!obs) continue;
|
|
3176
|
+
if (filterAgentId !== void 0 && obs.agentId !== filterAgentId) continue;
|
|
3177
|
+
if (enriched.length >= effectiveLimit) break;
|
|
3178
|
+
enriched.push({
|
|
3169
3179
|
observation: obs,
|
|
3170
3180
|
score: candidates[i].score,
|
|
3171
3181
|
sessionId: candidates[i].sessionId
|
|
@@ -3330,7 +3340,7 @@ function registerObserveFunction(sdk, kv, dedupMap, maxObservationsPerSession) {
|
|
|
3330
3340
|
const { saveImageToDisk } = await import("./image-store-Gpo2mgM9.mjs").then((n) => n.i);
|
|
3331
3341
|
const { filePath, bytesWritten } = await saveImageToDisk(pendingImageData);
|
|
3332
3342
|
raw.imageData = filePath;
|
|
3333
|
-
const { incrementImageRef } = await import("./image-refs-
|
|
3343
|
+
const { incrementImageRef } = await import("./image-refs-B5Zf_Djo.mjs").then((n) => n.n);
|
|
3334
3344
|
await incrementImageRef(kv, filePath);
|
|
3335
3345
|
sdk.trigger({
|
|
3336
3346
|
function_id: "mem::disk-size-delta",
|
|
@@ -5651,7 +5661,7 @@ function registerRememberFunction(sdk, kv) {
|
|
|
5651
5661
|
const deletedMemoryIds = [];
|
|
5652
5662
|
const deletedObservationIds = [];
|
|
5653
5663
|
let deletedSession = false;
|
|
5654
|
-
const { decrementImageRef } = await import("./image-refs-
|
|
5664
|
+
const { decrementImageRef } = await import("./image-refs-B5Zf_Djo.mjs").then((n) => n.n);
|
|
5655
5665
|
if (data.memoryId) {
|
|
5656
5666
|
const mem = await kv.get(KV.memories, data.memoryId);
|
|
5657
5667
|
await kv.delete(KV.memories, data.memoryId);
|
|
@@ -5758,7 +5768,7 @@ async function runRecoveredSessionConsolidation(sdk) {
|
|
|
5758
5768
|
function registerEvictFunction(sdk, kv) {
|
|
5759
5769
|
sdk.registerFunction("mem::evict", async (data) => {
|
|
5760
5770
|
const dryRun = data?.dryRun ?? false;
|
|
5761
|
-
const { decrementImageRef } = await import("./image-refs-
|
|
5771
|
+
const { decrementImageRef } = await import("./image-refs-B5Zf_Djo.mjs").then((n) => n.n);
|
|
5762
5772
|
const configOverride = await kv.get(KV.config, "eviction").catch(() => null);
|
|
5763
5773
|
const cfg = {
|
|
5764
5774
|
...DEFAULTS$1,
|
|
@@ -6278,7 +6288,10 @@ function registerSmartSearchFunction(sdk, kv, searchFn) {
|
|
|
6278
6288
|
sdk.registerFunction("mem::smart-search", async (data) => {
|
|
6279
6289
|
const isolated = isAgentScopeIsolated();
|
|
6280
6290
|
const explicitAgentId = typeof data.agentId === "string" && data.agentId.trim().length > 0 ? data.agentId.trim() : void 0;
|
|
6281
|
-
const
|
|
6291
|
+
const wildcardAgent = explicitAgentId === "*";
|
|
6292
|
+
const envAgentId = isolated ? getAgentId() : void 0;
|
|
6293
|
+
const filterAgentId = wildcardAgent ? void 0 : explicitAgentId ?? envAgentId;
|
|
6294
|
+
if (isolated && !wildcardAgent && !explicitAgentId && !envAgentId) throw new Error("mem::smart-search: AGENTMEMORY_AGENT_SCOPE=isolated is set but no agent id is available (env AGENT_ID unset and no explicit agentId in the call). Refusing to read cross-agent rows. Pass agentId: \"*\" to opt in to a wildcard read.");
|
|
6282
6295
|
if (data.expandIds && data.expandIds.length > 0) {
|
|
6283
6296
|
const raw = data.expandIds.slice(0, 20);
|
|
6284
6297
|
const items = raw.map((entry) => {
|
|
@@ -6570,7 +6583,7 @@ function registerAutoForgetFunction(sdk, kv) {
|
|
|
6570
6583
|
sdk.registerFunction("mem::auto-forget", async (data) => {
|
|
6571
6584
|
const dryRun = data?.dryRun ?? false;
|
|
6572
6585
|
const now = Date.now();
|
|
6573
|
-
const { decrementImageRef } = await import("./image-refs-
|
|
6586
|
+
const { decrementImageRef } = await import("./image-refs-B5Zf_Djo.mjs").then((n) => n.n);
|
|
6574
6587
|
const result = {
|
|
6575
6588
|
ttlExpired: [],
|
|
6576
6589
|
contradictions: [],
|
|
@@ -6828,7 +6841,9 @@ function registerExportImportFunction(sdk, kv) {
|
|
|
6828
6841
|
"0.9.22",
|
|
6829
6842
|
"0.9.23",
|
|
6830
6843
|
"0.9.24",
|
|
6831
|
-
"0.9.25"
|
|
6844
|
+
"0.9.25",
|
|
6845
|
+
"0.9.26",
|
|
6846
|
+
"0.9.27"
|
|
6832
6847
|
]).has(importData.version)) return {
|
|
6833
6848
|
success: false,
|
|
6834
6849
|
error: `Unsupported export version: ${importData.version}`
|
|
@@ -7352,19 +7367,167 @@ function buildGraphExtractionPrompt(observations) {
|
|
|
7352
7367
|
//#region src/functions/graph.ts
|
|
7353
7368
|
const DEFAULT_GRAPH_QUERY_LIMIT = 500;
|
|
7354
7369
|
const MAX_GRAPH_QUERY_LIMIT = 5e3;
|
|
7355
|
-
|
|
7370
|
+
const SNAPSHOT_TOP_NODES = DEFAULT_GRAPH_QUERY_LIMIT;
|
|
7371
|
+
const SNAPSHOT_KEY = "current";
|
|
7372
|
+
const LIVE_ENUMERATION_BUDGET_MS = 6e3;
|
|
7373
|
+
function withTimeout(p, ms, label) {
|
|
7374
|
+
return new Promise((resolve, reject) => {
|
|
7375
|
+
const t = setTimeout(() => reject(/* @__PURE__ */ new Error(`${label}: exceeded ${ms}ms budget`)), ms);
|
|
7376
|
+
p.then((v) => {
|
|
7377
|
+
clearTimeout(t);
|
|
7378
|
+
resolve(v);
|
|
7379
|
+
}, (err) => {
|
|
7380
|
+
clearTimeout(t);
|
|
7381
|
+
reject(err);
|
|
7382
|
+
});
|
|
7383
|
+
});
|
|
7384
|
+
}
|
|
7385
|
+
function emptySnapshot() {
|
|
7356
7386
|
return {
|
|
7357
|
-
|
|
7358
|
-
|
|
7387
|
+
version: 1,
|
|
7388
|
+
topNodes: [],
|
|
7389
|
+
topEdges: [],
|
|
7390
|
+
topDegrees: {},
|
|
7391
|
+
stats: {
|
|
7392
|
+
totalNodes: 0,
|
|
7393
|
+
totalEdges: 0,
|
|
7394
|
+
nodesByType: {},
|
|
7395
|
+
edgesByType: {}
|
|
7396
|
+
},
|
|
7397
|
+
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
7398
|
+
dirty: true
|
|
7359
7399
|
};
|
|
7360
7400
|
}
|
|
7361
|
-
function
|
|
7401
|
+
async function readSnapshot(kv) {
|
|
7402
|
+
try {
|
|
7403
|
+
const snap = await kv.get(KV.graphSnapshot, SNAPSHOT_KEY);
|
|
7404
|
+
if (snap && typeof snap === "object" && snap.version === 1) return snap;
|
|
7405
|
+
return null;
|
|
7406
|
+
} catch (err) {
|
|
7407
|
+
logger.warn("Graph snapshot read failed", { error: err instanceof Error ? err.message : String(err) });
|
|
7408
|
+
return null;
|
|
7409
|
+
}
|
|
7410
|
+
}
|
|
7411
|
+
function buildSnapshotFromArrays(nodes, edges) {
|
|
7412
|
+
const liveNodes = nodes.filter((n) => !n.stale);
|
|
7413
|
+
const liveEdges = edges.filter((e) => !e.stale);
|
|
7362
7414
|
const degree = /* @__PURE__ */ new Map();
|
|
7363
|
-
for (const
|
|
7364
|
-
degree.set(
|
|
7365
|
-
degree.set(
|
|
7415
|
+
for (const e of liveEdges) {
|
|
7416
|
+
degree.set(e.sourceNodeId, (degree.get(e.sourceNodeId) ?? 0) + 1);
|
|
7417
|
+
degree.set(e.targetNodeId, (degree.get(e.targetNodeId) ?? 0) + 1);
|
|
7418
|
+
}
|
|
7419
|
+
const ranked = [...liveNodes].sort((a, b) => (degree.get(b.id) ?? 0) - (degree.get(a.id) ?? 0)).slice(0, SNAPSHOT_TOP_NODES);
|
|
7420
|
+
const rankedIds = new Set(ranked.map((n) => n.id));
|
|
7421
|
+
const topEdges = liveEdges.filter((e) => rankedIds.has(e.sourceNodeId) && rankedIds.has(e.targetNodeId));
|
|
7422
|
+
const topDegrees = {};
|
|
7423
|
+
for (const n of ranked) topDegrees[n.id] = degree.get(n.id) ?? 0;
|
|
7424
|
+
const nodesByType = {};
|
|
7425
|
+
for (const n of liveNodes) nodesByType[n.type] = (nodesByType[n.type] || 0) + 1;
|
|
7426
|
+
const edgesByType = {};
|
|
7427
|
+
for (const e of liveEdges) edgesByType[e.type] = (edgesByType[e.type] || 0) + 1;
|
|
7428
|
+
return {
|
|
7429
|
+
version: 1,
|
|
7430
|
+
topNodes: ranked,
|
|
7431
|
+
topEdges,
|
|
7432
|
+
topDegrees,
|
|
7433
|
+
stats: {
|
|
7434
|
+
totalNodes: liveNodes.length,
|
|
7435
|
+
totalEdges: liveEdges.length,
|
|
7436
|
+
nodesByType,
|
|
7437
|
+
edgesByType
|
|
7438
|
+
},
|
|
7439
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7440
|
+
dirty: false
|
|
7441
|
+
};
|
|
7442
|
+
}
|
|
7443
|
+
function paginateFromSnapshot(snap, filterType, limit, offset) {
|
|
7444
|
+
const filteredNodes = filterType ? snap.topNodes.filter((n) => n.type === filterType) : snap.topNodes;
|
|
7445
|
+
const total = filterType ? snap.stats.nodesByType[filterType] ?? 0 : snap.stats.totalNodes;
|
|
7446
|
+
const pageNodes = filteredNodes.slice(offset, offset + limit);
|
|
7447
|
+
const pageIds = new Set(pageNodes.map((n) => n.id));
|
|
7448
|
+
return {
|
|
7449
|
+
nodes: pageNodes,
|
|
7450
|
+
edges: snap.topEdges.filter((e) => pageIds.has(e.sourceNodeId) && pageIds.has(e.targetNodeId)),
|
|
7451
|
+
depth: 0,
|
|
7452
|
+
totalNodes: total,
|
|
7453
|
+
totalEdges: snap.stats.totalEdges,
|
|
7454
|
+
truncated: total > pageNodes.length,
|
|
7455
|
+
limit,
|
|
7456
|
+
offset,
|
|
7457
|
+
fromSnapshot: true
|
|
7458
|
+
};
|
|
7459
|
+
}
|
|
7460
|
+
const REBUILD_SAFE_NODE_CEILING = 25e3;
|
|
7461
|
+
function nameIndexKey(type, name) {
|
|
7462
|
+
return `${type}|${name}`;
|
|
7463
|
+
}
|
|
7464
|
+
function edgeIndexKey(sourceNodeId, targetNodeId, type) {
|
|
7465
|
+
return `${sourceNodeId}|${targetNodeId}|${type}`;
|
|
7466
|
+
}
|
|
7467
|
+
async function applyDegreeDelta(kv, snap, nodeId, delta) {
|
|
7468
|
+
const prev = await kv.get(KV.graphNodeDegree, nodeId) ?? 0;
|
|
7469
|
+
const next = Math.max(0, prev + delta);
|
|
7470
|
+
await kv.set(KV.graphNodeDegree, nodeId, next);
|
|
7471
|
+
if (snap.topNodes.findIndex((n) => n.id === nodeId) !== -1) {
|
|
7472
|
+
snap.topDegrees[nodeId] = next;
|
|
7473
|
+
snap.topNodes.sort((a, b) => (snap.topDegrees[b.id] ?? 0) - (snap.topDegrees[a.id] ?? 0));
|
|
7474
|
+
return next;
|
|
7475
|
+
}
|
|
7476
|
+
if (snap.topNodes.length < SNAPSHOT_TOP_NODES) {
|
|
7477
|
+
const node = await kv.get(KV.graphNodes, nodeId);
|
|
7478
|
+
if (node && !node.stale) {
|
|
7479
|
+
snap.topNodes.push(node);
|
|
7480
|
+
snap.topDegrees[node.id] = next;
|
|
7481
|
+
snap.topNodes.sort((a, b) => (snap.topDegrees[b.id] ?? 0) - (snap.topDegrees[a.id] ?? 0));
|
|
7482
|
+
}
|
|
7483
|
+
return next;
|
|
7484
|
+
}
|
|
7485
|
+
const tailEntry = snap.topNodes[snap.topNodes.length - 1];
|
|
7486
|
+
if (!tailEntry) return next;
|
|
7487
|
+
if (next > (snap.topDegrees[tailEntry.id] ?? 0)) {
|
|
7488
|
+
const node = await kv.get(KV.graphNodes, nodeId);
|
|
7489
|
+
if (node && !node.stale) {
|
|
7490
|
+
const evicted = snap.topNodes.pop();
|
|
7491
|
+
if (evicted) delete snap.topDegrees[evicted.id];
|
|
7492
|
+
snap.topNodes.push(node);
|
|
7493
|
+
snap.topDegrees[node.id] = next;
|
|
7494
|
+
snap.topNodes.sort((a, b) => (snap.topDegrees[b.id] ?? 0) - (snap.topDegrees[a.id] ?? 0));
|
|
7495
|
+
}
|
|
7496
|
+
}
|
|
7497
|
+
return next;
|
|
7498
|
+
}
|
|
7499
|
+
function snapshotPushEdgeIfBothInTop(snap, edge) {
|
|
7500
|
+
const topIds = new Set(snap.topNodes.map((n) => n.id));
|
|
7501
|
+
if (topIds.has(edge.sourceNodeId) && topIds.has(edge.targetNodeId)) {
|
|
7502
|
+
if (!snap.topEdges.find((e) => e.id === edge.id)) snap.topEdges.push(edge);
|
|
7366
7503
|
}
|
|
7367
|
-
|
|
7504
|
+
}
|
|
7505
|
+
function mergeNode(existing, incoming, obsIds, capturedAt) {
|
|
7506
|
+
return {
|
|
7507
|
+
...existing,
|
|
7508
|
+
sourceObservationIds: [...new Set([
|
|
7509
|
+
...existing.sourceObservationIds,
|
|
7510
|
+
...incoming.sourceObservationIds,
|
|
7511
|
+
...obsIds
|
|
7512
|
+
])],
|
|
7513
|
+
properties: {
|
|
7514
|
+
...existing.properties,
|
|
7515
|
+
...incoming.properties
|
|
7516
|
+
},
|
|
7517
|
+
updatedAt: capturedAt
|
|
7518
|
+
};
|
|
7519
|
+
}
|
|
7520
|
+
function mergeEdge(existing, obsIds) {
|
|
7521
|
+
return {
|
|
7522
|
+
...existing,
|
|
7523
|
+
sourceObservationIds: [...new Set([...existing.sourceObservationIds, ...obsIds])]
|
|
7524
|
+
};
|
|
7525
|
+
}
|
|
7526
|
+
function resolvePagination(rawLimit, rawOffset) {
|
|
7527
|
+
return {
|
|
7528
|
+
limit: Math.max(1, Math.min(typeof rawLimit === "number" && Number.isFinite(rawLimit) ? Math.floor(rawLimit) : DEFAULT_GRAPH_QUERY_LIMIT, MAX_GRAPH_QUERY_LIMIT)),
|
|
7529
|
+
offset: Math.max(0, typeof rawOffset === "number" && Number.isFinite(rawOffset) ? Math.floor(rawOffset) : 0)
|
|
7530
|
+
};
|
|
7368
7531
|
}
|
|
7369
7532
|
function paginate(nodes, allEdges, depth, limit, offset) {
|
|
7370
7533
|
const totalNodes = nodes.length;
|
|
@@ -7461,45 +7624,76 @@ function registerGraphFunction(sdk, kv, provider) {
|
|
|
7461
7624
|
const response = await provider.compress(GRAPH_EXTRACTION_SYSTEM, prompt);
|
|
7462
7625
|
const obsIds = data.observations.map((o) => o.id);
|
|
7463
7626
|
const { nodes, edges } = parseGraphXml(response, obsIds);
|
|
7464
|
-
const
|
|
7465
|
-
const
|
|
7627
|
+
const snap = await readSnapshot(kv) ?? emptySnapshot();
|
|
7628
|
+
const capturedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7629
|
+
let newNodeCount = 0;
|
|
7630
|
+
let newEdgeCount = 0;
|
|
7631
|
+
const newEdgesForTopCheck = [];
|
|
7466
7632
|
for (const node of nodes) {
|
|
7467
|
-
const
|
|
7633
|
+
const indexKey = nameIndexKey(node.type, node.name);
|
|
7634
|
+
const existingId = await kv.get(KV.graphNameIndex, indexKey);
|
|
7635
|
+
let existing = null;
|
|
7636
|
+
if (existingId) {
|
|
7637
|
+
existing = await kv.get(KV.graphNodes, existingId);
|
|
7638
|
+
if (existing && snap.resetAt && typeof existing.createdAt === "string" && existing.createdAt < snap.resetAt) existing = null;
|
|
7639
|
+
}
|
|
7468
7640
|
if (existing) {
|
|
7469
|
-
const merged =
|
|
7470
|
-
...existing,
|
|
7471
|
-
sourceObservationIds: [...new Set([...existing.sourceObservationIds, ...obsIds])],
|
|
7472
|
-
properties: {
|
|
7473
|
-
...existing.properties,
|
|
7474
|
-
...node.properties
|
|
7475
|
-
}
|
|
7476
|
-
};
|
|
7641
|
+
const merged = mergeNode(existing, node, obsIds, capturedAt);
|
|
7477
7642
|
await kv.set(KV.graphNodes, existing.id, merged);
|
|
7478
|
-
const
|
|
7479
|
-
if (
|
|
7643
|
+
const topIdx = snap.topNodes.findIndex((n) => n.id === existing.id);
|
|
7644
|
+
if (topIdx !== -1) snap.topNodes[topIdx] = merged;
|
|
7480
7645
|
} else {
|
|
7481
7646
|
await kv.set(KV.graphNodes, node.id, node);
|
|
7482
|
-
|
|
7647
|
+
await kv.set(KV.graphNameIndex, indexKey, node.id);
|
|
7648
|
+
await kv.set(KV.graphNodeDegree, node.id, 0);
|
|
7649
|
+
snap.stats.totalNodes += 1;
|
|
7650
|
+
snap.stats.nodesByType[node.type] = (snap.stats.nodesByType[node.type] ?? 0) + 1;
|
|
7651
|
+
newNodeCount += 1;
|
|
7652
|
+
if (snap.topNodes.length < SNAPSHOT_TOP_NODES) {
|
|
7653
|
+
snap.topNodes.push(node);
|
|
7654
|
+
snap.topDegrees[node.id] = 0;
|
|
7655
|
+
}
|
|
7483
7656
|
}
|
|
7484
7657
|
}
|
|
7485
7658
|
for (const edge of edges) {
|
|
7486
|
-
const
|
|
7487
|
-
const
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
await kv.
|
|
7659
|
+
const eKey = edgeIndexKey(edge.sourceNodeId, edge.targetNodeId, edge.type);
|
|
7660
|
+
const existingId = await kv.get(KV.graphEdgeKey, eKey);
|
|
7661
|
+
let existing = null;
|
|
7662
|
+
if (existingId) {
|
|
7663
|
+
existing = await kv.get(KV.graphEdges, existingId);
|
|
7664
|
+
if (existing && snap.resetAt && typeof existing.createdAt === "string" && existing.createdAt < snap.resetAt) existing = null;
|
|
7665
|
+
}
|
|
7666
|
+
if (existing) {
|
|
7667
|
+
const merged = mergeEdge(existing, obsIds);
|
|
7668
|
+
await kv.set(KV.graphEdges, existing.id, merged);
|
|
7669
|
+
const topIdx = snap.topEdges.findIndex((e) => e.id === existing.id);
|
|
7670
|
+
if (topIdx !== -1) snap.topEdges[topIdx] = merged;
|
|
7491
7671
|
} else {
|
|
7492
7672
|
await kv.set(KV.graphEdges, edge.id, edge);
|
|
7493
|
-
|
|
7673
|
+
await kv.set(KV.graphEdgeKey, eKey, edge.id);
|
|
7674
|
+
snap.stats.totalEdges += 1;
|
|
7675
|
+
snap.stats.edgesByType[edge.type] = (snap.stats.edgesByType[edge.type] ?? 0) + 1;
|
|
7676
|
+
newEdgeCount += 1;
|
|
7677
|
+
await applyDegreeDelta(kv, snap, edge.sourceNodeId, 1);
|
|
7678
|
+
await applyDegreeDelta(kv, snap, edge.targetNodeId, 1);
|
|
7679
|
+
newEdgesForTopCheck.push(edge);
|
|
7494
7680
|
}
|
|
7495
7681
|
}
|
|
7682
|
+
for (const edge of newEdgesForTopCheck) snapshotPushEdgeIfBothInTop(snap, edge);
|
|
7683
|
+
if (newNodeCount > 0 || newEdgeCount > 0) {
|
|
7684
|
+
snap.updatedAt = capturedAt;
|
|
7685
|
+
snap.dirty = false;
|
|
7686
|
+
await kv.set(KV.graphSnapshot, SNAPSHOT_KEY, snap);
|
|
7687
|
+
}
|
|
7496
7688
|
await recordAudit(kv, "observe", "mem::graph-extract", obsIds, {
|
|
7497
7689
|
nodesExtracted: nodes.length,
|
|
7498
7690
|
edgesExtracted: edges.length
|
|
7499
7691
|
});
|
|
7500
7692
|
logger.info("Graph extraction complete", {
|
|
7501
7693
|
nodes: nodes.length,
|
|
7502
|
-
edges: edges.length
|
|
7694
|
+
edges: edges.length,
|
|
7695
|
+
newNodes: newNodeCount,
|
|
7696
|
+
newEdges: newEdgeCount
|
|
7503
7697
|
});
|
|
7504
7698
|
return {
|
|
7505
7699
|
success: true,
|
|
@@ -7516,10 +7710,49 @@ function registerGraphFunction(sdk, kv, provider) {
|
|
|
7516
7710
|
}
|
|
7517
7711
|
});
|
|
7518
7712
|
sdk.registerFunction("mem::graph-query", async (data) => {
|
|
7519
|
-
const allNodes = (await kv.list(KV.graphNodes)).filter((n) => !n.stale);
|
|
7520
|
-
const allEdges = (await kv.list(KV.graphEdges)).filter((e) => !e.stale);
|
|
7521
7713
|
const maxDepth = Math.min(data.maxDepth || 3, 5);
|
|
7522
7714
|
const { limit, offset } = resolvePagination(data.limit, data.offset);
|
|
7715
|
+
if (!data.query && !data.startNodeId) {
|
|
7716
|
+
const snap = await readSnapshot(kv);
|
|
7717
|
+
if (snap && snap.stats.totalNodes > 0) return paginateFromSnapshot(snap, data.nodeType, limit, offset);
|
|
7718
|
+
return {
|
|
7719
|
+
nodes: [],
|
|
7720
|
+
edges: [],
|
|
7721
|
+
depth: 0,
|
|
7722
|
+
totalNodes: 0,
|
|
7723
|
+
totalEdges: 0,
|
|
7724
|
+
truncated: false,
|
|
7725
|
+
limit,
|
|
7726
|
+
offset,
|
|
7727
|
+
warning: "No graph snapshot available. Either no graph has been extracted yet, or you are on a legacy corpus from a pre-#814 agentmemory build. Run POST /agentmemory/graph/snapshot-rebuild (safe up to ~25K nodes) or POST /agentmemory/graph/reset to wipe and let future extracts repopulate."
|
|
7728
|
+
};
|
|
7729
|
+
}
|
|
7730
|
+
let allNodes;
|
|
7731
|
+
let allEdges;
|
|
7732
|
+
try {
|
|
7733
|
+
const [rawNodes, rawEdges] = await withTimeout(Promise.all([kv.list(KV.graphNodes), kv.list(KV.graphEdges)]), LIVE_ENUMERATION_BUDGET_MS, "graph-query enumeration");
|
|
7734
|
+
allNodes = rawNodes.filter((n) => !n.stale);
|
|
7735
|
+
allEdges = rawEdges.filter((e) => !e.stale);
|
|
7736
|
+
} catch (err) {
|
|
7737
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7738
|
+
logger.warn("Graph query enumeration timed out, using snapshot", { error: msg });
|
|
7739
|
+
const snap = await readSnapshot(kv);
|
|
7740
|
+
if (snap) return {
|
|
7741
|
+
...paginateFromSnapshot(snap, data.nodeType, limit, offset),
|
|
7742
|
+
warning: "Live graph enumeration exceeded budget. Query / startNodeId paths degrade on >25K-node corpora until a per-node edge index lands. Result reflects top-degree snapshot, not the requested walk."
|
|
7743
|
+
};
|
|
7744
|
+
return {
|
|
7745
|
+
nodes: [],
|
|
7746
|
+
edges: [],
|
|
7747
|
+
depth: 0,
|
|
7748
|
+
totalNodes: 0,
|
|
7749
|
+
totalEdges: 0,
|
|
7750
|
+
truncated: false,
|
|
7751
|
+
limit,
|
|
7752
|
+
offset,
|
|
7753
|
+
warning: "Graph enumeration exceeded budget and no snapshot is available."
|
|
7754
|
+
};
|
|
7755
|
+
}
|
|
7523
7756
|
if (data.query) {
|
|
7524
7757
|
const lower = data.query.toLowerCase();
|
|
7525
7758
|
return paginate(allNodes.filter((n) => n.name.toLowerCase().includes(lower) || Object.values(n.properties).some((v) => typeof v === "string" && v.toLowerCase().includes(lower))), allEdges, 0, limit, offset);
|
|
@@ -7556,22 +7789,116 @@ function registerGraphFunction(sdk, kv, provider) {
|
|
|
7556
7789
|
}
|
|
7557
7790
|
return paginate(resultNodes, resultEdges, maxDepth, limit, offset);
|
|
7558
7791
|
}
|
|
7559
|
-
|
|
7560
|
-
if (data.nodeType) filtered = allNodes.filter((n) => n.type === data.nodeType);
|
|
7561
|
-
return paginate(rankByDegree(filtered, allEdges), allEdges, 0, limit, offset);
|
|
7792
|
+
return paginate([], [], 0, limit, offset);
|
|
7562
7793
|
});
|
|
7563
7794
|
sdk.registerFunction("mem::graph-stats", async () => {
|
|
7564
|
-
const
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7795
|
+
const snap = await readSnapshot(kv);
|
|
7796
|
+
if (snap) return {
|
|
7797
|
+
...snap.stats,
|
|
7798
|
+
fromSnapshot: true,
|
|
7799
|
+
updatedAt: snap.updatedAt,
|
|
7800
|
+
...snap.dirty ? { warning: "Snapshot is marked dirty (write was in-flight when read). Counts are eventually consistent." } : {}
|
|
7801
|
+
};
|
|
7570
7802
|
return {
|
|
7571
|
-
totalNodes:
|
|
7572
|
-
totalEdges:
|
|
7573
|
-
nodesByType,
|
|
7574
|
-
edgesByType
|
|
7803
|
+
totalNodes: 0,
|
|
7804
|
+
totalEdges: 0,
|
|
7805
|
+
nodesByType: {},
|
|
7806
|
+
edgesByType: {},
|
|
7807
|
+
fromSnapshot: false,
|
|
7808
|
+
warning: "No graph snapshot available. Run POST /agentmemory/graph/snapshot-rebuild (safe up to ~25K nodes) or POST /agentmemory/graph/reset to wipe and let future extracts repopulate."
|
|
7809
|
+
};
|
|
7810
|
+
});
|
|
7811
|
+
sdk.registerFunction("mem::graph-snapshot-rebuild", async (data) => {
|
|
7812
|
+
const started = Date.now();
|
|
7813
|
+
const forceRebuild = data?.force === true;
|
|
7814
|
+
try {
|
|
7815
|
+
if (!await readSnapshot(kv) && !forceRebuild) {
|
|
7816
|
+
logger.warn("Graph snapshot rebuild refused: no prior snapshot", { hint: "legacy corpus or empty store" });
|
|
7817
|
+
return {
|
|
7818
|
+
success: false,
|
|
7819
|
+
legacyCorpus: true,
|
|
7820
|
+
error: "No prior snapshot found. Rebuild would call kv.list on KV.graphNodes/Edges, which heartbeat-crashes the worker on corpora past the iii state response budget (~25K nodes). Either (a) call POST /agentmemory/graph/reset to drop into incremental-only mode and rebuild from new extracts, or (b) re-send with `force: true` if you're certain the corpus is small."
|
|
7821
|
+
};
|
|
7822
|
+
}
|
|
7823
|
+
} catch (err) {
|
|
7824
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7825
|
+
logger.warn("Graph snapshot pre-flight read failed", { error: msg });
|
|
7826
|
+
}
|
|
7827
|
+
try {
|
|
7828
|
+
const [nodes, edges] = await withTimeout(Promise.all([kv.list(KV.graphNodes), kv.list(KV.graphEdges)]), LIVE_ENUMERATION_BUDGET_MS, "graph-snapshot-rebuild enumeration");
|
|
7829
|
+
if (nodes.length > REBUILD_SAFE_NODE_CEILING) {
|
|
7830
|
+
logger.warn("Graph snapshot rebuild aborted: corpus too large", {
|
|
7831
|
+
totalNodes: nodes.length,
|
|
7832
|
+
ceiling: REBUILD_SAFE_NODE_CEILING
|
|
7833
|
+
});
|
|
7834
|
+
return {
|
|
7835
|
+
success: false,
|
|
7836
|
+
tooLarge: true,
|
|
7837
|
+
totalNodes: nodes.length,
|
|
7838
|
+
ceiling: REBUILD_SAFE_NODE_CEILING,
|
|
7839
|
+
error: `Corpus has ${nodes.length} graph nodes; safe-rebuild ceiling is ${REBUILD_SAFE_NODE_CEILING}. Run POST /agentmemory/graph/reset to wipe and let future extracts rebuild incrementally.`
|
|
7840
|
+
};
|
|
7841
|
+
}
|
|
7842
|
+
const liveNodes = nodes.filter((n) => !n.stale);
|
|
7843
|
+
const liveEdges = edges.filter((e) => !e.stale);
|
|
7844
|
+
const degree = /* @__PURE__ */ new Map();
|
|
7845
|
+
for (const e of liveEdges) {
|
|
7846
|
+
degree.set(e.sourceNodeId, (degree.get(e.sourceNodeId) ?? 0) + 1);
|
|
7847
|
+
degree.set(e.targetNodeId, (degree.get(e.targetNodeId) ?? 0) + 1);
|
|
7848
|
+
}
|
|
7849
|
+
const BATCH_SIZE = 100;
|
|
7850
|
+
for (let i = 0; i < liveNodes.length; i += BATCH_SIZE) {
|
|
7851
|
+
const batch = liveNodes.slice(i, i + BATCH_SIZE);
|
|
7852
|
+
await Promise.all(batch.flatMap((n) => [kv.set(KV.graphNameIndex, nameIndexKey(n.type, n.name), n.id), kv.set(KV.graphNodeDegree, n.id, degree.get(n.id) ?? 0)]));
|
|
7853
|
+
}
|
|
7854
|
+
for (let i = 0; i < liveEdges.length; i += BATCH_SIZE) {
|
|
7855
|
+
const batch = liveEdges.slice(i, i + BATCH_SIZE);
|
|
7856
|
+
await Promise.all(batch.map((e) => kv.set(KV.graphEdgeKey, edgeIndexKey(e.sourceNodeId, e.targetNodeId, e.type), e.id)));
|
|
7857
|
+
}
|
|
7858
|
+
const snap = buildSnapshotFromArrays(nodes, edges);
|
|
7859
|
+
await kv.set(KV.graphSnapshot, SNAPSHOT_KEY, snap);
|
|
7860
|
+
const tookMs = Date.now() - started;
|
|
7861
|
+
logger.info("Graph snapshot rebuilt", {
|
|
7862
|
+
totalNodes: snap.stats.totalNodes,
|
|
7863
|
+
totalEdges: snap.stats.totalEdges,
|
|
7864
|
+
topNodes: snap.topNodes.length,
|
|
7865
|
+
topEdges: snap.topEdges.length,
|
|
7866
|
+
tookMs
|
|
7867
|
+
});
|
|
7868
|
+
return {
|
|
7869
|
+
success: true,
|
|
7870
|
+
...snap.stats,
|
|
7871
|
+
topNodes: snap.topNodes.length,
|
|
7872
|
+
topEdges: snap.topEdges.length,
|
|
7873
|
+
updatedAt: snap.updatedAt,
|
|
7874
|
+
tookMs
|
|
7875
|
+
};
|
|
7876
|
+
} catch (err) {
|
|
7877
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7878
|
+
logger.error("Graph snapshot rebuild failed", { error: msg });
|
|
7879
|
+
return {
|
|
7880
|
+
success: false,
|
|
7881
|
+
error: msg
|
|
7882
|
+
};
|
|
7883
|
+
}
|
|
7884
|
+
});
|
|
7885
|
+
sdk.registerFunction("mem::graph-reset", async () => {
|
|
7886
|
+
const started = Date.now();
|
|
7887
|
+
const resetSnapshot = {
|
|
7888
|
+
...emptySnapshot(),
|
|
7889
|
+
resetAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7890
|
+
};
|
|
7891
|
+
await kv.set(KV.graphSnapshot, SNAPSHOT_KEY, resetSnapshot);
|
|
7892
|
+
const counts = { [KV.graphSnapshot]: 1 };
|
|
7893
|
+
const tookMs = Date.now() - started;
|
|
7894
|
+
logger.info("Graph state reset", {
|
|
7895
|
+
counts,
|
|
7896
|
+
tookMs
|
|
7897
|
+
});
|
|
7898
|
+
return {
|
|
7899
|
+
success: true,
|
|
7900
|
+
cleared: counts,
|
|
7901
|
+
tookMs
|
|
7575
7902
|
};
|
|
7576
7903
|
});
|
|
7577
7904
|
}
|
|
@@ -13394,7 +13721,7 @@ function registerRetentionFunctions(sdk, kv) {
|
|
|
13394
13721
|
const threshold = typeof data?.threshold === "number" && Number.isFinite(data.threshold) ? data.threshold : DEFAULT_DECAY.tierThresholds.cold;
|
|
13395
13722
|
const maxEvictRaw = typeof data?.maxEvict === "number" && Number.isInteger(data.maxEvict) ? data.maxEvict : 50;
|
|
13396
13723
|
const maxEvict = Math.min(1e3, Math.max(0, maxEvictRaw));
|
|
13397
|
-
const { decrementImageRef } = await import("./image-refs-
|
|
13724
|
+
const { decrementImageRef } = await import("./image-refs-B5Zf_Djo.mjs").then((n) => n.n);
|
|
13398
13725
|
const candidates = (await kv.list(KV.retentionScores)).filter((s) => s.score < threshold).sort((a, b) => a.score - b.score).slice(0, maxEvict);
|
|
13399
13726
|
if (data?.dryRun) return {
|
|
13400
13727
|
success: true,
|
|
@@ -14886,6 +15213,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
14886
15213
|
});
|
|
14887
15214
|
sdk.registerFunction("api::search", async (req) => {
|
|
14888
15215
|
const body = req.body ?? {};
|
|
15216
|
+
const queryAgentId = typeof req.query_params?.["agentId"] === "string" ? req.query_params["agentId"] : void 0;
|
|
14889
15217
|
if (typeof body.query !== "string" || !body.query.trim()) return {
|
|
14890
15218
|
status_code: 400,
|
|
14891
15219
|
body: { error: "query is required and must be a non-empty string" }
|
|
@@ -14914,13 +15242,15 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
14914
15242
|
status_code: 400,
|
|
14915
15243
|
body: { error: "token_budget must be a positive integer" }
|
|
14916
15244
|
};
|
|
15245
|
+
const bodyAgentId = typeof body.agentId === "string" && body.agentId.trim().length > 0 ? body.agentId.trim() : void 0;
|
|
14917
15246
|
const payload = {
|
|
14918
15247
|
query: body.query.trim(),
|
|
14919
15248
|
limit: body.limit,
|
|
14920
15249
|
project: body.project,
|
|
14921
15250
|
cwd: body.cwd,
|
|
14922
15251
|
format: typeof body.format === "string" ? body.format.trim().toLowerCase() : void 0,
|
|
14923
|
-
token_budget: body.token_budget
|
|
15252
|
+
token_budget: body.token_budget,
|
|
15253
|
+
agentId: bodyAgentId ?? queryAgentId
|
|
14924
15254
|
};
|
|
14925
15255
|
return {
|
|
14926
15256
|
status_code: 200,
|
|
@@ -15856,6 +16186,52 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15856
16186
|
http_method: "GET"
|
|
15857
16187
|
}
|
|
15858
16188
|
});
|
|
16189
|
+
sdk.registerFunction("api::graph-snapshot-rebuild", async (req) => {
|
|
16190
|
+
const authErr = checkAuth(req, secret);
|
|
16191
|
+
if (authErr) return authErr;
|
|
16192
|
+
try {
|
|
16193
|
+
return {
|
|
16194
|
+
status_code: 200,
|
|
16195
|
+
body: await sdk.trigger({
|
|
16196
|
+
function_id: "mem::graph-snapshot-rebuild",
|
|
16197
|
+
payload: {}
|
|
16198
|
+
})
|
|
16199
|
+
};
|
|
16200
|
+
} catch {
|
|
16201
|
+
return graphDisabledResponse();
|
|
16202
|
+
}
|
|
16203
|
+
});
|
|
16204
|
+
sdk.registerTrigger({
|
|
16205
|
+
type: "http",
|
|
16206
|
+
function_id: "api::graph-snapshot-rebuild",
|
|
16207
|
+
config: {
|
|
16208
|
+
api_path: "/agentmemory/graph/snapshot-rebuild",
|
|
16209
|
+
http_method: "POST"
|
|
16210
|
+
}
|
|
16211
|
+
});
|
|
16212
|
+
sdk.registerFunction("api::graph-reset", async (req) => {
|
|
16213
|
+
const authErr = checkAuth(req, secret);
|
|
16214
|
+
if (authErr) return authErr;
|
|
16215
|
+
try {
|
|
16216
|
+
return {
|
|
16217
|
+
status_code: 200,
|
|
16218
|
+
body: await sdk.trigger({
|
|
16219
|
+
function_id: "mem::graph-reset",
|
|
16220
|
+
payload: {}
|
|
16221
|
+
})
|
|
16222
|
+
};
|
|
16223
|
+
} catch {
|
|
16224
|
+
return graphDisabledResponse();
|
|
16225
|
+
}
|
|
16226
|
+
});
|
|
16227
|
+
sdk.registerTrigger({
|
|
16228
|
+
type: "http",
|
|
16229
|
+
function_id: "api::graph-reset",
|
|
16230
|
+
config: {
|
|
16231
|
+
api_path: "/agentmemory/graph/reset",
|
|
16232
|
+
http_method: "POST"
|
|
16233
|
+
}
|
|
16234
|
+
});
|
|
15859
16235
|
sdk.registerFunction("api::graph-extract", async (req) => {
|
|
15860
16236
|
const authErr = checkAuth(req, secret);
|
|
15861
16237
|
if (authErr) return authErr;
|
|
@@ -18290,13 +18666,15 @@ function registerMcpEndpoints(sdk, kv, secret) {
|
|
|
18290
18666
|
status_code: 400,
|
|
18291
18667
|
body: { error: "token_budget must be a positive integer" }
|
|
18292
18668
|
};
|
|
18669
|
+
const recallAgentId = typeof args.agentId === "string" && args.agentId.trim().length > 0 ? args.agentId.trim() : void 0;
|
|
18293
18670
|
const result = await sdk.trigger({
|
|
18294
18671
|
function_id: "mem::search",
|
|
18295
18672
|
payload: {
|
|
18296
18673
|
query: args.query,
|
|
18297
18674
|
limit: typeof args.limit === "number" ? args.limit : 10,
|
|
18298
18675
|
format,
|
|
18299
|
-
token_budget: tokenBudget
|
|
18676
|
+
token_budget: tokenBudget,
|
|
18677
|
+
agentId: recallAgentId
|
|
18300
18678
|
}
|
|
18301
18679
|
});
|
|
18302
18680
|
return {
|
|
@@ -19784,7 +20162,10 @@ function registerMcpEndpoints(sdk, kv, secret) {
|
|
|
19784
20162
|
limit: 10
|
|
19785
20163
|
}
|
|
19786
20164
|
}).catch(() => ({ results: [] }));
|
|
19787
|
-
const
|
|
20165
|
+
const memories = await kv.list(KV.memories);
|
|
20166
|
+
const isolated = isAgentScopeIsolated();
|
|
20167
|
+
const activeAgentId = isolated ? getAgentId() : void 0;
|
|
20168
|
+
const relevant = isolated && activeAgentId === void 0 ? [] : memories.filter((m) => m.isLatest).filter((m) => activeAgentId === void 0 || m.agentId === activeAgentId).slice(0, 5);
|
|
19788
20169
|
return {
|
|
19789
20170
|
status_code: 200,
|
|
19790
20171
|
body: { messages: [{
|
|
@@ -20155,7 +20536,7 @@ async function main() {
|
|
|
20155
20536
|
console.warn(`[agentmemory] Failed to backfill memories into BM25:`, err);
|
|
20156
20537
|
}
|
|
20157
20538
|
bootLog(`Ready. ${embeddingProvider ? "Triple-stream (BM25+Vector+Graph)" : "BM25+Graph"} search active.`);
|
|
20158
|
-
bootLog(`REST API:
|
|
20539
|
+
bootLog(`REST API: 128 endpoints at http://localhost:${config.restPort}/agentmemory/*`);
|
|
20159
20540
|
bootLog(`MCP surface (opt-in via \`npx @agentmemory/mcp\`): ${getAllTools().length} tools · 6 resources · 3 prompts`);
|
|
20160
20541
|
const viewerServer = startViewerServer(config.restPort + 2, kv, sdk, secret, config.restPort);
|
|
20161
20542
|
const autoForgetIntervalMs = parseInt(process.env.AUTO_FORGET_INTERVAL_MS || "3600000", 10);
|
|
@@ -20232,4 +20613,4 @@ main().catch((err) => {
|
|
|
20232
20613
|
//#endregion
|
|
20233
20614
|
export {};
|
|
20234
20615
|
|
|
20235
|
-
//# sourceMappingURL=src-
|
|
20616
|
+
//# sourceMappingURL=src-MOg2zKJs.mjs.map
|