@agentmemory/agentmemory 0.9.21 → 0.9.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +7 -2
- package/README.md +288 -33
- package/dist/cli.d.mts +5 -1
- package/dist/cli.d.mts.map +1 -0
- package/dist/cli.mjs +128 -703
- package/dist/cli.mjs.map +1 -1
- package/dist/connect-Cf9bmBqO.mjs +1020 -0
- package/dist/connect-Cf9bmBqO.mjs.map +1 -0
- package/dist/hooks/notification.mjs +46 -21
- package/dist/hooks/notification.mjs.map +1 -1
- package/dist/hooks/post-tool-failure.mjs +47 -21
- package/dist/hooks/post-tool-failure.mjs.map +1 -1
- package/dist/hooks/post-tool-use.mjs +57 -22
- package/dist/hooks/post-tool-use.mjs.map +1 -1
- package/dist/hooks/pre-compact.mjs +26 -2
- package/dist/hooks/pre-compact.mjs.map +1 -1
- package/dist/hooks/pre-tool-use.mjs +19 -12
- package/dist/hooks/pre-tool-use.mjs.map +1 -1
- package/dist/hooks/prompt-submit.mjs +39 -16
- package/dist/hooks/prompt-submit.mjs.map +1 -1
- package/dist/hooks/session-end.mjs +26 -33
- package/dist/hooks/session-end.mjs.map +1 -1
- package/dist/hooks/session-start.mjs +28 -3
- package/dist/hooks/session-start.mjs.map +1 -1
- package/dist/hooks/stop.mjs +14 -9
- package/dist/hooks/stop.mjs.map +1 -1
- package/dist/hooks/subagent-start.mjs +31 -4
- package/dist/hooks/subagent-start.mjs.map +1 -1
- package/dist/hooks/subagent-stop.mjs +45 -20
- package/dist/hooks/subagent-stop.mjs.map +1 -1
- package/dist/hooks/task-completed.mjs +44 -21
- package/dist/hooks/task-completed.mjs.map +1 -1
- package/dist/iii-config.docker.yaml +3 -2
- package/dist/iii-config.yaml +11 -2
- package/dist/{image-refs-R3tin9MR.mjs → image-refs-CJS5B9Gq.mjs} +2 -2
- package/dist/{image-refs-R3tin9MR.mjs.map → image-refs-CJS5B9Gq.mjs.map} +1 -1
- package/dist/{image-store-DyrKZKqZ.mjs → image-store-CdE0amb1.mjs} +1 -1
- package/dist/index.mjs +866 -380
- package/dist/index.mjs.map +1 -1
- package/dist/logger-xlVlvCWX.mjs +43 -0
- package/dist/logger-xlVlvCWX.mjs.map +1 -0
- package/dist/schema-BkALl7Z_.mjs +74 -0
- package/dist/schema-BkALl7Z_.mjs.map +1 -0
- package/dist/{src-D5arboxc.mjs → src-DvS3bhMe.mjs} +844 -395
- package/dist/src-DvS3bhMe.mjs.map +1 -0
- package/dist/{standalone-C7BgzzIN.mjs → standalone-DHQcPX_g.mjs} +107 -14
- package/dist/standalone-DHQcPX_g.mjs.map +1 -0
- package/dist/standalone.d.mts.map +1 -1
- package/dist/standalone.mjs +108 -12
- package/dist/standalone.mjs.map +1 -1
- package/dist/{tools-registry-CRTWUFw9.mjs → tools-registry-DJizX9Az.mjs} +51 -12
- package/dist/tools-registry-DJizX9Az.mjs.map +1 -0
- package/dist/version-BPfyI4Kc.mjs +6 -0
- package/dist/version-BPfyI4Kc.mjs.map +1 -0
- package/dist/viewer/index.html +85 -10
- package/iii-config.docker.yaml +3 -2
- package/iii-config.yaml +11 -2
- package/package.json +6 -4
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.codex-plugin/plugin.json +2 -2
- package/plugin/.mcp.copilot.json +15 -0
- package/plugin/.mcp.json +3 -2
- package/plugin/hooks/hooks.copilot.json +72 -0
- package/plugin/opencode/agentmemory-capture.ts +34 -9
- package/plugin/plugin.json +15 -0
- package/plugin/scripts/diagnostics.d.mts +17 -0
- package/plugin/scripts/diagnostics.d.mts.map +1 -0
- package/plugin/scripts/diagnostics.mjs.map +1 -0
- package/plugin/scripts/notification.mjs +46 -21
- package/plugin/scripts/notification.mjs.map +1 -1
- package/plugin/scripts/post-tool-failure.mjs +47 -21
- package/plugin/scripts/post-tool-failure.mjs.map +1 -1
- package/plugin/scripts/post-tool-use.mjs +57 -22
- package/plugin/scripts/post-tool-use.mjs.map +1 -1
- package/plugin/scripts/pre-compact.mjs +26 -2
- package/plugin/scripts/pre-compact.mjs.map +1 -1
- package/plugin/scripts/pre-tool-use.mjs +19 -12
- package/plugin/scripts/pre-tool-use.mjs.map +1 -1
- package/plugin/scripts/prompt-submit.mjs +39 -16
- package/plugin/scripts/prompt-submit.mjs.map +1 -1
- package/plugin/scripts/session-end.mjs +26 -33
- package/plugin/scripts/session-end.mjs.map +1 -1
- package/plugin/scripts/session-start.mjs +28 -3
- package/plugin/scripts/session-start.mjs.map +1 -1
- package/plugin/scripts/stop.mjs +14 -9
- package/plugin/scripts/stop.mjs.map +1 -1
- package/plugin/scripts/subagent-start.mjs +31 -4
- package/plugin/scripts/subagent-start.mjs.map +1 -1
- package/plugin/scripts/subagent-stop.mjs +45 -20
- package/plugin/scripts/subagent-stop.mjs.map +1 -1
- package/plugin/scripts/task-completed.mjs +44 -21
- package/plugin/scripts/task-completed.mjs.map +1 -1
- package/dist/src-D5arboxc.mjs.map +0 -1
- package/dist/standalone-C7BgzzIN.mjs.map +0 -1
- package/dist/tools-registry-CRTWUFw9.mjs.map +0 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"hooks": {
|
|
4
|
+
"sessionStart": [
|
|
5
|
+
{
|
|
6
|
+
"type": "command",
|
|
7
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/session-start.mjs"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"userPromptSubmitted": [
|
|
11
|
+
{
|
|
12
|
+
"type": "command",
|
|
13
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/prompt-submit.mjs"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"preToolUse": [
|
|
17
|
+
{
|
|
18
|
+
"type": "command",
|
|
19
|
+
"matcher": "edit|write|create|read|view|glob|grep",
|
|
20
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/pre-tool-use.mjs"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"postToolUse": [
|
|
24
|
+
{
|
|
25
|
+
"type": "command",
|
|
26
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/post-tool-use.mjs"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"postToolUseFailure": [
|
|
30
|
+
{
|
|
31
|
+
"type": "command",
|
|
32
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/post-tool-failure.mjs"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"preCompact": [
|
|
36
|
+
{
|
|
37
|
+
"type": "command",
|
|
38
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/pre-compact.mjs"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"agentStop": [
|
|
42
|
+
{
|
|
43
|
+
"type": "command",
|
|
44
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/stop.mjs"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"sessionEnd": [
|
|
48
|
+
{
|
|
49
|
+
"type": "command",
|
|
50
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/session-end.mjs"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"subagentStart": [
|
|
54
|
+
{
|
|
55
|
+
"type": "command",
|
|
56
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/subagent-start.mjs"
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"subagentStop": [
|
|
60
|
+
{
|
|
61
|
+
"type": "command",
|
|
62
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/subagent-stop.mjs"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"notification": [
|
|
66
|
+
{
|
|
67
|
+
"type": "command",
|
|
68
|
+
"command": "node ${COPILOT_PLUGIN_ROOT}/scripts/notification.mjs"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -64,6 +64,12 @@ const stashedFiles = new Map<string, Set<string>>();
|
|
|
64
64
|
const seenSubtaskIds = new Map<string, Set<string>>();
|
|
65
65
|
const seenToolCallIds = new Map<string, Set<string>>();
|
|
66
66
|
const contextInjectedSessions = new Set<string>();
|
|
67
|
+
// cache the context returned by POST /session/start so the chat
|
|
68
|
+
// system-transform hook can inject it without a second /context fetch.
|
|
69
|
+
// Auto-injection now happens at session.created (immediately) AND at
|
|
70
|
+
// the first prompt_submit (fallback for older OpenCode builds that
|
|
71
|
+
// don't implement experimental.chat.system.transform).
|
|
72
|
+
const startContextCache = new Map<string, string>();
|
|
67
73
|
|
|
68
74
|
function stashFor(sid: string): Set<string> {
|
|
69
75
|
let s = stashedFiles.get(sid);
|
|
@@ -178,16 +184,26 @@ export const AgentmemoryCapturePlugin: Plugin = async (ctx) => {
|
|
|
178
184
|
seenSubtaskIds.delete(activeSessionId);
|
|
179
185
|
seenToolCallIds.delete(activeSessionId);
|
|
180
186
|
contextInjectedSessions.delete(activeSessionId);
|
|
181
|
-
|
|
182
|
-
|
|
187
|
+
// Snapshot the session id locally — `activeSessionId` is mutable
|
|
188
|
+
// and another `session.created` event during the await could
|
|
189
|
+
// rebind it, causing context to be cached against the wrong key.
|
|
190
|
+
const sessionId = activeSessionId;
|
|
191
|
+
const startResult = await postJson("/session/start", {
|
|
192
|
+
sessionId,
|
|
183
193
|
title: info?.title ?? null,
|
|
184
194
|
parentID: info?.parentID ?? null,
|
|
185
195
|
version: info?.version ?? null,
|
|
186
196
|
project: projectPath,
|
|
187
197
|
cwd: projectPath,
|
|
188
198
|
});
|
|
189
|
-
|
|
190
|
-
|
|
199
|
+
// cache the context returned at session/start so the
|
|
200
|
+
// chat.system.transform hook injects it without a second fetch.
|
|
201
|
+
const startCtx = (startResult as any)?.context;
|
|
202
|
+
if (typeof startCtx === "string" && startCtx.length > 0) {
|
|
203
|
+
startContextCache.set(sessionId, startCtx);
|
|
204
|
+
}
|
|
205
|
+
if (pendingConfig) {
|
|
206
|
+
await observe(sessionId, "config_loaded", pendingConfig);
|
|
191
207
|
pendingConfig = null;
|
|
192
208
|
}
|
|
193
209
|
}
|
|
@@ -257,6 +273,7 @@ export const AgentmemoryCapturePlugin: Plugin = async (ctx) => {
|
|
|
257
273
|
post("/consolidate-pipeline", { tier: "all", force: true }, 30000);
|
|
258
274
|
if (sid === activeSessionId) activeSessionId = null;
|
|
259
275
|
stashedFiles.delete(sid);
|
|
276
|
+
startContextCache.delete(sid);
|
|
260
277
|
seenSubtaskIds.delete(sid);
|
|
261
278
|
seenToolCallIds.delete(sid);
|
|
262
279
|
contextInjectedSessions.delete(sid);
|
|
@@ -588,11 +605,19 @@ export const AgentmemoryCapturePlugin: Plugin = async (ctx) => {
|
|
|
588
605
|
if (!contextInjectedSessions.has(sid)) {
|
|
589
606
|
if (!Array.isArray(output.system)) return;
|
|
590
607
|
output.system.push(AGENTMEMORY_INSTRUCTIONS);
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
608
|
+
// prefer the context already fetched at session.created;
|
|
609
|
+
// fall back to a fresh /context call if the cache missed (e.g.
|
|
610
|
+
// session resumed across plugin reloads).
|
|
611
|
+
let ctx = startContextCache.get(sid);
|
|
612
|
+
if (typeof ctx !== "string" || ctx.length === 0) {
|
|
613
|
+
const result = await postJson("/context", {
|
|
614
|
+
sessionId: sid,
|
|
615
|
+
project: projectPath,
|
|
616
|
+
});
|
|
617
|
+
ctx = (result as any)?.context;
|
|
618
|
+
} else {
|
|
619
|
+
startContextCache.delete(sid);
|
|
620
|
+
}
|
|
596
621
|
if (typeof ctx === "string" && ctx.length > 0) {
|
|
597
622
|
output.system.push(ctx);
|
|
598
623
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentmemory",
|
|
3
|
+
"version": "0.9.23",
|
|
4
|
+
"description": "Persistent memory for AI coding agents -- captures tool usage, compresses via LLM, injects context into future sessions. 12 hooks, 53 MCP tools, 8 skills, real-time viewer.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Rohit Ghumare",
|
|
7
|
+
"url": "https://github.com/rohitg00"
|
|
8
|
+
},
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
|
+
"homepage": "https://github.com/rohitg00/agentmemory",
|
|
11
|
+
"repository": "https://github.com/rohitg00/agentmemory",
|
|
12
|
+
"skills": "skills/",
|
|
13
|
+
"mcpServers": ".mcp.copilot.json",
|
|
14
|
+
"hooks": "hooks/hooks.copilot.json"
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ISdk } from "iii-sdk";
|
|
2
|
+
|
|
3
|
+
//#region src/state/kv.d.ts
|
|
4
|
+
declare class StateKV {
|
|
5
|
+
private sdk;
|
|
6
|
+
constructor(sdk: ISdk);
|
|
7
|
+
get<T = unknown>(scope: string, key: string): Promise<T | null>;
|
|
8
|
+
set<T = unknown>(scope: string, key: string, data: T): Promise<T>;
|
|
9
|
+
delete(scope: string, key: string): Promise<void>;
|
|
10
|
+
list<T = unknown>(scope: string): Promise<T[]>;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/functions/diagnostics.d.ts
|
|
14
|
+
declare function registerDiagnosticsFunction(sdk: ISdk, kv: StateKV): void;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { registerDiagnosticsFunction };
|
|
17
|
+
//# sourceMappingURL=diagnostics.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.mts","names":[],"sources":["../../src/state/kv.ts","../../src/functions/diagnostics.ts"],"mappings":";;;cAEa,OAAA;EAAA,QACS,GAAA;cAAA,GAAA,EAAK,IAAA;EAEnB,GAAA,aAAA,CAAiB,KAAA,UAAe,GAAA,WAAc,OAAA,CAAQ,CAAA;EAOtD,GAAA,aAAA,CAAiB,KAAA,UAAe,GAAA,UAAa,IAAA,EAAM,CAAA,GAAI,OAAA,CAAQ,CAAA;EAO/D,MAAA,CAAO,KAAA,UAAe,GAAA,WAAc,OAAA;EAOpC,IAAA,aAAA,CAAkB,KAAA,WAAgB,OAAA,CAAQ,CAAA;AAAA;;;iBC0BlC,2BAAA,CAA4B,GAAA,EAAK,IAAA,EAAM,EAAA,EAAI,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.mjs","names":[],"sources":["../../src/state/schema.ts","../../src/state/keyed-mutex.ts","../../src/functions/diagnostics.ts"],"sourcesContent":["export const KV = {\n sessions: \"mem:sessions\",\n observations: (sessionId: string) => `mem:obs:${sessionId}`,\n memories: \"mem:memories\",\n summaries: \"mem:summaries\",\n config: \"mem:config\",\n metrics: \"mem:metrics\",\n health: \"mem:health\",\n embeddings: (obsId: string) => `mem:emb:${obsId}`,\n bm25Index: \"mem:index:bm25\",\n relations: \"mem:relations\",\n profiles: \"mem:profiles\",\n claudeBridge: \"mem:claude-bridge\",\n graphNodes: \"mem:graph:nodes\",\n graphEdges: \"mem:graph:edges\",\n semantic: \"mem:semantic\",\n procedural: \"mem:procedural\",\n teamShared: (teamId: string) => `mem:team:${teamId}:shared`,\n teamUsers: (teamId: string, userId: string) =>\n `mem:team:${teamId}:users:${userId}`,\n teamProfile: (teamId: string) => `mem:team:${teamId}:profile`,\n audit: \"mem:audit\",\n actions: \"mem:actions\",\n actionEdges: \"mem:action-edges\",\n leases: \"mem:leases\",\n routines: \"mem:routines\",\n routineRuns: \"mem:routine-runs\",\n signals: \"mem:signals\",\n checkpoints: \"mem:checkpoints\",\n mesh: \"mem:mesh\",\n sketches: \"mem:sketches\",\n facets: \"mem:facets\",\n sentinels: \"mem:sentinels\",\n crystals: \"mem:crystals\",\n} as const;\n\nexport const STREAM = {\n name: \"mem-live\",\n group: (sessionId: string) => sessionId,\n viewerGroup: \"viewer\",\n} as const;\n\nexport function generateId(prefix: string): string {\n const ts = Date.now().toString(36);\n const rand = crypto.randomUUID().replace(/-/g, \"\").slice(0, 12);\n return `${prefix}_${ts}_${rand}`;\n}\n\nexport function fingerprintId(prefix: string, content: string): string {\n const crypto = require(\"node:crypto\") as typeof import(\"node:crypto\");\n const hash = crypto.createHash(\"sha256\").update(content).digest(\"hex\");\n return `${prefix}_${hash.slice(0, 16)}`;\n}\n\nexport function jaccardSimilarity(a: string, b: string): number {\n const setA = new Set(a.split(/\\s+/).filter((t) => t.length > 2));\n const setB = new Set(b.split(/\\s+/).filter((t) => t.length > 2));\n if (setA.size === 0 && setB.size === 0) return 1;\n if (setA.size === 0 || setB.size === 0) return 0;\n let intersection = 0;\n for (const word of setA) {\n if (setB.has(word)) intersection++;\n }\n return intersection / (setA.size + setB.size - intersection);\n}\n","const locks = new Map<string, Promise<void>>();\n\nexport function withKeyedLock<T>(\n key: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const prev = locks.get(key) ?? Promise.resolve();\n const next = prev.then(fn, fn);\n const cleanup = next.then(\n () => {},\n () => {},\n );\n locks.set(key, cleanup);\n cleanup.then(() => {\n if (locks.get(key) === cleanup) locks.delete(key);\n });\n return next;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport type {\n Action,\n ActionEdge,\n Lease,\n Checkpoint,\n Signal,\n Sketch,\n MeshPeer,\n Session,\n Memory,\n} from \"../types.js\";\n\ninterface Sentinel {\n id: string;\n name: string;\n type: \"webhook\" | \"timer\" | \"threshold\" | \"pattern\" | \"approval\" | \"custom\";\n status: \"watching\" | \"triggered\" | \"cancelled\" | \"expired\";\n config: Record<string, unknown>;\n result?: unknown;\n createdAt: string;\n triggeredAt?: string;\n expiresAt?: string;\n linkedActionIds: string[];\n escalatedAt?: string;\n}\n\ninterface DiagnosticCheck {\n name: string;\n category: string;\n status: \"pass\" | \"warn\" | \"fail\";\n message: string;\n fixable: boolean;\n}\n\nconst ALL_CATEGORIES = [\n \"actions\",\n \"leases\",\n \"sentinels\",\n \"sketches\",\n \"signals\",\n \"sessions\",\n \"memories\",\n \"mesh\",\n];\n\nconst TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1000;\nconst ONE_HOUR_MS = 60 * 60 * 1000;\n\nexport function registerDiagnosticsFunction(sdk: ISdk, kv: StateKV): void {\n sdk.registerFunction(\n { id: \"mem::diagnose\" },\n async (data: { categories?: string[] }) => {\n const categories = data.categories && data.categories.length > 0\n ? data.categories.filter((c) => ALL_CATEGORIES.includes(c))\n : ALL_CATEGORIES;\n\n const checks: DiagnosticCheck[] = [];\n const now = Date.now();\n\n if (categories.includes(\"actions\")) {\n const actions = await kv.list<Action>(KV.actions);\n const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n const leases = await kv.list<Lease>(KV.leases);\n const actionMap = new Map(actions.map((a) => [a.id, a]));\n\n for (const action of actions) {\n if (action.status === \"active\") {\n const hasActiveLease = leases.some(\n (l) =>\n l.actionId === action.id &&\n l.status === \"active\" &&\n new Date(l.expiresAt).getTime() > now,\n );\n if (!hasActiveLease) {\n checks.push({\n name: `active-no-lease:${action.id}`,\n category: \"actions\",\n status: \"warn\",\n message: `Action \"${action.title}\" is active but has no active lease`,\n fixable: false,\n });\n }\n }\n\n if (action.status === \"blocked\") {\n const deps = allEdges.filter(\n (e) => e.sourceActionId === action.id && e.type === \"requires\",\n );\n if (deps.length > 0) {\n const allDone = deps.every((d) => {\n const target = actionMap.get(d.targetActionId);\n return target && target.status === \"done\";\n });\n if (allDone) {\n checks.push({\n name: `blocked-deps-done:${action.id}`,\n category: \"actions\",\n status: \"fail\",\n message: `Action \"${action.title}\" is blocked but all dependencies are done`,\n fixable: true,\n });\n }\n }\n }\n\n if (action.status === \"pending\") {\n const deps = allEdges.filter(\n (e) => e.sourceActionId === action.id && e.type === \"requires\",\n );\n if (deps.length > 0) {\n const hasUnsatisfied = deps.some((d) => {\n const target = actionMap.get(d.targetActionId);\n return !target || target.status !== \"done\";\n });\n if (hasUnsatisfied) {\n checks.push({\n name: `pending-unsatisfied-deps:${action.id}`,\n category: \"actions\",\n status: \"fail\",\n message: `Action \"${action.title}\" is pending but has unsatisfied dependencies`,\n fixable: true,\n });\n }\n }\n }\n }\n\n if (\n !checks.some((c) => c.category === \"actions\" && c.status !== \"pass\")\n ) {\n checks.push({\n name: \"actions-ok\",\n category: \"actions\",\n status: \"pass\",\n message: `All ${actions.length} actions are consistent`,\n fixable: false,\n });\n }\n }\n\n if (categories.includes(\"leases\")) {\n const leases = await kv.list<Lease>(KV.leases);\n const actions = await kv.list<Action>(KV.actions);\n const actionIds = new Set(actions.map((a) => a.id));\n let leaseIssues = 0;\n\n for (const lease of leases) {\n if (\n lease.status === \"active\" &&\n new Date(lease.expiresAt).getTime() <= now\n ) {\n checks.push({\n name: `expired-lease:${lease.id}`,\n category: \"leases\",\n status: \"fail\",\n message: `Lease ${lease.id} for action ${lease.actionId} expired at ${lease.expiresAt}`,\n fixable: true,\n });\n leaseIssues++;\n }\n\n if (!actionIds.has(lease.actionId)) {\n checks.push({\n name: `orphaned-lease:${lease.id}`,\n category: \"leases\",\n status: \"fail\",\n message: `Lease ${lease.id} references non-existent action ${lease.actionId}`,\n fixable: true,\n });\n leaseIssues++;\n }\n }\n\n if (leaseIssues === 0) {\n checks.push({\n name: \"leases-ok\",\n category: \"leases\",\n status: \"pass\",\n message: `All ${leases.length} leases are healthy`,\n fixable: false,\n });\n }\n }\n\n if (categories.includes(\"sentinels\")) {\n const sentinels = await kv.list<Sentinel>(KV.sentinels);\n const actions = await kv.list<Action>(KV.actions);\n const actionIds = new Set(actions.map((a) => a.id));\n let sentinelIssues = 0;\n\n for (const sentinel of sentinels) {\n if (\n sentinel.status === \"watching\" &&\n sentinel.expiresAt &&\n new Date(sentinel.expiresAt).getTime() <= now\n ) {\n checks.push({\n name: `expired-sentinel:${sentinel.id}`,\n category: \"sentinels\",\n status: \"fail\",\n message: `Sentinel \"${sentinel.name}\" expired at ${sentinel.expiresAt}`,\n fixable: true,\n });\n sentinelIssues++;\n }\n\n for (const actionId of sentinel.linkedActionIds) {\n if (!actionIds.has(actionId)) {\n checks.push({\n name: `sentinel-missing-action:${sentinel.id}:${actionId}`,\n category: \"sentinels\",\n status: \"warn\",\n message: `Sentinel \"${sentinel.name}\" references non-existent action ${actionId}`,\n fixable: false,\n });\n sentinelIssues++;\n }\n }\n }\n\n if (sentinelIssues === 0) {\n checks.push({\n name: \"sentinels-ok\",\n category: \"sentinels\",\n status: \"pass\",\n message: `All ${sentinels.length} sentinels are healthy`,\n fixable: false,\n });\n }\n }\n\n if (categories.includes(\"sketches\")) {\n const sketches = await kv.list<Sketch>(KV.sketches);\n let sketchIssues = 0;\n\n for (const sketch of sketches) {\n if (\n sketch.status === \"active\" &&\n new Date(sketch.expiresAt).getTime() <= now\n ) {\n checks.push({\n name: `expired-sketch:${sketch.id}`,\n category: \"sketches\",\n status: \"fail\",\n message: `Sketch \"${sketch.title}\" expired at ${sketch.expiresAt}`,\n fixable: true,\n });\n sketchIssues++;\n }\n }\n\n if (sketchIssues === 0) {\n checks.push({\n name: \"sketches-ok\",\n category: \"sketches\",\n status: \"pass\",\n message: `All ${sketches.length} sketches are healthy`,\n fixable: false,\n });\n }\n }\n\n if (categories.includes(\"signals\")) {\n const signals = await kv.list<Signal>(KV.signals);\n let signalIssues = 0;\n\n for (const signal of signals) {\n if (\n signal.expiresAt &&\n new Date(signal.expiresAt).getTime() <= now\n ) {\n checks.push({\n name: `expired-signal:${signal.id}`,\n category: \"signals\",\n status: \"fail\",\n message: `Signal from \"${signal.from}\" expired at ${signal.expiresAt}`,\n fixable: true,\n });\n signalIssues++;\n }\n }\n\n if (signalIssues === 0) {\n checks.push({\n name: \"signals-ok\",\n category: \"signals\",\n status: \"pass\",\n message: `All ${signals.length} signals are healthy`,\n fixable: false,\n });\n }\n }\n\n if (categories.includes(\"sessions\")) {\n const sessions = await kv.list<Session>(KV.sessions);\n let sessionIssues = 0;\n\n for (const session of sessions) {\n if (\n session.status === \"active\" &&\n now - new Date(session.startedAt).getTime() > TWENTY_FOUR_HOURS_MS\n ) {\n checks.push({\n name: `abandoned-session:${session.id}`,\n category: \"sessions\",\n status: \"warn\",\n message: `Session ${session.id} has been active for over 24 hours`,\n fixable: false,\n });\n sessionIssues++;\n }\n }\n\n if (sessionIssues === 0) {\n checks.push({\n name: \"sessions-ok\",\n category: \"sessions\",\n status: \"pass\",\n message: `All ${sessions.length} sessions are healthy`,\n fixable: false,\n });\n }\n }\n\n if (categories.includes(\"memories\")) {\n const memories = await kv.list<Memory>(KV.memories);\n const memoryIds = new Set(memories.map((m) => m.id));\n const supersededBy = new Map<string, string>();\n let memoryIssues = 0;\n\n for (const memory of memories) {\n if (memory.supersedes && memory.supersedes.length > 0) {\n for (const sid of memory.supersedes) {\n if (!memoryIds.has(sid)) {\n checks.push({\n name: `memory-missing-supersedes:${memory.id}:${sid}`,\n category: \"memories\",\n status: \"warn\",\n message: `Memory \"${memory.title}\" supersedes non-existent memory ${sid}`,\n fixable: false,\n });\n memoryIssues++;\n }\n supersededBy.set(sid, memory.id);\n }\n }\n }\n\n for (const memory of memories) {\n if (memory.isLatest && supersededBy.has(memory.id)) {\n checks.push({\n name: `memory-stale-latest:${memory.id}`,\n category: \"memories\",\n status: \"fail\",\n message: `Memory \"${memory.title}\" has isLatest=true but is superseded by ${supersededBy.get(memory.id)}`,\n fixable: true,\n });\n memoryIssues++;\n }\n }\n\n if (memoryIssues === 0) {\n checks.push({\n name: \"memories-ok\",\n category: \"memories\",\n status: \"pass\",\n message: `All ${memories.length} memories are consistent`,\n fixable: false,\n });\n }\n }\n\n if (categories.includes(\"mesh\")) {\n const peers = await kv.list<MeshPeer>(KV.mesh);\n let meshIssues = 0;\n\n for (const peer of peers) {\n if (\n peer.lastSyncAt &&\n now - new Date(peer.lastSyncAt).getTime() > ONE_HOUR_MS\n ) {\n checks.push({\n name: `stale-peer:${peer.id}`,\n category: \"mesh\",\n status: \"warn\",\n message: `Peer \"${peer.name}\" last synced over 1 hour ago`,\n fixable: false,\n });\n meshIssues++;\n }\n\n if (peer.status === \"error\") {\n checks.push({\n name: `error-peer:${peer.id}`,\n category: \"mesh\",\n status: \"warn\",\n message: `Peer \"${peer.name}\" is in error state`,\n fixable: false,\n });\n meshIssues++;\n }\n }\n\n if (meshIssues === 0) {\n checks.push({\n name: \"mesh-ok\",\n category: \"mesh\",\n status: \"pass\",\n message: `All ${peers.length} mesh peers are healthy`,\n fixable: false,\n });\n }\n }\n\n const summary = {\n pass: checks.filter((c) => c.status === \"pass\").length,\n warn: checks.filter((c) => c.status === \"warn\").length,\n fail: checks.filter((c) => c.status === \"fail\").length,\n fixable: checks.filter((c) => c.fixable).length,\n };\n\n return { success: true, checks, summary };\n },\n );\n\n sdk.registerFunction(\n { id: \"mem::heal\" },\n async (data: { categories?: string[]; dryRun?: boolean }) => {\n const dryRun = data.dryRun ?? false;\n const categories = data.categories && data.categories.length > 0\n ? data.categories.filter((c) => ALL_CATEGORIES.includes(c))\n : ALL_CATEGORIES;\n\n let fixed = 0;\n let skipped = 0;\n const details: string[] = [];\n const now = Date.now();\n\n if (categories.includes(\"actions\")) {\n const actions = await kv.list<Action>(KV.actions);\n const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n const actionMap = new Map(actions.map((a) => [a.id, a]));\n\n for (const action of actions) {\n if (action.status === \"blocked\") {\n const deps = allEdges.filter(\n (e) => e.sourceActionId === action.id && e.type === \"requires\",\n );\n if (deps.length > 0) {\n const allDone = deps.every((d) => {\n const target = actionMap.get(d.targetActionId);\n return target && target.status === \"done\";\n });\n if (allDone) {\n if (dryRun) {\n details.push(\n `[dry-run] Would unblock action \"${action.title}\" (${action.id})`,\n );\n fixed++;\n continue;\n }\n const didFix = await withKeyedLock(\n `mem:action:${action.id}`,\n async () => {\n const fresh = await kv.get<Action>(KV.actions, action.id);\n if (!fresh || fresh.status !== \"blocked\") return false;\n const freshEdges = await kv.list<ActionEdge>(KV.actionEdges);\n const freshDeps = freshEdges.filter(\n (e) =>\n e.sourceActionId === fresh.id && e.type === \"requires\",\n );\n const freshActions = await kv.list<Action>(KV.actions);\n const freshMap = new Map(\n freshActions.map((a) => [a.id, a]),\n );\n const stillAllDone = freshDeps.every((d) => {\n const target = freshMap.get(d.targetActionId);\n return target && target.status === \"done\";\n });\n if (!stillAllDone) return false;\n fresh.status = \"pending\";\n fresh.updatedAt = new Date().toISOString();\n await kv.set(KV.actions, fresh.id, fresh);\n return true;\n },\n );\n if (didFix) {\n details.push(\n `Unblocked action \"${action.title}\" (${action.id})`,\n );\n fixed++;\n } else {\n skipped++;\n }\n }\n }\n }\n\n if (action.status === \"pending\") {\n const deps = allEdges.filter(\n (e) => e.sourceActionId === action.id && e.type === \"requires\",\n );\n if (deps.length > 0) {\n const hasUnsatisfied = deps.some((d) => {\n const target = actionMap.get(d.targetActionId);\n return !target || target.status !== \"done\";\n });\n if (hasUnsatisfied) {\n if (dryRun) {\n details.push(\n `[dry-run] Would block action \"${action.title}\" (${action.id})`,\n );\n fixed++;\n continue;\n }\n const didFix = await withKeyedLock(\n `mem:action:${action.id}`,\n async () => {\n const fresh = await kv.get<Action>(KV.actions, action.id);\n if (!fresh || fresh.status !== \"pending\") return false;\n const freshEdges = await kv.list<ActionEdge>(KV.actionEdges);\n const freshDeps = freshEdges.filter(\n (e) =>\n e.sourceActionId === fresh.id && e.type === \"requires\",\n );\n const freshActions = await kv.list<Action>(KV.actions);\n const freshMap = new Map(\n freshActions.map((a) => [a.id, a]),\n );\n const stillUnsatisfied = freshDeps.some((d) => {\n const target = freshMap.get(d.targetActionId);\n return !target || target.status !== \"done\";\n });\n if (!stillUnsatisfied) return false;\n fresh.status = \"blocked\";\n fresh.updatedAt = new Date().toISOString();\n await kv.set(KV.actions, fresh.id, fresh);\n return true;\n },\n );\n if (didFix) {\n details.push(\n `Blocked action \"${action.title}\" (${action.id})`,\n );\n fixed++;\n } else {\n skipped++;\n }\n }\n }\n }\n }\n }\n\n if (categories.includes(\"leases\")) {\n const leases = await kv.list<Lease>(KV.leases);\n const actions = await kv.list<Action>(KV.actions);\n const actionIds = new Set(actions.map((a) => a.id));\n\n for (const lease of leases) {\n if (\n lease.status === \"active\" &&\n new Date(lease.expiresAt).getTime() <= now\n ) {\n if (dryRun) {\n details.push(\n `[dry-run] Would expire lease ${lease.id} for action ${lease.actionId}`,\n );\n fixed++;\n continue;\n }\n const didFix = await withKeyedLock(\n `mem:lease:${lease.actionId}`,\n async () => {\n const fresh = await kv.get<Lease>(KV.leases, lease.id);\n if (\n !fresh ||\n fresh.status !== \"active\" ||\n new Date(fresh.expiresAt).getTime() > Date.now()\n ) {\n return false;\n }\n fresh.status = \"expired\";\n await kv.set(KV.leases, fresh.id, fresh);\n\n const action = await kv.get<Action>(KV.actions, fresh.actionId);\n if (\n action &&\n action.status === \"active\" &&\n action.assignedTo === fresh.agentId\n ) {\n action.status = \"pending\";\n action.assignedTo = undefined;\n action.updatedAt = new Date().toISOString();\n await kv.set(KV.actions, action.id, action);\n }\n return true;\n },\n );\n if (didFix) {\n details.push(\n `Expired lease ${lease.id} for action ${lease.actionId}`,\n );\n fixed++;\n } else {\n skipped++;\n }\n continue;\n }\n\n if (!actionIds.has(lease.actionId)) {\n if (dryRun) {\n details.push(\n `[dry-run] Would delete orphaned lease ${lease.id}`,\n );\n fixed++;\n continue;\n }\n await kv.delete(KV.leases, lease.id);\n details.push(`Deleted orphaned lease ${lease.id}`);\n fixed++;\n }\n }\n }\n\n if (categories.includes(\"sentinels\")) {\n const sentinels = await kv.list<Sentinel>(KV.sentinels);\n\n for (const sentinel of sentinels) {\n if (\n sentinel.status === \"watching\" &&\n sentinel.expiresAt &&\n new Date(sentinel.expiresAt).getTime() <= now\n ) {\n if (dryRun) {\n details.push(\n `[dry-run] Would expire sentinel \"${sentinel.name}\" (${sentinel.id})`,\n );\n fixed++;\n continue;\n }\n const didFix = await withKeyedLock(\n `mem:sentinel:${sentinel.id}`,\n async () => {\n const fresh = await kv.get<Sentinel>(\n KV.sentinels,\n sentinel.id,\n );\n if (!fresh || fresh.status !== \"watching\") return false;\n if (\n !fresh.expiresAt ||\n new Date(fresh.expiresAt).getTime() > Date.now()\n ) {\n return false;\n }\n fresh.status = \"expired\";\n await kv.set(KV.sentinels, fresh.id, fresh);\n return true;\n },\n );\n if (didFix) {\n details.push(\n `Expired sentinel \"${sentinel.name}\" (${sentinel.id})`,\n );\n fixed++;\n } else {\n skipped++;\n }\n }\n }\n }\n\n if (categories.includes(\"sketches\")) {\n const sketches = await kv.list<Sketch>(KV.sketches);\n\n for (const sketch of sketches) {\n if (\n sketch.status === \"active\" &&\n new Date(sketch.expiresAt).getTime() <= now\n ) {\n if (dryRun) {\n details.push(\n `[dry-run] Would discard expired sketch \"${sketch.title}\" (${sketch.id})`,\n );\n fixed++;\n continue;\n }\n const didFix = await withKeyedLock(\n `mem:sketch:${sketch.id}`,\n async () => {\n const fresh = await kv.get<Sketch>(KV.sketches, sketch.id);\n if (\n !fresh ||\n fresh.status !== \"active\" ||\n new Date(fresh.expiresAt).getTime() > Date.now()\n ) {\n return false;\n }\n\n const allEdges = await kv.list<ActionEdge>(KV.actionEdges);\n const actionIdSet = new Set(fresh.actionIds);\n for (const edge of allEdges) {\n if (\n actionIdSet.has(edge.sourceActionId) ||\n actionIdSet.has(edge.targetActionId)\n ) {\n await kv.delete(KV.actionEdges, edge.id);\n }\n }\n for (const actionId of fresh.actionIds) {\n await kv.delete(KV.actions, actionId);\n }\n\n fresh.status = \"discarded\";\n fresh.discardedAt = new Date().toISOString();\n await kv.set(KV.sketches, fresh.id, fresh);\n return true;\n },\n );\n if (didFix) {\n details.push(\n `Discarded expired sketch \"${sketch.title}\" (${sketch.id})`,\n );\n fixed++;\n } else {\n skipped++;\n }\n }\n }\n }\n\n if (categories.includes(\"signals\")) {\n const signals = await kv.list<Signal>(KV.signals);\n\n for (const signal of signals) {\n if (\n signal.expiresAt &&\n new Date(signal.expiresAt).getTime() <= now\n ) {\n if (dryRun) {\n details.push(\n `[dry-run] Would delete expired signal ${signal.id}`,\n );\n fixed++;\n continue;\n }\n await kv.delete(KV.signals, signal.id);\n details.push(`Deleted expired signal ${signal.id}`);\n fixed++;\n }\n }\n }\n\n if (categories.includes(\"memories\")) {\n const memories = await kv.list<Memory>(KV.memories);\n const supersededBy = new Map<string, string>();\n\n for (const memory of memories) {\n if (memory.supersedes && memory.supersedes.length > 0) {\n for (const sid of memory.supersedes) {\n supersededBy.set(sid, memory.id);\n }\n }\n }\n\n for (const memory of memories) {\n if (memory.isLatest && supersededBy.has(memory.id)) {\n if (dryRun) {\n details.push(\n `[dry-run] Would set isLatest=false on memory \"${memory.title}\" (${memory.id})`,\n );\n fixed++;\n continue;\n }\n const didFix = await withKeyedLock(\n `mem:memory:${memory.id}`,\n async () => {\n const fresh = await kv.get<Memory>(KV.memories, memory.id);\n if (!fresh || !fresh.isLatest) return false;\n fresh.isLatest = false;\n fresh.updatedAt = new Date().toISOString();\n await kv.set(KV.memories, fresh.id, fresh);\n return true;\n },\n );\n if (didFix) {\n details.push(\n `Set isLatest=false on memory \"${memory.title}\" (${memory.id})`,\n );\n fixed++;\n } else {\n skipped++;\n }\n }\n }\n }\n\n return { success: true, fixed, skipped, details };\n },\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/hooks/_project.ts
|
|
6
|
+
function resolveProject(cwd) {
|
|
7
|
+
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
|
|
8
|
+
if (explicit && explicit.trim()) return explicit.trim();
|
|
9
|
+
const dir = cwd && cwd.trim() ? cwd : process.cwd();
|
|
10
|
+
try {
|
|
11
|
+
const top = execSync("git rev-parse --show-toplevel", {
|
|
12
|
+
cwd: dir,
|
|
13
|
+
stdio: [
|
|
14
|
+
"ignore",
|
|
15
|
+
"pipe",
|
|
16
|
+
"ignore"
|
|
17
|
+
],
|
|
18
|
+
timeout: 500
|
|
19
|
+
}).toString().trim();
|
|
20
|
+
if (top) return basename(top);
|
|
21
|
+
} catch {}
|
|
22
|
+
return basename(dir);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
2
26
|
//#region src/hooks/notification.ts
|
|
3
27
|
function isSdkChildContext(payload) {
|
|
4
28
|
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
@@ -22,27 +46,28 @@ async function main() {
|
|
|
22
46
|
return;
|
|
23
47
|
}
|
|
24
48
|
if (isSdkChildContext(data)) return;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
49
|
+
const notificationType = data.notification_type ?? data.notificationType;
|
|
50
|
+
if (notificationType !== "permission_prompt") return;
|
|
51
|
+
const rawSessionId = data.session_id ?? data.sessionId;
|
|
52
|
+
const sessionId = typeof rawSessionId === "string" && rawSessionId.length > 0 ? rawSessionId : "unknown";
|
|
53
|
+
fetch(`${REST_URL}/agentmemory/observe`, {
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: authHeaders(),
|
|
56
|
+
body: JSON.stringify({
|
|
57
|
+
hookType: "notification",
|
|
58
|
+
sessionId,
|
|
59
|
+
project: resolveProject(data.cwd),
|
|
60
|
+
cwd: data.cwd || process.cwd(),
|
|
61
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
62
|
+
data: {
|
|
63
|
+
notification_type: notificationType,
|
|
64
|
+
title: data.title,
|
|
65
|
+
message: data.message
|
|
66
|
+
}
|
|
67
|
+
}),
|
|
68
|
+
signal: AbortSignal.timeout(2e3)
|
|
69
|
+
}).catch(() => {});
|
|
70
|
+
setTimeout(() => process.exit(0), 500).unref();
|
|
46
71
|
}
|
|
47
72
|
main();
|
|
48
73
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification.mjs","names":[],"sources":["../../src/hooks/notification.ts"],"sourcesContent":["#!/usr/bin/env node\n\nfunction isSdkChildContext(payload: unknown): boolean {\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\n if (!payload || typeof payload !== \"object\") return false;\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\n}\n\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\n\nfunction authHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\n return h;\n}\n\nasync function main() {\n let input = \"\";\n for await (const chunk of process.stdin) {\n input += chunk;\n }\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(input);\n } catch {\n return;\n }\n\n if (isSdkChildContext(data)) return;\n
|
|
1
|
+
{"version":3,"file":"notification.mjs","names":[],"sources":["../../src/hooks/_project.ts","../../src/hooks/notification.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\nimport { basename } from \"node:path\";\n\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\nexport function resolveProject(cwd?: string): string {\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\n if (explicit && explicit.trim()) return explicit.trim();\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\n try {\n const top = execSync(\"git rev-parse --show-toplevel\", {\n cwd: dir,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 500,\n })\n .toString()\n .trim();\n if (top) return basename(top);\n } catch {}\n return basename(dir);\n}\n","#!/usr/bin/env node\nimport { resolveProject } from \"./_project.js\";\n\nfunction isSdkChildContext(payload: unknown): boolean {\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\n if (!payload || typeof payload !== \"object\") return false;\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\n}\n\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\n\nfunction authHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\n return h;\n}\n\nasync function main() {\n let input = \"\";\n for await (const chunk of process.stdin) {\n input += chunk;\n }\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(input);\n } catch {\n return;\n }\n\n if (isSdkChildContext(data)) return;\n const notificationType = data.notification_type ?? data.notificationType;\n if (notificationType !== \"permission_prompt\") return;\n\n const rawSessionId = data.session_id ?? data.sessionId;\n const sessionId =\n typeof rawSessionId === \"string\" && rawSessionId.length > 0\n ? rawSessionId\n : \"unknown\";\n\n fetch(`${REST_URL}/agentmemory/observe`, {\n method: \"POST\",\n headers: authHeaders(),\n body: JSON.stringify({\n hookType: \"notification\",\n sessionId,\n project: resolveProject(data.cwd as string | undefined),\n cwd: (data.cwd as string | undefined) || process.cwd(),\n timestamp: new Date().toISOString(),\n data: {\n notification_type: notificationType,\n title: data.title,\n message: data.message,\n },\n }),\n signal: AbortSignal.timeout(2000),\n }).catch(() => {});\n setTimeout(() => process.exit(0), 500).unref();\n}\n\nmain();\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"}
|
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/hooks/_project.ts
|
|
6
|
+
function resolveProject(cwd) {
|
|
7
|
+
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
|
|
8
|
+
if (explicit && explicit.trim()) return explicit.trim();
|
|
9
|
+
const dir = cwd && cwd.trim() ? cwd : process.cwd();
|
|
10
|
+
try {
|
|
11
|
+
const top = execSync("git rev-parse --show-toplevel", {
|
|
12
|
+
cwd: dir,
|
|
13
|
+
stdio: [
|
|
14
|
+
"ignore",
|
|
15
|
+
"pipe",
|
|
16
|
+
"ignore"
|
|
17
|
+
],
|
|
18
|
+
timeout: 500
|
|
19
|
+
}).toString().trim();
|
|
20
|
+
if (top) return basename(top);
|
|
21
|
+
} catch {}
|
|
22
|
+
return basename(dir);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
2
26
|
//#region src/hooks/post-tool-failure.ts
|
|
3
27
|
function isSdkChildContext(payload) {
|
|
4
28
|
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
@@ -22,27 +46,29 @@ async function main() {
|
|
|
22
46
|
return;
|
|
23
47
|
}
|
|
24
48
|
if (isSdkChildContext(data)) return;
|
|
25
|
-
if (data.is_interrupt) return;
|
|
26
|
-
const sessionId = data.session_id || "unknown";
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
})
|
|
45
|
-
|
|
49
|
+
if (data.is_interrupt || data.isInterrupt) return;
|
|
50
|
+
const sessionId = data.session_id || data.sessionId || "unknown";
|
|
51
|
+
const toolName = data.tool_name ?? data.toolName;
|
|
52
|
+
const toolInput = data.tool_input ?? data.toolArgs;
|
|
53
|
+
const error = data.error ?? data.errorMessage;
|
|
54
|
+
fetch(`${REST_URL}/agentmemory/observe`, {
|
|
55
|
+
method: "POST",
|
|
56
|
+
headers: authHeaders(),
|
|
57
|
+
body: JSON.stringify({
|
|
58
|
+
hookType: "post_tool_failure",
|
|
59
|
+
sessionId,
|
|
60
|
+
project: resolveProject(data.cwd),
|
|
61
|
+
cwd: data.cwd || process.cwd(),
|
|
62
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
63
|
+
data: {
|
|
64
|
+
tool_name: toolName,
|
|
65
|
+
tool_input: typeof toolInput === "string" ? toolInput.slice(0, 4e3) : JSON.stringify(toolInput ?? "").slice(0, 4e3),
|
|
66
|
+
error: typeof error === "string" ? error.slice(0, 4e3) : JSON.stringify(error ?? "").slice(0, 4e3)
|
|
67
|
+
}
|
|
68
|
+
}),
|
|
69
|
+
signal: AbortSignal.timeout(3e3)
|
|
70
|
+
}).catch(() => {});
|
|
71
|
+
setTimeout(() => process.exit(0), 500).unref();
|
|
46
72
|
}
|
|
47
73
|
main();
|
|
48
74
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-tool-failure.mjs","names":[],"sources":["../../src/hooks/post-tool-failure.ts"],"sourcesContent":["#!/usr/bin/env node\n\nfunction isSdkChildContext(payload: unknown): boolean {\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\n if (!payload || typeof payload !== \"object\") return false;\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\n}\n\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\n\nfunction authHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\n return h;\n}\n\nasync function main() {\n let input = \"\";\n for await (const chunk of process.stdin) {\n input += chunk;\n }\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(input);\n } catch {\n return;\n }\n\n if (isSdkChildContext(data)) return;\n if (data.is_interrupt) return;\n\n const sessionId = (data.session_id as string) || \"unknown\";\n
|
|
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\";\nimport { basename } from \"node:path\";\n\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\nexport function resolveProject(cwd?: string): string {\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\n if (explicit && explicit.trim()) return explicit.trim();\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\n try {\n const top = execSync(\"git rev-parse --show-toplevel\", {\n cwd: dir,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 500,\n })\n .toString()\n .trim();\n if (top) return basename(top);\n } catch {}\n return basename(dir);\n}\n","#!/usr/bin/env node\nimport { resolveProject } from \"./_project.js\";\n\nfunction isSdkChildContext(payload: unknown): boolean {\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\n if (!payload || typeof payload !== \"object\") return false;\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\n}\n\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\n\nfunction authHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\n return h;\n}\n\nasync function main() {\n let input = \"\";\n for await (const chunk of process.stdin) {\n input += chunk;\n }\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(input);\n } catch {\n return;\n }\n\n if (isSdkChildContext(data)) return;\n if (data.is_interrupt || data.isInterrupt) return;\n\n const sessionId = ((data.session_id || data.sessionId) as string) || \"unknown\";\n const toolName = data.tool_name ?? data.toolName;\n const toolInput = data.tool_input ?? data.toolArgs;\n const error = data.error ?? data.errorMessage;\n\n fetch(`${REST_URL}/agentmemory/observe`, {\n method: \"POST\",\n headers: authHeaders(),\n body: JSON.stringify({\n hookType: \"post_tool_failure\",\n sessionId,\n project: resolveProject(data.cwd as string | undefined),\n cwd: (data.cwd as string | undefined) || process.cwd(),\n timestamp: new Date().toISOString(),\n data: {\n tool_name: toolName,\n tool_input:\n typeof toolInput === \"string\"\n ? toolInput.slice(0, 4000)\n : JSON.stringify(toolInput ?? \"\").slice(0, 4000),\n error:\n typeof error === \"string\"\n ? error.slice(0, 4000)\n : JSON.stringify(error ?? \"\").slice(0, 4000),\n },\n }),\n signal: AbortSignal.timeout(3000),\n }).catch(() => {});\n setTimeout(() => process.exit(0), 500).unref();\n}\n\nmain();\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"}
|
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/hooks/_project.ts
|
|
6
|
+
function resolveProject(cwd) {
|
|
7
|
+
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
|
|
8
|
+
if (explicit && explicit.trim()) return explicit.trim();
|
|
9
|
+
const dir = cwd && cwd.trim() ? cwd : process.cwd();
|
|
10
|
+
try {
|
|
11
|
+
const top = execSync("git rev-parse --show-toplevel", {
|
|
12
|
+
cwd: dir,
|
|
13
|
+
stdio: [
|
|
14
|
+
"ignore",
|
|
15
|
+
"pipe",
|
|
16
|
+
"ignore"
|
|
17
|
+
],
|
|
18
|
+
timeout: 500
|
|
19
|
+
}).toString().trim();
|
|
20
|
+
if (top) return basename(top);
|
|
21
|
+
} catch {}
|
|
22
|
+
return basename(dir);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
2
26
|
//#region src/hooks/post-tool-use.ts
|
|
3
27
|
function isSdkChildContext(payload) {
|
|
4
28
|
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
@@ -22,28 +46,39 @@ async function main() {
|
|
|
22
46
|
return;
|
|
23
47
|
}
|
|
24
48
|
if (isSdkChildContext(data)) return;
|
|
25
|
-
const sessionId = data.session_id || "unknown";
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
49
|
+
const sessionId = data.session_id || data.sessionId || "unknown";
|
|
50
|
+
const toolName = data.tool_name ?? data.toolName;
|
|
51
|
+
const toolInput = data.tool_input ?? data.toolArgs;
|
|
52
|
+
const { imageData, cleanOutput } = extractImageData(toolOutput(data));
|
|
53
|
+
fetch(`${REST_URL}/agentmemory/observe`, {
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: authHeaders(),
|
|
56
|
+
body: JSON.stringify({
|
|
57
|
+
hookType: "post_tool_use",
|
|
58
|
+
sessionId,
|
|
59
|
+
project: resolveProject(data.cwd),
|
|
60
|
+
cwd: data.cwd || process.cwd(),
|
|
61
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
62
|
+
data: {
|
|
63
|
+
tool_name: toolName,
|
|
64
|
+
tool_input: toolInput,
|
|
65
|
+
tool_output: truncate(cleanOutput, 8e3),
|
|
66
|
+
...imageData ? { image_data: imageData } : {}
|
|
67
|
+
}
|
|
68
|
+
}),
|
|
69
|
+
signal: AbortSignal.timeout(3e3)
|
|
70
|
+
}).catch(() => {});
|
|
71
|
+
setTimeout(() => process.exit(0), 500).unref();
|
|
72
|
+
}
|
|
73
|
+
function toolOutput(data) {
|
|
74
|
+
if (data.tool_response !== void 0) return data.tool_response;
|
|
75
|
+
if (data.tool_output !== void 0) return data.tool_output;
|
|
76
|
+
const result = data.tool_result ?? data.toolResult;
|
|
77
|
+
if (typeof result === "object" && result !== null) {
|
|
78
|
+
const obj = result;
|
|
79
|
+
return obj.text_result_for_llm ?? obj.textResultForLlm ?? result;
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
47
82
|
}
|
|
48
83
|
function isBase64Image(val) {
|
|
49
84
|
return typeof val === "string" && (val.startsWith("data:image/") || val.startsWith("iVBORw0KGgo") || val.startsWith("/9j/"));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-tool-use.mjs","names":[],"sources":["../../src/hooks/post-tool-use.ts"],"sourcesContent":["#!/usr/bin/env node\n\nfunction isSdkChildContext(payload: unknown): boolean {\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\n if (!payload || typeof payload !== \"object\") return false;\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\n}\n\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\n\nfunction authHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\n return h;\n}\n\nasync function main() {\n let input = \"\";\n for await (const chunk of process.stdin) {\n input += chunk;\n }\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(input);\n } catch {\n return;\n }\n\n if (isSdkChildContext(data)) return;\n\n const sessionId = (data.session_id as string) || \"unknown\";\n\n const { imageData, cleanOutput } = extractImageData(data
|
|
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\";\nimport { basename } from \"node:path\";\n\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\nexport function resolveProject(cwd?: string): string {\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\n if (explicit && explicit.trim()) return explicit.trim();\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\n try {\n const top = execSync(\"git rev-parse --show-toplevel\", {\n cwd: dir,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 500,\n })\n .toString()\n .trim();\n if (top) return basename(top);\n } catch {}\n return basename(dir);\n}\n","#!/usr/bin/env node\nimport { resolveProject } from \"./_project.js\";\n\nfunction isSdkChildContext(payload: unknown): boolean {\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\n if (!payload || typeof payload !== \"object\") return false;\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\n}\n\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\n\nfunction authHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\n return h;\n}\n\nasync function main() {\n let input = \"\";\n for await (const chunk of process.stdin) {\n input += chunk;\n }\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(input);\n } catch {\n return;\n }\n\n if (isSdkChildContext(data)) return;\n\n const sessionId = ((data.session_id || data.sessionId) as string) || \"unknown\";\n const toolName = data.tool_name ?? data.toolName;\n const toolInput = data.tool_input ?? data.toolArgs;\n\n const { imageData, cleanOutput } = extractImageData(toolOutput(data));\n\n fetch(`${REST_URL}/agentmemory/observe`, {\n method: \"POST\",\n headers: authHeaders(),\n body: JSON.stringify({\n hookType: \"post_tool_use\",\n sessionId,\n project: resolveProject(data.cwd as string | undefined),\n cwd: (data.cwd as string | undefined) || process.cwd(),\n timestamp: new Date().toISOString(),\n data: {\n tool_name: toolName,\n tool_input: toolInput,\n tool_output: truncate(cleanOutput, 8000),\n ...(imageData ? { image_data: imageData } : {}),\n },\n }),\n signal: AbortSignal.timeout(3000),\n }).catch(() => {});\n setTimeout(() => process.exit(0), 500).unref();\n}\n\nfunction toolOutput(data: Record<string, unknown>): unknown {\n if (data.tool_response !== undefined) return data.tool_response;\n if (data.tool_output !== undefined) return data.tool_output;\n const result = data.tool_result ?? data.toolResult;\n if (typeof result === \"object\" && result !== null) {\n const obj = result as Record<string, unknown>;\n return obj.text_result_for_llm ?? obj.textResultForLlm ?? result;\n }\n return result;\n}\n\nfunction isBase64Image(val: unknown): val is string {\n return typeof val === \"string\" && (\n val.startsWith(\"data:image/\") ||\n val.startsWith(\"iVBORw0KGgo\") ||\n val.startsWith(\"/9j/\")\n );\n}\n\nfunction extractImageData(output: unknown): { imageData: string | undefined; cleanOutput: unknown } {\n if (isBase64Image(output)) {\n return { imageData: output, cleanOutput: \"[image data extracted]\" };\n }\n\n if (typeof output === \"object\" && output !== null && !Array.isArray(output)) {\n const obj = output as Record<string, unknown>;\n let imageData: string | undefined;\n const clean: Record<string, unknown> = {};\n\n for (const [key, val] of Object.entries(obj)) {\n if (!imageData && isBase64Image(val)) {\n imageData = val;\n clean[key] = \"[image data extracted]\";\n } else {\n clean[key] = val;\n }\n }\n\n return { imageData, cleanOutput: clean };\n }\n\n return { imageData: undefined, cleanOutput: output };\n}\n\nfunction truncate(value: unknown, max: number): unknown {\n if (typeof value === \"string\" && value.length > max) {\n return value.slice(0, max) + \"\\n[...truncated]\";\n }\n if (typeof value === \"object\" && value !== null) {\n const str = JSON.stringify(value);\n if (str.length > max) return str.slice(0, max) + \"...[truncated]\";\n return value;\n }\n return value;\n}\n\nmain();\n"],"mappings":"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"}
|