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 @@
|
|
|
1
|
+
{"version":3,"file":"notification.mjs","names":[],"sources":["../../src/hooks/_project.ts","../../src/hooks/notification.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\r\nimport { basename } from \"node:path\";\r\n\r\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\r\nexport function resolveProject(cwd?: string): string {\r\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\r\n if (explicit && explicit.trim()) return explicit.trim();\r\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\r\n try {\r\n const top = execSync(\"git rev-parse --show-toplevel\", {\r\n cwd: dir,\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n timeout: 500,\r\n })\r\n .toString()\r\n .trim();\r\n if (top) return basename(top);\r\n } catch {}\r\n return basename(dir);\r\n}\r\n","#!/usr/bin/env node\r\nimport { resolveProject } from \"./_project.js\";\r\n\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n const notificationType = data.notification_type ?? data.notificationType;\r\n if (notificationType !== \"permission_prompt\") return;\r\n\r\n const rawSessionId = data.session_id ?? data.sessionId;\r\n const sessionId =\r\n typeof rawSessionId === \"string\" && rawSessionId.length > 0\r\n ? rawSessionId\r\n : \"unknown\";\r\n\r\n fetch(`${REST_URL}/agentmemory/observe`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({\r\n hookType: \"notification\",\r\n sessionId,\r\n project: resolveProject(data.cwd as string | undefined),\r\n cwd: (data.cwd as string | undefined) || process.cwd(),\r\n timestamp: new Date().toISOString(),\r\n data: {\r\n notification_type: notificationType,\r\n title: data.title,\r\n message: data.message,\r\n },\r\n }),\r\n signal: AbortSignal.timeout(2000),\r\n }).catch(() => {});\r\n setTimeout(() => process.exit(0), 500).unref();\r\n}\r\n\r\nmain();\r\n"],"mappings":";;;;AAIA,SAAgB,eAAe,KAAsB;CACnD,MAAM,WAAW,QAAQ,IAAI;AAC7B,KAAI,YAAY,SAAS,MAAM,CAAE,QAAO,SAAS,MAAM;CACvD,MAAM,MAAM,OAAO,IAAI,MAAM,GAAG,MAAM,QAAQ,KAAK;AACnD,KAAI;EACF,MAAM,MAAM,SAAS,iCAAiC;GACpD,KAAK;GACL,OAAO;IAAC;IAAU;IAAQ;IAAS;GACnC,SAAS;GACV,CAAC,CACC,UAAU,CACV,MAAM;AACT,MAAI,IAAK,QAAO,SAAS,IAAI;SACvB;AACR,QAAO,SAAS,IAAI;;;;ACftB,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;CAC7B,MAAM,mBAAmB,KAAK,qBAAqB,KAAK;AACxD,KAAI,qBAAqB,oBAAqB;CAE9C,MAAM,eAAe,KAAK,cAAc,KAAK;CAC7C,MAAM,YACJ,OAAO,iBAAiB,YAAY,aAAa,SAAS,IACtD,eACA;AAEN,OAAM,GAAG,SAAS,uBAAuB;EACvC,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU;GACnB,UAAU;GACV;GACA,SAAS,eAAe,KAAK,IAA0B;GACvD,KAAM,KAAK,OAA8B,QAAQ,KAAK;GACtD,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,MAAM;IACJ,mBAAmB;IACnB,OAAO,KAAK;IACZ,SAAS,KAAK;IACf;GACF,CAAC;EACF,QAAQ,YAAY,QAAQ,IAAK;EAClC,CAAC,CAAC,YAAY,GAAG;AAClB,kBAAiB,QAAQ,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO;;AAGhD,MAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
//#region src/hooks/post-commit.ts
|
|
5
|
+
const exec = promisify(execFile);
|
|
6
|
+
function isSdkChildContext(payload) {
|
|
7
|
+
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
8
|
+
if (!payload || typeof payload !== "object") return false;
|
|
9
|
+
return payload.entrypoint === "sdk-ts";
|
|
10
|
+
}
|
|
11
|
+
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
|
|
12
|
+
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
|
|
13
|
+
const TIMEOUT_MS = 1500;
|
|
14
|
+
function authHeaders() {
|
|
15
|
+
const h = { "Content-Type": "application/json" };
|
|
16
|
+
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
|
|
17
|
+
return h;
|
|
18
|
+
}
|
|
19
|
+
async function git(args, cwd) {
|
|
20
|
+
try {
|
|
21
|
+
const { stdout } = await exec("git", args, {
|
|
22
|
+
cwd,
|
|
23
|
+
timeout: 1500
|
|
24
|
+
});
|
|
25
|
+
return stdout.trim();
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function main() {
|
|
31
|
+
let input = "";
|
|
32
|
+
for await (const chunk of process.stdin) input += chunk;
|
|
33
|
+
let data = {};
|
|
34
|
+
if (input.trim()) try {
|
|
35
|
+
data = JSON.parse(input);
|
|
36
|
+
} catch {}
|
|
37
|
+
if (isSdkChildContext(data)) return;
|
|
38
|
+
const cwd = data.cwd || process.env["AGENTMEMORY_CWD"] || process.cwd();
|
|
39
|
+
const sessionId = data.session_id || process.env["AGENTMEMORY_SESSION_ID"] || void 0;
|
|
40
|
+
const sha = process.env["AGENTMEMORY_COMMIT_SHA"] || await git(["rev-parse", "HEAD"], cwd);
|
|
41
|
+
if (!sha) return;
|
|
42
|
+
const branch = await git([
|
|
43
|
+
"rev-parse",
|
|
44
|
+
"--abbrev-ref",
|
|
45
|
+
"HEAD"
|
|
46
|
+
], cwd);
|
|
47
|
+
const repo = await git([
|
|
48
|
+
"config",
|
|
49
|
+
"--get",
|
|
50
|
+
"remote.origin.url"
|
|
51
|
+
], cwd);
|
|
52
|
+
const message = await git([
|
|
53
|
+
"log",
|
|
54
|
+
"-1",
|
|
55
|
+
"--pretty=%B",
|
|
56
|
+
sha
|
|
57
|
+
], cwd);
|
|
58
|
+
const author = await git([
|
|
59
|
+
"log",
|
|
60
|
+
"-1",
|
|
61
|
+
"--pretty=%an <%ae>",
|
|
62
|
+
sha
|
|
63
|
+
], cwd);
|
|
64
|
+
const authoredAt = await git([
|
|
65
|
+
"log",
|
|
66
|
+
"-1",
|
|
67
|
+
"--pretty=%aI",
|
|
68
|
+
sha
|
|
69
|
+
], cwd);
|
|
70
|
+
const filesRaw = await git([
|
|
71
|
+
"diff-tree",
|
|
72
|
+
"--no-commit-id",
|
|
73
|
+
"--name-only",
|
|
74
|
+
"-r",
|
|
75
|
+
sha
|
|
76
|
+
], cwd);
|
|
77
|
+
const files = filesRaw ? filesRaw.split("\n").filter(Boolean) : void 0;
|
|
78
|
+
const body = {
|
|
79
|
+
sessionId,
|
|
80
|
+
sha,
|
|
81
|
+
branch: branch || void 0,
|
|
82
|
+
repo: repo || void 0,
|
|
83
|
+
message: message || void 0,
|
|
84
|
+
author: author || void 0,
|
|
85
|
+
authoredAt: authoredAt || void 0,
|
|
86
|
+
files
|
|
87
|
+
};
|
|
88
|
+
try {
|
|
89
|
+
await fetch(`${REST_URL}/agentmemory/session/commit`, {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers: authHeaders(),
|
|
92
|
+
body: JSON.stringify(body),
|
|
93
|
+
signal: AbortSignal.timeout(TIMEOUT_MS)
|
|
94
|
+
});
|
|
95
|
+
} catch {}
|
|
96
|
+
}
|
|
97
|
+
main();
|
|
98
|
+
//#endregion
|
|
99
|
+
export {};
|
|
100
|
+
|
|
101
|
+
//# sourceMappingURL=post-commit.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-commit.mjs","names":[],"sources":["../../src/hooks/post-commit.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nimport { execFile } from \"node:child_process\";\r\nimport { promisify } from \"node:util\";\r\n\r\nconst exec = promisify(execFile);\r\n\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\nconst TIMEOUT_MS = 1500;\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function git(args: string[], cwd: string): Promise<string | null> {\r\n try {\r\n const { stdout } = await exec(\"git\", args, { cwd, timeout: 1500 });\r\n return stdout.trim();\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown> = {};\r\n if (input.trim()) {\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n // Direct invocation from .git/hooks/post-commit may pass no stdin.\r\n }\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n\r\n const cwd =\r\n (data.cwd as string) ||\r\n process.env[\"AGENTMEMORY_CWD\"] ||\r\n process.cwd();\r\n const sessionId =\r\n (data.session_id as string) ||\r\n process.env[\"AGENTMEMORY_SESSION_ID\"] ||\r\n undefined;\r\n\r\n const sha =\r\n process.env[\"AGENTMEMORY_COMMIT_SHA\"] ||\r\n (await git([\"rev-parse\", \"HEAD\"], cwd));\r\n if (!sha) return;\r\n\r\n const branch = await git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"], cwd);\r\n const repo = await git([\"config\", \"--get\", \"remote.origin.url\"], cwd);\r\n const message = await git([\"log\", \"-1\", \"--pretty=%B\", sha], cwd);\r\n const author = await git([\"log\", \"-1\", \"--pretty=%an <%ae>\", sha], cwd);\r\n const authoredAt = await git([\"log\", \"-1\", \"--pretty=%aI\", sha], cwd);\r\n const filesRaw = await git(\r\n [\"diff-tree\", \"--no-commit-id\", \"--name-only\", \"-r\", sha],\r\n cwd,\r\n );\r\n const files = filesRaw ? filesRaw.split(\"\\n\").filter(Boolean) : undefined;\r\n\r\n const body = {\r\n sessionId,\r\n sha,\r\n branch: branch || undefined,\r\n repo: repo || undefined,\r\n message: message || undefined,\r\n author: author || undefined,\r\n authoredAt: authoredAt || undefined,\r\n files,\r\n };\r\n\r\n try {\r\n await fetch(`${REST_URL}/agentmemory/session/commit`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify(body),\r\n signal: AbortSignal.timeout(TIMEOUT_MS),\r\n });\r\n } catch {\r\n // best-effort\r\n }\r\n}\r\n\r\nmain();\r\n"],"mappings":";;;;AAKA,MAAM,OAAO,UAAU,SAAS;AAEhC,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AACpD,MAAM,aAAa;AAEnB,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,IAAI,MAAgB,KAAqC;AACtE,KAAI;EACF,MAAM,EAAE,WAAW,MAAM,KAAK,OAAO,MAAM;GAAE;GAAK,SAAS;GAAM,CAAC;AAClE,SAAO,OAAO,MAAM;SACd;AACN,SAAO;;;AAIX,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI,OAAgC,EAAE;AACtC,KAAI,MAAM,MAAM,CACd,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AAKV,KAAI,kBAAkB,KAAK,CAAE;CAE7B,MAAM,MACH,KAAK,OACN,QAAQ,IAAI,sBACZ,QAAQ,KAAK;CACf,MAAM,YACH,KAAK,cACN,QAAQ,IAAI,6BACZ,KAAA;CAEF,MAAM,MACJ,QAAQ,IAAI,6BACX,MAAM,IAAI,CAAC,aAAa,OAAO,EAAE,IAAI;AACxC,KAAI,CAAC,IAAK;CAEV,MAAM,SAAS,MAAM,IAAI;EAAC;EAAa;EAAgB;EAAO,EAAE,IAAI;CACpE,MAAM,OAAO,MAAM,IAAI;EAAC;EAAU;EAAS;EAAoB,EAAE,IAAI;CACrE,MAAM,UAAU,MAAM,IAAI;EAAC;EAAO;EAAM;EAAe;EAAI,EAAE,IAAI;CACjE,MAAM,SAAS,MAAM,IAAI;EAAC;EAAO;EAAM;EAAsB;EAAI,EAAE,IAAI;CACvE,MAAM,aAAa,MAAM,IAAI;EAAC;EAAO;EAAM;EAAgB;EAAI,EAAE,IAAI;CACrE,MAAM,WAAW,MAAM,IACrB;EAAC;EAAa;EAAkB;EAAe;EAAM;EAAI,EACzD,IACD;CACD,MAAM,QAAQ,WAAW,SAAS,MAAM,KAAK,CAAC,OAAO,QAAQ,GAAG,KAAA;CAEhE,MAAM,OAAO;EACX;EACA;EACA,QAAQ,UAAU,KAAA;EAClB,MAAM,QAAQ,KAAA;EACd,SAAS,WAAW,KAAA;EACpB,QAAQ,UAAU,KAAA;EAClB,YAAY,cAAc,KAAA;EAC1B;EACD;AAED,KAAI;AACF,QAAM,MAAM,GAAG,SAAS,8BAA8B;GACpD,QAAQ;GACR,SAAS,aAAa;GACtB,MAAM,KAAK,UAAU,KAAK;GAC1B,QAAQ,YAAY,QAAQ,WAAW;GACxC,CAAC;SACI;;AAKV,MAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
//#region src/hooks/_project.ts
|
|
5
|
+
function resolveProject(cwd) {
|
|
6
|
+
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
|
|
7
|
+
if (explicit && explicit.trim()) return explicit.trim();
|
|
8
|
+
const dir = cwd && cwd.trim() ? cwd : process.cwd();
|
|
9
|
+
try {
|
|
10
|
+
const top = execSync("git rev-parse --show-toplevel", {
|
|
11
|
+
cwd: dir,
|
|
12
|
+
stdio: [
|
|
13
|
+
"ignore",
|
|
14
|
+
"pipe",
|
|
15
|
+
"ignore"
|
|
16
|
+
],
|
|
17
|
+
timeout: 500
|
|
18
|
+
}).toString().trim();
|
|
19
|
+
if (top) return basename(top);
|
|
20
|
+
} catch {}
|
|
21
|
+
return basename(dir);
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/hooks/post-tool-failure.ts
|
|
25
|
+
function isSdkChildContext(payload) {
|
|
26
|
+
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
27
|
+
if (!payload || typeof payload !== "object") return false;
|
|
28
|
+
return payload.entrypoint === "sdk-ts";
|
|
29
|
+
}
|
|
30
|
+
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
|
|
31
|
+
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
|
|
32
|
+
function authHeaders() {
|
|
33
|
+
const h = { "Content-Type": "application/json" };
|
|
34
|
+
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
|
|
35
|
+
return h;
|
|
36
|
+
}
|
|
37
|
+
async function main() {
|
|
38
|
+
let input = "";
|
|
39
|
+
for await (const chunk of process.stdin) input += chunk;
|
|
40
|
+
let data;
|
|
41
|
+
try {
|
|
42
|
+
data = JSON.parse(input);
|
|
43
|
+
} catch {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (isSdkChildContext(data)) return;
|
|
47
|
+
if (data.is_interrupt || data.isInterrupt) return;
|
|
48
|
+
const sessionId = data.session_id || data.sessionId || "unknown";
|
|
49
|
+
const toolName = data.tool_name ?? data.toolName;
|
|
50
|
+
const toolInput = data.tool_input ?? data.toolArgs;
|
|
51
|
+
const error = data.error ?? data.errorMessage;
|
|
52
|
+
fetch(`${REST_URL}/agentmemory/observe`, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: authHeaders(),
|
|
55
|
+
body: JSON.stringify({
|
|
56
|
+
hookType: "post_tool_failure",
|
|
57
|
+
sessionId,
|
|
58
|
+
project: resolveProject(data.cwd),
|
|
59
|
+
cwd: data.cwd || process.cwd(),
|
|
60
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
61
|
+
data: {
|
|
62
|
+
tool_name: toolName,
|
|
63
|
+
tool_input: typeof toolInput === "string" ? toolInput.slice(0, 4e3) : JSON.stringify(toolInput ?? "").slice(0, 4e3),
|
|
64
|
+
error: typeof error === "string" ? error.slice(0, 4e3) : JSON.stringify(error ?? "").slice(0, 4e3)
|
|
65
|
+
}
|
|
66
|
+
}),
|
|
67
|
+
signal: AbortSignal.timeout(3e3)
|
|
68
|
+
}).catch(() => {});
|
|
69
|
+
setTimeout(() => process.exit(0), 500).unref();
|
|
70
|
+
}
|
|
71
|
+
main();
|
|
72
|
+
//#endregion
|
|
73
|
+
export {};
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=post-tool-failure.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-tool-failure.mjs","names":[],"sources":["../../src/hooks/_project.ts","../../src/hooks/post-tool-failure.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\r\nimport { basename } from \"node:path\";\r\n\r\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\r\nexport function resolveProject(cwd?: string): string {\r\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\r\n if (explicit && explicit.trim()) return explicit.trim();\r\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\r\n try {\r\n const top = execSync(\"git rev-parse --show-toplevel\", {\r\n cwd: dir,\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n timeout: 500,\r\n })\r\n .toString()\r\n .trim();\r\n if (top) return basename(top);\r\n } catch {}\r\n return basename(dir);\r\n}\r\n","#!/usr/bin/env node\r\nimport { resolveProject } from \"./_project.js\";\r\n\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n if (data.is_interrupt || data.isInterrupt) return;\r\n\r\n const sessionId = ((data.session_id || data.sessionId) as string) || \"unknown\";\r\n const toolName = data.tool_name ?? data.toolName;\r\n const toolInput = data.tool_input ?? data.toolArgs;\r\n const error = data.error ?? data.errorMessage;\r\n\r\n fetch(`${REST_URL}/agentmemory/observe`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({\r\n hookType: \"post_tool_failure\",\r\n sessionId,\r\n project: resolveProject(data.cwd as string | undefined),\r\n cwd: (data.cwd as string | undefined) || process.cwd(),\r\n timestamp: new Date().toISOString(),\r\n data: {\r\n tool_name: toolName,\r\n tool_input:\r\n typeof toolInput === \"string\"\r\n ? toolInput.slice(0, 4000)\r\n : JSON.stringify(toolInput ?? \"\").slice(0, 4000),\r\n error:\r\n typeof error === \"string\"\r\n ? error.slice(0, 4000)\r\n : JSON.stringify(error ?? \"\").slice(0, 4000),\r\n },\r\n }),\r\n signal: AbortSignal.timeout(3000),\r\n }).catch(() => {});\r\n setTimeout(() => process.exit(0), 500).unref();\r\n}\r\n\r\nmain();\r\n"],"mappings":";;;;AAIA,SAAgB,eAAe,KAAsB;CACnD,MAAM,WAAW,QAAQ,IAAI;AAC7B,KAAI,YAAY,SAAS,MAAM,CAAE,QAAO,SAAS,MAAM;CACvD,MAAM,MAAM,OAAO,IAAI,MAAM,GAAG,MAAM,QAAQ,KAAK;AACnD,KAAI;EACF,MAAM,MAAM,SAAS,iCAAiC;GACpD,KAAK;GACL,OAAO;IAAC;IAAU;IAAQ;IAAS;GACnC,SAAS;GACV,CAAC,CACC,UAAU,CACV,MAAM;AACT,MAAI,IAAK,QAAO,SAAS,IAAI;SACvB;AACR,QAAO,SAAS,IAAI;;;;ACftB,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;AAC7B,KAAI,KAAK,gBAAgB,KAAK,YAAa;CAE3C,MAAM,YAAc,KAAK,cAAc,KAAK,aAAyB;CACrE,MAAM,WAAW,KAAK,aAAa,KAAK;CACxC,MAAM,YAAY,KAAK,cAAc,KAAK;CAC1C,MAAM,QAAQ,KAAK,SAAS,KAAK;AAEjC,OAAM,GAAG,SAAS,uBAAuB;EACvC,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU;GACnB,UAAU;GACV;GACA,SAAS,eAAe,KAAK,IAA0B;GACvD,KAAM,KAAK,OAA8B,QAAQ,KAAK;GACtD,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,MAAM;IACJ,WAAW;IACX,YACE,OAAO,cAAc,WACjB,UAAU,MAAM,GAAG,IAAK,GACxB,KAAK,UAAU,aAAa,GAAG,CAAC,MAAM,GAAG,IAAK;IACpD,OACE,OAAO,UAAU,WACb,MAAM,MAAM,GAAG,IAAK,GACpB,KAAK,UAAU,SAAS,GAAG,CAAC,MAAM,GAAG,IAAK;IACjD;GACF,CAAC;EACF,QAAQ,YAAY,QAAQ,IAAK;EAClC,CAAC,CAAC,YAAY,GAAG;AAClB,kBAAiB,QAAQ,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO;;AAGhD,MAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
//#region src/hooks/_project.ts
|
|
5
|
+
function resolveProject(cwd) {
|
|
6
|
+
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
|
|
7
|
+
if (explicit && explicit.trim()) return explicit.trim();
|
|
8
|
+
const dir = cwd && cwd.trim() ? cwd : process.cwd();
|
|
9
|
+
try {
|
|
10
|
+
const top = execSync("git rev-parse --show-toplevel", {
|
|
11
|
+
cwd: dir,
|
|
12
|
+
stdio: [
|
|
13
|
+
"ignore",
|
|
14
|
+
"pipe",
|
|
15
|
+
"ignore"
|
|
16
|
+
],
|
|
17
|
+
timeout: 500
|
|
18
|
+
}).toString().trim();
|
|
19
|
+
if (top) return basename(top);
|
|
20
|
+
} catch {}
|
|
21
|
+
return basename(dir);
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/hooks/post-tool-use.ts
|
|
25
|
+
function isSdkChildContext(payload) {
|
|
26
|
+
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
27
|
+
if (!payload || typeof payload !== "object") return false;
|
|
28
|
+
return payload.entrypoint === "sdk-ts";
|
|
29
|
+
}
|
|
30
|
+
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
|
|
31
|
+
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
|
|
32
|
+
function authHeaders() {
|
|
33
|
+
const h = { "Content-Type": "application/json" };
|
|
34
|
+
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
|
|
35
|
+
return h;
|
|
36
|
+
}
|
|
37
|
+
async function main() {
|
|
38
|
+
let input = "";
|
|
39
|
+
for await (const chunk of process.stdin) input += chunk;
|
|
40
|
+
let data;
|
|
41
|
+
try {
|
|
42
|
+
data = JSON.parse(input);
|
|
43
|
+
} catch {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (isSdkChildContext(data)) return;
|
|
47
|
+
const sessionId = data.session_id || data.sessionId || "unknown";
|
|
48
|
+
const toolName = data.tool_name ?? data.toolName;
|
|
49
|
+
const toolInput = data.tool_input ?? data.toolArgs;
|
|
50
|
+
const { imageData, cleanOutput } = extractImageData(toolOutput(data));
|
|
51
|
+
fetch(`${REST_URL}/agentmemory/observe`, {
|
|
52
|
+
method: "POST",
|
|
53
|
+
headers: authHeaders(),
|
|
54
|
+
body: JSON.stringify({
|
|
55
|
+
hookType: "post_tool_use",
|
|
56
|
+
sessionId,
|
|
57
|
+
project: resolveProject(data.cwd),
|
|
58
|
+
cwd: data.cwd || process.cwd(),
|
|
59
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
60
|
+
data: {
|
|
61
|
+
tool_name: toolName,
|
|
62
|
+
tool_input: toolInput,
|
|
63
|
+
tool_output: truncate(cleanOutput, 8e3),
|
|
64
|
+
...imageData ? { image_data: imageData } : {}
|
|
65
|
+
}
|
|
66
|
+
}),
|
|
67
|
+
signal: AbortSignal.timeout(3e3)
|
|
68
|
+
}).catch(() => {});
|
|
69
|
+
setTimeout(() => process.exit(0), 500).unref();
|
|
70
|
+
}
|
|
71
|
+
function toolOutput(data) {
|
|
72
|
+
if (data.tool_response !== void 0) return data.tool_response;
|
|
73
|
+
if (data.tool_output !== void 0) return data.tool_output;
|
|
74
|
+
const result = data.tool_result ?? data.toolResult;
|
|
75
|
+
if (typeof result === "object" && result !== null) {
|
|
76
|
+
const obj = result;
|
|
77
|
+
return obj.text_result_for_llm ?? obj.textResultForLlm ?? result;
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
function isBase64Image(val) {
|
|
82
|
+
return typeof val === "string" && (val.startsWith("data:image/") || val.startsWith("iVBORw0KGgo") || val.startsWith("/9j/"));
|
|
83
|
+
}
|
|
84
|
+
function extractImageData(output) {
|
|
85
|
+
if (isBase64Image(output)) return {
|
|
86
|
+
imageData: output,
|
|
87
|
+
cleanOutput: "[image data extracted]"
|
|
88
|
+
};
|
|
89
|
+
if (typeof output === "object" && output !== null && !Array.isArray(output)) {
|
|
90
|
+
const obj = output;
|
|
91
|
+
let imageData;
|
|
92
|
+
const clean = {};
|
|
93
|
+
for (const [key, val] of Object.entries(obj)) if (!imageData && isBase64Image(val)) {
|
|
94
|
+
imageData = val;
|
|
95
|
+
clean[key] = "[image data extracted]";
|
|
96
|
+
} else clean[key] = val;
|
|
97
|
+
return {
|
|
98
|
+
imageData,
|
|
99
|
+
cleanOutput: clean
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
imageData: void 0,
|
|
104
|
+
cleanOutput: output
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function truncate(value, max) {
|
|
108
|
+
if (typeof value === "string" && value.length > max) return value.slice(0, max) + "\n[...truncated]";
|
|
109
|
+
if (typeof value === "object" && value !== null) {
|
|
110
|
+
const str = JSON.stringify(value);
|
|
111
|
+
if (str.length > max) return str.slice(0, max) + "...[truncated]";
|
|
112
|
+
return value;
|
|
113
|
+
}
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
main();
|
|
117
|
+
//#endregion
|
|
118
|
+
export {};
|
|
119
|
+
|
|
120
|
+
//# sourceMappingURL=post-tool-use.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-tool-use.mjs","names":[],"sources":["../../src/hooks/_project.ts","../../src/hooks/post-tool-use.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\r\nimport { basename } from \"node:path\";\r\n\r\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\r\nexport function resolveProject(cwd?: string): string {\r\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\r\n if (explicit && explicit.trim()) return explicit.trim();\r\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\r\n try {\r\n const top = execSync(\"git rev-parse --show-toplevel\", {\r\n cwd: dir,\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n timeout: 500,\r\n })\r\n .toString()\r\n .trim();\r\n if (top) return basename(top);\r\n } catch {}\r\n return basename(dir);\r\n}\r\n","#!/usr/bin/env node\r\nimport { resolveProject } from \"./_project.js\";\r\n\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n\r\n const sessionId = ((data.session_id || data.sessionId) as string) || \"unknown\";\r\n const toolName = data.tool_name ?? data.toolName;\r\n const toolInput = data.tool_input ?? data.toolArgs;\r\n\r\n const { imageData, cleanOutput } = extractImageData(toolOutput(data));\r\n\r\n fetch(`${REST_URL}/agentmemory/observe`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({\r\n hookType: \"post_tool_use\",\r\n sessionId,\r\n project: resolveProject(data.cwd as string | undefined),\r\n cwd: (data.cwd as string | undefined) || process.cwd(),\r\n timestamp: new Date().toISOString(),\r\n data: {\r\n tool_name: toolName,\r\n tool_input: toolInput,\r\n tool_output: truncate(cleanOutput, 8000),\r\n ...(imageData ? { image_data: imageData } : {}),\r\n },\r\n }),\r\n signal: AbortSignal.timeout(3000),\r\n }).catch(() => {});\r\n setTimeout(() => process.exit(0), 500).unref();\r\n}\r\n\r\nfunction toolOutput(data: Record<string, unknown>): unknown {\r\n if (data.tool_response !== undefined) return data.tool_response;\r\n if (data.tool_output !== undefined) return data.tool_output;\r\n const result = data.tool_result ?? data.toolResult;\r\n if (typeof result === \"object\" && result !== null) {\r\n const obj = result as Record<string, unknown>;\r\n return obj.text_result_for_llm ?? obj.textResultForLlm ?? result;\r\n }\r\n return result;\r\n}\r\n\r\nfunction isBase64Image(val: unknown): val is string {\r\n return typeof val === \"string\" && (\r\n val.startsWith(\"data:image/\") ||\r\n val.startsWith(\"iVBORw0KGgo\") ||\r\n val.startsWith(\"/9j/\")\r\n );\r\n}\r\n\r\nfunction extractImageData(output: unknown): { imageData: string | undefined; cleanOutput: unknown } {\r\n if (isBase64Image(output)) {\r\n return { imageData: output, cleanOutput: \"[image data extracted]\" };\r\n }\r\n\r\n if (typeof output === \"object\" && output !== null && !Array.isArray(output)) {\r\n const obj = output as Record<string, unknown>;\r\n let imageData: string | undefined;\r\n const clean: Record<string, unknown> = {};\r\n\r\n for (const [key, val] of Object.entries(obj)) {\r\n if (!imageData && isBase64Image(val)) {\r\n imageData = val;\r\n clean[key] = \"[image data extracted]\";\r\n } else {\r\n clean[key] = val;\r\n }\r\n }\r\n\r\n return { imageData, cleanOutput: clean };\r\n }\r\n\r\n return { imageData: undefined, cleanOutput: output };\r\n}\r\n\r\nfunction truncate(value: unknown, max: number): unknown {\r\n if (typeof value === \"string\" && value.length > max) {\r\n return value.slice(0, max) + \"\\n[...truncated]\";\r\n }\r\n if (typeof value === \"object\" && value !== null) {\r\n const str = JSON.stringify(value);\r\n if (str.length > max) return str.slice(0, max) + \"...[truncated]\";\r\n return value;\r\n }\r\n return value;\r\n}\r\n\r\nmain();\r\n"],"mappings":";;;;AAIA,SAAgB,eAAe,KAAsB;CACnD,MAAM,WAAW,QAAQ,IAAI;AAC7B,KAAI,YAAY,SAAS,MAAM,CAAE,QAAO,SAAS,MAAM;CACvD,MAAM,MAAM,OAAO,IAAI,MAAM,GAAG,MAAM,QAAQ,KAAK;AACnD,KAAI;EACF,MAAM,MAAM,SAAS,iCAAiC;GACpD,KAAK;GACL,OAAO;IAAC;IAAU;IAAQ;IAAS;GACnC,SAAS;GACV,CAAC,CACC,UAAU,CACV,MAAM;AACT,MAAI,IAAK,QAAO,SAAS,IAAI;SACvB;AACR,QAAO,SAAS,IAAI;;;;ACftB,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;CAE7B,MAAM,YAAc,KAAK,cAAc,KAAK,aAAyB;CACrE,MAAM,WAAW,KAAK,aAAa,KAAK;CACxC,MAAM,YAAY,KAAK,cAAc,KAAK;CAE1C,MAAM,EAAE,WAAW,gBAAgB,iBAAiB,WAAW,KAAK,CAAC;AAErE,OAAM,GAAG,SAAS,uBAAuB;EACvC,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU;GACnB,UAAU;GACV;GACA,SAAS,eAAe,KAAK,IAA0B;GACvD,KAAM,KAAK,OAA8B,QAAQ,KAAK;GACtD,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,MAAM;IACJ,WAAW;IACX,YAAY;IACZ,aAAa,SAAS,aAAa,IAAK;IACxC,GAAI,YAAY,EAAE,YAAY,WAAW,GAAG,EAAE;IAC/C;GACF,CAAC;EACF,QAAQ,YAAY,QAAQ,IAAK;EAClC,CAAC,CAAC,YAAY,GAAG;AAClB,kBAAiB,QAAQ,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO;;AAGhD,SAAS,WAAW,MAAwC;AAC1D,KAAI,KAAK,kBAAkB,KAAA,EAAW,QAAO,KAAK;AAClD,KAAI,KAAK,gBAAgB,KAAA,EAAW,QAAO,KAAK;CAChD,MAAM,SAAS,KAAK,eAAe,KAAK;AACxC,KAAI,OAAO,WAAW,YAAY,WAAW,MAAM;EACjD,MAAM,MAAM;AACZ,SAAO,IAAI,uBAAuB,IAAI,oBAAoB;;AAE5D,QAAO;;AAGT,SAAS,cAAc,KAA6B;AAClD,QAAO,OAAO,QAAQ,aACpB,IAAI,WAAW,cAAc,IAC7B,IAAI,WAAW,cAAc,IAC7B,IAAI,WAAW,OAAO;;AAI1B,SAAS,iBAAiB,QAA0E;AAClG,KAAI,cAAc,OAAO,CACvB,QAAO;EAAE,WAAW;EAAQ,aAAa;EAA0B;AAGrE,KAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,CAAC,MAAM,QAAQ,OAAO,EAAE;EAC3E,MAAM,MAAM;EACZ,IAAI;EACJ,MAAM,QAAiC,EAAE;AAEzC,OAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,IAAI,CAC1C,KAAI,CAAC,aAAa,cAAc,IAAI,EAAE;AACpC,eAAY;AACZ,SAAM,OAAO;QAEb,OAAM,OAAO;AAIjB,SAAO;GAAE;GAAW,aAAa;GAAO;;AAG1C,QAAO;EAAE,WAAW,KAAA;EAAW,aAAa;EAAQ;;AAGtD,SAAS,SAAS,OAAgB,KAAsB;AACtD,KAAI,OAAO,UAAU,YAAY,MAAM,SAAS,IAC9C,QAAO,MAAM,MAAM,GAAG,IAAI,GAAG;AAE/B,KAAI,OAAO,UAAU,YAAY,UAAU,MAAM;EAC/C,MAAM,MAAM,KAAK,UAAU,MAAM;AACjC,MAAI,IAAI,SAAS,IAAK,QAAO,IAAI,MAAM,GAAG,IAAI,GAAG;AACjD,SAAO;;AAET,QAAO;;AAGT,MAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
//#region src/hooks/_project.ts
|
|
5
|
+
function resolveProject(cwd) {
|
|
6
|
+
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
|
|
7
|
+
if (explicit && explicit.trim()) return explicit.trim();
|
|
8
|
+
const dir = cwd && cwd.trim() ? cwd : process.cwd();
|
|
9
|
+
try {
|
|
10
|
+
const top = execSync("git rev-parse --show-toplevel", {
|
|
11
|
+
cwd: dir,
|
|
12
|
+
stdio: [
|
|
13
|
+
"ignore",
|
|
14
|
+
"pipe",
|
|
15
|
+
"ignore"
|
|
16
|
+
],
|
|
17
|
+
timeout: 500
|
|
18
|
+
}).toString().trim();
|
|
19
|
+
if (top) return basename(top);
|
|
20
|
+
} catch {}
|
|
21
|
+
return basename(dir);
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/hooks/pre-compact.ts
|
|
25
|
+
function isSdkChildContext(payload) {
|
|
26
|
+
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
27
|
+
if (!payload || typeof payload !== "object") return false;
|
|
28
|
+
return payload.entrypoint === "sdk-ts";
|
|
29
|
+
}
|
|
30
|
+
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
|
|
31
|
+
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
|
|
32
|
+
function authHeaders() {
|
|
33
|
+
const h = { "Content-Type": "application/json" };
|
|
34
|
+
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
|
|
35
|
+
return h;
|
|
36
|
+
}
|
|
37
|
+
async function main() {
|
|
38
|
+
let input = "";
|
|
39
|
+
for await (const chunk of process.stdin) input += chunk;
|
|
40
|
+
let data;
|
|
41
|
+
try {
|
|
42
|
+
data = JSON.parse(input);
|
|
43
|
+
} catch {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (isSdkChildContext(data)) return;
|
|
47
|
+
const sessionId = data.session_id || data.sessionId || "unknown";
|
|
48
|
+
const project = resolveProject(data.cwd);
|
|
49
|
+
if (process.env["CLAUDE_MEMORY_BRIDGE"] === "true") try {
|
|
50
|
+
await fetch(`${REST_URL}/agentmemory/claude-bridge/sync`, {
|
|
51
|
+
method: "POST",
|
|
52
|
+
headers: authHeaders(),
|
|
53
|
+
body: JSON.stringify({}),
|
|
54
|
+
signal: AbortSignal.timeout(5e3)
|
|
55
|
+
});
|
|
56
|
+
} catch {}
|
|
57
|
+
try {
|
|
58
|
+
const res = await fetch(`${REST_URL}/agentmemory/context`, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: authHeaders(),
|
|
61
|
+
body: JSON.stringify({
|
|
62
|
+
sessionId,
|
|
63
|
+
project,
|
|
64
|
+
budget: 1500
|
|
65
|
+
}),
|
|
66
|
+
signal: AbortSignal.timeout(5e3)
|
|
67
|
+
});
|
|
68
|
+
if (res.ok) {
|
|
69
|
+
const result = await res.json();
|
|
70
|
+
if (result.context) process.stdout.write(result.context);
|
|
71
|
+
}
|
|
72
|
+
} catch {}
|
|
73
|
+
}
|
|
74
|
+
main();
|
|
75
|
+
//#endregion
|
|
76
|
+
export {};
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=pre-compact.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-compact.mjs","names":[],"sources":["../../src/hooks/_project.ts","../../src/hooks/pre-compact.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\r\nimport { basename } from \"node:path\";\r\n\r\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\r\nexport function resolveProject(cwd?: string): string {\r\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\r\n if (explicit && explicit.trim()) return explicit.trim();\r\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\r\n try {\r\n const top = execSync(\"git rev-parse --show-toplevel\", {\r\n cwd: dir,\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n timeout: 500,\r\n })\r\n .toString()\r\n .trim();\r\n if (top) return basename(top);\r\n } catch {}\r\n return basename(dir);\r\n}\r\n","#!/usr/bin/env node\r\nimport { resolveProject } from \"./_project.js\";\r\n\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n\r\n const sessionId = ((data.session_id || data.sessionId) as string) || \"unknown\";\r\n const project = resolveProject(data.cwd as string | undefined);\r\n\r\n if (process.env[\"CLAUDE_MEMORY_BRIDGE\"] === \"true\") {\r\n try {\r\n await fetch(`${REST_URL}/agentmemory/claude-bridge/sync`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({}),\r\n signal: AbortSignal.timeout(5000),\r\n });\r\n } catch {\r\n // best-effort\r\n }\r\n }\r\n\r\n try {\r\n const res = await fetch(`${REST_URL}/agentmemory/context`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({ sessionId, project, budget: 1500 }),\r\n signal: AbortSignal.timeout(5000),\r\n });\r\n\r\n if (res.ok) {\r\n const result = (await res.json()) as { context?: string };\r\n if (result.context) {\r\n process.stdout.write(result.context);\r\n }\r\n }\r\n } catch {\r\n // best effort -- don't block compaction\r\n }\r\n}\r\n\r\nmain();\r\n"],"mappings":";;;;AAIA,SAAgB,eAAe,KAAsB;CACnD,MAAM,WAAW,QAAQ,IAAI;AAC7B,KAAI,YAAY,SAAS,MAAM,CAAE,QAAO,SAAS,MAAM;CACvD,MAAM,MAAM,OAAO,IAAI,MAAM,GAAG,MAAM,QAAQ,KAAK;AACnD,KAAI;EACF,MAAM,MAAM,SAAS,iCAAiC;GACpD,KAAK;GACL,OAAO;IAAC;IAAU;IAAQ;IAAS;GACnC,SAAS;GACV,CAAC,CACC,UAAU,CACV,MAAM;AACT,MAAI,IAAK,QAAO,SAAS,IAAI;SACvB;AACR,QAAO,SAAS,IAAI;;;;ACftB,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;CAE7B,MAAM,YAAc,KAAK,cAAc,KAAK,aAAyB;CACrE,MAAM,UAAU,eAAe,KAAK,IAA0B;AAE9D,KAAI,QAAQ,IAAI,4BAA4B,OAC1C,KAAI;AACF,QAAM,MAAM,GAAG,SAAS,kCAAkC;GACxD,QAAQ;GACR,SAAS,aAAa;GACtB,MAAM,KAAK,UAAU,EAAE,CAAC;GACxB,QAAQ,YAAY,QAAQ,IAAK;GAClC,CAAC;SACI;AAKV,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,GAAG,SAAS,uBAAuB;GACzD,QAAQ;GACR,SAAS,aAAa;GACtB,MAAM,KAAK,UAAU;IAAE;IAAW;IAAS,QAAQ;IAAM,CAAC;GAC1D,QAAQ,YAAY,QAAQ,IAAK;GAClC,CAAC;AAEF,MAAI,IAAI,IAAI;GACV,MAAM,SAAU,MAAM,IAAI,MAAM;AAChC,OAAI,OAAO,QACT,SAAQ,OAAO,MAAM,OAAO,QAAQ;;SAGlC;;AAKV,MAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
//#region src/hooks/pre-tool-use.ts
|
|
3
|
+
function isSdkChildContext(payload) {
|
|
4
|
+
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
5
|
+
if (!payload || typeof payload !== "object") return false;
|
|
6
|
+
return payload.entrypoint === "sdk-ts";
|
|
7
|
+
}
|
|
8
|
+
const INJECT_CONTEXT = process.env["AGENTMEMORY_INJECT_CONTEXT"] === "true";
|
|
9
|
+
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
|
|
10
|
+
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
|
|
11
|
+
function authHeaders() {
|
|
12
|
+
const h = { "Content-Type": "application/json" };
|
|
13
|
+
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
|
|
14
|
+
return h;
|
|
15
|
+
}
|
|
16
|
+
async function main() {
|
|
17
|
+
if (!INJECT_CONTEXT) return;
|
|
18
|
+
let input = "";
|
|
19
|
+
for await (const chunk of process.stdin) input += chunk;
|
|
20
|
+
let data;
|
|
21
|
+
try {
|
|
22
|
+
data = JSON.parse(input);
|
|
23
|
+
} catch {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (isSdkChildContext(data)) return;
|
|
27
|
+
const toolName = typeof data.tool_name === "string" ? data.tool_name : typeof data.toolName === "string" ? data.toolName : void 0;
|
|
28
|
+
if (!toolName) return;
|
|
29
|
+
const normalizedToolName = toolName.toLowerCase();
|
|
30
|
+
if (![
|
|
31
|
+
"edit",
|
|
32
|
+
"write",
|
|
33
|
+
"create",
|
|
34
|
+
"read",
|
|
35
|
+
"view",
|
|
36
|
+
"glob",
|
|
37
|
+
"grep"
|
|
38
|
+
].includes(normalizedToolName)) return;
|
|
39
|
+
const rawToolInput = data.tool_input ?? data.toolArgs;
|
|
40
|
+
const toolInput = typeof rawToolInput === "object" && rawToolInput !== null && !Array.isArray(rawToolInput) ? rawToolInput : {};
|
|
41
|
+
const files = [];
|
|
42
|
+
const fileKeys = normalizedToolName === "grep" ? ["path", "file"] : [
|
|
43
|
+
"file_path",
|
|
44
|
+
"path",
|
|
45
|
+
"file",
|
|
46
|
+
"pattern"
|
|
47
|
+
];
|
|
48
|
+
for (const key of fileKeys) {
|
|
49
|
+
const val = toolInput[key];
|
|
50
|
+
if (typeof val === "string" && val.length > 0) files.push(val);
|
|
51
|
+
}
|
|
52
|
+
if (files.length === 0) return;
|
|
53
|
+
const terms = [];
|
|
54
|
+
if (normalizedToolName === "grep" || normalizedToolName === "glob") {
|
|
55
|
+
const pattern = toolInput["pattern"];
|
|
56
|
+
if (typeof pattern === "string" && pattern.length > 0) terms.push(pattern);
|
|
57
|
+
}
|
|
58
|
+
const rawSessionId = data.session_id || data.sessionId;
|
|
59
|
+
const sessionId = typeof rawSessionId === "string" && rawSessionId.length > 0 ? rawSessionId : "unknown";
|
|
60
|
+
const project = typeof data.project === "string" && data.project.trim().length > 0 ? data.project.trim() : void 0;
|
|
61
|
+
try {
|
|
62
|
+
const res = await fetch(`${REST_URL}/agentmemory/enrich`, {
|
|
63
|
+
method: "POST",
|
|
64
|
+
headers: authHeaders(),
|
|
65
|
+
body: JSON.stringify({
|
|
66
|
+
sessionId,
|
|
67
|
+
files,
|
|
68
|
+
terms,
|
|
69
|
+
toolName,
|
|
70
|
+
...project !== void 0 && { project }
|
|
71
|
+
}),
|
|
72
|
+
signal: AbortSignal.timeout(2e3)
|
|
73
|
+
});
|
|
74
|
+
if (res.ok) {
|
|
75
|
+
const result = await res.json();
|
|
76
|
+
if (result.context) process.stdout.write(result.context);
|
|
77
|
+
}
|
|
78
|
+
} catch {}
|
|
79
|
+
}
|
|
80
|
+
main();
|
|
81
|
+
//#endregion
|
|
82
|
+
export {};
|
|
83
|
+
|
|
84
|
+
//# sourceMappingURL=pre-tool-use.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-tool-use.mjs","names":[],"sources":["../../src/hooks/pre-tool-use.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\n// Pre-tool-use enrichment hook.\r\n//\r\n// THIS HOOK IS A NO-OP BY DEFAULT AS OF 0.8.10 (#143). Previously it\r\n// fired /agentmemory/enrich on every Edit/Write/Read/Glob/Grep tool call\r\n// and wrote up to 4000 chars of context to stdout. Claude Code reads\r\n// PreToolUse stdout and prepends it to the model's next turn, which meant\r\n// agentmemory was silently injecting ~1000 tokens into every tool turn\r\n// via the user's Claude Code session. On Claude Pro that burned entire\r\n// allocations in a handful of messages (@adrianricardo, #143).\r\n//\r\n// Users who explicitly want pre-tool enrichment opt in with:\r\n// AGENTMEMORY_INJECT_CONTEXT=true in ~/.agentmemory/.env\r\n// and restart Claude Code. Expect your session input token count to grow\r\n// proportionally with the number of file-touching tool calls per turn.\r\nconst INJECT_CONTEXT = process.env[\"AGENTMEMORY_INJECT_CONTEXT\"] === \"true\";\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n // Default off: exit immediately so we don't even open stdin. This keeps\r\n // Claude Code's tool-call hot path as cheap as possible.\r\n if (!INJECT_CONTEXT) return;\r\n\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n\r\n const toolName =\r\n typeof data.tool_name === \"string\"\r\n ? data.tool_name\r\n : typeof data.toolName === \"string\"\r\n ? data.toolName\r\n : undefined;\r\n if (!toolName) return;\r\n\r\n const normalizedToolName = toolName.toLowerCase();\r\n const fileTools = [\"edit\", \"write\", \"create\", \"read\", \"view\", \"glob\", \"grep\"];\r\n if (!fileTools.includes(normalizedToolName)) return;\r\n\r\n const rawToolInput = data.tool_input ?? data.toolArgs;\r\n const toolInput =\r\n typeof rawToolInput === \"object\" &&\r\n rawToolInput !== null &&\r\n !Array.isArray(rawToolInput)\r\n ? (rawToolInput as Record<string, unknown>)\r\n : {};\r\n const files: string[] = [];\r\n const fileKeys =\r\n normalizedToolName === \"grep\"\r\n ? [\"path\", \"file\"]\r\n : [\"file_path\", \"path\", \"file\", \"pattern\"];\r\n for (const key of fileKeys) {\r\n const val = toolInput[key];\r\n if (typeof val === \"string\" && val.length > 0) files.push(val);\r\n }\r\n if (files.length === 0) return;\r\n\r\n const terms: string[] = [];\r\n if (normalizedToolName === \"grep\" || normalizedToolName === \"glob\") {\r\n const pattern = toolInput[\"pattern\"];\r\n if (typeof pattern === \"string\" && pattern.length > 0) {\r\n terms.push(pattern);\r\n }\r\n }\r\n\r\n const rawSessionId = data.session_id || data.sessionId;\r\n const sessionId =\r\n typeof rawSessionId === \"string\" && rawSessionId.length > 0\r\n ? rawSessionId\r\n : \"unknown\";\r\n const project =\r\n typeof data.project === \"string\" && data.project.trim().length > 0\r\n ? data.project.trim()\r\n : undefined;\r\n\r\n try {\r\n const res = await fetch(`${REST_URL}/agentmemory/enrich`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({\r\n sessionId,\r\n files,\r\n terms,\r\n toolName,\r\n ...(project !== undefined && { project }),\r\n }),\r\n signal: AbortSignal.timeout(2000),\r\n });\r\n\r\n if (res.ok) {\r\n const result = (await res.json()) as { context?: string };\r\n if (result.context) {\r\n process.stdout.write(result.context);\r\n }\r\n }\r\n } catch {\r\n // don't block tool execution\r\n }\r\n}\r\n\r\nmain();\r\n"],"mappings":";;AAEA,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAiB9D,MAAM,iBAAiB,QAAQ,IAAI,kCAAkC;AAErE,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;AAGpB,KAAI,CAAC,eAAgB;CAErB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;CAE7B,MAAM,WACJ,OAAO,KAAK,cAAc,WACtB,KAAK,YACL,OAAO,KAAK,aAAa,WACvB,KAAK,WACL,KAAA;AACR,KAAI,CAAC,SAAU;CAEf,MAAM,qBAAqB,SAAS,aAAa;AAEjD,KAAI,CAAC;EADc;EAAQ;EAAS;EAAU;EAAQ;EAAQ;EAAQ;EACxD,CAAC,SAAS,mBAAmB,CAAE;CAE7C,MAAM,eAAe,KAAK,cAAc,KAAK;CAC7C,MAAM,YACJ,OAAO,iBAAiB,YACxB,iBAAiB,QACjB,CAAC,MAAM,QAAQ,aAAa,GACvB,eACD,EAAE;CACR,MAAM,QAAkB,EAAE;CAC1B,MAAM,WACJ,uBAAuB,SACnB,CAAC,QAAQ,OAAO,GAChB;EAAC;EAAa;EAAQ;EAAQ;EAAU;AAC9C,MAAK,MAAM,OAAO,UAAU;EAC1B,MAAM,MAAM,UAAU;AACtB,MAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,EAAG,OAAM,KAAK,IAAI;;AAEhE,KAAI,MAAM,WAAW,EAAG;CAExB,MAAM,QAAkB,EAAE;AAC1B,KAAI,uBAAuB,UAAU,uBAAuB,QAAQ;EAClE,MAAM,UAAU,UAAU;AAC1B,MAAI,OAAO,YAAY,YAAY,QAAQ,SAAS,EAClD,OAAM,KAAK,QAAQ;;CAIvB,MAAM,eAAe,KAAK,cAAc,KAAK;CAC7C,MAAM,YACJ,OAAO,iBAAiB,YAAY,aAAa,SAAS,IACtD,eACA;CACN,MAAM,UACJ,OAAO,KAAK,YAAY,YAAY,KAAK,QAAQ,MAAM,CAAC,SAAS,IAC7D,KAAK,QAAQ,MAAM,GACnB,KAAA;AAEN,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,GAAG,SAAS,sBAAsB;GACxD,QAAQ;GACR,SAAS,aAAa;GACtB,MAAM,KAAK,UAAU;IACnB;IACA;IACA;IACA;IACA,GAAI,YAAY,KAAA,KAAa,EAAE,SAAS;IACzC,CAAC;GACF,QAAQ,YAAY,QAAQ,IAAK;GAClC,CAAC;AAEF,MAAI,IAAI,IAAI;GACV,MAAM,SAAU,MAAM,IAAI,MAAM;AAChC,OAAI,OAAO,QACT,SAAQ,OAAO,MAAM,OAAO,QAAQ;;SAGlC;;AAKV,MAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
//#region src/hooks/_project.ts
|
|
5
|
+
function resolveProject(cwd) {
|
|
6
|
+
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
|
|
7
|
+
if (explicit && explicit.trim()) return explicit.trim();
|
|
8
|
+
const dir = cwd && cwd.trim() ? cwd : process.cwd();
|
|
9
|
+
try {
|
|
10
|
+
const top = execSync("git rev-parse --show-toplevel", {
|
|
11
|
+
cwd: dir,
|
|
12
|
+
stdio: [
|
|
13
|
+
"ignore",
|
|
14
|
+
"pipe",
|
|
15
|
+
"ignore"
|
|
16
|
+
],
|
|
17
|
+
timeout: 500
|
|
18
|
+
}).toString().trim();
|
|
19
|
+
if (top) return basename(top);
|
|
20
|
+
} catch {}
|
|
21
|
+
return basename(dir);
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/hooks/prompt-submit.ts
|
|
25
|
+
function isSdkChildContext(payload) {
|
|
26
|
+
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
27
|
+
if (!payload || typeof payload !== "object") return false;
|
|
28
|
+
return payload.entrypoint === "sdk-ts";
|
|
29
|
+
}
|
|
30
|
+
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
|
|
31
|
+
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
|
|
32
|
+
function authHeaders() {
|
|
33
|
+
const h = { "Content-Type": "application/json" };
|
|
34
|
+
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
|
|
35
|
+
return h;
|
|
36
|
+
}
|
|
37
|
+
async function main() {
|
|
38
|
+
let input = "";
|
|
39
|
+
for await (const chunk of process.stdin) input += chunk;
|
|
40
|
+
let data;
|
|
41
|
+
try {
|
|
42
|
+
data = JSON.parse(input);
|
|
43
|
+
} catch {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (isSdkChildContext(data)) return;
|
|
47
|
+
const sessionId = data.session_id || data.sessionId || "unknown";
|
|
48
|
+
fetch(`${REST_URL}/agentmemory/observe`, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: authHeaders(),
|
|
51
|
+
body: JSON.stringify({
|
|
52
|
+
hookType: "prompt_submit",
|
|
53
|
+
sessionId,
|
|
54
|
+
project: resolveProject(data.cwd),
|
|
55
|
+
cwd: data.cwd || process.cwd(),
|
|
56
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57
|
+
data: { prompt: data.prompt ?? data.userPrompt }
|
|
58
|
+
}),
|
|
59
|
+
signal: AbortSignal.timeout(3e3)
|
|
60
|
+
}).catch(() => {});
|
|
61
|
+
setTimeout(() => process.exit(0), 500).unref();
|
|
62
|
+
}
|
|
63
|
+
main();
|
|
64
|
+
//#endregion
|
|
65
|
+
export {};
|
|
66
|
+
|
|
67
|
+
//# sourceMappingURL=prompt-submit.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-submit.mjs","names":[],"sources":["../../src/hooks/_project.ts","../../src/hooks/prompt-submit.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\r\nimport { basename } from \"node:path\";\r\n\r\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\r\nexport function resolveProject(cwd?: string): string {\r\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\r\n if (explicit && explicit.trim()) return explicit.trim();\r\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\r\n try {\r\n const top = execSync(\"git rev-parse --show-toplevel\", {\r\n cwd: dir,\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n timeout: 500,\r\n })\r\n .toString()\r\n .trim();\r\n if (top) return basename(top);\r\n } catch {}\r\n return basename(dir);\r\n}\r\n","#!/usr/bin/env node\r\nimport { resolveProject } from \"./_project.js\";\r\n\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n\r\n const sessionId = ((data.session_id || data.sessionId) as string) || \"unknown\";\r\n\r\n fetch(`${REST_URL}/agentmemory/observe`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({\r\n hookType: \"prompt_submit\",\r\n sessionId,\r\n project: resolveProject(data.cwd as string | undefined),\r\n cwd: (data.cwd as string | undefined) || process.cwd(),\r\n timestamp: new Date().toISOString(),\r\n data: { prompt: data.prompt ?? data.userPrompt },\r\n }),\r\n signal: AbortSignal.timeout(3000),\r\n }).catch(() => {});\r\n setTimeout(() => process.exit(0), 500).unref();\r\n}\r\n\r\nmain();\r\n"],"mappings":";;;;AAIA,SAAgB,eAAe,KAAsB;CACnD,MAAM,WAAW,QAAQ,IAAI;AAC7B,KAAI,YAAY,SAAS,MAAM,CAAE,QAAO,SAAS,MAAM;CACvD,MAAM,MAAM,OAAO,IAAI,MAAM,GAAG,MAAM,QAAQ,KAAK;AACnD,KAAI;EACF,MAAM,MAAM,SAAS,iCAAiC;GACpD,KAAK;GACL,OAAO;IAAC;IAAU;IAAQ;IAAS;GACnC,SAAS;GACV,CAAC,CACC,UAAU,CACV,MAAM;AACT,MAAI,IAAK,QAAO,SAAS,IAAI;SACvB;AACR,QAAO,SAAS,IAAI;;;;ACftB,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;CAE7B,MAAM,YAAc,KAAK,cAAc,KAAK,aAAyB;AAErE,OAAM,GAAG,SAAS,uBAAuB;EACvC,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU;GACnB,UAAU;GACV;GACA,SAAS,eAAe,KAAK,IAA0B;GACvD,KAAM,KAAK,OAA8B,QAAQ,KAAK;GACtD,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,MAAM,EAAE,QAAQ,KAAK,UAAU,KAAK,YAAY;GACjD,CAAC;EACF,QAAQ,YAAY,QAAQ,IAAK;EAClC,CAAC,CAAC,YAAY,GAAG;AAClB,kBAAiB,QAAQ,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO;;AAGhD,MAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|