feat(hooks): add telemetry handlers for codex/copilot/gemini
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
import { Plugin } from "@opencode-ai/plugin";
|
||||
|
||||
const INGEST_URL = process.env.AGENTMON_INGEST_URL || "http://localhost:8080";
|
||||
|
||||
let buffer: any[] = [];
|
||||
let flushTimer: NodeJS.Timeout | null = null;
|
||||
const BATCH_SIZE = 10;
|
||||
const FLUSH_MS = 2000;
|
||||
|
||||
let currentSessionId: string | undefined;
|
||||
let currentRunId: string | undefined;
|
||||
|
||||
function enqueue(event: any) {
|
||||
buffer.push(event);
|
||||
if (buffer.length >= BATCH_SIZE) {
|
||||
flush();
|
||||
} else if (!flushTimer) {
|
||||
flushTimer = setTimeout(flush, FLUSH_MS);
|
||||
}
|
||||
}
|
||||
|
||||
async function flush() {
|
||||
if (flushTimer) {
|
||||
clearTimeout(flushTimer);
|
||||
flushTimer = null;
|
||||
}
|
||||
if (buffer.length === 0) return;
|
||||
|
||||
const batch = buffer.splice(0, BATCH_SIZE);
|
||||
try {
|
||||
await fetch(`${INGEST_URL}/v1/events`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(batch),
|
||||
});
|
||||
} catch (e) {
|
||||
console.debug("[agentmon] failed to flush events");
|
||||
}
|
||||
}
|
||||
|
||||
function buildEnvelope(type: string, data: any) {
|
||||
return {
|
||||
schema: { name: "agentmon.event", version: 1 },
|
||||
event: {
|
||||
id: crypto.randomUUID(),
|
||||
type,
|
||||
ts: new Date().toISOString(),
|
||||
source: {
|
||||
framework: "opencode",
|
||||
client_id: "opencode",
|
||||
host: require("os").hostname(),
|
||||
},
|
||||
},
|
||||
...(data.correlation && { correlation: data.correlation }),
|
||||
...(data.payload && { payload: data.payload }),
|
||||
...(data.attributes && { attributes: data.attributes }),
|
||||
};
|
||||
}
|
||||
|
||||
export const agentmon: Plugin = async (input) => {
|
||||
return {
|
||||
"tool.execute.before": async (data: any) => {
|
||||
if (!currentSessionId) {
|
||||
currentSessionId = crypto.randomUUID();
|
||||
currentRunId = crypto.randomUUID();
|
||||
|
||||
enqueue(buildEnvelope("session.start", {
|
||||
correlation: { session_id: currentSessionId },
|
||||
}));
|
||||
|
||||
enqueue(buildEnvelope("run.start", {
|
||||
correlation: { session_id: currentSessionId, run_id: currentRunId },
|
||||
}));
|
||||
}
|
||||
|
||||
const spanId = crypto.randomUUID();
|
||||
enqueue(buildEnvelope("span.start", {
|
||||
correlation: { session_id: currentSessionId, run_id: currentRunId, span_id: spanId },
|
||||
attributes: { span_kind: "tool", name: data.tool },
|
||||
payload: { input: (JSON.stringify(data.input) ?? "").substring(0, 200) },
|
||||
}));
|
||||
},
|
||||
|
||||
"tool.execute.after": async (data: any) => {
|
||||
if (!currentSessionId || !currentRunId) return;
|
||||
|
||||
enqueue(buildEnvelope("span.end", {
|
||||
correlation: { session_id: currentSessionId, run_id: currentRunId },
|
||||
attributes: { span_kind: "tool", name: data.tool },
|
||||
payload: {
|
||||
status: data.error ? "error" : "success",
|
||||
result_preview: data.result ? JSON.stringify(data.result).substring(0, 500) : undefined,
|
||||
duration_ms: data.duration,
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
||||
"chat.message": async (data: any) => {
|
||||
if (!currentSessionId) {
|
||||
currentSessionId = data.sessionID || crypto.randomUUID();
|
||||
currentRunId = crypto.randomUUID();
|
||||
|
||||
enqueue(buildEnvelope("session.start", {
|
||||
correlation: { session_id: currentSessionId },
|
||||
}));
|
||||
|
||||
enqueue(buildEnvelope("run.start", {
|
||||
correlation: { session_id: currentSessionId, run_id: currentRunId },
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
"experimental.session.compacting": async (data: any) => {
|
||||
if (currentSessionId && currentRunId) {
|
||||
enqueue(buildEnvelope("span.start", {
|
||||
correlation: { session_id: currentSessionId, run_id: currentRunId },
|
||||
attributes: { span_kind: "internal", name: "context_compaction" },
|
||||
}));
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user