feat(hooks): add Hermes telemetry handler

This commit is contained in:
William Valentin
2026-05-20 17:35:56 -07:00
parent 78376bdd83
commit 27d40ce28f
9 changed files with 2452 additions and 0 deletions
+23
View File
@@ -172,6 +172,7 @@ async function readStdin() {
var INGEST_URL = process.env.AGENTMON_INGEST_URL || "http://localhost:8080";
var FRAMEWORK = process.env.AGENTMON_FRAMEWORK || "claude-code";
var HOST = process.env.AGENTMON_HOST || hostname();
var ALLOW_STARTUP_SESSIONS = process.env.AGENTMON_CLAUDE_ALLOW_STARTUP === "1";
var { enqueue, flush } = createTransport(INGEST_URL);
var STATE_DIR = join(homedir(), ".agentmon-state");
function ensureStateDir() {
@@ -231,6 +232,15 @@ function isNonPersistentClaudeLaunch() {
({ cmd }) => cmd.includes("/claude") && cmd.includes("--no-session-persistence")
);
}
function hasClaudeProcessAncestor() {
return getProcessTree().some(({ cmd }) => {
if (!cmd)
return false;
if (cmd.includes("agentmon-handler") || cmd.includes("/hooks/claude-code/handler"))
return false;
return /(^|[/\s])claude(\s|$)/.test(cmd) || cmd.includes("@anthropic-ai/claude-code");
});
}
var activeRuns = /* @__PURE__ */ new Map();
var activeSpans = /* @__PURE__ */ new Map();
var activeSubagents = /* @__PURE__ */ new Map();
@@ -319,6 +329,10 @@ async function handleSessionStart(input) {
console.error("[agentmon] ignoring claude-code startup from --no-session-persistence launch");
return;
}
if (pickString(input.source) === "startup" && (!ALLOW_STARTUP_SESSIONS || !hasClaudeProcessAncestor())) {
console.error("[agentmon] ignoring claude-code startup session");
return;
}
const runId = randomUUID2();
activeRuns.set(sessionKey, runId);
saveState(sessionKey, { runId, spans: {} });
@@ -388,6 +402,15 @@ async function handlePromptSubmit(input) {
}
}));
}
if (!runId && sessionKey) {
enqueue(buildEnvelope(FRAMEWORK, HOST, "session.start", sessionKey, {
attributes: {
cwd: pickString(input.cwd),
transcript_path: pickString(input.transcript_path),
source: pickString(input.source)
}
}));
}
const newRunId = randomUUID2();
if (sessionKey) {
activeRuns.set(sessionKey, newRunId);
+23
View File
@@ -17,6 +17,7 @@ import {
const INGEST_URL = process.env.AGENTMON_INGEST_URL || 'http://localhost:8080';
const FRAMEWORK = process.env.AGENTMON_FRAMEWORK || 'claude-code';
const HOST = process.env.AGENTMON_HOST || hostname();
const ALLOW_STARTUP_SESSIONS = process.env.AGENTMON_CLAUDE_ALLOW_STARTUP === '1';
const { enqueue, flush } = createTransport(INGEST_URL);
@@ -89,6 +90,14 @@ function isNonPersistentClaudeLaunch() {
cmd.includes('/claude') && cmd.includes('--no-session-persistence')
);
}
function hasClaudeProcessAncestor() {
return getProcessTree().some(({ cmd }) => {
if (!cmd) return false;
if (cmd.includes('agentmon-handler') || cmd.includes('/hooks/claude-code/handler')) return false;
return /(^|[/\s])claude(\s|$)/.test(cmd) || cmd.includes('@anthropic-ai/claude-code');
});
}
// ─────────────────────────────────────────────────────────────────────────────
const activeRuns = new Map<string, string>();
@@ -182,6 +191,10 @@ async function handleSessionStart(input: Dict) {
console.error('[agentmon] ignoring claude-code startup from --no-session-persistence launch');
return;
}
if (pickString(input.source) === 'startup' && (!ALLOW_STARTUP_SESSIONS || !hasClaudeProcessAncestor())) {
console.error('[agentmon] ignoring claude-code startup session');
return;
}
const runId = randomUUID();
activeRuns.set(sessionKey, runId);
@@ -262,6 +275,16 @@ async function handlePromptSubmit(input: Dict) {
}));
}
if (!runId && sessionKey) {
enqueue(buildEnvelope(FRAMEWORK, HOST, 'session.start', sessionKey, {
attributes: {
cwd: pickString(input.cwd),
transcript_path: pickString(input.transcript_path),
source: pickString(input.source),
},
}));
}
const newRunId = randomUUID();
if (sessionKey) {
activeRuns.set(sessionKey, newRunId);