ziiagentmemory 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +175 -0
- package/AGENTS.md +124 -0
- package/LICENSE +190 -0
- package/README.md +1546 -0
- package/dist/cli.d.mts +5 -0
- package/dist/cli.d.mts.map +1 -0
- package/dist/cli.mjs +2859 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/config-ChC9EtgV.mjs +259 -0
- package/dist/config-ChC9EtgV.mjs.map +1 -0
- package/dist/connect-JnsJXc68.mjs +1075 -0
- package/dist/connect-JnsJXc68.mjs.map +1 -0
- package/dist/hooks/notification.d.mts +1 -0
- package/dist/hooks/notification.mjs +74 -0
- package/dist/hooks/notification.mjs.map +1 -0
- package/dist/hooks/post-commit.d.mts +1 -0
- package/dist/hooks/post-commit.mjs +101 -0
- package/dist/hooks/post-commit.mjs.map +1 -0
- package/dist/hooks/post-tool-failure.d.mts +1 -0
- package/dist/hooks/post-tool-failure.mjs +75 -0
- package/dist/hooks/post-tool-failure.mjs.map +1 -0
- package/dist/hooks/post-tool-use.d.mts +1 -0
- package/dist/hooks/post-tool-use.mjs +120 -0
- package/dist/hooks/post-tool-use.mjs.map +1 -0
- package/dist/hooks/pre-compact.d.mts +1 -0
- package/dist/hooks/pre-compact.mjs +78 -0
- package/dist/hooks/pre-compact.mjs.map +1 -0
- package/dist/hooks/pre-tool-use.d.mts +1 -0
- package/dist/hooks/pre-tool-use.mjs +84 -0
- package/dist/hooks/pre-tool-use.mjs.map +1 -0
- package/dist/hooks/prompt-submit.d.mts +1 -0
- package/dist/hooks/prompt-submit.mjs +67 -0
- package/dist/hooks/prompt-submit.mjs.map +1 -0
- package/dist/hooks/session-end.d.mts +1 -0
- package/dist/hooks/session-end.mjs +60 -0
- package/dist/hooks/session-end.mjs.map +1 -0
- package/dist/hooks/session-start.d.mts +1 -0
- package/dist/hooks/session-start.mjs +85 -0
- package/dist/hooks/session-start.mjs.map +1 -0
- package/dist/hooks/stop.d.mts +1 -0
- package/dist/hooks/stop.mjs +44 -0
- package/dist/hooks/stop.mjs.map +1 -0
- package/dist/hooks/subagent-start.d.mts +1 -0
- package/dist/hooks/subagent-start.mjs +73 -0
- package/dist/hooks/subagent-start.mjs.map +1 -0
- package/dist/hooks/subagent-stop.d.mts +1 -0
- package/dist/hooks/subagent-stop.mjs +74 -0
- package/dist/hooks/subagent-stop.mjs.map +1 -0
- package/dist/hooks/task-completed.d.mts +1 -0
- package/dist/hooks/task-completed.mjs +73 -0
- package/dist/hooks/task-completed.mjs.map +1 -0
- package/dist/image-refs-BKLmp_sD.mjs +34 -0
- package/dist/image-refs-BKLmp_sD.mjs.map +1 -0
- package/dist/image-refs-C2YU7BIm.mjs +34 -0
- package/dist/image-refs-C2YU7BIm.mjs.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +22324 -0
- package/dist/index.mjs.map +1 -0
- package/dist/keyed-mutex-DTHtcZrt.mjs +88 -0
- package/dist/keyed-mutex-DTHtcZrt.mjs.map +1 -0
- package/dist/logger-BEB7pCI9.mjs +43 -0
- package/dist/logger-BEB7pCI9.mjs.map +1 -0
- package/dist/schema-CNiCWzV9.mjs +78 -0
- package/dist/schema-CNiCWzV9.mjs.map +1 -0
- package/dist/src-Cr3pH_uH.mjs +20745 -0
- package/dist/src-Cr3pH_uH.mjs.map +1 -0
- package/dist/standalone-C6KzNkt5.mjs +700 -0
- package/dist/standalone-C6KzNkt5.mjs.map +1 -0
- package/dist/standalone.d.mts +25 -0
- package/dist/standalone.d.mts.map +1 -0
- package/dist/standalone.mjs +1867 -0
- package/dist/standalone.mjs.map +1 -0
- package/dist/tools-registry-DCt2KAWA.mjs +1145 -0
- package/dist/tools-registry-DCt2KAWA.mjs.map +1 -0
- package/docker-compose.yml +47 -0
- package/iii-config.docker.yaml +53 -0
- package/iii-config.yaml +61 -0
- package/package.json +99 -0
- package/plugin/.claude-plugin/plugin.json +13 -0
- package/plugin/.codex-plugin/plugin.json +15 -0
- package/plugin/.mcp.copilot.json +15 -0
- package/plugin/.mcp.json +13 -0
- package/plugin/hooks/hooks.codex.json +67 -0
- package/plugin/hooks/hooks.copilot.json +72 -0
- package/plugin/hooks/hooks.json +125 -0
- package/plugin/opencode/README.md +229 -0
- package/plugin/opencode/agentmemory-capture.ts +687 -0
- package/plugin/opencode/commands/recall.md +19 -0
- package/plugin/opencode/commands/remember.md +19 -0
- package/plugin/opencode/plugin.json +12 -0
- package/plugin/plugin.json +15 -0
- package/plugin/scripts/diagnostics.mjs +551 -0
- package/plugin/scripts/notification.d.mts +1 -0
- package/plugin/scripts/notification.mjs +74 -0
- package/plugin/scripts/notification.mjs.map +1 -0
- package/plugin/scripts/post-commit.d.mts +1 -0
- package/plugin/scripts/post-commit.mjs +101 -0
- package/plugin/scripts/post-commit.mjs.map +1 -0
- package/plugin/scripts/post-tool-failure.d.mts +1 -0
- package/plugin/scripts/post-tool-failure.mjs +75 -0
- package/plugin/scripts/post-tool-failure.mjs.map +1 -0
- package/plugin/scripts/post-tool-use.d.mts +1 -0
- package/plugin/scripts/post-tool-use.mjs +120 -0
- package/plugin/scripts/post-tool-use.mjs.map +1 -0
- package/plugin/scripts/pre-compact.d.mts +1 -0
- package/plugin/scripts/pre-compact.mjs +78 -0
- package/plugin/scripts/pre-compact.mjs.map +1 -0
- package/plugin/scripts/pre-tool-use.d.mts +1 -0
- package/plugin/scripts/pre-tool-use.mjs +84 -0
- package/plugin/scripts/pre-tool-use.mjs.map +1 -0
- package/plugin/scripts/prompt-submit.d.mts +1 -0
- package/plugin/scripts/prompt-submit.mjs +67 -0
- package/plugin/scripts/prompt-submit.mjs.map +1 -0
- package/plugin/scripts/session-end.d.mts +1 -0
- package/plugin/scripts/session-end.mjs +60 -0
- package/plugin/scripts/session-end.mjs.map +1 -0
- package/plugin/scripts/session-start.d.mts +1 -0
- package/plugin/scripts/session-start.mjs +85 -0
- package/plugin/scripts/session-start.mjs.map +1 -0
- package/plugin/scripts/stop.d.mts +1 -0
- package/plugin/scripts/stop.mjs +44 -0
- package/plugin/scripts/stop.mjs.map +1 -0
- package/plugin/scripts/subagent-start.d.mts +1 -0
- package/plugin/scripts/subagent-start.mjs +73 -0
- package/plugin/scripts/subagent-start.mjs.map +1 -0
- package/plugin/scripts/subagent-stop.d.mts +1 -0
- package/plugin/scripts/subagent-stop.mjs +74 -0
- package/plugin/scripts/subagent-stop.mjs.map +1 -0
- package/plugin/scripts/task-completed.d.mts +1 -0
- package/plugin/scripts/task-completed.mjs +73 -0
- package/plugin/scripts/task-completed.mjs.map +1 -0
- package/plugin/skills/_shared/TROUBLESHOOTING.md +38 -0
- package/plugin/skills/agentmemory-agents/REFERENCE.md +28 -0
- package/plugin/skills/agentmemory-agents/SKILL.md +34 -0
- package/plugin/skills/agentmemory-architecture/SKILL.md +33 -0
- package/plugin/skills/agentmemory-config/REFERENCE.md +42 -0
- package/plugin/skills/agentmemory-config/SKILL.md +37 -0
- package/plugin/skills/agentmemory-hooks/REFERENCE.md +20 -0
- package/plugin/skills/agentmemory-hooks/SKILL.md +39 -0
- package/plugin/skills/agentmemory-mcp-tools/REFERENCE.md +65 -0
- package/plugin/skills/agentmemory-mcp-tools/SKILL.md +39 -0
- package/plugin/skills/agentmemory-rest-api/REFERENCE.md +129 -0
- package/plugin/skills/agentmemory-rest-api/SKILL.md +43 -0
- package/plugin/skills/commit-context/EXAMPLES.md +71 -0
- package/plugin/skills/commit-context/SKILL.md +64 -0
- package/plugin/skills/commit-history/EXAMPLES.md +71 -0
- package/plugin/skills/commit-history/SKILL.md +62 -0
- package/plugin/skills/forget/EXAMPLES.md +75 -0
- package/plugin/skills/forget/SKILL.md +66 -0
- package/plugin/skills/handoff/EXAMPLES.md +56 -0
- package/plugin/skills/handoff/SKILL.md +68 -0
- package/plugin/skills/recall/EXAMPLES.md +74 -0
- package/plugin/skills/recall/SKILL.md +60 -0
- package/plugin/skills/recap/EXAMPLES.md +60 -0
- package/plugin/skills/recap/SKILL.md +63 -0
- package/plugin/skills/remember/EXAMPLES.md +67 -0
- package/plugin/skills/remember/SKILL.md +61 -0
- package/plugin/skills/session-history/EXAMPLES.md +59 -0
- package/plugin/skills/session-history/SKILL.md +61 -0
- package/plugin/skills/write-agentmemory-skill/SKILL.md +40 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join, resolve, sep } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { mkdir, stat, unlink, utimes, writeFile } from "node:fs/promises";
|
|
6
|
+
//#region src/utils/image-store.ts
|
|
7
|
+
const IMAGES_DIR = join(homedir(), ".agentmemory", "images");
|
|
8
|
+
const DEFAULT_MAX_BYTES = 500 * 1024 * 1024;
|
|
9
|
+
function getMaxBytes() {
|
|
10
|
+
return Number(process.env.AGENTMEMORY_IMAGE_STORE_MAX_BYTES) || DEFAULT_MAX_BYTES;
|
|
11
|
+
}
|
|
12
|
+
function isManagedImagePath(filePath) {
|
|
13
|
+
const resolved = resolve(filePath);
|
|
14
|
+
const normalizedImagesDir = resolve(IMAGES_DIR);
|
|
15
|
+
return resolved.startsWith(normalizedImagesDir + sep) || resolved === normalizedImagesDir;
|
|
16
|
+
}
|
|
17
|
+
function contentHash(data) {
|
|
18
|
+
return createHash("sha256").update(data).digest("hex");
|
|
19
|
+
}
|
|
20
|
+
async function saveImageToDisk(base64Data) {
|
|
21
|
+
if (!base64Data) return {
|
|
22
|
+
filePath: "",
|
|
23
|
+
bytesWritten: 0
|
|
24
|
+
};
|
|
25
|
+
if (!existsSync(IMAGES_DIR)) await mkdir(IMAGES_DIR, { recursive: true });
|
|
26
|
+
let cleanBase64 = base64Data;
|
|
27
|
+
let ext = "png";
|
|
28
|
+
if (base64Data.startsWith("data:image/")) {
|
|
29
|
+
const commaIdx = base64Data.indexOf(",");
|
|
30
|
+
if (commaIdx !== -1) {
|
|
31
|
+
const meta = base64Data.substring(0, commaIdx);
|
|
32
|
+
if (meta.includes("jpeg") || meta.includes("jpg")) ext = "jpg";
|
|
33
|
+
else if (meta.includes("webp")) ext = "webp";
|
|
34
|
+
else if (meta.includes("gif")) ext = "gif";
|
|
35
|
+
cleanBase64 = base64Data.substring(commaIdx + 1);
|
|
36
|
+
}
|
|
37
|
+
} else if (base64Data.startsWith("/9j/")) ext = "jpg";
|
|
38
|
+
const filePath = join(IMAGES_DIR, `${contentHash(cleanBase64)}.${ext}`);
|
|
39
|
+
if (existsSync(filePath)) return {
|
|
40
|
+
filePath,
|
|
41
|
+
bytesWritten: 0
|
|
42
|
+
};
|
|
43
|
+
await writeFile(filePath, Buffer.from(cleanBase64, "base64"));
|
|
44
|
+
return {
|
|
45
|
+
filePath,
|
|
46
|
+
bytesWritten: (await stat(filePath)).size
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async function deleteImage(filePath) {
|
|
50
|
+
if (!filePath) return { deletedBytes: 0 };
|
|
51
|
+
if (!isManagedImagePath(filePath)) return { deletedBytes: 0 };
|
|
52
|
+
try {
|
|
53
|
+
if (existsSync(filePath)) {
|
|
54
|
+
const size = (await stat(filePath)).size;
|
|
55
|
+
await unlink(filePath);
|
|
56
|
+
return { deletedBytes: size };
|
|
57
|
+
}
|
|
58
|
+
} catch (err) {
|
|
59
|
+
console.error("[agentmemory] Failed to delete image context:", err);
|
|
60
|
+
}
|
|
61
|
+
return { deletedBytes: 0 };
|
|
62
|
+
}
|
|
63
|
+
/** Touch an image file to update its mtime (marking it as recently used for LRU eviction) */
|
|
64
|
+
async function touchImage(filePath) {
|
|
65
|
+
if (!filePath || !isManagedImagePath(filePath)) return;
|
|
66
|
+
try {
|
|
67
|
+
if (existsSync(filePath)) {
|
|
68
|
+
const now = /* @__PURE__ */ new Date();
|
|
69
|
+
await utimes(filePath, now, now);
|
|
70
|
+
}
|
|
71
|
+
} catch (err) {}
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/state/keyed-mutex.ts
|
|
75
|
+
const locks = /* @__PURE__ */ new Map();
|
|
76
|
+
function withKeyedLock(key, fn) {
|
|
77
|
+
const next = (locks.get(key) ?? Promise.resolve()).then(fn, fn);
|
|
78
|
+
const cleanup = next.then(() => {}, () => {});
|
|
79
|
+
locks.set(key, cleanup);
|
|
80
|
+
cleanup.then(() => {
|
|
81
|
+
if (locks.get(key) === cleanup) locks.delete(key);
|
|
82
|
+
});
|
|
83
|
+
return next;
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { isManagedImagePath as a, getMaxBytes as i, IMAGES_DIR as n, saveImageToDisk as o, deleteImage as r, touchImage as s, withKeyedLock as t };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=keyed-mutex-DTHtcZrt.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyed-mutex-DTHtcZrt.mjs","names":[],"sources":["../src/utils/image-store.ts","../src/state/keyed-mutex.ts"],"sourcesContent":["import { homedir } from \"node:os\";\r\nimport { join, resolve, sep } from \"node:path\";\r\nimport { existsSync } from \"node:fs\";\r\nimport { mkdir, writeFile, unlink, utimes, stat } from \"node:fs/promises\";\r\nimport { createHash } from \"node:crypto\";\r\n\r\nexport const IMAGES_DIR = join(homedir(), \".agentmemory\", \"images\");\r\n\r\nconst DEFAULT_MAX_BYTES = 500 * 1024 * 1024;\r\n\r\nexport function getMaxBytes(): number {\r\n return Number(process.env.AGENTMEMORY_IMAGE_STORE_MAX_BYTES) || DEFAULT_MAX_BYTES;\r\n}\r\n\r\nexport function isManagedImagePath(filePath: string): boolean {\r\n const resolved = resolve(filePath);\r\n const normalizedImagesDir = resolve(IMAGES_DIR);\r\n return resolved.startsWith(normalizedImagesDir + sep) || resolved === normalizedImagesDir;\r\n}\r\n\r\nfunction contentHash(data: string): string {\r\n return createHash(\"sha256\").update(data).digest(\"hex\");\r\n}\r\n\r\nexport async function saveImageToDisk(base64Data: string): Promise<{ filePath: string; bytesWritten: number }> {\r\n if (!base64Data) return { filePath: \"\", bytesWritten: 0 };\r\n\r\n if (!existsSync(IMAGES_DIR)) {\r\n await mkdir(IMAGES_DIR, { recursive: true });\r\n }\r\n\r\n let cleanBase64 = base64Data;\r\n let ext = \"png\";\r\n\r\n if (base64Data.startsWith(\"data:image/\")) {\r\n const commaIdx = base64Data.indexOf(\",\");\r\n if (commaIdx !== -1) {\r\n const meta = base64Data.substring(0, commaIdx);\r\n if (meta.includes(\"jpeg\") || meta.includes(\"jpg\")) ext = \"jpg\";\r\n else if (meta.includes(\"webp\")) ext = \"webp\";\r\n else if (meta.includes(\"gif\")) ext = \"gif\";\r\n cleanBase64 = base64Data.substring(commaIdx + 1);\r\n }\r\n } else if (base64Data.startsWith(\"/9j/\")) {\r\n ext = \"jpg\";\r\n }\r\n\r\n const hash = contentHash(cleanBase64);\r\n const filePath = join(IMAGES_DIR, `${hash}.${ext}`);\r\n\r\n if (existsSync(filePath)) {\r\n return { filePath, bytesWritten: 0 };\r\n }\r\n\r\n const buffer = Buffer.from(cleanBase64, \"base64\");\r\n await writeFile(filePath, buffer);\r\n\r\n const s = await stat(filePath);\r\n\r\n return { filePath, bytesWritten: s.size };\r\n}\r\n\r\nexport async function deleteImage(filePath: string | undefined): Promise<{ deletedBytes: number }> {\r\n if (!filePath) return { deletedBytes: 0 };\r\n if (!isManagedImagePath(filePath)) return { deletedBytes: 0 };\r\n try {\r\n if (existsSync(filePath)) {\r\n const s = await stat(filePath);\r\n const size = s.size;\r\n await unlink(filePath);\r\n return { deletedBytes: size };\r\n }\r\n } catch (err) {\r\n console.error(\"[agentmemory] Failed to delete image context:\", err);\r\n }\r\n return { deletedBytes: 0 };\r\n}\r\n\r\n/** Touch an image file to update its mtime (marking it as recently used for LRU eviction) */\r\nexport async function touchImage(filePath: string): Promise<void> {\r\n if (!filePath || !isManagedImagePath(filePath)) return;\r\n try {\r\n if (existsSync(filePath)) {\r\n const now = new Date();\r\n await utimes(filePath, now, now);\r\n }\r\n } catch (err) {\r\n // Ignore touch errors silently\r\n }\r\n}\r\n","const locks = new Map<string, Promise<void>>();\r\n\r\nexport function withKeyedLock<T>(\r\n key: string,\r\n fn: () => Promise<T>,\r\n): Promise<T> {\r\n const prev = locks.get(key) ?? Promise.resolve();\r\n const next = prev.then(fn, fn);\r\n const cleanup = next.then(\r\n () => {},\r\n () => {},\r\n );\r\n locks.set(key, cleanup);\r\n cleanup.then(() => {\r\n if (locks.get(key) === cleanup) locks.delete(key);\r\n });\r\n return next;\r\n}\r\n"],"mappings":";;;;;;AAMA,MAAa,aAAa,KAAK,SAAS,EAAE,gBAAgB,SAAS;AAEnE,MAAM,oBAAoB,MAAM,OAAO;AAEvC,SAAgB,cAAsB;AACpC,QAAO,OAAO,QAAQ,IAAI,kCAAkC,IAAI;;AAGlE,SAAgB,mBAAmB,UAA2B;CAC5D,MAAM,WAAW,QAAQ,SAAS;CAClC,MAAM,sBAAsB,QAAQ,WAAW;AAC/C,QAAO,SAAS,WAAW,sBAAsB,IAAI,IAAI,aAAa;;AAGxE,SAAS,YAAY,MAAsB;AACzC,QAAO,WAAW,SAAS,CAAC,OAAO,KAAK,CAAC,OAAO,MAAM;;AAGxD,eAAsB,gBAAgB,YAAyE;AAC7G,KAAI,CAAC,WAAY,QAAO;EAAE,UAAU;EAAI,cAAc;EAAG;AAEzD,KAAI,CAAC,WAAW,WAAW,CACzB,OAAM,MAAM,YAAY,EAAE,WAAW,MAAM,CAAC;CAG9C,IAAI,cAAc;CAClB,IAAI,MAAM;AAEV,KAAI,WAAW,WAAW,cAAc,EAAE;EACvC,MAAM,WAAW,WAAW,QAAQ,IAAI;AACxC,MAAI,aAAa,IAAI;GACnB,MAAM,OAAO,WAAW,UAAU,GAAG,SAAS;AAC9C,OAAI,KAAK,SAAS,OAAO,IAAI,KAAK,SAAS,MAAM,CAAE,OAAM;YAChD,KAAK,SAAS,OAAO,CAAE,OAAM;YAC7B,KAAK,SAAS,MAAM,CAAE,OAAM;AACrC,iBAAc,WAAW,UAAU,WAAW,EAAE;;YAE1C,WAAW,WAAW,OAAO,CACrC,OAAM;CAIT,MAAM,WAAW,KAAK,YAAY,GADrB,YAAY,YACgB,CAAC,GAAG,MAAM;AAEnD,KAAI,WAAW,SAAS,CACtB,QAAO;EAAE;EAAU,cAAc;EAAG;AAItC,OAAM,UAAU,UADD,OAAO,KAAK,aAAa,SACR,CAAC;AAIjC,QAAO;EAAE;EAAU,eAAc,MAFjB,KAAK,SAAS,EAEK;EAAM;;AAG3C,eAAsB,YAAY,UAAiE;AACjG,KAAI,CAAC,SAAU,QAAO,EAAE,cAAc,GAAG;AACzC,KAAI,CAAC,mBAAmB,SAAS,CAAE,QAAO,EAAE,cAAc,GAAG;AAC7D,KAAI;AACF,MAAI,WAAW,SAAS,EAAE;GAExB,MAAM,QAAO,MADG,KAAK,SAAS,EACf;AACf,SAAM,OAAO,SAAS;AACtB,UAAO,EAAE,cAAc,MAAM;;UAExB,KAAK;AACZ,UAAQ,MAAM,iDAAiD,IAAI;;AAErE,QAAO,EAAE,cAAc,GAAG;;;AAI5B,eAAsB,WAAW,UAAiC;AAChE,KAAI,CAAC,YAAY,CAAC,mBAAmB,SAAS,CAAE;AAChD,KAAI;AACF,MAAI,WAAW,SAAS,EAAE;GACxB,MAAM,sBAAM,IAAI,MAAM;AACtB,SAAM,OAAO,UAAU,KAAK,IAAI;;UAE3B,KAAK;;;;ACtFhB,MAAM,wBAAQ,IAAI,KAA4B;AAE9C,SAAgB,cACd,KACA,IACY;CAEZ,MAAM,QADO,MAAM,IAAI,IAAI,IAAI,QAAQ,SAAS,EAC9B,KAAK,IAAI,GAAG;CAC9B,MAAM,UAAU,KAAK,WACb,UACA,GACP;AACD,OAAM,IAAI,KAAK,QAAQ;AACvB,SAAQ,WAAW;AACjB,MAAI,MAAM,IAAI,IAAI,KAAK,QAAS,OAAM,OAAO,IAAI;GACjD;AACF,QAAO"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/logger.ts
|
|
2
|
+
function fmt(level, msg, fields) {
|
|
3
|
+
if (!fields || Object.keys(fields).length === 0) return `[agentmemory] ${level} ${msg}`;
|
|
4
|
+
try {
|
|
5
|
+
return `[agentmemory] ${level} ${msg} ${JSON.stringify(fields)}`;
|
|
6
|
+
} catch {
|
|
7
|
+
return `[agentmemory] ${level} ${msg}`;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function emit(level, msg, fields) {
|
|
11
|
+
try {
|
|
12
|
+
process.stderr.write(fmt(level, msg, fields) + "\n");
|
|
13
|
+
} catch {}
|
|
14
|
+
}
|
|
15
|
+
const logger = {
|
|
16
|
+
info(msg, fields) {
|
|
17
|
+
emit("info", msg, fields);
|
|
18
|
+
},
|
|
19
|
+
warn(msg, fields) {
|
|
20
|
+
emit("warn", msg, fields);
|
|
21
|
+
},
|
|
22
|
+
error(msg, fields) {
|
|
23
|
+
emit("error", msg, fields);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
let bootVerbose = process.env["AGENTMEMORY_VERBOSE"] === "1" || process.env["AGENTMEMORY_VERBOSE"] === "true";
|
|
27
|
+
const bootBuffer = [];
|
|
28
|
+
function setBootVerbose(enabled) {
|
|
29
|
+
bootVerbose = enabled;
|
|
30
|
+
}
|
|
31
|
+
function bootLog(msg) {
|
|
32
|
+
if (bootVerbose) {
|
|
33
|
+
try {
|
|
34
|
+
process.stderr.write(`[agentmemory] ${msg}\n`);
|
|
35
|
+
} catch {}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (bootBuffer.length < 500) bootBuffer.push(msg);
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { logger as n, setBootVerbose as r, bootLog as t };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=logger-BEB7pCI9.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger-BEB7pCI9.mjs","names":[],"sources":["../src/logger.ts"],"sourcesContent":["// Thin logging shim for agentmemory.\r\n//\r\n// iii-sdk v0.11 dropped `getContext()`, which had been the source of a\r\n// contextual logger in every function handler (`getContext().logger`).\r\n// Migrating directly to the v0.11 OTEL-based `getLogger()` would force\r\n// every call site to care about the OTEL Logger API shape (`emit(...)`\r\n// with severity numbers and attributes maps). Instead, this module\r\n// exposes a single `logger` singleton with the same `.info/.warn/.error`\r\n// signature the old code used, so the mechanical replacement across\r\n// 30+ function files is: drop the `getContext` import, drop the\r\n// `const ctx = getContext();` line, and rename `ctx.logger.*` to\r\n// `logger.*`. Nothing else changes.\r\n//\r\n// Output goes to stderr as `[agentmemory] <level> <msg> <json-fields>`.\r\n// The iii-engine's `iii-exec` worker runs the agentmemory binary as a\r\n// child process and forwards stderr into `docker logs\r\n// agentmemory-iii-engine-1`, so these lines end up next to the engine's\r\n// own output without needing any OTEL wiring. If we later want\r\n// structured OTEL logs, this file is the only thing that changes.\r\n//\r\n// See rohitg00/agentmemory#143 follow-up — the #116 migration updated\r\n// test mocks but left the real `getContext()` imports in place, which\r\n// passed `npm test` (tests mock iii-sdk) and `npm run build` (tsdown\r\n// doesn't type-check) but crashed `node dist/index.mjs` on first\r\n// import.\r\n\r\ntype Fields = Record<string, unknown> | undefined;\r\n\r\nfunction fmt(level: string, msg: string, fields: Fields): string {\r\n if (!fields || Object.keys(fields).length === 0) {\r\n return `[agentmemory] ${level} ${msg}`;\r\n }\r\n try {\r\n return `[agentmemory] ${level} ${msg} ${JSON.stringify(fields)}`;\r\n } catch {\r\n // Fields contained a circular reference or a BigInt — fall back\r\n // to the plain message so a log line never throws.\r\n return `[agentmemory] ${level} ${msg}`;\r\n }\r\n}\r\n\r\nfunction emit(level: string, msg: string, fields: Fields): void {\r\n try {\r\n process.stderr.write(fmt(level, msg, fields) + \"\\n\");\r\n } catch {\r\n // stderr is unavailable in some weird test/worker contexts — swallow\r\n // so no log line can ever crash a handler.\r\n }\r\n}\r\n\r\nexport const logger = {\r\n info(msg: string, fields?: Fields): void {\r\n emit(\"info\", msg, fields);\r\n },\r\n warn(msg: string, fields?: Fields): void {\r\n emit(\"warn\", msg, fields);\r\n },\r\n error(msg: string, fields?: Fields): void {\r\n emit(\"error\", msg, fields);\r\n },\r\n};\r\n\r\n// ---------- boot log ----------\r\n//\r\n// `bootLog` is for the one-shot status lines that every register-*\r\n// function used to dump via `console.log` during engine startup. On a\r\n// fresh install that's ~25 lines of `[agentmemory] X enabled` noise\r\n// before the user can see a prompt. In quiet mode (default), each\r\n// line is captured into a buffer and discarded; the CLI surfaces a\r\n// single compressed summary instead. In verbose mode (set by\r\n// `--verbose` or `AGENTMEMORY_VERBOSE=1`) the lines pass straight\r\n// through to stderr exactly like the old console.log calls.\r\n\r\nlet bootVerbose =\r\n process.env[\"AGENTMEMORY_VERBOSE\"] === \"1\" ||\r\n process.env[\"AGENTMEMORY_VERBOSE\"] === \"true\";\r\n\r\nconst bootBuffer: string[] = [];\r\n\r\nexport function setBootVerbose(enabled: boolean): void {\r\n bootVerbose = enabled;\r\n}\r\n\r\nexport function isBootVerbose(): boolean {\r\n return bootVerbose;\r\n}\r\n\r\nexport function bootLog(msg: string): void {\r\n if (bootVerbose) {\r\n try {\r\n process.stderr.write(`[agentmemory] ${msg}\\n`);\r\n } catch {\r\n // stderr unavailable — drop.\r\n }\r\n return;\r\n }\r\n if (bootBuffer.length < 500) bootBuffer.push(msg);\r\n}\r\n\r\nexport function bootWarn(msg: string): void {\r\n // Warnings always surface; they're rare and the user needs to see\r\n // them even when the rest of the boot log is suppressed.\r\n try {\r\n process.stderr.write(`[agentmemory] warn ${msg}\\n`);\r\n } catch {}\r\n}\r\n\r\nexport function getBootBuffer(): readonly string[] {\r\n return bootBuffer;\r\n}\r\n"],"mappings":";AA4BA,SAAS,IAAI,OAAe,KAAa,QAAwB;AAC/D,KAAI,CAAC,UAAU,OAAO,KAAK,OAAO,CAAC,WAAW,EAC5C,QAAO,iBAAiB,MAAM,GAAG;AAEnC,KAAI;AACF,SAAO,iBAAiB,MAAM,GAAG,IAAI,GAAG,KAAK,UAAU,OAAO;SACxD;AAGN,SAAO,iBAAiB,MAAM,GAAG;;;AAIrC,SAAS,KAAK,OAAe,KAAa,QAAsB;AAC9D,KAAI;AACF,UAAQ,OAAO,MAAM,IAAI,OAAO,KAAK,OAAO,GAAG,KAAK;SAC9C;;AAMV,MAAa,SAAS;CACpB,KAAK,KAAa,QAAuB;AACvC,OAAK,QAAQ,KAAK,OAAO;;CAE3B,KAAK,KAAa,QAAuB;AACvC,OAAK,QAAQ,KAAK,OAAO;;CAE3B,MAAM,KAAa,QAAuB;AACxC,OAAK,SAAS,KAAK,OAAO;;CAE7B;AAaD,IAAI,cACF,QAAQ,IAAI,2BAA2B,OACvC,QAAQ,IAAI,2BAA2B;AAEzC,MAAM,aAAuB,EAAE;AAE/B,SAAgB,eAAe,SAAwB;AACrD,eAAc;;AAOhB,SAAgB,QAAQ,KAAmB;AACzC,KAAI,aAAa;AACf,MAAI;AACF,WAAQ,OAAO,MAAM,iBAAiB,IAAI,IAAI;UACxC;AAGR;;AAEF,KAAI,WAAW,SAAS,IAAK,YAAW,KAAK,IAAI"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
//#region src/state/schema.ts
|
|
3
|
+
const KV = {
|
|
4
|
+
sessions: "mem:sessions",
|
|
5
|
+
observations: (sessionId) => `mem:obs:${sessionId}`,
|
|
6
|
+
memories: "mem:memories",
|
|
7
|
+
summaries: "mem:summaries",
|
|
8
|
+
config: "mem:config",
|
|
9
|
+
metrics: "mem:metrics",
|
|
10
|
+
health: "mem:health",
|
|
11
|
+
embeddings: (obsId) => `mem:emb:${obsId}`,
|
|
12
|
+
bm25Index: "mem:index:bm25",
|
|
13
|
+
relations: "mem:relations",
|
|
14
|
+
profiles: "mem:profiles",
|
|
15
|
+
claudeBridge: "mem:claude-bridge",
|
|
16
|
+
graphNodes: "mem:graph:nodes",
|
|
17
|
+
graphEdges: "mem:graph:edges",
|
|
18
|
+
graphSnapshot: "mem:graph:snapshot",
|
|
19
|
+
graphNameIndex: "mem:graph:name-index",
|
|
20
|
+
graphEdgeKey: "mem:graph:edge-key",
|
|
21
|
+
graphNodeDegree: "mem:graph:node-degree",
|
|
22
|
+
semantic: "mem:semantic",
|
|
23
|
+
procedural: "mem:procedural",
|
|
24
|
+
teamShared: (teamId) => `mem:team:${teamId}:shared`,
|
|
25
|
+
teamUsers: (teamId, userId) => `mem:team:${teamId}:users:${userId}`,
|
|
26
|
+
teamProfile: (teamId) => `mem:team:${teamId}:profile`,
|
|
27
|
+
audit: "mem:audit",
|
|
28
|
+
actions: "mem:actions",
|
|
29
|
+
actionEdges: "mem:action-edges",
|
|
30
|
+
leases: "mem:leases",
|
|
31
|
+
routines: "mem:routines",
|
|
32
|
+
routineRuns: "mem:routine-runs",
|
|
33
|
+
signals: "mem:signals",
|
|
34
|
+
checkpoints: "mem:checkpoints",
|
|
35
|
+
mesh: "mem:mesh",
|
|
36
|
+
sketches: "mem:sketches",
|
|
37
|
+
facets: "mem:facets",
|
|
38
|
+
sentinels: "mem:sentinels",
|
|
39
|
+
crystals: "mem:crystals",
|
|
40
|
+
lessons: "mem:lessons",
|
|
41
|
+
insights: "mem:insights",
|
|
42
|
+
graphEdgeHistory: "mem:graph:edge-history",
|
|
43
|
+
enrichedChunks: (sessionId) => `mem:enriched:${sessionId}`,
|
|
44
|
+
latentEmbeddings: (obsId) => `mem:latent:${obsId}`,
|
|
45
|
+
retentionScores: "mem:retention",
|
|
46
|
+
accessLog: "mem:access",
|
|
47
|
+
imageRefs: "mem:image-refs",
|
|
48
|
+
imageEmbeddings: "mem:image-embeddings",
|
|
49
|
+
slots: "mem:slots",
|
|
50
|
+
globalSlots: "mem:slots:global",
|
|
51
|
+
state: "mem:state",
|
|
52
|
+
commits: "mem:commits",
|
|
53
|
+
recentSearches: "mem:recent-searches"
|
|
54
|
+
};
|
|
55
|
+
const STREAM = {
|
|
56
|
+
name: "mem-live",
|
|
57
|
+
group: (sessionId) => sessionId,
|
|
58
|
+
viewerGroup: "viewer"
|
|
59
|
+
};
|
|
60
|
+
function generateId(prefix) {
|
|
61
|
+
return `${prefix}_${Date.now().toString(36)}_${crypto.randomUUID().replace(/-/g, "").slice(0, 12)}`;
|
|
62
|
+
}
|
|
63
|
+
function fingerprintId(prefix, content) {
|
|
64
|
+
return `${prefix}_${createHash("sha256").update(content).digest("hex").slice(0, 16)}`;
|
|
65
|
+
}
|
|
66
|
+
function jaccardSimilarity(a, b) {
|
|
67
|
+
const setA = new Set(a.split(/\s+/).filter((t) => t.length > 2));
|
|
68
|
+
const setB = new Set(b.split(/\s+/).filter((t) => t.length > 2));
|
|
69
|
+
if (setA.size === 0 && setB.size === 0) return 1;
|
|
70
|
+
if (setA.size === 0 || setB.size === 0) return 0;
|
|
71
|
+
let intersection = 0;
|
|
72
|
+
for (const word of setA) if (setB.has(word)) intersection++;
|
|
73
|
+
return intersection / (setA.size + setB.size - intersection);
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { jaccardSimilarity as a, generateId as i, STREAM as n, fingerprintId as r, KV as t };
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=schema-CNiCWzV9.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-CNiCWzV9.mjs","names":[],"sources":["../src/state/schema.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\r\n\r\nexport const KV = {\r\n sessions: \"mem:sessions\",\r\n observations: (sessionId: string) => `mem:obs:${sessionId}`,\r\n memories: \"mem:memories\",\r\n summaries: \"mem:summaries\",\r\n config: \"mem:config\",\r\n metrics: \"mem:metrics\",\r\n health: \"mem:health\",\r\n embeddings: (obsId: string) => `mem:emb:${obsId}`,\r\n bm25Index: \"mem:index:bm25\",\r\n relations: \"mem:relations\",\r\n profiles: \"mem:profiles\",\r\n claudeBridge: \"mem:claude-bridge\",\r\n graphNodes: \"mem:graph:nodes\",\r\n graphEdges: \"mem:graph:edges\",\r\n // #814: precomputed snapshot of the top-degree subgraph and aggregate\r\n // type counts. Saves /graph/query and /graph/stats from a full\r\n // kv.list enumeration over 75K+ node corpora, which exceeds the iii\r\n // invocation timeout and surfaces as \"Invocation stopped\" 500s.\r\n // Single fixed key (\"current\") so writes are read-modify-write under\r\n // the same keyed mutex as graph-extract.\r\n graphSnapshot: \"mem:graph:snapshot\",\r\n // #814 v2: targeted-lookup indexes so graph-extract never enumerates\r\n // the full nodes/edges scope. Each entry is a single small kv.get,\r\n // bounded payload — works at 75K+ nodes where kv.list would block\r\n // the worker event loop (37MB WS frame parse blocks heartbeat,\r\n // worker is declared dead before any Promise.race timer can fire).\r\n // - graphNameIndex: key `${type}|${name}` -> nodeId. Replaces the\r\n // existingNodes.find() O(n) dedup scan inside mem::graph-extract.\r\n // - graphEdgeKey: key `${src}|${tgt}|${type}` -> edgeId. Same for\r\n // edge dedup.\r\n // - graphNodeDegree: key nodeId -> incident-edge count. Read /\r\n // incremented on edge writes to maintain the snapshot top-N\r\n // ranking without scanning all edges.\r\n graphNameIndex: \"mem:graph:name-index\",\r\n graphEdgeKey: \"mem:graph:edge-key\",\r\n graphNodeDegree: \"mem:graph:node-degree\",\r\n semantic: \"mem:semantic\",\r\n procedural: \"mem:procedural\",\r\n teamShared: (teamId: string) => `mem:team:${teamId}:shared`,\r\n teamUsers: (teamId: string, userId: string) =>\r\n `mem:team:${teamId}:users:${userId}`,\r\n teamProfile: (teamId: string) => `mem:team:${teamId}:profile`,\r\n audit: \"mem:audit\",\r\n actions: \"mem:actions\",\r\n actionEdges: \"mem:action-edges\",\r\n leases: \"mem:leases\",\r\n routines: \"mem:routines\",\r\n routineRuns: \"mem:routine-runs\",\r\n signals: \"mem:signals\",\r\n checkpoints: \"mem:checkpoints\",\r\n mesh: \"mem:mesh\",\r\n sketches: \"mem:sketches\",\r\n facets: \"mem:facets\",\r\n sentinels: \"mem:sentinels\",\r\n crystals: \"mem:crystals\",\r\n lessons: \"mem:lessons\",\r\n insights: \"mem:insights\",\r\n graphEdgeHistory: \"mem:graph:edge-history\",\r\n enrichedChunks: (sessionId: string) => `mem:enriched:${sessionId}`,\r\n latentEmbeddings: (obsId: string) => `mem:latent:${obsId}`,\r\n retentionScores: \"mem:retention\",\r\n accessLog: \"mem:access\",\r\n imageRefs: \"mem:image-refs\",\r\n imageEmbeddings: \"mem:image-embeddings\",\r\n slots: \"mem:slots\",\r\n globalSlots: \"mem:slots:global\",\r\n state: \"mem:state\",\r\n commits: \"mem:commits\",\r\n // #771: tracks the most recent smart-search call per session, used by\r\n // the followup-rate diagnostic. Key = sessionId. TTL-swept hourly.\r\n recentSearches: \"mem:recent-searches\",\r\n} as const;\r\n\r\nexport const STREAM = {\r\n name: \"mem-live\",\r\n group: (sessionId: string) => sessionId,\r\n viewerGroup: \"viewer\",\r\n} as const;\r\n\r\nexport function generateId(prefix: string): string {\r\n const ts = Date.now().toString(36);\r\n const rand = crypto.randomUUID().replace(/-/g, \"\").slice(0, 12);\r\n return `${prefix}_${ts}_${rand}`;\r\n}\r\n\r\nexport function fingerprintId(prefix: string, content: string): string {\r\n const hash = createHash(\"sha256\").update(content).digest(\"hex\");\r\n return `${prefix}_${hash.slice(0, 16)}`;\r\n}\r\n\r\nexport function jaccardSimilarity(a: string, b: string): number {\r\n const setA = new Set(a.split(/\\s+/).filter((t) => t.length > 2));\r\n const setB = new Set(b.split(/\\s+/).filter((t) => t.length > 2));\r\n if (setA.size === 0 && setB.size === 0) return 1;\r\n if (setA.size === 0 || setB.size === 0) return 0;\r\n let intersection = 0;\r\n for (const word of setA) {\r\n if (setB.has(word)) intersection++;\r\n }\r\n return intersection / (setA.size + setB.size - intersection);\r\n}\r\n"],"mappings":";;AAEA,MAAa,KAAK;CAChB,UAAU;CACV,eAAe,cAAsB,WAAW;CAChD,UAAU;CACV,WAAW;CACX,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,aAAa,UAAkB,WAAW;CAC1C,WAAW;CACX,WAAW;CACX,UAAU;CACV,cAAc;CACd,YAAY;CACZ,YAAY;CAOZ,eAAe;CAaf,gBAAgB;CAChB,cAAc;CACd,iBAAiB;CACjB,UAAU;CACV,YAAY;CACZ,aAAa,WAAmB,YAAY,OAAO;CACnD,YAAY,QAAgB,WAC1B,YAAY,OAAO,SAAS;CAC9B,cAAc,WAAmB,YAAY,OAAO;CACpD,OAAO;CACP,SAAS;CACT,aAAa;CACb,QAAQ;CACR,UAAU;CACV,aAAa;CACb,SAAS;CACT,aAAa;CACb,MAAM;CACN,UAAU;CACV,QAAQ;CACR,WAAW;CACX,UAAU;CACV,SAAS;CACT,UAAU;CACV,kBAAkB;CAClB,iBAAiB,cAAsB,gBAAgB;CACvD,mBAAmB,UAAkB,cAAc;CACnD,iBAAiB;CACjB,WAAW;CACX,WAAW;CACX,iBAAiB;CACjB,OAAO;CACP,aAAa;CACb,OAAO;CACP,SAAS;CAGT,gBAAgB;CACjB;AAED,MAAa,SAAS;CACpB,MAAM;CACN,QAAQ,cAAsB;CAC9B,aAAa;CACd;AAED,SAAgB,WAAW,QAAwB;AAGjD,QAAO,GAAG,OAAO,GAFN,KAAK,KAAK,CAAC,SAAS,GAET,CAAC,GADV,OAAO,YAAY,CAAC,QAAQ,MAAM,GAAG,CAAC,MAAM,GAAG,GAC9B;;AAGhC,SAAgB,cAAc,QAAgB,SAAyB;AAErE,QAAO,GAAG,OAAO,GADJ,WAAW,SAAS,CAAC,OAAO,QAAQ,CAAC,OAAO,MACjC,CAAC,MAAM,GAAG,GAAG;;AAGvC,SAAgB,kBAAkB,GAAW,GAAmB;CAC9D,MAAM,OAAO,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC,QAAQ,MAAM,EAAE,SAAS,EAAE,CAAC;CAChE,MAAM,OAAO,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC,QAAQ,MAAM,EAAE,SAAS,EAAE,CAAC;AAChE,KAAI,KAAK,SAAS,KAAK,KAAK,SAAS,EAAG,QAAO;AAC/C,KAAI,KAAK,SAAS,KAAK,KAAK,SAAS,EAAG,QAAO;CAC/C,IAAI,eAAe;AACnB,MAAK,MAAM,QAAQ,KACjB,KAAI,KAAK,IAAI,KAAK,CAAE;AAEtB,QAAO,gBAAgB,KAAK,OAAO,KAAK,OAAO"}
|