@agentmemory/agentmemory 0.9.22 → 0.9.24
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 +7 -2
- package/README.md +144 -32
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +42 -25
- package/dist/cli.mjs.map +1 -1
- package/dist/{connect-BQQXpyDS.mjs → connect-Cf9bmBqO.mjs} +290 -33
- package/dist/connect-Cf9bmBqO.mjs.map +1 -0
- package/dist/hooks/notification.mjs +46 -21
- package/dist/hooks/notification.mjs.map +1 -1
- package/dist/hooks/post-tool-failure.mjs +47 -21
- package/dist/hooks/post-tool-failure.mjs.map +1 -1
- package/dist/hooks/post-tool-use.mjs +57 -22
- package/dist/hooks/post-tool-use.mjs.map +1 -1
- package/dist/hooks/pre-compact.mjs +26 -2
- package/dist/hooks/pre-compact.mjs.map +1 -1
- package/dist/hooks/pre-tool-use.mjs +19 -12
- package/dist/hooks/pre-tool-use.mjs.map +1 -1
- package/dist/hooks/prompt-submit.mjs +39 -16
- package/dist/hooks/prompt-submit.mjs.map +1 -1
- package/dist/hooks/session-end.mjs +26 -33
- package/dist/hooks/session-end.mjs.map +1 -1
- package/dist/hooks/session-start.mjs +28 -3
- package/dist/hooks/session-start.mjs.map +1 -1
- package/dist/hooks/stop.mjs +14 -17
- package/dist/hooks/stop.mjs.map +1 -1
- package/dist/hooks/subagent-start.mjs +31 -4
- package/dist/hooks/subagent-start.mjs.map +1 -1
- package/dist/hooks/subagent-stop.mjs +45 -20
- package/dist/hooks/subagent-stop.mjs.map +1 -1
- package/dist/hooks/task-completed.mjs +44 -21
- package/dist/hooks/task-completed.mjs.map +1 -1
- package/dist/iii-config.docker.yaml +3 -2
- package/dist/iii-config.yaml +11 -2
- package/dist/index.mjs +336 -57
- package/dist/index.mjs.map +1 -1
- package/dist/{src-gpTAJuBy.mjs → src-B8J9Exum.mjs} +323 -58
- package/dist/src-B8J9Exum.mjs.map +1 -0
- package/dist/{standalone-C4i7ktpn.mjs → standalone-CPfsVTBA.mjs} +92 -11
- package/dist/standalone-CPfsVTBA.mjs.map +1 -0
- package/dist/standalone.mjs +94 -9
- package/dist/standalone.mjs.map +1 -1
- package/dist/{tools-registry-B7Y6nJsr.mjs → tools-registry-DJizX9Az.mjs} +16 -2
- package/dist/tools-registry-DJizX9Az.mjs.map +1 -0
- package/dist/version-BWEBnKAp.mjs +6 -0
- package/dist/version-BWEBnKAp.mjs.map +1 -0
- package/dist/viewer/index.html +9 -2
- package/iii-config.docker.yaml +3 -2
- package/iii-config.yaml +11 -2
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.codex-plugin/plugin.json +2 -2
- package/plugin/.mcp.copilot.json +15 -0
- package/plugin/hooks/hooks.copilot.json +72 -0
- package/plugin/plugin.json +15 -0
- package/plugin/scripts/notification.mjs +46 -21
- package/plugin/scripts/notification.mjs.map +1 -1
- package/plugin/scripts/post-tool-failure.mjs +47 -21
- package/plugin/scripts/post-tool-failure.mjs.map +1 -1
- package/plugin/scripts/post-tool-use.mjs +57 -22
- package/plugin/scripts/post-tool-use.mjs.map +1 -1
- package/plugin/scripts/pre-compact.mjs +26 -2
- package/plugin/scripts/pre-compact.mjs.map +1 -1
- package/plugin/scripts/pre-tool-use.mjs +19 -12
- package/plugin/scripts/pre-tool-use.mjs.map +1 -1
- package/plugin/scripts/prompt-submit.mjs +39 -16
- package/plugin/scripts/prompt-submit.mjs.map +1 -1
- package/plugin/scripts/session-end.mjs +26 -33
- package/plugin/scripts/session-end.mjs.map +1 -1
- package/plugin/scripts/session-start.mjs +28 -3
- package/plugin/scripts/session-start.mjs.map +1 -1
- package/plugin/scripts/stop.mjs +14 -17
- package/plugin/scripts/stop.mjs.map +1 -1
- package/plugin/scripts/subagent-start.mjs +31 -4
- package/plugin/scripts/subagent-start.mjs.map +1 -1
- package/plugin/scripts/subagent-stop.mjs +45 -20
- package/plugin/scripts/subagent-stop.mjs.map +1 -1
- package/plugin/scripts/task-completed.mjs +44 -21
- package/plugin/scripts/task-completed.mjs.map +1 -1
- package/dist/connect-BQQXpyDS.mjs.map +0 -1
- package/dist/src-gpTAJuBy.mjs.map +0 -1
- package/dist/standalone-C4i7ktpn.mjs.map +0 -1
- package/dist/tools-registry-B7Y6nJsr.mjs.map +0 -1
- package/dist/version-DvQMNbEH.mjs +0 -6
- package/dist/version-DvQMNbEH.mjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { a as jaccardSimilarity, i as generateId, n as STREAM, r as fingerprintId, t as KV } from "./schema-BkALl7Z_.mjs";
|
|
2
2
|
import { n as logger, t as bootLog } from "./logger-xlVlvCWX.mjs";
|
|
3
|
-
import { t as VERSION } from "./version-
|
|
3
|
+
import { t as VERSION } from "./version-BWEBnKAp.mjs";
|
|
4
4
|
import { a as isManagedImagePath, getImageRefCount, i as getMaxBytes, n as IMAGES_DIR, r as deleteImage, t as withKeyedLock } from "./image-refs-CJS5B9Gq.mjs";
|
|
5
|
-
import { _ as loadEmbeddingConfig, a as getAgentId, b as loadTeamConfig, d as isConsolidationEnabled, f as isContextInjectionEnabled, g as loadConfig, h as loadClaudeBridgeConfig, i as detectLlmProviderKind, l as isAgentScopeIsolated, m as isGraphExtractionEnabled, n as getVisibleTools, o as getConsolidationDecayDays, p as isDropStaleIndexEnabled, r as detectEmbeddingProvider, s as getEnvVar, t as getAllTools, u as isAutoCompressEnabled, v as loadFallbackConfig, y as loadSnapshotConfig } from "./tools-registry-
|
|
5
|
+
import { _ as loadEmbeddingConfig, a as getAgentId, b as loadTeamConfig, d as isConsolidationEnabled, f as isContextInjectionEnabled, g as loadConfig, h as loadClaudeBridgeConfig, i as detectLlmProviderKind, l as isAgentScopeIsolated, m as isGraphExtractionEnabled, n as getVisibleTools, o as getConsolidationDecayDays, p as isDropStaleIndexEnabled, r as detectEmbeddingProvider, s as getEnvVar, t as getAllTools, u as isAutoCompressEnabled, v as loadFallbackConfig, y as loadSnapshotConfig } from "./tools-registry-DJizX9Az.mjs";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import { execFile } from "node:child_process";
|
|
8
8
|
import { constants, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
@@ -639,16 +639,30 @@ function resolveDimensions(model, override) {
|
|
|
639
639
|
* `api-key` header instead of `Authorization: Bearer`.
|
|
640
640
|
*
|
|
641
641
|
* Required env vars:
|
|
642
|
-
* OPENAI_API_KEY
|
|
642
|
+
* OPENAI_API_KEY — API key (fallback for OPENAI_EMBEDDING_API_KEY)
|
|
643
643
|
*
|
|
644
644
|
* Optional:
|
|
645
|
-
* OPENAI_BASE_URL
|
|
646
|
-
*
|
|
647
|
-
*
|
|
648
|
-
*
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
645
|
+
* OPENAI_BASE_URL — base URL without path (default: https://api.openai.com).
|
|
646
|
+
* Azure: https://<resource>.openai.azure.com/openai/deployments/<deployment>
|
|
647
|
+
* OPENAI_EMBEDDING_BASE_URL — embedding-specific base URL override (defaults
|
|
648
|
+
* to OPENAI_BASE_URL). Lets operators run
|
|
649
|
+
* embeddings on a separate endpoint from chat —
|
|
650
|
+
* e.g. local Ollama / LM Studio / llama.cpp /
|
|
651
|
+
* vLLM at http://localhost:1234 for unlimited
|
|
652
|
+
* free embeddings, while keeping chat
|
|
653
|
+
* completions on a rate-limited but high-quality
|
|
654
|
+
* hosted provider. Azure detection runs on
|
|
655
|
+
* whichever URL ends up selected.
|
|
656
|
+
* OPENAI_EMBEDDING_API_KEY — separate API key for the embedding endpoint
|
|
657
|
+
* (defaults to OPENAI_API_KEY). Useful when the
|
|
658
|
+
* embedding endpoint requires a different key
|
|
659
|
+
* or no key at all (set to e.g. "local" for
|
|
660
|
+
* endpoints that ignore Authorization).
|
|
661
|
+
* OPENAI_API_VERSION — Azure api-version query param (default: 2024-08-01-preview)
|
|
662
|
+
* OPENAI_EMBEDDING_MODEL — model name (default: text-embedding-3-small)
|
|
663
|
+
* OPENAI_EMBEDDING_DIMENSIONS — override reported dimensions (required for
|
|
664
|
+
* custom / self-hosted models not in the
|
|
665
|
+
* MODEL_DIMENSIONS table above)
|
|
652
666
|
*/
|
|
653
667
|
var OpenAIEmbeddingProvider = class {
|
|
654
668
|
name = "openai";
|
|
@@ -659,9 +673,9 @@ var OpenAIEmbeddingProvider = class {
|
|
|
659
673
|
isAzure;
|
|
660
674
|
azureApiVersion;
|
|
661
675
|
constructor(apiKey) {
|
|
662
|
-
this.apiKey = apiKey || getEnvVar("OPENAI_API_KEY") || "";
|
|
663
|
-
if (!this.apiKey) throw new Error("
|
|
664
|
-
this.baseUrl = normalizeBaseUrl(getEnvVar("OPENAI_BASE_URL"));
|
|
676
|
+
this.apiKey = apiKey || getEnvVar("OPENAI_EMBEDDING_API_KEY") || getEnvVar("OPENAI_API_KEY") || "";
|
|
677
|
+
if (!this.apiKey) throw new Error("API key is required (via constructor, OPENAI_EMBEDDING_API_KEY, or OPENAI_API_KEY)");
|
|
678
|
+
this.baseUrl = normalizeBaseUrl(getEnvVar("OPENAI_EMBEDDING_BASE_URL") || getEnvVar("OPENAI_BASE_URL"));
|
|
665
679
|
this.model = getEnvVar("OPENAI_EMBEDDING_MODEL") || DEFAULT_MODEL$1;
|
|
666
680
|
this.dimensions = resolveDimensions(this.model, getEnvVar("OPENAI_EMBEDDING_DIMENSIONS"));
|
|
667
681
|
this.isAzure = detectAzure(this.baseUrl);
|
|
@@ -1038,10 +1052,11 @@ var StateKV = class {
|
|
|
1038
1052
|
//#endregion
|
|
1039
1053
|
//#region src/state/vector-index.ts
|
|
1040
1054
|
function float32ToBase64(arr) {
|
|
1041
|
-
return Buffer.from(arr.buffer).toString("base64");
|
|
1055
|
+
return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength).toString("base64");
|
|
1042
1056
|
}
|
|
1043
1057
|
function base64ToFloat32(b64) {
|
|
1044
|
-
|
|
1058
|
+
const buf = Buffer.from(b64, "base64");
|
|
1059
|
+
return new Float32Array(buf.buffer, buf.byteOffset, buf.byteLength / Float32Array.BYTES_PER_ELEMENT);
|
|
1045
1060
|
}
|
|
1046
1061
|
function cosineSimilarity(a, b) {
|
|
1047
1062
|
if (a.length !== b.length) return 0;
|
|
@@ -1162,7 +1177,7 @@ var VectorIndex = class VectorIndex {
|
|
|
1162
1177
|
function memoryToObservation(memory) {
|
|
1163
1178
|
return {
|
|
1164
1179
|
id: memory.id,
|
|
1165
|
-
sessionId: memory.sessionIds[0] ?? "memory",
|
|
1180
|
+
sessionId: memory.sessionIds?.[0] ?? "memory",
|
|
1166
1181
|
timestamp: memory.createdAt,
|
|
1167
1182
|
type: "decision",
|
|
1168
1183
|
title: memory.title,
|
|
@@ -2783,7 +2798,7 @@ async function rebuildIndex(kv) {
|
|
|
2783
2798
|
idx.add(memoryToObservation(memory));
|
|
2784
2799
|
await enqueue({
|
|
2785
2800
|
id: memory.id,
|
|
2786
|
-
sessionId: memory.sessionIds[0] ?? "memory",
|
|
2801
|
+
sessionId: memory.sessionIds?.[0] ?? "memory",
|
|
2787
2802
|
text: memory.title + " " + memory.content,
|
|
2788
2803
|
context: {
|
|
2789
2804
|
kind: "memory",
|
|
@@ -2842,8 +2857,8 @@ function registerSearchFunction(sdk, kv) {
|
|
|
2842
2857
|
if (!Number.isInteger(data.limit) || data.limit < 1) throw new Error("mem::search: limit must be a positive integer");
|
|
2843
2858
|
effectiveLimit = Math.min(data.limit, MAX_LIMIT);
|
|
2844
2859
|
}
|
|
2845
|
-
const projectFilter = typeof data.project === "string" && data.project.length > 0 ? data.project : void 0;
|
|
2846
|
-
const cwdFilter = typeof data.cwd === "string" && data.cwd.length > 0 ? data.cwd : void 0;
|
|
2860
|
+
const projectFilter = typeof data.project === "string" && data.project.trim().length > 0 ? data.project.trim() : void 0;
|
|
2861
|
+
const cwdFilter = typeof data.cwd === "string" && data.cwd.trim().length > 0 ? data.cwd.trim() : void 0;
|
|
2847
2862
|
const format = typeof data.format === "string" ? data.format : "full";
|
|
2848
2863
|
if (![
|
|
2849
2864
|
"full",
|
|
@@ -2869,14 +2884,25 @@ function registerSearchFunction(sdk, kv) {
|
|
|
2869
2884
|
sessionCache.set(sessionId, s ?? null);
|
|
2870
2885
|
return s ?? null;
|
|
2871
2886
|
};
|
|
2887
|
+
const memoryProjectCache = /* @__PURE__ */ new Map();
|
|
2888
|
+
const loadMemoryProject = async (obsId) => {
|
|
2889
|
+
if (memoryProjectCache.has(obsId)) return memoryProjectCache.get(obsId);
|
|
2890
|
+
const proj = (await kv.get(KV.memories, obsId).catch(() => null))?.project ?? null;
|
|
2891
|
+
memoryProjectCache.set(obsId, proj);
|
|
2892
|
+
return proj;
|
|
2893
|
+
};
|
|
2872
2894
|
const candidates = [];
|
|
2873
2895
|
for (const r of results) {
|
|
2874
2896
|
if (candidates.length >= effectiveLimit) break;
|
|
2875
2897
|
if (filtering) {
|
|
2876
2898
|
const s = await loadSession(r.sessionId);
|
|
2877
|
-
if (
|
|
2878
|
-
|
|
2879
|
-
|
|
2899
|
+
if (s) {
|
|
2900
|
+
if (projectFilter && s.project !== projectFilter) continue;
|
|
2901
|
+
if (cwdFilter && s.cwd !== cwdFilter) continue;
|
|
2902
|
+
} else if (projectFilter) {
|
|
2903
|
+
const memProject = await loadMemoryProject(r.obsId);
|
|
2904
|
+
if (memProject !== null && memProject !== projectFilter) continue;
|
|
2905
|
+
}
|
|
2880
2906
|
}
|
|
2881
2907
|
candidates.push(r);
|
|
2882
2908
|
}
|
|
@@ -3521,10 +3547,10 @@ const DEFAULT_SLOTS = [
|
|
|
3521
3547
|
}
|
|
3522
3548
|
];
|
|
3523
3549
|
function isSlotsEnabled() {
|
|
3524
|
-
return
|
|
3550
|
+
return getEnvVar("AGENTMEMORY_SLOTS") === "true";
|
|
3525
3551
|
}
|
|
3526
3552
|
function isReflectEnabled() {
|
|
3527
|
-
return
|
|
3553
|
+
return getEnvVar("AGENTMEMORY_REFLECT") === "true";
|
|
3528
3554
|
}
|
|
3529
3555
|
function scopeKv(scope) {
|
|
3530
3556
|
return scope === "global" ? KV.globalSlots : KV.slots;
|
|
@@ -4789,8 +4815,78 @@ function isAllowedPath(dbPath) {
|
|
|
4789
4815
|
const resolved = resolve(dbPath);
|
|
4790
4816
|
return ALLOWED_DIRS.some((dir) => resolved.startsWith(dir + "/"));
|
|
4791
4817
|
}
|
|
4818
|
+
async function inferMemoryProjects(kv, dryRun = false) {
|
|
4819
|
+
const memories = await kv.list(KV.memories);
|
|
4820
|
+
const sessionCache = /* @__PURE__ */ new Map();
|
|
4821
|
+
const loadSession = async (sid) => {
|
|
4822
|
+
if (sessionCache.has(sid)) return sessionCache.get(sid);
|
|
4823
|
+
const s = await kv.get(KV.sessions, sid).catch(() => null);
|
|
4824
|
+
sessionCache.set(sid, s);
|
|
4825
|
+
return s;
|
|
4826
|
+
};
|
|
4827
|
+
let updated = 0;
|
|
4828
|
+
let skipped = 0;
|
|
4829
|
+
let ambiguous = 0;
|
|
4830
|
+
for (const memory of memories) {
|
|
4831
|
+
if (memory.project) {
|
|
4832
|
+
skipped++;
|
|
4833
|
+
continue;
|
|
4834
|
+
}
|
|
4835
|
+
const sessionIds = memory.sessionIds ?? [];
|
|
4836
|
+
if (sessionIds.length === 0) {
|
|
4837
|
+
ambiguous++;
|
|
4838
|
+
continue;
|
|
4839
|
+
}
|
|
4840
|
+
const projects = [];
|
|
4841
|
+
for (const sid of sessionIds) {
|
|
4842
|
+
const session = await loadSession(sid);
|
|
4843
|
+
if (session?.project) projects.push(session.project);
|
|
4844
|
+
}
|
|
4845
|
+
if (projects.length === 0) {
|
|
4846
|
+
ambiguous++;
|
|
4847
|
+
continue;
|
|
4848
|
+
}
|
|
4849
|
+
const freq = /* @__PURE__ */ new Map();
|
|
4850
|
+
for (const p of projects) freq.set(p, (freq.get(p) ?? 0) + 1);
|
|
4851
|
+
const sorted = [...freq.entries()].sort((a, b) => b[1] - a[1]);
|
|
4852
|
+
const [topProject, topCount] = sorted[0];
|
|
4853
|
+
if (topCount <= projects.length / 2 && sorted.length > 1) {
|
|
4854
|
+
ambiguous++;
|
|
4855
|
+
continue;
|
|
4856
|
+
}
|
|
4857
|
+
if (!dryRun) {
|
|
4858
|
+
memory.project = topProject;
|
|
4859
|
+
await kv.set(KV.memories, memory.id, memory);
|
|
4860
|
+
}
|
|
4861
|
+
updated++;
|
|
4862
|
+
}
|
|
4863
|
+
logger.info("inferMemoryProjects complete", {
|
|
4864
|
+
updated,
|
|
4865
|
+
skipped,
|
|
4866
|
+
ambiguous,
|
|
4867
|
+
dryRun
|
|
4868
|
+
});
|
|
4869
|
+
return {
|
|
4870
|
+
updated,
|
|
4871
|
+
skipped,
|
|
4872
|
+
ambiguous
|
|
4873
|
+
};
|
|
4874
|
+
}
|
|
4792
4875
|
function registerMigrateFunction(sdk, kv) {
|
|
4793
4876
|
sdk.registerFunction("mem::migrate", async (data) => {
|
|
4877
|
+
if (data.step === "infer-memory-projects") {
|
|
4878
|
+
const dryRun = data.dryRun ?? false;
|
|
4879
|
+
logger.info("Migration step: infer-memory-projects", { dryRun });
|
|
4880
|
+
return {
|
|
4881
|
+
success: true,
|
|
4882
|
+
step: "infer-memory-projects",
|
|
4883
|
+
...await inferMemoryProjects(kv, dryRun)
|
|
4884
|
+
};
|
|
4885
|
+
}
|
|
4886
|
+
if (!data.dbPath) return {
|
|
4887
|
+
success: false,
|
|
4888
|
+
error: "Either step or dbPath is required"
|
|
4889
|
+
};
|
|
4794
4890
|
logger.info("Migration started", { dbPath: data.dbPath });
|
|
4795
4891
|
if (!isAllowedPath(data.dbPath)) return {
|
|
4796
4892
|
success: false,
|
|
@@ -5066,9 +5162,10 @@ function registerConsolidateFunction(sdk, kv, provider) {
|
|
|
5066
5162
|
llmCallCount++;
|
|
5067
5163
|
const parsed = parseMemoryXml(response, sessionIds);
|
|
5068
5164
|
if (!parsed) continue;
|
|
5069
|
-
const existingMatch = existingMemories.find((m) => m.title.toLowerCase() === parsed.title.toLowerCase());
|
|
5070
5165
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5071
5166
|
const obsIds = [...new Set(top.map((o) => o.id))];
|
|
5167
|
+
const scopedProject = typeof data.project === "string" && data.project.trim().length > 0 ? data.project.trim() : void 0;
|
|
5168
|
+
const existingMatch = existingMemories.find((m) => m.title.toLowerCase() === parsed.title.toLowerCase() && (!scopedProject || !m.project || m.project === scopedProject));
|
|
5072
5169
|
if (existingMatch) {
|
|
5073
5170
|
existingMatch.isLatest = false;
|
|
5074
5171
|
await kv.set(KV.memories, existingMatch.id, existingMatch);
|
|
@@ -5085,7 +5182,8 @@ function registerConsolidateFunction(sdk, kv, provider) {
|
|
|
5085
5182
|
parentId: existingMatch.id,
|
|
5086
5183
|
supersedes: [existingMatch.id, ...existingMatch.supersedes || []],
|
|
5087
5184
|
sourceObservationIds: obsIds,
|
|
5088
|
-
isLatest: true
|
|
5185
|
+
isLatest: true,
|
|
5186
|
+
...scopedProject !== void 0 && { project: scopedProject }
|
|
5089
5187
|
};
|
|
5090
5188
|
await kv.set(KV.memories, evolved.id, evolved);
|
|
5091
5189
|
await recordAudit(kv, "evolve", "mem::consolidate", [evolved.id], {
|
|
@@ -5104,7 +5202,8 @@ function registerConsolidateFunction(sdk, kv, provider) {
|
|
|
5104
5202
|
...parsed,
|
|
5105
5203
|
sourceObservationIds: obsIds,
|
|
5106
5204
|
version: 1,
|
|
5107
|
-
isLatest: true
|
|
5205
|
+
isLatest: true,
|
|
5206
|
+
...scopedProject !== void 0 && { project: scopedProject }
|
|
5108
5207
|
};
|
|
5109
5208
|
await kv.set(KV.memories, memory.id, memory);
|
|
5110
5209
|
await recordAudit(kv, "remember", "mem::consolidate", [memory.id], {
|
|
@@ -5245,6 +5344,7 @@ function registerRememberFunction(sdk, kv) {
|
|
|
5245
5344
|
"fact"
|
|
5246
5345
|
]).has(data.type || "") ? data.type : "fact";
|
|
5247
5346
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5347
|
+
const project = typeof data.project === "string" && data.project.trim().length > 0 ? data.project.trim() : void 0;
|
|
5248
5348
|
return withKeyedLock("mem:remember", async () => {
|
|
5249
5349
|
const existingMemories = await kv.list(KV.memories);
|
|
5250
5350
|
let supersededId;
|
|
@@ -5253,6 +5353,7 @@ function registerRememberFunction(sdk, kv) {
|
|
|
5253
5353
|
const lowerContent = data.content.toLowerCase();
|
|
5254
5354
|
for (const existing of existingMemories) {
|
|
5255
5355
|
if (existing.isLatest === false) continue;
|
|
5356
|
+
if (project && existing.project && existing.project !== project) continue;
|
|
5256
5357
|
if (jaccardSimilarity(lowerContent, existing.content.toLowerCase()) > .7) {
|
|
5257
5358
|
supersededId = existing.id;
|
|
5258
5359
|
supersededVersion = existing.version ?? 1;
|
|
@@ -5277,7 +5378,8 @@ function registerRememberFunction(sdk, kv) {
|
|
|
5277
5378
|
supersedes: supersededId ? [supersededId] : [],
|
|
5278
5379
|
sourceObservationIds: (data.sourceObservationIds || []).filter((id) => typeof id === "string" && id.length > 0),
|
|
5279
5380
|
isLatest: true,
|
|
5280
|
-
...callAgentId ? { agentId: callAgentId } : {}
|
|
5381
|
+
...callAgentId ? { agentId: callAgentId } : {},
|
|
5382
|
+
...project !== void 0 && { project }
|
|
5281
5383
|
};
|
|
5282
5384
|
if (data.ttlDays && typeof data.ttlDays === "number" && data.ttlDays > 0) memory.forgetAfter = new Date(Date.now() + data.ttlDays * 864e5).toISOString();
|
|
5283
5385
|
if (supersededMemory) {
|
|
@@ -5293,7 +5395,7 @@ function registerRememberFunction(sdk, kv) {
|
|
|
5293
5395
|
error: err instanceof Error ? err.message : String(err)
|
|
5294
5396
|
});
|
|
5295
5397
|
}
|
|
5296
|
-
await vectorIndexAddGuarded(memory.id, memory.sessionIds[0] ?? "memory", memory.title + " " + memory.content, {
|
|
5398
|
+
await vectorIndexAddGuarded(memory.id, memory.sessionIds?.[0] ?? "memory", memory.title + " " + memory.content, {
|
|
5297
5399
|
kind: "memory",
|
|
5298
5400
|
logId: memory.id
|
|
5299
5401
|
});
|
|
@@ -5304,7 +5406,8 @@ function registerRememberFunction(sdk, kv) {
|
|
|
5304
5406
|
});
|
|
5305
5407
|
logger.info("Memory saved", {
|
|
5306
5408
|
memId: memory.id,
|
|
5307
|
-
type: memory.type
|
|
5409
|
+
type: memory.type,
|
|
5410
|
+
project: memory.project
|
|
5308
5411
|
});
|
|
5309
5412
|
return {
|
|
5310
5413
|
success: true,
|
|
@@ -6341,7 +6444,9 @@ function registerExportImportFunction(sdk, kv) {
|
|
|
6341
6444
|
"0.9.19",
|
|
6342
6445
|
"0.9.20",
|
|
6343
6446
|
"0.9.21",
|
|
6344
|
-
"0.9.22"
|
|
6447
|
+
"0.9.22",
|
|
6448
|
+
"0.9.23",
|
|
6449
|
+
"0.9.24"
|
|
6345
6450
|
]).has(importData.version)) return {
|
|
6346
6451
|
success: false,
|
|
6347
6452
|
error: `Unsupported export version: ${importData.version}`
|
|
@@ -6464,6 +6569,7 @@ function registerExportImportFunction(sdk, kv) {
|
|
|
6464
6569
|
continue;
|
|
6465
6570
|
}
|
|
6466
6571
|
}
|
|
6572
|
+
if (!Array.isArray(memory.sessionIds)) memory.sessionIds = [];
|
|
6467
6573
|
await kv.set(KV.memories, memory.id, memory);
|
|
6468
6574
|
stats.memories++;
|
|
6469
6575
|
}
|
|
@@ -6667,6 +6773,7 @@ function escapeXml(s) {
|
|
|
6667
6773
|
}
|
|
6668
6774
|
function registerEnrichFunction(sdk, kv) {
|
|
6669
6775
|
sdk.registerFunction("mem::enrich", async (data) => {
|
|
6776
|
+
const project = typeof data.project === "string" && data.project.trim().length > 0 ? data.project.trim() : void 0;
|
|
6670
6777
|
const parts = [];
|
|
6671
6778
|
const fileContextPromise = sdk.trigger({
|
|
6672
6779
|
function_id: "mem::file-context",
|
|
@@ -6680,10 +6787,11 @@ function registerEnrichFunction(sdk, kv) {
|
|
|
6680
6787
|
function_id: "mem::search",
|
|
6681
6788
|
payload: {
|
|
6682
6789
|
query: searchQueries.join(" "),
|
|
6683
|
-
limit: 5
|
|
6790
|
+
limit: 5,
|
|
6791
|
+
...project !== void 0 && { project }
|
|
6684
6792
|
}
|
|
6685
6793
|
}).catch(() => ({ results: [] })) : Promise.resolve({ results: [] });
|
|
6686
|
-
const bugMemoriesPromise = kv.list(KV.memories).then((memories) => memories.filter((m) => m.type === "bug" && m.isLatest && m.files.some((f) => data.files.some((df) => f.includes(df) || df.includes(f)))).sort((a, b) => new Date(b.updatedAt || b.createdAt).getTime() - new Date(a.updatedAt || a.createdAt).getTime())).catch(() => []);
|
|
6794
|
+
const bugMemoriesPromise = kv.list(KV.memories).then((memories) => memories.filter((m) => m.type === "bug" && m.isLatest && (!project || !m.project || m.project === project) && m.files.some((f) => data.files.some((df) => f.includes(df) || df.includes(f)))).sort((a, b) => new Date(b.updatedAt || b.createdAt).getTime() - new Date(a.updatedAt || a.createdAt).getTime())).catch(() => []);
|
|
6687
6795
|
const [fileContext, searchResult, bugMemories] = await Promise.all([
|
|
6688
6796
|
fileContextPromise,
|
|
6689
6797
|
searchPromise,
|
|
@@ -6706,6 +6814,7 @@ function registerEnrichFunction(sdk, kv) {
|
|
|
6706
6814
|
}
|
|
6707
6815
|
logger.info("Enrichment completed", {
|
|
6708
6816
|
sessionId: data.sessionId,
|
|
6817
|
+
project,
|
|
6709
6818
|
fileCount: data.files.length,
|
|
6710
6819
|
contextLength: context.length,
|
|
6711
6820
|
truncated
|
|
@@ -6863,16 +6972,24 @@ function buildGraphExtractionPrompt(observations) {
|
|
|
6863
6972
|
|
|
6864
6973
|
//#endregion
|
|
6865
6974
|
//#region src/functions/graph.ts
|
|
6975
|
+
function parseAttrs(raw) {
|
|
6976
|
+
const attrs = {};
|
|
6977
|
+
const attrRegex = /([A-Za-z_][\w:-]*)="([^"]*)"/g;
|
|
6978
|
+
let m;
|
|
6979
|
+
while ((m = attrRegex.exec(raw)) !== null) attrs[m[1]] = m[2];
|
|
6980
|
+
return attrs;
|
|
6981
|
+
}
|
|
6866
6982
|
function parseGraphXml(xml, observationIds) {
|
|
6867
6983
|
const nodes = [];
|
|
6868
6984
|
const edges = [];
|
|
6869
6985
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6870
|
-
const
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
const
|
|
6874
|
-
const
|
|
6875
|
-
const
|
|
6986
|
+
const entitySelfClose = /<entity\b([^>]*?)\/>/g;
|
|
6987
|
+
const entityWithBody = /<entity\b([^>]*[^/])>([\s\S]*?)<\/entity>/g;
|
|
6988
|
+
const addEntity = (rawAttrs, propsBlock = "") => {
|
|
6989
|
+
const attrs = parseAttrs(rawAttrs);
|
|
6990
|
+
const type = attrs["type"];
|
|
6991
|
+
const name = attrs["name"];
|
|
6992
|
+
if (!type || !name) return;
|
|
6876
6993
|
const properties = {};
|
|
6877
6994
|
const propRegex = /<property\s+key="([^"]+)">([^<]*)<\/property>/g;
|
|
6878
6995
|
let propMatch;
|
|
@@ -6885,17 +7002,23 @@ function parseGraphXml(xml, observationIds) {
|
|
|
6885
7002
|
sourceObservationIds: observationIds,
|
|
6886
7003
|
createdAt: now
|
|
6887
7004
|
});
|
|
6888
|
-
}
|
|
6889
|
-
|
|
7005
|
+
};
|
|
7006
|
+
let match;
|
|
7007
|
+
while ((match = entitySelfClose.exec(xml)) !== null) addEntity(match[1]);
|
|
7008
|
+
while ((match = entityWithBody.exec(xml)) !== null) addEntity(match[1], match[2]);
|
|
7009
|
+
const relRegex = /<relationship\b([^>]*?)\/>/g;
|
|
6890
7010
|
while ((match = relRegex.exec(xml)) !== null) {
|
|
6891
|
-
const
|
|
6892
|
-
const
|
|
6893
|
-
const
|
|
6894
|
-
const
|
|
6895
|
-
|
|
7011
|
+
const attrs = parseAttrs(match[1]);
|
|
7012
|
+
const type = attrs["type"];
|
|
7013
|
+
const sourceName = attrs["source"];
|
|
7014
|
+
const targetName = attrs["target"];
|
|
7015
|
+
if (!type || !sourceName || !targetName) continue;
|
|
7016
|
+
const parsedWeight = parseFloat(attrs["weight"] ?? "");
|
|
7017
|
+
const weight = Number.isFinite(parsedWeight) ? parsedWeight : .5;
|
|
6896
7018
|
const sourceNode = nodes.find((n) => n.name === sourceName);
|
|
6897
7019
|
const targetNode = nodes.find((n) => n.name === targetName);
|
|
6898
|
-
if (sourceNode
|
|
7020
|
+
if (!sourceNode || !targetNode) continue;
|
|
7021
|
+
edges.push({
|
|
6899
7022
|
id: generateId("ge"),
|
|
6900
7023
|
type,
|
|
6901
7024
|
sourceNodeId: sourceNode.id,
|
|
@@ -7109,7 +7232,7 @@ function registerConsolidationPipelineFunction(sdk, kv, provider) {
|
|
|
7109
7232
|
if (!data?.force && !isConsolidationEnabled()) return {
|
|
7110
7233
|
success: false,
|
|
7111
7234
|
skipped: true,
|
|
7112
|
-
reason: "CONSOLIDATION_ENABLED
|
|
7235
|
+
reason: "Consolidation disabled: set CONSOLIDATION_ENABLED=true or configure an LLM provider (ANTHROPIC_API_KEY / OPENAI_API_KEY / OPENROUTER_API_KEY / GEMINI_API_KEY / GOOGLE_API_KEY / MINIMAX_API_KEY / OPENAI_BASE_URL / AGENTMEMORY_PROVIDER=agent-sdk)"
|
|
7113
7236
|
};
|
|
7114
7237
|
const tier = data?.tier || "all";
|
|
7115
7238
|
const decayDays = getConsolidationDecayDays();
|
|
@@ -10279,11 +10402,34 @@ function registerDiagnosticsFunction(sdk, kv) {
|
|
|
10279
10402
|
});
|
|
10280
10403
|
memoryIssues++;
|
|
10281
10404
|
}
|
|
10405
|
+
const latestMemories = memories.filter((m) => m.isLatest);
|
|
10406
|
+
const unscopedCount = latestMemories.filter((m) => !m.project).length;
|
|
10407
|
+
if (unscopedCount === 0) checks.push({
|
|
10408
|
+
name: "memory-project-coverage",
|
|
10409
|
+
category: "memories",
|
|
10410
|
+
status: "pass",
|
|
10411
|
+
message: `All ${latestMemories.length} latest memories have a project scope`,
|
|
10412
|
+
fixable: false
|
|
10413
|
+
});
|
|
10414
|
+
else if (unscopedCount <= 10) checks.push({
|
|
10415
|
+
name: "memory-project-coverage",
|
|
10416
|
+
category: "memories",
|
|
10417
|
+
status: "warn",
|
|
10418
|
+
message: `${unscopedCount} of ${latestMemories.length} latest memories have no project scope — run POST /agentmemory/migrate {"step":"infer-memory-projects"} to backfill`,
|
|
10419
|
+
fixable: true
|
|
10420
|
+
});
|
|
10421
|
+
else checks.push({
|
|
10422
|
+
name: "memory-project-coverage",
|
|
10423
|
+
category: "memories",
|
|
10424
|
+
status: "fail",
|
|
10425
|
+
message: `${unscopedCount} of ${latestMemories.length} latest memories have no project scope — run POST /agentmemory/migrate {"step":"infer-memory-projects"} to backfill`,
|
|
10426
|
+
fixable: true
|
|
10427
|
+
});
|
|
10282
10428
|
if (memoryIssues === 0) checks.push({
|
|
10283
10429
|
name: "memories-ok",
|
|
10284
10430
|
category: "memories",
|
|
10285
10431
|
status: "pass",
|
|
10286
|
-
message: `All ${memories.length} memories are consistent`,
|
|
10432
|
+
message: `All ${memories.length} memories are structurally consistent`,
|
|
10287
10433
|
fixable: false
|
|
10288
10434
|
});
|
|
10289
10435
|
}
|
|
@@ -14056,6 +14202,22 @@ function consolidationDisabledResponse() {
|
|
|
14056
14202
|
docsHref: "https://github.com/rohitg00/agentmemory#consolidation"
|
|
14057
14203
|
});
|
|
14058
14204
|
}
|
|
14205
|
+
function slotsDisabledResponse() {
|
|
14206
|
+
return flagDisabledResponse({
|
|
14207
|
+
error: "Memory slots not enabled",
|
|
14208
|
+
flag: "AGENTMEMORY_SLOTS",
|
|
14209
|
+
enableHow: "Set AGENTMEMORY_SLOTS=true (in ~/.agentmemory/.env or the shell) and restart.",
|
|
14210
|
+
docsHref: "https://github.com/rohitg00/agentmemory#memory-slots"
|
|
14211
|
+
});
|
|
14212
|
+
}
|
|
14213
|
+
function reflectDisabledResponse() {
|
|
14214
|
+
return flagDisabledResponse({
|
|
14215
|
+
error: "Slot reflection not enabled",
|
|
14216
|
+
flag: "AGENTMEMORY_REFLECT",
|
|
14217
|
+
enableHow: "Set AGENTMEMORY_REFLECT=true (in ~/.agentmemory/.env or the shell) and restart. Requires AGENTMEMORY_SLOTS=true.",
|
|
14218
|
+
docsHref: "https://github.com/rohitg00/agentmemory#memory-slots"
|
|
14219
|
+
});
|
|
14220
|
+
}
|
|
14059
14221
|
function asNonEmptyString$1(value) {
|
|
14060
14222
|
if (typeof value !== "string") return null;
|
|
14061
14223
|
const trimmed = value.trim();
|
|
@@ -14500,6 +14662,14 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
14500
14662
|
path: "status",
|
|
14501
14663
|
value: "completed"
|
|
14502
14664
|
}]);
|
|
14665
|
+
try {
|
|
14666
|
+
sdk.triggerVoid("event::session::stopped", { sessionId });
|
|
14667
|
+
} catch (err) {
|
|
14668
|
+
logger.warn("event::session::stopped triggerVoid failed", {
|
|
14669
|
+
sessionId,
|
|
14670
|
+
error: err instanceof Error ? err.message : String(err)
|
|
14671
|
+
});
|
|
14672
|
+
}
|
|
14503
14673
|
return {
|
|
14504
14674
|
status_code: 200,
|
|
14505
14675
|
body: { success: true }
|
|
@@ -14718,11 +14888,21 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
14718
14888
|
status_code: 400,
|
|
14719
14889
|
body: { error: "terms must be an array of strings" }
|
|
14720
14890
|
};
|
|
14891
|
+
if (req.body.project !== void 0 && (typeof req.body.project !== "string" || !req.body.project.trim())) return {
|
|
14892
|
+
status_code: 400,
|
|
14893
|
+
body: { error: "project must be a non-empty string" }
|
|
14894
|
+
};
|
|
14721
14895
|
return {
|
|
14722
14896
|
status_code: 200,
|
|
14723
14897
|
body: await sdk.trigger({
|
|
14724
14898
|
function_id: "mem::enrich",
|
|
14725
|
-
payload:
|
|
14899
|
+
payload: {
|
|
14900
|
+
sessionId: req.body.sessionId,
|
|
14901
|
+
files: req.body.files,
|
|
14902
|
+
...req.body.terms !== void 0 && { terms: req.body.terms },
|
|
14903
|
+
...req.body.toolName !== void 0 && { toolName: req.body.toolName },
|
|
14904
|
+
...req.body.project !== void 0 && { project: req.body.project }
|
|
14905
|
+
}
|
|
14726
14906
|
})
|
|
14727
14907
|
};
|
|
14728
14908
|
});
|
|
@@ -14741,11 +14921,23 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
14741
14921
|
status_code: 400,
|
|
14742
14922
|
body: { error: "content is required" }
|
|
14743
14923
|
};
|
|
14924
|
+
if (req.body.project !== void 0 && (typeof req.body.project !== "string" || !req.body.project.trim())) return {
|
|
14925
|
+
status_code: 400,
|
|
14926
|
+
body: { error: "project must be a non-empty string" }
|
|
14927
|
+
};
|
|
14744
14928
|
return {
|
|
14745
14929
|
status_code: 201,
|
|
14746
14930
|
body: await sdk.trigger({
|
|
14747
14931
|
function_id: "mem::remember",
|
|
14748
|
-
payload:
|
|
14932
|
+
payload: {
|
|
14933
|
+
content: req.body.content,
|
|
14934
|
+
...req.body.type !== void 0 && { type: req.body.type },
|
|
14935
|
+
...req.body.concepts !== void 0 && { concepts: req.body.concepts },
|
|
14936
|
+
...req.body.files !== void 0 && { files: req.body.files },
|
|
14937
|
+
...req.body.ttlDays !== void 0 && { ttlDays: req.body.ttlDays },
|
|
14938
|
+
...req.body.sourceObservationIds !== void 0 && { sourceObservationIds: req.body.sourceObservationIds },
|
|
14939
|
+
...req.body.project !== void 0 && { project: req.body.project }
|
|
14940
|
+
}
|
|
14749
14941
|
})
|
|
14750
14942
|
};
|
|
14751
14943
|
});
|
|
@@ -14840,15 +15032,21 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
14840
15032
|
sdk.registerFunction("api::migrate", async (req) => {
|
|
14841
15033
|
const authErr = checkAuth(req, secret);
|
|
14842
15034
|
if (authErr) return authErr;
|
|
14843
|
-
|
|
15035
|
+
const hasStep = typeof req.body?.step === "string" && req.body.step.trim().length > 0;
|
|
15036
|
+
const hasDbPath = typeof req.body?.dbPath === "string" && req.body.dbPath.trim().length > 0;
|
|
15037
|
+
if (!hasStep && !hasDbPath) return {
|
|
14844
15038
|
status_code: 400,
|
|
14845
|
-
body: { error: "dbPath is required" }
|
|
15039
|
+
body: { error: "Either step (string) or dbPath (string) is required" }
|
|
14846
15040
|
};
|
|
14847
15041
|
return {
|
|
14848
15042
|
status_code: 200,
|
|
14849
15043
|
body: await sdk.trigger({
|
|
14850
15044
|
function_id: "mem::migrate",
|
|
14851
|
-
payload:
|
|
15045
|
+
payload: {
|
|
15046
|
+
...req.body.step !== void 0 && { step: req.body.step },
|
|
15047
|
+
...req.body.dbPath !== void 0 && { dbPath: req.body.dbPath },
|
|
15048
|
+
...req.body.dryRun !== void 0 && { dryRun: req.body.dryRun }
|
|
15049
|
+
}
|
|
14852
15050
|
})
|
|
14853
15051
|
};
|
|
14854
15052
|
});
|
|
@@ -15194,6 +15392,63 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15194
15392
|
http_method: "POST"
|
|
15195
15393
|
}
|
|
15196
15394
|
});
|
|
15395
|
+
sdk.registerFunction("api::graph-build", async (req) => {
|
|
15396
|
+
const authErr = checkAuth(req, secret);
|
|
15397
|
+
if (authErr) return authErr;
|
|
15398
|
+
const batchSize = Math.max(1, Math.min(100, Number(req.body?.batchSize) || 25));
|
|
15399
|
+
try {
|
|
15400
|
+
const sessions = await kv.list(KV.sessions);
|
|
15401
|
+
let totalNodes = 0;
|
|
15402
|
+
let totalEdges = 0;
|
|
15403
|
+
let batchesRun = 0;
|
|
15404
|
+
for (const session of sessions) {
|
|
15405
|
+
const sid = session?.id;
|
|
15406
|
+
if (typeof sid !== "string" || sid.length === 0) continue;
|
|
15407
|
+
const compressed = (await kv.list(KV.observations(sid))).filter((o) => o && typeof o.title === "string" && o.title.length > 0);
|
|
15408
|
+
if (compressed.length === 0) continue;
|
|
15409
|
+
for (let i = 0; i < compressed.length; i += batchSize) {
|
|
15410
|
+
const batch = compressed.slice(i, i + batchSize);
|
|
15411
|
+
try {
|
|
15412
|
+
const result = await sdk.trigger({
|
|
15413
|
+
function_id: "mem::graph-extract",
|
|
15414
|
+
payload: { observations: batch }
|
|
15415
|
+
});
|
|
15416
|
+
if (result?.success) {
|
|
15417
|
+
totalNodes += Number(result.nodesAdded) || 0;
|
|
15418
|
+
totalEdges += Number(result.edgesAdded) || 0;
|
|
15419
|
+
}
|
|
15420
|
+
batchesRun++;
|
|
15421
|
+
} catch (err) {
|
|
15422
|
+
logger.warn("graph-build batch failed", {
|
|
15423
|
+
sessionId: sid,
|
|
15424
|
+
batchIndex: Math.floor(i / batchSize),
|
|
15425
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15426
|
+
});
|
|
15427
|
+
}
|
|
15428
|
+
}
|
|
15429
|
+
}
|
|
15430
|
+
return {
|
|
15431
|
+
status_code: 200,
|
|
15432
|
+
body: {
|
|
15433
|
+
success: true,
|
|
15434
|
+
sessions: sessions.length,
|
|
15435
|
+
batches: batchesRun,
|
|
15436
|
+
nodes: totalNodes,
|
|
15437
|
+
edges: totalEdges
|
|
15438
|
+
}
|
|
15439
|
+
};
|
|
15440
|
+
} catch {
|
|
15441
|
+
return graphDisabledResponse();
|
|
15442
|
+
}
|
|
15443
|
+
});
|
|
15444
|
+
sdk.registerTrigger({
|
|
15445
|
+
type: "http",
|
|
15446
|
+
function_id: "api::graph-build",
|
|
15447
|
+
config: {
|
|
15448
|
+
api_path: "/agentmemory/graph/build",
|
|
15449
|
+
http_method: "POST"
|
|
15450
|
+
}
|
|
15451
|
+
});
|
|
15197
15452
|
sdk.registerFunction("api::consolidate-pipeline", async (req) => {
|
|
15198
15453
|
const authErr = checkAuth(req, secret);
|
|
15199
15454
|
if (authErr) return authErr;
|
|
@@ -15651,6 +15906,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15651
15906
|
sdk.registerFunction("api::slot-list", async (req) => {
|
|
15652
15907
|
const authErr = checkAuth(req, secret);
|
|
15653
15908
|
if (authErr) return authErr;
|
|
15909
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15654
15910
|
return {
|
|
15655
15911
|
status_code: 200,
|
|
15656
15912
|
body: await sdk.trigger({
|
|
@@ -15670,6 +15926,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15670
15926
|
sdk.registerFunction("api::slot-get", async (req) => {
|
|
15671
15927
|
const authErr = checkAuth(req, secret);
|
|
15672
15928
|
if (authErr) return authErr;
|
|
15929
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15673
15930
|
const label = asNonEmptyString$1(req.query_params?.["label"]);
|
|
15674
15931
|
if (!label) return {
|
|
15675
15932
|
status_code: 400,
|
|
@@ -15700,6 +15957,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15700
15957
|
sdk.registerFunction("api::slot-create", async (req) => {
|
|
15701
15958
|
const authErr = checkAuth(req, secret);
|
|
15702
15959
|
if (authErr) return authErr;
|
|
15960
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15703
15961
|
const body = req.body ?? {};
|
|
15704
15962
|
const label = asNonEmptyString$1(body["label"]);
|
|
15705
15963
|
if (!label) return {
|
|
@@ -15762,6 +16020,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15762
16020
|
sdk.registerFunction("api::slot-append", async (req) => {
|
|
15763
16021
|
const authErr = checkAuth(req, secret);
|
|
15764
16022
|
if (authErr) return authErr;
|
|
16023
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15765
16024
|
const body = req.body ?? {};
|
|
15766
16025
|
const label = asNonEmptyString$1(body["label"]);
|
|
15767
16026
|
const text = typeof body["text"] === "string" ? body["text"] : null;
|
|
@@ -15801,6 +16060,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15801
16060
|
sdk.registerFunction("api::slot-replace", async (req) => {
|
|
15802
16061
|
const authErr = checkAuth(req, secret);
|
|
15803
16062
|
if (authErr) return authErr;
|
|
16063
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15804
16064
|
const body = req.body ?? {};
|
|
15805
16065
|
const label = asNonEmptyString$1(body["label"]);
|
|
15806
16066
|
const content = body["content"];
|
|
@@ -15840,6 +16100,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15840
16100
|
sdk.registerFunction("api::slot-delete", async (req) => {
|
|
15841
16101
|
const authErr = checkAuth(req, secret);
|
|
15842
16102
|
if (authErr) return authErr;
|
|
16103
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15843
16104
|
const label = asNonEmptyString$1(req.query_params?.["label"]);
|
|
15844
16105
|
if (!label) return {
|
|
15845
16106
|
status_code: 400,
|
|
@@ -15870,6 +16131,8 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15870
16131
|
sdk.registerFunction("api::slot-reflect", async (req) => {
|
|
15871
16132
|
const authErr = checkAuth(req, secret);
|
|
15872
16133
|
if (authErr) return authErr;
|
|
16134
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
16135
|
+
if (!isReflectEnabled()) return reflectDisabledResponse();
|
|
15873
16136
|
const body = req.body ?? {};
|
|
15874
16137
|
const sessionId = asNonEmptyString$1(body["sessionId"]);
|
|
15875
16138
|
if (!sessionId) return {
|
|
@@ -17572,13 +17835,15 @@ function registerMcpEndpoints(sdk, kv, secret) {
|
|
|
17572
17835
|
const type = args.type || "fact";
|
|
17573
17836
|
const concepts = typeof args.concepts === "string" ? args.concepts.split(",").map((c) => c.trim()).filter(Boolean) : [];
|
|
17574
17837
|
const files = typeof args.files === "string" ? args.files.split(",").map((f) => f.trim()).filter(Boolean) : [];
|
|
17838
|
+
const project = typeof args.project === "string" && args.project.trim().length > 0 ? args.project.trim() : void 0;
|
|
17575
17839
|
const result = await sdk.trigger({
|
|
17576
17840
|
function_id: "mem::remember",
|
|
17577
17841
|
payload: {
|
|
17578
17842
|
content: args.content,
|
|
17579
17843
|
type,
|
|
17580
17844
|
concepts,
|
|
17581
|
-
files
|
|
17845
|
+
files,
|
|
17846
|
+
...project !== void 0 && { project }
|
|
17582
17847
|
}
|
|
17583
17848
|
});
|
|
17584
17849
|
return {
|
|
@@ -19425,7 +19690,7 @@ async function main() {
|
|
|
19425
19690
|
if (bm25Index.has(memory.id)) continue;
|
|
19426
19691
|
bm25Index.add({
|
|
19427
19692
|
id: memory.id,
|
|
19428
|
-
sessionId: memory.sessionIds[0] ?? "memory",
|
|
19693
|
+
sessionId: memory.sessionIds?.[0] ?? "memory",
|
|
19429
19694
|
timestamp: memory.createdAt,
|
|
19430
19695
|
type: "decision",
|
|
19431
19696
|
title: memory.title,
|
|
@@ -19445,7 +19710,7 @@ async function main() {
|
|
|
19445
19710
|
console.warn(`[agentmemory] Failed to backfill memories into BM25:`, err);
|
|
19446
19711
|
}
|
|
19447
19712
|
bootLog(`Ready. ${embeddingProvider ? "Triple-stream (BM25+Vector+Graph)" : "BM25+Graph"} search active.`);
|
|
19448
|
-
bootLog(`REST API:
|
|
19713
|
+
bootLog(`REST API: 125 endpoints at http://localhost:${config.restPort}/agentmemory/*`);
|
|
19449
19714
|
bootLog(`MCP surface (opt-in via \`npx @agentmemory/mcp\`): ${getAllTools().length} tools · 6 resources · 3 prompts`);
|
|
19450
19715
|
const viewerServer = startViewerServer(config.restPort + 2, kv, sdk, secret, config.restPort);
|
|
19451
19716
|
const autoForgetIntervalMs = parseInt(process.env.AUTO_FORGET_INTERVAL_MS || "3600000", 10);
|
|
@@ -19514,4 +19779,4 @@ main().catch((err) => {
|
|
|
19514
19779
|
|
|
19515
19780
|
//#endregion
|
|
19516
19781
|
export { };
|
|
19517
|
-
//# sourceMappingURL=src-
|
|
19782
|
+
//# sourceMappingURL=src-B8J9Exum.mjs.map
|