78 lines
2.1 KiB
TypeScript
78 lines
2.1 KiB
TypeScript
import type { VerboseLevel } from "../auto-reply/thinking.js";
|
|
|
|
export type AgentEventStream = "lifecycle" | "tool" | "assistant" | "error" | (string & {});
|
|
|
|
export type AgentEventPayload = {
|
|
runId: string;
|
|
seq: number;
|
|
stream: AgentEventStream;
|
|
ts: number;
|
|
data: Record<string, unknown>;
|
|
sessionKey?: string;
|
|
};
|
|
|
|
export type AgentRunContext = {
|
|
sessionKey?: string;
|
|
verboseLevel?: VerboseLevel;
|
|
};
|
|
|
|
// Keep per-run counters so streams stay strictly monotonic per runId.
|
|
const seqByRun = new Map<string, number>();
|
|
const listeners = new Set<(evt: AgentEventPayload) => void>();
|
|
const runContextById = new Map<string, AgentRunContext>();
|
|
|
|
export function registerAgentRunContext(runId: string, context: AgentRunContext) {
|
|
if (!runId) return;
|
|
const existing = runContextById.get(runId);
|
|
if (!existing) {
|
|
runContextById.set(runId, { ...context });
|
|
return;
|
|
}
|
|
if (context.sessionKey && existing.sessionKey !== context.sessionKey) {
|
|
existing.sessionKey = context.sessionKey;
|
|
}
|
|
if (context.verboseLevel && existing.verboseLevel !== context.verboseLevel) {
|
|
existing.verboseLevel = context.verboseLevel;
|
|
}
|
|
}
|
|
|
|
export function getAgentRunContext(runId: string) {
|
|
return runContextById.get(runId);
|
|
}
|
|
|
|
export function clearAgentRunContext(runId: string) {
|
|
runContextById.delete(runId);
|
|
}
|
|
|
|
export function resetAgentRunContextForTest() {
|
|
runContextById.clear();
|
|
}
|
|
|
|
export function emitAgentEvent(event: Omit<AgentEventPayload, "seq" | "ts">) {
|
|
const nextSeq = (seqByRun.get(event.runId) ?? 0) + 1;
|
|
seqByRun.set(event.runId, nextSeq);
|
|
const context = runContextById.get(event.runId);
|
|
const sessionKey =
|
|
typeof event.sessionKey === "string" && event.sessionKey.trim()
|
|
? event.sessionKey
|
|
: context?.sessionKey;
|
|
const enriched: AgentEventPayload = {
|
|
...event,
|
|
sessionKey,
|
|
seq: nextSeq,
|
|
ts: Date.now(),
|
|
};
|
|
for (const listener of listeners) {
|
|
try {
|
|
listener(enriched);
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
}
|
|
|
|
export function onAgentEvent(listener: (evt: AgentEventPayload) => void) {
|
|
listeners.add(listener);
|
|
return () => listeners.delete(listener);
|
|
}
|