import { EventEmitter } from 'node:events'; /** Fired by audit-log.logInvocation after a successful (or failed) agent * invocation has been recorded. Mirrors the shape audit-log already * builds, plus a `ts` ISO string for client-side sorting. */ export interface AuditEvent { type: 'audit'; ts: string; agent: string; intent: string; platform: string; durationMs: number; cost: number; success: boolean; traceId: string; userId: string; } /** Fired when approval-bus enqueues a new pending or resolves one. The * /api/approvals snapshot is still authoritative; this event lets the * UI refresh that tab (and the in-chat card) without waiting on the * 3 s poll. */ export interface ApprovalEvent { type: 'approval'; phase: 'requested' | 'resolved'; reqId: string; threadId: string; platform: string; toolName: string; /** Present on resolved events — 'allow' / 'deny' / 'timeout' from the * bus's metrics buckets. Absent on `requested`. */ outcome?: 'allow' | 'deny' | 'timeout'; } /** Fired on job-board state transitions. The dashboard subscribes to * refresh the Jobs tab without polling. */ export interface JobEvent { type: 'job'; phase: 'created' | 'started' | 'completed' | 'failed' | 'cancelled'; jobId: number; agent: string; } /** Periodic metrics tick. Different from individual audit events: this * is a snapshot of the full per-agent state (counters + latency * quantiles) so the Health tab's sparkline doesn't have to derive * everything from raw audits. Emitted by an internal interval, not by * any specific call site. */ export interface MetricsEvent { type: 'metrics'; ts: string; agents: Array<{ agent: string; total: number; success: number; failure: number; p50Ms: number; p95Ms: number; p99Ms: number; }>; } /** v1.2.86 — long-task goal state changes. Fired when a goal is * created, has its status changed, or gets a progress note appended. * Web /tasks/goals subscribes via SSE so the list refreshes in real * time without a manual reload. */ export interface GoalEvent { type: 'goal'; phase: 'created' | 'status' | 'progress'; goalId: number; platform: string; channelId: string; threadId: string; /** New status when phase='status' or 'created'. */ status?: 'active' | 'paused' | 'completed' | 'cancelled'; /** Short headline (truncated title or progress note) for UI consumers. */ summary?: string; ts: string; } export type AgimEvent = AuditEvent | ApprovalEvent | JobEvent | MetricsEvent | GoalEvent; declare class AgimEventBus extends EventEmitter { /** Bounded recent-event log so a freshly-connected SSE client can * catch up on what happened in the last few seconds without needing * a separate REST poll. Cap at 200 entries — enough for the dashboard * to show a meaningful "what just happened" feed without bloating * process memory. */ private recent; private static readonly RECENT_CAP; constructor(); /** * Publish a typed event. Listeners are called synchronously inside * EventEmitter.emit; errors thrown from a listener are caught here so * a bad subscriber can't break audit-log / approval-bus / job-board. */ publish(event: AgimEvent): void; /** Snapshot of the recent ring buffer. Used by SSE handler on * connection to replay the last N events to a fresh client. */ getRecent(): AgimEvent[]; } export declare const eventBus: AgimEventBus; export {}; //# sourceMappingURL=event-bus.d.ts.map