import type { BotConfig } from "../config/config.js"; export type DiagnosticSessionState = "idle" | "processing" | "waiting"; type DiagnosticBaseEvent = { ts: number; seq: number; }; export type DiagnosticUsageEvent = DiagnosticBaseEvent & { type: "model.usage"; sessionKey?: string; sessionId?: string; channel?: string; provider?: string; model?: string; usage: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number; promptTokens?: number; total?: number; }; lastCallUsage?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number; total?: number; }; context?: { limit?: number; used?: number; }; costUsd?: number; durationMs?: number; }; export type DiagnosticWebhookReceivedEvent = DiagnosticBaseEvent & { type: "webhook.received"; channel: string; updateType?: string; chatId?: number | string; }; export type DiagnosticWebhookProcessedEvent = DiagnosticBaseEvent & { type: "webhook.processed"; channel: string; updateType?: string; chatId?: number | string; durationMs?: number; }; export type DiagnosticWebhookErrorEvent = DiagnosticBaseEvent & { type: "webhook.error"; channel: string; updateType?: string; chatId?: number | string; error: string; }; export type DiagnosticMessageQueuedEvent = DiagnosticBaseEvent & { type: "message.queued"; sessionKey?: string; sessionId?: string; channel?: string; source: string; queueDepth?: number; }; export type DiagnosticMessageProcessedEvent = DiagnosticBaseEvent & { type: "message.processed"; channel: string; messageId?: number | string; chatId?: number | string; sessionKey?: string; sessionId?: string; durationMs?: number; outcome: "completed" | "skipped" | "error"; reason?: string; error?: string; }; export type DiagnosticSessionStateEvent = DiagnosticBaseEvent & { type: "session.state"; sessionKey?: string; sessionId?: string; prevState?: DiagnosticSessionState; state: DiagnosticSessionState; reason?: string; queueDepth?: number; }; export type DiagnosticSessionStuckEvent = DiagnosticBaseEvent & { type: "session.stuck"; sessionKey?: string; sessionId?: string; state: DiagnosticSessionState; ageMs: number; queueDepth?: number; }; export type DiagnosticLaneEnqueueEvent = DiagnosticBaseEvent & { type: "queue.lane.enqueue"; lane: string; queueSize: number; }; export type DiagnosticLaneDequeueEvent = DiagnosticBaseEvent & { type: "queue.lane.dequeue"; lane: string; queueSize: number; waitMs: number; }; export type DiagnosticRunAttemptEvent = DiagnosticBaseEvent & { type: "run.attempt"; sessionKey?: string; sessionId?: string; runId: string; attempt: number; }; export type DiagnosticHeartbeatEvent = DiagnosticBaseEvent & { type: "diagnostic.heartbeat"; webhooks: { received: number; processed: number; errors: number; }; active: number; waiting: number; queued: number; }; export type DiagnosticToolLoopEvent = DiagnosticBaseEvent & { type: "tool.loop"; sessionKey?: string; sessionId?: string; toolName: string; level: "warning" | "critical"; action: "warn" | "block"; detector: "generic_repeat" | "known_poll_no_progress" | "global_circuit_breaker" | "ping_pong"; count: number; message: string; pairedToolName?: string; }; export type DiagnosticEventPayload = DiagnosticUsageEvent | DiagnosticWebhookReceivedEvent | DiagnosticWebhookProcessedEvent | DiagnosticWebhookErrorEvent | DiagnosticMessageQueuedEvent | DiagnosticMessageProcessedEvent | DiagnosticSessionStateEvent | DiagnosticSessionStuckEvent | DiagnosticLaneEnqueueEvent | DiagnosticLaneDequeueEvent | DiagnosticRunAttemptEvent | DiagnosticHeartbeatEvent | DiagnosticToolLoopEvent; export type DiagnosticEventInput = DiagnosticEventPayload extends infer Event ? Event extends DiagnosticEventPayload ? Omit : never : never; export declare function isDiagnosticsEnabled(config?: BotConfig): boolean; export declare function emitDiagnosticEvent(event: DiagnosticEventInput): void; export declare function onDiagnosticEvent(listener: (evt: DiagnosticEventPayload) => void): () => void; export declare function resetDiagnosticEventsForTest(): void; export {};