chore: import upstream snapshot with attribution
CI / test (20, macos-latest) (push) Has been cancelled
CI / test (20, ubuntu-latest) (push) Has been cancelled
CI / test (22, macos-latest) (push) Has been cancelled
CI / test (22, ubuntu-latest) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:01:18 +08:00
commit 979fb22d7c
613 changed files with 113494 additions and 0 deletions
+551
View File
@@ -0,0 +1,551 @@
//#region src/state/schema.ts
const KV = {
sessions: "mem:sessions",
observations: (sessionId) => `mem:obs:${sessionId}`,
memories: "mem:memories",
summaries: "mem:summaries",
config: "mem:config",
metrics: "mem:metrics",
health: "mem:health",
embeddings: (obsId) => `mem:emb:${obsId}`,
bm25Index: "mem:index:bm25",
relations: "mem:relations",
profiles: "mem:profiles",
claudeBridge: "mem:claude-bridge",
graphNodes: "mem:graph:nodes",
graphEdges: "mem:graph:edges",
semantic: "mem:semantic",
procedural: "mem:procedural",
teamShared: (teamId) => `mem:team:${teamId}:shared`,
teamUsers: (teamId, userId) => `mem:team:${teamId}:users:${userId}`,
teamProfile: (teamId) => `mem:team:${teamId}:profile`,
audit: "mem:audit",
actions: "mem:actions",
actionEdges: "mem:action-edges",
leases: "mem:leases",
routines: "mem:routines",
routineRuns: "mem:routine-runs",
signals: "mem:signals",
checkpoints: "mem:checkpoints",
mesh: "mem:mesh",
sketches: "mem:sketches",
facets: "mem:facets",
sentinels: "mem:sentinels",
crystals: "mem:crystals"
};
//#endregion
//#region src/state/keyed-mutex.ts
const locks = /* @__PURE__ */ new Map();
function withKeyedLock(key, fn) {
const next = (locks.get(key) ?? Promise.resolve()).then(fn, fn);
const cleanup = next.then(() => {}, () => {});
locks.set(key, cleanup);
cleanup.then(() => {
if (locks.get(key) === cleanup) locks.delete(key);
});
return next;
}
//#endregion
//#region src/functions/diagnostics.ts
const ALL_CATEGORIES = [
"actions",
"leases",
"sentinels",
"sketches",
"signals",
"sessions",
"memories",
"mesh"
];
const TWENTY_FOUR_HOURS_MS = 1440 * 60 * 1e3;
const ONE_HOUR_MS = 3600 * 1e3;
function registerDiagnosticsFunction(sdk, kv) {
sdk.registerFunction("mem::diagnose", async (data) => {
const categories = data.categories && data.categories.length > 0 ? data.categories.filter((c) => ALL_CATEGORIES.includes(c)) : ALL_CATEGORIES;
const checks = [];
const now = Date.now();
if (categories.includes("actions")) {
const actions = await kv.list(KV.actions);
const allEdges = await kv.list(KV.actionEdges);
const leases = await kv.list(KV.leases);
const actionMap = new Map(actions.map((a) => [a.id, a]));
for (const action of actions) {
if (action.status === "active") {
if (!leases.some((l) => l.actionId === action.id && l.status === "active" && new Date(l.expiresAt).getTime() > now)) checks.push({
name: `active-no-lease:${action.id}`,
category: "actions",
status: "warn",
message: `Action "${action.title}" is active but has no active lease`,
fixable: false
});
}
if (action.status === "blocked") {
const deps = allEdges.filter((e) => e.sourceActionId === action.id && e.type === "requires");
if (deps.length > 0) {
if (deps.every((d) => {
const target = actionMap.get(d.targetActionId);
return target && target.status === "done";
})) checks.push({
name: `blocked-deps-done:${action.id}`,
category: "actions",
status: "fail",
message: `Action "${action.title}" is blocked but all dependencies are done`,
fixable: true
});
}
}
if (action.status === "pending") {
const deps = allEdges.filter((e) => e.sourceActionId === action.id && e.type === "requires");
if (deps.length > 0) {
if (deps.some((d) => {
const target = actionMap.get(d.targetActionId);
return !target || target.status !== "done";
})) checks.push({
name: `pending-unsatisfied-deps:${action.id}`,
category: "actions",
status: "fail",
message: `Action "${action.title}" is pending but has unsatisfied dependencies`,
fixable: true
});
}
}
}
if (!checks.some((c) => c.category === "actions" && c.status !== "pass")) checks.push({
name: "actions-ok",
category: "actions",
status: "pass",
message: `All ${actions.length} actions are consistent`,
fixable: false
});
}
if (categories.includes("leases")) {
const leases = await kv.list(KV.leases);
const actions = await kv.list(KV.actions);
const actionIds = new Set(actions.map((a) => a.id));
let leaseIssues = 0;
for (const lease of leases) {
if (lease.status === "active" && new Date(lease.expiresAt).getTime() <= now) {
checks.push({
name: `expired-lease:${lease.id}`,
category: "leases",
status: "fail",
message: `Lease ${lease.id} for action ${lease.actionId} expired at ${lease.expiresAt}`,
fixable: true
});
leaseIssues++;
}
if (!actionIds.has(lease.actionId)) {
checks.push({
name: `orphaned-lease:${lease.id}`,
category: "leases",
status: "fail",
message: `Lease ${lease.id} references non-existent action ${lease.actionId}`,
fixable: true
});
leaseIssues++;
}
}
if (leaseIssues === 0) checks.push({
name: "leases-ok",
category: "leases",
status: "pass",
message: `All ${leases.length} leases are healthy`,
fixable: false
});
}
if (categories.includes("sentinels")) {
const sentinels = await kv.list(KV.sentinels);
const actions = await kv.list(KV.actions);
const actionIds = new Set(actions.map((a) => a.id));
let sentinelIssues = 0;
for (const sentinel of sentinels) {
if (sentinel.status === "watching" && sentinel.expiresAt && new Date(sentinel.expiresAt).getTime() <= now) {
checks.push({
name: `expired-sentinel:${sentinel.id}`,
category: "sentinels",
status: "fail",
message: `Sentinel "${sentinel.name}" expired at ${sentinel.expiresAt}`,
fixable: true
});
sentinelIssues++;
}
for (const actionId of sentinel.linkedActionIds) if (!actionIds.has(actionId)) {
checks.push({
name: `sentinel-missing-action:${sentinel.id}:${actionId}`,
category: "sentinels",
status: "warn",
message: `Sentinel "${sentinel.name}" references non-existent action ${actionId}`,
fixable: false
});
sentinelIssues++;
}
}
if (sentinelIssues === 0) checks.push({
name: "sentinels-ok",
category: "sentinels",
status: "pass",
message: `All ${sentinels.length} sentinels are healthy`,
fixable: false
});
}
if (categories.includes("sketches")) {
const sketches = await kv.list(KV.sketches);
let sketchIssues = 0;
for (const sketch of sketches) if (sketch.status === "active" && new Date(sketch.expiresAt).getTime() <= now) {
checks.push({
name: `expired-sketch:${sketch.id}`,
category: "sketches",
status: "fail",
message: `Sketch "${sketch.title}" expired at ${sketch.expiresAt}`,
fixable: true
});
sketchIssues++;
}
if (sketchIssues === 0) checks.push({
name: "sketches-ok",
category: "sketches",
status: "pass",
message: `All ${sketches.length} sketches are healthy`,
fixable: false
});
}
if (categories.includes("signals")) {
const signals = await kv.list(KV.signals);
let signalIssues = 0;
for (const signal of signals) if (signal.expiresAt && new Date(signal.expiresAt).getTime() <= now) {
checks.push({
name: `expired-signal:${signal.id}`,
category: "signals",
status: "fail",
message: `Signal from "${signal.from}" expired at ${signal.expiresAt}`,
fixable: true
});
signalIssues++;
}
if (signalIssues === 0) checks.push({
name: "signals-ok",
category: "signals",
status: "pass",
message: `All ${signals.length} signals are healthy`,
fixable: false
});
}
if (categories.includes("sessions")) {
const sessions = await kv.list(KV.sessions);
let sessionIssues = 0;
for (const session of sessions) if (session.status === "active" && now - new Date(session.startedAt).getTime() > TWENTY_FOUR_HOURS_MS) {
checks.push({
name: `abandoned-session:${session.id}`,
category: "sessions",
status: "warn",
message: `Session ${session.id} has been active for over 24 hours`,
fixable: false
});
sessionIssues++;
}
if (sessionIssues === 0) checks.push({
name: "sessions-ok",
category: "sessions",
status: "pass",
message: `All ${sessions.length} sessions are healthy`,
fixable: false
});
}
if (categories.includes("memories")) {
const memories = await kv.list(KV.memories);
const memoryIds = new Set(memories.map((m) => m.id));
const supersededBy = /* @__PURE__ */ new Map();
let memoryIssues = 0;
for (const memory of memories) if (memory.supersedes && memory.supersedes.length > 0) for (const sid of memory.supersedes) {
if (!memoryIds.has(sid)) {
checks.push({
name: `memory-missing-supersedes:${memory.id}:${sid}`,
category: "memories",
status: "warn",
message: `Memory "${memory.title}" supersedes non-existent memory ${sid}`,
fixable: false
});
memoryIssues++;
}
supersededBy.set(sid, memory.id);
}
for (const memory of memories) if (memory.isLatest && supersededBy.has(memory.id)) {
checks.push({
name: `memory-stale-latest:${memory.id}`,
category: "memories",
status: "fail",
message: `Memory "${memory.title}" has isLatest=true but is superseded by ${supersededBy.get(memory.id)}`,
fixable: true
});
memoryIssues++;
}
if (memoryIssues === 0) checks.push({
name: "memories-ok",
category: "memories",
status: "pass",
message: `All ${memories.length} memories are consistent`,
fixable: false
});
}
if (categories.includes("mesh")) {
const peers = await kv.list(KV.mesh);
let meshIssues = 0;
for (const peer of peers) {
if (peer.lastSyncAt && now - new Date(peer.lastSyncAt).getTime() > ONE_HOUR_MS) {
checks.push({
name: `stale-peer:${peer.id}`,
category: "mesh",
status: "warn",
message: `Peer "${peer.name}" last synced over 1 hour ago`,
fixable: false
});
meshIssues++;
}
if (peer.status === "error") {
checks.push({
name: `error-peer:${peer.id}`,
category: "mesh",
status: "warn",
message: `Peer "${peer.name}" is in error state`,
fixable: false
});
meshIssues++;
}
}
if (meshIssues === 0) checks.push({
name: "mesh-ok",
category: "mesh",
status: "pass",
message: `All ${peers.length} mesh peers are healthy`,
fixable: false
});
}
return {
success: true,
checks,
summary: {
pass: checks.filter((c) => c.status === "pass").length,
warn: checks.filter((c) => c.status === "warn").length,
fail: checks.filter((c) => c.status === "fail").length,
fixable: checks.filter((c) => c.fixable).length
}
};
});
sdk.registerFunction("mem::heal", async (data) => {
const dryRun = data.dryRun ?? false;
const categories = data.categories && data.categories.length > 0 ? data.categories.filter((c) => ALL_CATEGORIES.includes(c)) : ALL_CATEGORIES;
let fixed = 0;
let skipped = 0;
const details = [];
const now = Date.now();
if (categories.includes("actions")) {
const actions = await kv.list(KV.actions);
const allEdges = await kv.list(KV.actionEdges);
const actionMap = new Map(actions.map((a) => [a.id, a]));
for (const action of actions) {
if (action.status === "blocked") {
const deps = allEdges.filter((e) => e.sourceActionId === action.id && e.type === "requires");
if (deps.length > 0) {
if (deps.every((d) => {
const target = actionMap.get(d.targetActionId);
return target && target.status === "done";
})) {
if (dryRun) {
details.push(`[dry-run] Would unblock action "${action.title}" (${action.id})`);
fixed++;
continue;
}
if (await withKeyedLock(`mem:action:${action.id}`, async () => {
const fresh = await kv.get(KV.actions, action.id);
if (!fresh || fresh.status !== "blocked") return false;
const freshDeps = (await kv.list(KV.actionEdges)).filter((e) => e.sourceActionId === fresh.id && e.type === "requires");
const freshActions = await kv.list(KV.actions);
const freshMap = new Map(freshActions.map((a) => [a.id, a]));
if (!freshDeps.every((d) => {
const target = freshMap.get(d.targetActionId);
return target && target.status === "done";
})) return false;
fresh.status = "pending";
fresh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
await kv.set(KV.actions, fresh.id, fresh);
return true;
})) {
details.push(`Unblocked action "${action.title}" (${action.id})`);
fixed++;
} else skipped++;
}
}
}
if (action.status === "pending") {
const deps = allEdges.filter((e) => e.sourceActionId === action.id && e.type === "requires");
if (deps.length > 0) {
if (deps.some((d) => {
const target = actionMap.get(d.targetActionId);
return !target || target.status !== "done";
})) {
if (dryRun) {
details.push(`[dry-run] Would block action "${action.title}" (${action.id})`);
fixed++;
continue;
}
if (await withKeyedLock(`mem:action:${action.id}`, async () => {
const fresh = await kv.get(KV.actions, action.id);
if (!fresh || fresh.status !== "pending") return false;
const freshDeps = (await kv.list(KV.actionEdges)).filter((e) => e.sourceActionId === fresh.id && e.type === "requires");
const freshActions = await kv.list(KV.actions);
const freshMap = new Map(freshActions.map((a) => [a.id, a]));
if (!freshDeps.some((d) => {
const target = freshMap.get(d.targetActionId);
return !target || target.status !== "done";
})) return false;
fresh.status = "blocked";
fresh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
await kv.set(KV.actions, fresh.id, fresh);
return true;
})) {
details.push(`Blocked action "${action.title}" (${action.id})`);
fixed++;
} else skipped++;
}
}
}
}
}
if (categories.includes("leases")) {
const leases = await kv.list(KV.leases);
const actions = await kv.list(KV.actions);
const actionIds = new Set(actions.map((a) => a.id));
for (const lease of leases) {
if (lease.status === "active" && new Date(lease.expiresAt).getTime() <= now) {
if (dryRun) {
details.push(`[dry-run] Would expire lease ${lease.id} for action ${lease.actionId}`);
fixed++;
continue;
}
if (await withKeyedLock(`mem:action:${lease.actionId}`, async () => {
const fresh = await kv.get(KV.leases, lease.id);
if (!fresh || fresh.status !== "active" || new Date(fresh.expiresAt).getTime() > Date.now()) return false;
fresh.status = "expired";
await kv.set(KV.leases, fresh.id, fresh);
const action = await kv.get(KV.actions, fresh.actionId);
if (action && action.status === "active" && action.assignedTo === fresh.agentId) {
action.status = "pending";
action.assignedTo = void 0;
action.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
await kv.set(KV.actions, action.id, action);
}
return true;
})) {
details.push(`Expired lease ${lease.id} for action ${lease.actionId}`);
fixed++;
} else skipped++;
continue;
}
if (!actionIds.has(lease.actionId)) {
if (dryRun) {
details.push(`[dry-run] Would delete orphaned lease ${lease.id}`);
fixed++;
continue;
}
await kv.delete(KV.leases, lease.id);
details.push(`Deleted orphaned lease ${lease.id}`);
fixed++;
}
}
}
if (categories.includes("sentinels")) {
const sentinels = await kv.list(KV.sentinels);
for (const sentinel of sentinels) if (sentinel.status === "watching" && sentinel.expiresAt && new Date(sentinel.expiresAt).getTime() <= now) {
if (dryRun) {
details.push(`[dry-run] Would expire sentinel "${sentinel.name}" (${sentinel.id})`);
fixed++;
continue;
}
if (await withKeyedLock(`mem:sentinel:${sentinel.id}`, async () => {
const fresh = await kv.get(KV.sentinels, sentinel.id);
if (!fresh || fresh.status !== "watching") return false;
if (!fresh.expiresAt || new Date(fresh.expiresAt).getTime() > Date.now()) return false;
fresh.status = "expired";
await kv.set(KV.sentinels, fresh.id, fresh);
return true;
})) {
details.push(`Expired sentinel "${sentinel.name}" (${sentinel.id})`);
fixed++;
} else skipped++;
}
}
if (categories.includes("sketches")) {
const sketches = await kv.list(KV.sketches);
for (const sketch of sketches) if (sketch.status === "active" && new Date(sketch.expiresAt).getTime() <= now) {
if (dryRun) {
details.push(`[dry-run] Would discard expired sketch "${sketch.title}" (${sketch.id})`);
fixed++;
continue;
}
if (await withKeyedLock(`mem:sketch:${sketch.id}`, async () => {
const fresh = await kv.get(KV.sketches, sketch.id);
if (!fresh || fresh.status !== "active" || new Date(fresh.expiresAt).getTime() > Date.now()) return false;
const allEdges = await kv.list(KV.actionEdges);
const actionIdSet = new Set(fresh.actionIds);
for (const edge of allEdges) if (actionIdSet.has(edge.sourceActionId) || actionIdSet.has(edge.targetActionId)) await kv.delete(KV.actionEdges, edge.id);
for (const actionId of fresh.actionIds) await kv.delete(KV.actions, actionId);
fresh.status = "discarded";
fresh.discardedAt = (/* @__PURE__ */ new Date()).toISOString();
await kv.set(KV.sketches, fresh.id, fresh);
return true;
})) {
details.push(`Discarded expired sketch "${sketch.title}" (${sketch.id})`);
fixed++;
} else skipped++;
}
}
if (categories.includes("signals")) {
const signals = await kv.list(KV.signals);
for (const signal of signals) if (signal.expiresAt && new Date(signal.expiresAt).getTime() <= now) {
if (dryRun) {
details.push(`[dry-run] Would delete expired signal ${signal.id}`);
fixed++;
continue;
}
await kv.delete(KV.signals, signal.id);
details.push(`Deleted expired signal ${signal.id}`);
fixed++;
}
}
if (categories.includes("memories")) {
const memories = await kv.list(KV.memories);
const supersededBy = /* @__PURE__ */ new Map();
for (const memory of memories) if (memory.supersedes && memory.supersedes.length > 0) for (const sid of memory.supersedes) supersededBy.set(sid, memory.id);
for (const memory of memories) if (memory.isLatest && supersededBy.has(memory.id)) {
if (dryRun) {
details.push(`[dry-run] Would set isLatest=false on memory "${memory.title}" (${memory.id})`);
fixed++;
continue;
}
if (await withKeyedLock(`mem:memory:${memory.id}`, async () => {
const fresh = await kv.get(KV.memories, memory.id);
if (!fresh || !fresh.isLatest) return false;
fresh.isLatest = false;
fresh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
await kv.set(KV.memories, fresh.id, fresh);
return true;
})) {
details.push(`Set isLatest=false on memory "${memory.title}" (${memory.id})`);
fixed++;
} else skipped++;
}
}
return {
success: true,
fixed,
skipped,
details
};
});
}
//#endregion
export { registerDiagnosticsFunction };
//# sourceMappingURL=diagnostics.mjs.map
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env node
import { execSync } from "node:child_process";
import { basename } from "node:path";
//#region src/hooks/_project.ts
function resolveProject(cwd) {
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
if (explicit && explicit.trim()) return explicit.trim();
const dir = cwd && cwd.trim() ? cwd : process.cwd();
try {
const top = execSync("git rev-parse --show-toplevel", {
cwd: dir,
stdio: [
"ignore",
"pipe",
"ignore"
],
timeout: 500
}).toString().trim();
if (top) return basename(top);
} catch {}
return basename(dir);
}
//#endregion
//#region src/hooks/notification.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const notificationType = data.notification_type ?? data.notificationType;
if (notificationType !== "permission_prompt") return;
const rawSessionId = data.session_id ?? data.sessionId;
const sessionId = typeof rawSessionId === "string" && rawSessionId.length > 0 ? rawSessionId : "unknown";
fetch(`${REST_URL}/agentmemory/observe`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
hookType: "notification",
sessionId,
project: resolveProject(data.cwd),
cwd: data.cwd || process.cwd(),
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
data: {
notification_type: notificationType,
title: data.title,
message: data.message
}
}),
signal: AbortSignal.timeout(2e3)
}).catch(() => {});
setTimeout(() => process.exit(0), 500).unref();
}
main();
//#endregion
export { };
//# sourceMappingURL=notification.mjs.map
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env node
import { execFile } from "node:child_process";
import { promisify } from "node:util";
//#region src/hooks/post-commit.ts
const exec = promisify(execFile);
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
const TIMEOUT_MS = 1500;
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function git(args, cwd) {
try {
const { stdout } = await exec("git", args, {
cwd,
timeout: 1500
});
return stdout.trim();
} catch {
return null;
}
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data = {};
if (input.trim()) try {
data = JSON.parse(input);
} catch {}
if (isSdkChildContext(data)) return;
const cwd = data.cwd || process.env["AGENTMEMORY_CWD"] || process.cwd();
const sessionId = data.session_id || process.env["AGENTMEMORY_SESSION_ID"] || void 0;
const sha = process.env["AGENTMEMORY_COMMIT_SHA"] || await git(["rev-parse", "HEAD"], cwd);
if (!sha) return;
const branch = await git([
"rev-parse",
"--abbrev-ref",
"HEAD"
], cwd);
const repo = await git([
"config",
"--get",
"remote.origin.url"
], cwd);
const message = await git([
"log",
"-1",
"--pretty=%B",
sha
], cwd);
const author = await git([
"log",
"-1",
"--pretty=%an <%ae>",
sha
], cwd);
const authoredAt = await git([
"log",
"-1",
"--pretty=%aI",
sha
], cwd);
const filesRaw = await git([
"diff-tree",
"--no-commit-id",
"--name-only",
"-r",
sha
], cwd);
const files = filesRaw ? filesRaw.split("\n").filter(Boolean) : void 0;
const body = {
sessionId,
sha,
branch: branch || void 0,
repo: repo || void 0,
message: message || void 0,
author: author || void 0,
authoredAt: authoredAt || void 0,
files
};
try {
await fetch(`${REST_URL}/agentmemory/session/commit`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify(body),
signal: AbortSignal.timeout(TIMEOUT_MS)
});
} catch {}
}
main();
//#endregion
export { };
//# sourceMappingURL=post-commit.mjs.map
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env node
import { execSync } from "node:child_process";
import { basename } from "node:path";
//#region src/hooks/_project.ts
function resolveProject(cwd) {
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
if (explicit && explicit.trim()) return explicit.trim();
const dir = cwd && cwd.trim() ? cwd : process.cwd();
try {
const top = execSync("git rev-parse --show-toplevel", {
cwd: dir,
stdio: [
"ignore",
"pipe",
"ignore"
],
timeout: 500
}).toString().trim();
if (top) return basename(top);
} catch {}
return basename(dir);
}
//#endregion
//#region src/hooks/post-tool-failure.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
if (data.is_interrupt || data.isInterrupt) return;
const sessionId = data.session_id || data.sessionId || "unknown";
const toolName = data.tool_name ?? data.toolName;
const toolInput = data.tool_input ?? data.toolArgs;
const error = data.error ?? data.errorMessage;
fetch(`${REST_URL}/agentmemory/observe`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
hookType: "post_tool_failure",
sessionId,
project: resolveProject(data.cwd),
cwd: data.cwd || process.cwd(),
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
data: {
tool_name: toolName,
tool_input: typeof toolInput === "string" ? toolInput.slice(0, 4e3) : JSON.stringify(toolInput ?? "").slice(0, 4e3),
error: typeof error === "string" ? error.slice(0, 4e3) : JSON.stringify(error ?? "").slice(0, 4e3)
}
}),
signal: AbortSignal.timeout(3e3)
}).catch(() => {});
setTimeout(() => process.exit(0), 500).unref();
}
main();
//#endregion
export { };
//# sourceMappingURL=post-tool-failure.mjs.map
+122
View File
@@ -0,0 +1,122 @@
#!/usr/bin/env node
import { execSync } from "node:child_process";
import { basename } from "node:path";
//#region src/hooks/_project.ts
function resolveProject(cwd) {
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
if (explicit && explicit.trim()) return explicit.trim();
const dir = cwd && cwd.trim() ? cwd : process.cwd();
try {
const top = execSync("git rev-parse --show-toplevel", {
cwd: dir,
stdio: [
"ignore",
"pipe",
"ignore"
],
timeout: 500
}).toString().trim();
if (top) return basename(top);
} catch {}
return basename(dir);
}
//#endregion
//#region src/hooks/post-tool-use.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const sessionId = data.session_id || data.sessionId || "unknown";
const toolName = data.tool_name ?? data.toolName;
const toolInput = data.tool_input ?? data.toolArgs;
const { imageData, cleanOutput } = extractImageData(toolOutput(data));
fetch(`${REST_URL}/agentmemory/observe`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
hookType: "post_tool_use",
sessionId,
project: resolveProject(data.cwd),
cwd: data.cwd || process.cwd(),
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
data: {
tool_name: toolName,
tool_input: toolInput,
tool_output: truncate(cleanOutput, 8e3),
...imageData ? { image_data: imageData } : {}
}
}),
signal: AbortSignal.timeout(3e3)
}).catch(() => {});
setTimeout(() => process.exit(0), 500).unref();
}
function toolOutput(data) {
if (data.tool_response !== void 0) return data.tool_response;
if (data.tool_output !== void 0) return data.tool_output;
const result = data.tool_result ?? data.toolResult;
if (typeof result === "object" && result !== null) {
const obj = result;
return obj.text_result_for_llm ?? obj.textResultForLlm ?? result;
}
return result;
}
function isBase64Image(val) {
return typeof val === "string" && (val.startsWith("data:image/") || val.startsWith("iVBORw0KGgo") || val.startsWith("/9j/"));
}
function extractImageData(output) {
if (isBase64Image(output)) return {
imageData: output,
cleanOutput: "[image data extracted]"
};
if (typeof output === "object" && output !== null && !Array.isArray(output)) {
const obj = output;
let imageData;
const clean = {};
for (const [key, val] of Object.entries(obj)) if (!imageData && isBase64Image(val)) {
imageData = val;
clean[key] = "[image data extracted]";
} else clean[key] = val;
return {
imageData,
cleanOutput: clean
};
}
return {
imageData: void 0,
cleanOutput: output
};
}
function truncate(value, max) {
if (typeof value === "string" && value.length > max) return value.slice(0, max) + "\n[...truncated]";
if (typeof value === "object" && value !== null) {
const str = JSON.stringify(value);
if (str.length > max) return str.slice(0, max) + "...[truncated]";
return value;
}
return value;
}
main();
//#endregion
export { };
//# sourceMappingURL=post-tool-use.mjs.map
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env node
import { execSync } from "node:child_process";
import { basename } from "node:path";
//#region src/hooks/_project.ts
function resolveProject(cwd) {
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
if (explicit && explicit.trim()) return explicit.trim();
const dir = cwd && cwd.trim() ? cwd : process.cwd();
try {
const top = execSync("git rev-parse --show-toplevel", {
cwd: dir,
stdio: [
"ignore",
"pipe",
"ignore"
],
timeout: 500
}).toString().trim();
if (top) return basename(top);
} catch {}
return basename(dir);
}
//#endregion
//#region src/hooks/pre-compact.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const sessionId = data.session_id || data.sessionId || "unknown";
const project = resolveProject(data.cwd);
if (process.env["CLAUDE_MEMORY_BRIDGE"] === "true") try {
await fetch(`${REST_URL}/agentmemory/claude-bridge/sync`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({}),
signal: AbortSignal.timeout(5e3)
});
} catch {}
try {
const res = await fetch(`${REST_URL}/agentmemory/context`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
sessionId,
project,
budget: 1500
}),
signal: AbortSignal.timeout(5e3)
});
if (res.ok) {
const result = await res.json();
if (result.context) process.stdout.write(result.context);
}
} catch {}
}
main();
//#endregion
export { };
//# sourceMappingURL=pre-compact.mjs.map
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env node
//#region src/hooks/pre-tool-use.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const INJECT_CONTEXT = process.env["AGENTMEMORY_INJECT_CONTEXT"] === "true";
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
if (!INJECT_CONTEXT) return;
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const toolName = typeof data.tool_name === "string" ? data.tool_name : typeof data.toolName === "string" ? data.toolName : void 0;
if (!toolName) return;
const normalizedToolName = toolName.toLowerCase();
if (![
"edit",
"write",
"create",
"read",
"view",
"glob",
"grep"
].includes(normalizedToolName)) return;
const rawToolInput = data.tool_input ?? data.toolArgs;
const toolInput = typeof rawToolInput === "object" && rawToolInput !== null && !Array.isArray(rawToolInput) ? rawToolInput : {};
const files = [];
const fileKeys = normalizedToolName === "grep" ? ["path", "file"] : [
"file_path",
"path",
"file",
"pattern"
];
for (const key of fileKeys) {
const val = toolInput[key];
if (typeof val === "string" && val.length > 0) files.push(val);
}
if (files.length === 0) return;
const terms = [];
if (normalizedToolName === "grep" || normalizedToolName === "glob") {
const pattern = toolInput["pattern"];
if (typeof pattern === "string" && pattern.length > 0) terms.push(pattern);
}
const rawSessionId = data.session_id || data.sessionId;
const sessionId = typeof rawSessionId === "string" && rawSessionId.length > 0 ? rawSessionId : "unknown";
const project = typeof data.project === "string" && data.project.trim().length > 0 ? data.project.trim() : void 0;
try {
const res = await fetch(`${REST_URL}/agentmemory/enrich`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
sessionId,
files,
terms,
toolName,
...project !== void 0 && { project }
}),
signal: AbortSignal.timeout(2e3)
});
if (res.ok) {
const result = await res.json();
if (result.context) process.stdout.write(result.context);
}
} catch {}
}
main();
//#endregion
export { };
//# sourceMappingURL=pre-tool-use.mjs.map
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env node
import { execSync } from "node:child_process";
import { basename } from "node:path";
//#region src/hooks/_project.ts
function resolveProject(cwd) {
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
if (explicit && explicit.trim()) return explicit.trim();
const dir = cwd && cwd.trim() ? cwd : process.cwd();
try {
const top = execSync("git rev-parse --show-toplevel", {
cwd: dir,
stdio: [
"ignore",
"pipe",
"ignore"
],
timeout: 500
}).toString().trim();
if (top) return basename(top);
} catch {}
return basename(dir);
}
//#endregion
//#region src/hooks/prompt-submit.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const sessionId = data.session_id || data.sessionId || "unknown";
fetch(`${REST_URL}/agentmemory/observe`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
hookType: "prompt_submit",
sessionId,
project: resolveProject(data.cwd),
cwd: data.cwd || process.cwd(),
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
data: { prompt: data.prompt ?? data.userPrompt }
}),
signal: AbortSignal.timeout(3e3)
}).catch(() => {});
setTimeout(() => process.exit(0), 500).unref();
}
main();
//#endregion
export { };
//# sourceMappingURL=prompt-submit.mjs.map
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env node
//#region src/hooks/session-end.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const sessionId = data.session_id || data.sessionId || "unknown";
fetch(`${REST_URL}/agentmemory/session/end`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({ sessionId }),
signal: AbortSignal.timeout(3e4)
}).catch(() => {});
if (process.env["CONSOLIDATION_ENABLED"] === "true") {
fetch(`${REST_URL}/agentmemory/crystals/auto`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({ olderThanDays: 0 }),
signal: AbortSignal.timeout(6e4)
}).catch(() => {});
fetch(`${REST_URL}/agentmemory/consolidate-pipeline`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
tier: "all",
force: true
}),
signal: AbortSignal.timeout(12e4)
}).catch(() => {});
}
if (process.env["CLAUDE_MEMORY_BRIDGE"] === "true") fetch(`${REST_URL}/agentmemory/claude-bridge/sync`, {
method: "POST",
headers: authHeaders(),
signal: AbortSignal.timeout(3e4)
}).catch(() => {});
setTimeout(() => process.exit(0), 1500).unref();
}
main();
//#endregion
export { };
//# sourceMappingURL=session-end.mjs.map
+87
View File
@@ -0,0 +1,87 @@
#!/usr/bin/env node
import { execSync } from "node:child_process";
import { basename } from "node:path";
//#region src/hooks/_project.ts
function resolveProject(cwd) {
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
if (explicit && explicit.trim()) return explicit.trim();
const dir = cwd && cwd.trim() ? cwd : process.cwd();
try {
const top = execSync("git rev-parse --show-toplevel", {
cwd: dir,
stdio: [
"ignore",
"pipe",
"ignore"
],
timeout: 500
}).toString().trim();
if (top) return basename(top);
} catch {}
return basename(dir);
}
//#endregion
//#region src/hooks/session-start.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const INJECT_CONTEXT = process.env["AGENTMEMORY_INJECT_CONTEXT"] === "true";
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
const INJECT_TIMEOUT_MS = 1500;
const REGISTER_TIMEOUT_MS = 800;
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const sessionId = data.session_id || data.sessionId || `ses_${Date.now().toString(36)}`;
const cwd = data.cwd || process.cwd();
const project = resolveProject(data.cwd);
const url = `${REST_URL}/agentmemory/session/start`;
const init = {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
sessionId,
project,
cwd
})
};
if (!INJECT_CONTEXT) {
fetch(url, {
...init,
signal: AbortSignal.timeout(REGISTER_TIMEOUT_MS)
}).catch(() => {});
return;
}
try {
const res = await fetch(url, {
...init,
signal: AbortSignal.timeout(INJECT_TIMEOUT_MS)
});
if (res.ok) {
const result = await res.json();
if (result.context) process.stdout.write(result.context);
}
} catch {}
}
main();
//#endregion
export { };
//# sourceMappingURL=session-start.mjs.map
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env node
//#region src/hooks/stop.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const sessionId = data.session_id || data.sessionId || "unknown";
fetch(`${REST_URL}/agentmemory/summarize`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({ sessionId }),
signal: AbortSignal.timeout(12e4)
}).catch(() => {});
fetch(`${REST_URL}/agentmemory/session/end`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({ sessionId }),
signal: AbortSignal.timeout(5e3)
}).catch(() => {});
setTimeout(() => process.exit(0), 1500).unref();
}
main();
//#endregion
export { };
//# sourceMappingURL=stop.mjs.map
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env node
import { execSync } from "node:child_process";
import { basename } from "node:path";
//#region src/hooks/_project.ts
function resolveProject(cwd) {
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
if (explicit && explicit.trim()) return explicit.trim();
const dir = cwd && cwd.trim() ? cwd : process.cwd();
try {
const top = execSync("git rev-parse --show-toplevel", {
cwd: dir,
stdio: [
"ignore",
"pipe",
"ignore"
],
timeout: 500
}).toString().trim();
if (top) return basename(top);
} catch {}
return basename(dir);
}
//#endregion
//#region src/hooks/subagent-start.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
const TIMEOUT_MS = 800;
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const sessionId = data.session_id || data.sessionId || "unknown";
const agentId = data.agent_id || data.agentName;
const agentType = data.agent_type || data.agentDisplayName || data.agentName;
fetch(`${REST_URL}/agentmemory/observe`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
hookType: "subagent_start",
sessionId,
project: resolveProject(data.cwd),
cwd: data.cwd || process.cwd(),
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
data: {
agent_id: agentId,
agent_type: agentType
}
}),
signal: AbortSignal.timeout(TIMEOUT_MS)
}).catch(() => {});
setTimeout(() => process.exit(0), 500).unref();
}
main();
//#endregion
export { };
//# sourceMappingURL=subagent-start.mjs.map
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env node
import { execSync } from "node:child_process";
import { basename } from "node:path";
//#region src/hooks/_project.ts
function resolveProject(cwd) {
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
if (explicit && explicit.trim()) return explicit.trim();
const dir = cwd && cwd.trim() ? cwd : process.cwd();
try {
const top = execSync("git rev-parse --show-toplevel", {
cwd: dir,
stdio: [
"ignore",
"pipe",
"ignore"
],
timeout: 500
}).toString().trim();
if (top) return basename(top);
} catch {}
return basename(dir);
}
//#endregion
//#region src/hooks/subagent-stop.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const sessionId = data.session_id || data.sessionId || "unknown";
const agentId = data.agent_id || data.agentName;
const agentType = data.agent_type || data.agentDisplayName || data.agentName;
const lastMsg = typeof data.last_assistant_message === "string" ? data.last_assistant_message.slice(0, 4e3) : "";
fetch(`${REST_URL}/agentmemory/observe`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
hookType: "subagent_stop",
sessionId,
project: resolveProject(data.cwd),
cwd: data.cwd || process.cwd(),
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
data: {
agent_id: agentId,
agent_type: agentType,
last_message: lastMsg
}
}),
signal: AbortSignal.timeout(2e3)
}).catch(() => {});
setTimeout(() => process.exit(0), 500).unref();
}
main();
//#endregion
export { };
//# sourceMappingURL=subagent-stop.mjs.map
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env node
import { execSync } from "node:child_process";
import { basename } from "node:path";
//#region src/hooks/_project.ts
function resolveProject(cwd) {
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
if (explicit && explicit.trim()) return explicit.trim();
const dir = cwd && cwd.trim() ? cwd : process.cwd();
try {
const top = execSync("git rev-parse --show-toplevel", {
cwd: dir,
stdio: [
"ignore",
"pipe",
"ignore"
],
timeout: 500
}).toString().trim();
if (top) return basename(top);
} catch {}
return basename(dir);
}
//#endregion
//#region src/hooks/task-completed.ts
function isSdkChildContext(payload) {
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
if (!payload || typeof payload !== "object") return false;
return payload.entrypoint === "sdk-ts";
}
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
function authHeaders() {
const h = { "Content-Type": "application/json" };
if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
return h;
}
async function main() {
let input = "";
for await (const chunk of process.stdin) input += chunk;
let data;
try {
data = JSON.parse(input);
} catch {
return;
}
if (isSdkChildContext(data)) return;
const sessionId = data.session_id || "unknown";
fetch(`${REST_URL}/agentmemory/observe`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
hookType: "task_completed",
sessionId,
project: resolveProject(data.cwd),
cwd: data.cwd || process.cwd(),
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
data: {
task_id: data.task_id,
task_subject: data.task_subject,
task_description: typeof data.task_description === "string" ? data.task_description.slice(0, 2e3) : "",
teammate_name: data.teammate_name,
team_name: data.team_name
}
}),
signal: AbortSignal.timeout(2e3)
}).catch(() => {});
setTimeout(() => process.exit(0), 500).unref();
}
main();
//#endregion
export { };
//# sourceMappingURL=task-completed.mjs.map