@agentmemory/agentmemory 0.9.22 → 0.9.23
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 +32 -18
- 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 +335 -57
- package/dist/index.mjs.map +1 -1
- package/dist/{src-gpTAJuBy.mjs → src-DvS3bhMe.mjs} +322 -58
- package/dist/src-DvS3bhMe.mjs.map +1 -0
- package/dist/{standalone-C4i7ktpn.mjs → standalone-DHQcPX_g.mjs} +92 -11
- package/dist/standalone-DHQcPX_g.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-BPfyI4Kc.mjs +6 -0
- package/dist/version-BPfyI4Kc.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-BPfyI4Kc.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,8 @@ 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"
|
|
6345
6449
|
]).has(importData.version)) return {
|
|
6346
6450
|
success: false,
|
|
6347
6451
|
error: `Unsupported export version: ${importData.version}`
|
|
@@ -6464,6 +6568,7 @@ function registerExportImportFunction(sdk, kv) {
|
|
|
6464
6568
|
continue;
|
|
6465
6569
|
}
|
|
6466
6570
|
}
|
|
6571
|
+
if (!Array.isArray(memory.sessionIds)) memory.sessionIds = [];
|
|
6467
6572
|
await kv.set(KV.memories, memory.id, memory);
|
|
6468
6573
|
stats.memories++;
|
|
6469
6574
|
}
|
|
@@ -6667,6 +6772,7 @@ function escapeXml(s) {
|
|
|
6667
6772
|
}
|
|
6668
6773
|
function registerEnrichFunction(sdk, kv) {
|
|
6669
6774
|
sdk.registerFunction("mem::enrich", async (data) => {
|
|
6775
|
+
const project = typeof data.project === "string" && data.project.trim().length > 0 ? data.project.trim() : void 0;
|
|
6670
6776
|
const parts = [];
|
|
6671
6777
|
const fileContextPromise = sdk.trigger({
|
|
6672
6778
|
function_id: "mem::file-context",
|
|
@@ -6680,10 +6786,11 @@ function registerEnrichFunction(sdk, kv) {
|
|
|
6680
6786
|
function_id: "mem::search",
|
|
6681
6787
|
payload: {
|
|
6682
6788
|
query: searchQueries.join(" "),
|
|
6683
|
-
limit: 5
|
|
6789
|
+
limit: 5,
|
|
6790
|
+
...project !== void 0 && { project }
|
|
6684
6791
|
}
|
|
6685
6792
|
}).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(() => []);
|
|
6793
|
+
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
6794
|
const [fileContext, searchResult, bugMemories] = await Promise.all([
|
|
6688
6795
|
fileContextPromise,
|
|
6689
6796
|
searchPromise,
|
|
@@ -6706,6 +6813,7 @@ function registerEnrichFunction(sdk, kv) {
|
|
|
6706
6813
|
}
|
|
6707
6814
|
logger.info("Enrichment completed", {
|
|
6708
6815
|
sessionId: data.sessionId,
|
|
6816
|
+
project,
|
|
6709
6817
|
fileCount: data.files.length,
|
|
6710
6818
|
contextLength: context.length,
|
|
6711
6819
|
truncated
|
|
@@ -6863,16 +6971,24 @@ function buildGraphExtractionPrompt(observations) {
|
|
|
6863
6971
|
|
|
6864
6972
|
//#endregion
|
|
6865
6973
|
//#region src/functions/graph.ts
|
|
6974
|
+
function parseAttrs(raw) {
|
|
6975
|
+
const attrs = {};
|
|
6976
|
+
const attrRegex = /([A-Za-z_][\w:-]*)="([^"]*)"/g;
|
|
6977
|
+
let m;
|
|
6978
|
+
while ((m = attrRegex.exec(raw)) !== null) attrs[m[1]] = m[2];
|
|
6979
|
+
return attrs;
|
|
6980
|
+
}
|
|
6866
6981
|
function parseGraphXml(xml, observationIds) {
|
|
6867
6982
|
const nodes = [];
|
|
6868
6983
|
const edges = [];
|
|
6869
6984
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6870
|
-
const
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
const
|
|
6874
|
-
const
|
|
6875
|
-
const
|
|
6985
|
+
const entitySelfClose = /<entity\b([^>]*?)\/>/g;
|
|
6986
|
+
const entityWithBody = /<entity\b([^>]*[^/])>([\s\S]*?)<\/entity>/g;
|
|
6987
|
+
const addEntity = (rawAttrs, propsBlock = "") => {
|
|
6988
|
+
const attrs = parseAttrs(rawAttrs);
|
|
6989
|
+
const type = attrs["type"];
|
|
6990
|
+
const name = attrs["name"];
|
|
6991
|
+
if (!type || !name) return;
|
|
6876
6992
|
const properties = {};
|
|
6877
6993
|
const propRegex = /<property\s+key="([^"]+)">([^<]*)<\/property>/g;
|
|
6878
6994
|
let propMatch;
|
|
@@ -6885,17 +7001,23 @@ function parseGraphXml(xml, observationIds) {
|
|
|
6885
7001
|
sourceObservationIds: observationIds,
|
|
6886
7002
|
createdAt: now
|
|
6887
7003
|
});
|
|
6888
|
-
}
|
|
6889
|
-
|
|
7004
|
+
};
|
|
7005
|
+
let match;
|
|
7006
|
+
while ((match = entitySelfClose.exec(xml)) !== null) addEntity(match[1]);
|
|
7007
|
+
while ((match = entityWithBody.exec(xml)) !== null) addEntity(match[1], match[2]);
|
|
7008
|
+
const relRegex = /<relationship\b([^>]*?)\/>/g;
|
|
6890
7009
|
while ((match = relRegex.exec(xml)) !== null) {
|
|
6891
|
-
const
|
|
6892
|
-
const
|
|
6893
|
-
const
|
|
6894
|
-
const
|
|
6895
|
-
|
|
7010
|
+
const attrs = parseAttrs(match[1]);
|
|
7011
|
+
const type = attrs["type"];
|
|
7012
|
+
const sourceName = attrs["source"];
|
|
7013
|
+
const targetName = attrs["target"];
|
|
7014
|
+
if (!type || !sourceName || !targetName) continue;
|
|
7015
|
+
const parsedWeight = parseFloat(attrs["weight"] ?? "");
|
|
7016
|
+
const weight = Number.isFinite(parsedWeight) ? parsedWeight : .5;
|
|
6896
7017
|
const sourceNode = nodes.find((n) => n.name === sourceName);
|
|
6897
7018
|
const targetNode = nodes.find((n) => n.name === targetName);
|
|
6898
|
-
if (sourceNode
|
|
7019
|
+
if (!sourceNode || !targetNode) continue;
|
|
7020
|
+
edges.push({
|
|
6899
7021
|
id: generateId("ge"),
|
|
6900
7022
|
type,
|
|
6901
7023
|
sourceNodeId: sourceNode.id,
|
|
@@ -7109,7 +7231,7 @@ function registerConsolidationPipelineFunction(sdk, kv, provider) {
|
|
|
7109
7231
|
if (!data?.force && !isConsolidationEnabled()) return {
|
|
7110
7232
|
success: false,
|
|
7111
7233
|
skipped: true,
|
|
7112
|
-
reason: "CONSOLIDATION_ENABLED
|
|
7234
|
+
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
7235
|
};
|
|
7114
7236
|
const tier = data?.tier || "all";
|
|
7115
7237
|
const decayDays = getConsolidationDecayDays();
|
|
@@ -10279,11 +10401,34 @@ function registerDiagnosticsFunction(sdk, kv) {
|
|
|
10279
10401
|
});
|
|
10280
10402
|
memoryIssues++;
|
|
10281
10403
|
}
|
|
10404
|
+
const latestMemories = memories.filter((m) => m.isLatest);
|
|
10405
|
+
const unscopedCount = latestMemories.filter((m) => !m.project).length;
|
|
10406
|
+
if (unscopedCount === 0) checks.push({
|
|
10407
|
+
name: "memory-project-coverage",
|
|
10408
|
+
category: "memories",
|
|
10409
|
+
status: "pass",
|
|
10410
|
+
message: `All ${latestMemories.length} latest memories have a project scope`,
|
|
10411
|
+
fixable: false
|
|
10412
|
+
});
|
|
10413
|
+
else if (unscopedCount <= 10) checks.push({
|
|
10414
|
+
name: "memory-project-coverage",
|
|
10415
|
+
category: "memories",
|
|
10416
|
+
status: "warn",
|
|
10417
|
+
message: `${unscopedCount} of ${latestMemories.length} latest memories have no project scope — run POST /agentmemory/migrate {"step":"infer-memory-projects"} to backfill`,
|
|
10418
|
+
fixable: true
|
|
10419
|
+
});
|
|
10420
|
+
else checks.push({
|
|
10421
|
+
name: "memory-project-coverage",
|
|
10422
|
+
category: "memories",
|
|
10423
|
+
status: "fail",
|
|
10424
|
+
message: `${unscopedCount} of ${latestMemories.length} latest memories have no project scope — run POST /agentmemory/migrate {"step":"infer-memory-projects"} to backfill`,
|
|
10425
|
+
fixable: true
|
|
10426
|
+
});
|
|
10282
10427
|
if (memoryIssues === 0) checks.push({
|
|
10283
10428
|
name: "memories-ok",
|
|
10284
10429
|
category: "memories",
|
|
10285
10430
|
status: "pass",
|
|
10286
|
-
message: `All ${memories.length} memories are consistent`,
|
|
10431
|
+
message: `All ${memories.length} memories are structurally consistent`,
|
|
10287
10432
|
fixable: false
|
|
10288
10433
|
});
|
|
10289
10434
|
}
|
|
@@ -14056,6 +14201,22 @@ function consolidationDisabledResponse() {
|
|
|
14056
14201
|
docsHref: "https://github.com/rohitg00/agentmemory#consolidation"
|
|
14057
14202
|
});
|
|
14058
14203
|
}
|
|
14204
|
+
function slotsDisabledResponse() {
|
|
14205
|
+
return flagDisabledResponse({
|
|
14206
|
+
error: "Memory slots not enabled",
|
|
14207
|
+
flag: "AGENTMEMORY_SLOTS",
|
|
14208
|
+
enableHow: "Set AGENTMEMORY_SLOTS=true (in ~/.agentmemory/.env or the shell) and restart.",
|
|
14209
|
+
docsHref: "https://github.com/rohitg00/agentmemory#memory-slots"
|
|
14210
|
+
});
|
|
14211
|
+
}
|
|
14212
|
+
function reflectDisabledResponse() {
|
|
14213
|
+
return flagDisabledResponse({
|
|
14214
|
+
error: "Slot reflection not enabled",
|
|
14215
|
+
flag: "AGENTMEMORY_REFLECT",
|
|
14216
|
+
enableHow: "Set AGENTMEMORY_REFLECT=true (in ~/.agentmemory/.env or the shell) and restart. Requires AGENTMEMORY_SLOTS=true.",
|
|
14217
|
+
docsHref: "https://github.com/rohitg00/agentmemory#memory-slots"
|
|
14218
|
+
});
|
|
14219
|
+
}
|
|
14059
14220
|
function asNonEmptyString$1(value) {
|
|
14060
14221
|
if (typeof value !== "string") return null;
|
|
14061
14222
|
const trimmed = value.trim();
|
|
@@ -14500,6 +14661,14 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
14500
14661
|
path: "status",
|
|
14501
14662
|
value: "completed"
|
|
14502
14663
|
}]);
|
|
14664
|
+
try {
|
|
14665
|
+
sdk.triggerVoid("event::session::stopped", { sessionId });
|
|
14666
|
+
} catch (err) {
|
|
14667
|
+
logger.warn("event::session::stopped triggerVoid failed", {
|
|
14668
|
+
sessionId,
|
|
14669
|
+
error: err instanceof Error ? err.message : String(err)
|
|
14670
|
+
});
|
|
14671
|
+
}
|
|
14503
14672
|
return {
|
|
14504
14673
|
status_code: 200,
|
|
14505
14674
|
body: { success: true }
|
|
@@ -14718,11 +14887,21 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
14718
14887
|
status_code: 400,
|
|
14719
14888
|
body: { error: "terms must be an array of strings" }
|
|
14720
14889
|
};
|
|
14890
|
+
if (req.body.project !== void 0 && (typeof req.body.project !== "string" || !req.body.project.trim())) return {
|
|
14891
|
+
status_code: 400,
|
|
14892
|
+
body: { error: "project must be a non-empty string" }
|
|
14893
|
+
};
|
|
14721
14894
|
return {
|
|
14722
14895
|
status_code: 200,
|
|
14723
14896
|
body: await sdk.trigger({
|
|
14724
14897
|
function_id: "mem::enrich",
|
|
14725
|
-
payload:
|
|
14898
|
+
payload: {
|
|
14899
|
+
sessionId: req.body.sessionId,
|
|
14900
|
+
files: req.body.files,
|
|
14901
|
+
...req.body.terms !== void 0 && { terms: req.body.terms },
|
|
14902
|
+
...req.body.toolName !== void 0 && { toolName: req.body.toolName },
|
|
14903
|
+
...req.body.project !== void 0 && { project: req.body.project }
|
|
14904
|
+
}
|
|
14726
14905
|
})
|
|
14727
14906
|
};
|
|
14728
14907
|
});
|
|
@@ -14741,11 +14920,23 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
14741
14920
|
status_code: 400,
|
|
14742
14921
|
body: { error: "content is required" }
|
|
14743
14922
|
};
|
|
14923
|
+
if (req.body.project !== void 0 && (typeof req.body.project !== "string" || !req.body.project.trim())) return {
|
|
14924
|
+
status_code: 400,
|
|
14925
|
+
body: { error: "project must be a non-empty string" }
|
|
14926
|
+
};
|
|
14744
14927
|
return {
|
|
14745
14928
|
status_code: 201,
|
|
14746
14929
|
body: await sdk.trigger({
|
|
14747
14930
|
function_id: "mem::remember",
|
|
14748
|
-
payload:
|
|
14931
|
+
payload: {
|
|
14932
|
+
content: req.body.content,
|
|
14933
|
+
...req.body.type !== void 0 && { type: req.body.type },
|
|
14934
|
+
...req.body.concepts !== void 0 && { concepts: req.body.concepts },
|
|
14935
|
+
...req.body.files !== void 0 && { files: req.body.files },
|
|
14936
|
+
...req.body.ttlDays !== void 0 && { ttlDays: req.body.ttlDays },
|
|
14937
|
+
...req.body.sourceObservationIds !== void 0 && { sourceObservationIds: req.body.sourceObservationIds },
|
|
14938
|
+
...req.body.project !== void 0 && { project: req.body.project }
|
|
14939
|
+
}
|
|
14749
14940
|
})
|
|
14750
14941
|
};
|
|
14751
14942
|
});
|
|
@@ -14840,15 +15031,21 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
14840
15031
|
sdk.registerFunction("api::migrate", async (req) => {
|
|
14841
15032
|
const authErr = checkAuth(req, secret);
|
|
14842
15033
|
if (authErr) return authErr;
|
|
14843
|
-
|
|
15034
|
+
const hasStep = typeof req.body?.step === "string" && req.body.step.trim().length > 0;
|
|
15035
|
+
const hasDbPath = typeof req.body?.dbPath === "string" && req.body.dbPath.trim().length > 0;
|
|
15036
|
+
if (!hasStep && !hasDbPath) return {
|
|
14844
15037
|
status_code: 400,
|
|
14845
|
-
body: { error: "dbPath is required" }
|
|
15038
|
+
body: { error: "Either step (string) or dbPath (string) is required" }
|
|
14846
15039
|
};
|
|
14847
15040
|
return {
|
|
14848
15041
|
status_code: 200,
|
|
14849
15042
|
body: await sdk.trigger({
|
|
14850
15043
|
function_id: "mem::migrate",
|
|
14851
|
-
payload:
|
|
15044
|
+
payload: {
|
|
15045
|
+
...req.body.step !== void 0 && { step: req.body.step },
|
|
15046
|
+
...req.body.dbPath !== void 0 && { dbPath: req.body.dbPath },
|
|
15047
|
+
...req.body.dryRun !== void 0 && { dryRun: req.body.dryRun }
|
|
15048
|
+
}
|
|
14852
15049
|
})
|
|
14853
15050
|
};
|
|
14854
15051
|
});
|
|
@@ -15194,6 +15391,63 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15194
15391
|
http_method: "POST"
|
|
15195
15392
|
}
|
|
15196
15393
|
});
|
|
15394
|
+
sdk.registerFunction("api::graph-build", async (req) => {
|
|
15395
|
+
const authErr = checkAuth(req, secret);
|
|
15396
|
+
if (authErr) return authErr;
|
|
15397
|
+
const batchSize = Math.max(1, Math.min(100, Number(req.body?.batchSize) || 25));
|
|
15398
|
+
try {
|
|
15399
|
+
const sessions = await kv.list(KV.sessions);
|
|
15400
|
+
let totalNodes = 0;
|
|
15401
|
+
let totalEdges = 0;
|
|
15402
|
+
let batchesRun = 0;
|
|
15403
|
+
for (const session of sessions) {
|
|
15404
|
+
const sid = session?.id;
|
|
15405
|
+
if (typeof sid !== "string" || sid.length === 0) continue;
|
|
15406
|
+
const compressed = (await kv.list(KV.observations(sid))).filter((o) => o && typeof o.title === "string" && o.title.length > 0);
|
|
15407
|
+
if (compressed.length === 0) continue;
|
|
15408
|
+
for (let i = 0; i < compressed.length; i += batchSize) {
|
|
15409
|
+
const batch = compressed.slice(i, i + batchSize);
|
|
15410
|
+
try {
|
|
15411
|
+
const result = await sdk.trigger({
|
|
15412
|
+
function_id: "mem::graph-extract",
|
|
15413
|
+
payload: { observations: batch }
|
|
15414
|
+
});
|
|
15415
|
+
if (result?.success) {
|
|
15416
|
+
totalNodes += Number(result.nodesAdded) || 0;
|
|
15417
|
+
totalEdges += Number(result.edgesAdded) || 0;
|
|
15418
|
+
}
|
|
15419
|
+
batchesRun++;
|
|
15420
|
+
} catch (err) {
|
|
15421
|
+
logger.warn("graph-build batch failed", {
|
|
15422
|
+
sessionId: sid,
|
|
15423
|
+
batchIndex: Math.floor(i / batchSize),
|
|
15424
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15425
|
+
});
|
|
15426
|
+
}
|
|
15427
|
+
}
|
|
15428
|
+
}
|
|
15429
|
+
return {
|
|
15430
|
+
status_code: 200,
|
|
15431
|
+
body: {
|
|
15432
|
+
success: true,
|
|
15433
|
+
sessions: sessions.length,
|
|
15434
|
+
batches: batchesRun,
|
|
15435
|
+
nodes: totalNodes,
|
|
15436
|
+
edges: totalEdges
|
|
15437
|
+
}
|
|
15438
|
+
};
|
|
15439
|
+
} catch {
|
|
15440
|
+
return graphDisabledResponse();
|
|
15441
|
+
}
|
|
15442
|
+
});
|
|
15443
|
+
sdk.registerTrigger({
|
|
15444
|
+
type: "http",
|
|
15445
|
+
function_id: "api::graph-build",
|
|
15446
|
+
config: {
|
|
15447
|
+
api_path: "/agentmemory/graph/build",
|
|
15448
|
+
http_method: "POST"
|
|
15449
|
+
}
|
|
15450
|
+
});
|
|
15197
15451
|
sdk.registerFunction("api::consolidate-pipeline", async (req) => {
|
|
15198
15452
|
const authErr = checkAuth(req, secret);
|
|
15199
15453
|
if (authErr) return authErr;
|
|
@@ -15651,6 +15905,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15651
15905
|
sdk.registerFunction("api::slot-list", async (req) => {
|
|
15652
15906
|
const authErr = checkAuth(req, secret);
|
|
15653
15907
|
if (authErr) return authErr;
|
|
15908
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15654
15909
|
return {
|
|
15655
15910
|
status_code: 200,
|
|
15656
15911
|
body: await sdk.trigger({
|
|
@@ -15670,6 +15925,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15670
15925
|
sdk.registerFunction("api::slot-get", async (req) => {
|
|
15671
15926
|
const authErr = checkAuth(req, secret);
|
|
15672
15927
|
if (authErr) return authErr;
|
|
15928
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15673
15929
|
const label = asNonEmptyString$1(req.query_params?.["label"]);
|
|
15674
15930
|
if (!label) return {
|
|
15675
15931
|
status_code: 400,
|
|
@@ -15700,6 +15956,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15700
15956
|
sdk.registerFunction("api::slot-create", async (req) => {
|
|
15701
15957
|
const authErr = checkAuth(req, secret);
|
|
15702
15958
|
if (authErr) return authErr;
|
|
15959
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15703
15960
|
const body = req.body ?? {};
|
|
15704
15961
|
const label = asNonEmptyString$1(body["label"]);
|
|
15705
15962
|
if (!label) return {
|
|
@@ -15762,6 +16019,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15762
16019
|
sdk.registerFunction("api::slot-append", async (req) => {
|
|
15763
16020
|
const authErr = checkAuth(req, secret);
|
|
15764
16021
|
if (authErr) return authErr;
|
|
16022
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15765
16023
|
const body = req.body ?? {};
|
|
15766
16024
|
const label = asNonEmptyString$1(body["label"]);
|
|
15767
16025
|
const text = typeof body["text"] === "string" ? body["text"] : null;
|
|
@@ -15801,6 +16059,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15801
16059
|
sdk.registerFunction("api::slot-replace", async (req) => {
|
|
15802
16060
|
const authErr = checkAuth(req, secret);
|
|
15803
16061
|
if (authErr) return authErr;
|
|
16062
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15804
16063
|
const body = req.body ?? {};
|
|
15805
16064
|
const label = asNonEmptyString$1(body["label"]);
|
|
15806
16065
|
const content = body["content"];
|
|
@@ -15840,6 +16099,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15840
16099
|
sdk.registerFunction("api::slot-delete", async (req) => {
|
|
15841
16100
|
const authErr = checkAuth(req, secret);
|
|
15842
16101
|
if (authErr) return authErr;
|
|
16102
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
15843
16103
|
const label = asNonEmptyString$1(req.query_params?.["label"]);
|
|
15844
16104
|
if (!label) return {
|
|
15845
16105
|
status_code: 400,
|
|
@@ -15870,6 +16130,8 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
15870
16130
|
sdk.registerFunction("api::slot-reflect", async (req) => {
|
|
15871
16131
|
const authErr = checkAuth(req, secret);
|
|
15872
16132
|
if (authErr) return authErr;
|
|
16133
|
+
if (!isSlotsEnabled()) return slotsDisabledResponse();
|
|
16134
|
+
if (!isReflectEnabled()) return reflectDisabledResponse();
|
|
15873
16135
|
const body = req.body ?? {};
|
|
15874
16136
|
const sessionId = asNonEmptyString$1(body["sessionId"]);
|
|
15875
16137
|
if (!sessionId) return {
|
|
@@ -17572,13 +17834,15 @@ function registerMcpEndpoints(sdk, kv, secret) {
|
|
|
17572
17834
|
const type = args.type || "fact";
|
|
17573
17835
|
const concepts = typeof args.concepts === "string" ? args.concepts.split(",").map((c) => c.trim()).filter(Boolean) : [];
|
|
17574
17836
|
const files = typeof args.files === "string" ? args.files.split(",").map((f) => f.trim()).filter(Boolean) : [];
|
|
17837
|
+
const project = typeof args.project === "string" && args.project.trim().length > 0 ? args.project.trim() : void 0;
|
|
17575
17838
|
const result = await sdk.trigger({
|
|
17576
17839
|
function_id: "mem::remember",
|
|
17577
17840
|
payload: {
|
|
17578
17841
|
content: args.content,
|
|
17579
17842
|
type,
|
|
17580
17843
|
concepts,
|
|
17581
|
-
files
|
|
17844
|
+
files,
|
|
17845
|
+
...project !== void 0 && { project }
|
|
17582
17846
|
}
|
|
17583
17847
|
});
|
|
17584
17848
|
return {
|
|
@@ -19425,7 +19689,7 @@ async function main() {
|
|
|
19425
19689
|
if (bm25Index.has(memory.id)) continue;
|
|
19426
19690
|
bm25Index.add({
|
|
19427
19691
|
id: memory.id,
|
|
19428
|
-
sessionId: memory.sessionIds[0] ?? "memory",
|
|
19692
|
+
sessionId: memory.sessionIds?.[0] ?? "memory",
|
|
19429
19693
|
timestamp: memory.createdAt,
|
|
19430
19694
|
type: "decision",
|
|
19431
19695
|
title: memory.title,
|
|
@@ -19445,7 +19709,7 @@ async function main() {
|
|
|
19445
19709
|
console.warn(`[agentmemory] Failed to backfill memories into BM25:`, err);
|
|
19446
19710
|
}
|
|
19447
19711
|
bootLog(`Ready. ${embeddingProvider ? "Triple-stream (BM25+Vector+Graph)" : "BM25+Graph"} search active.`);
|
|
19448
|
-
bootLog(`REST API:
|
|
19712
|
+
bootLog(`REST API: 125 endpoints at http://localhost:${config.restPort}/agentmemory/*`);
|
|
19449
19713
|
bootLog(`MCP surface (opt-in via \`npx @agentmemory/mcp\`): ${getAllTools().length} tools · 6 resources · 3 prompts`);
|
|
19450
19714
|
const viewerServer = startViewerServer(config.restPort + 2, kv, sdk, secret, config.restPort);
|
|
19451
19715
|
const autoForgetIntervalMs = parseInt(process.env.AUTO_FORGET_INTERVAL_MS || "3600000", 10);
|
|
@@ -19514,4 +19778,4 @@ main().catch((err) => {
|
|
|
19514
19778
|
|
|
19515
19779
|
//#endregion
|
|
19516
19780
|
export { };
|
|
19517
|
-
//# sourceMappingURL=src-
|
|
19781
|
+
//# sourceMappingURL=src-DvS3bhMe.mjs.map
|