import type { ExtensionDiagnosticInput } from "./extension-diagnostics"; import type { McpConnection } from "./mcp"; import type { ModelProvider } from "./model-providers"; /** Support metadata only. Never add conversation content or arbitrary metadata. */ export const DIAGNOSTIC_LIMITS = { maxAgeMs: 7 * 24 * 60 * 60 * 1000, maxRows: 500, maxStoreBytes: 256 * 1024, maxEventBytes: 2048, maxExportBytes: 600 * 1024, } as const; export type DiagnosticKind = | "extension" | "approval" | "turn" | "model" | "model-attempt" | "tool" | "task" | "connection" | "recovery"; export interface DiagnosticEvent { kind: DiagnosticKind; timestamp: number; id: string | null; conversationId: string | null; requestId: string | null; phase: "start" | "finish" | "transition"; status: | "started" | "completed" | "error" | "aborted" | "skipped" | "pending" | "running" | "succeeded" | "failed" | "cancelled" | "dispatching" | "dispatch_error" | "detected" | "connected" | "disconnected" | "unknown"; durationMs: number | null; details: { extensionOperation?: ExtensionDiagnosticInput["operation"]; extensionFailure?: ExtensionDiagnosticInput["failure"]; capabilityVersion?: string | null; approvalResolution?: "approved" | "denied"; capabilityId?: string | null; capabilityFingerprint?: string | null; capabilitySourceId?: string | null; capabilitySourceKind?: "mcp" | "skill"; approvalDecision?: "allow" | "ask" | "never" | "unavailable"; policyRevision?: number; policySource?: "capability" | "source" | "default"; provider?: ModelProvider | "unknown"; model?: string | null; httpStatus?: number | null; failureStage?: "request" | "stream-read" | "stream-event"; errorCategory?: | "authentication" | "billing" | "rate-limit" | "not-found" | "upstream-unavailable" | "invalid-request" | "unknown"; gatewayErrorCode?: number | null; cfRay?: string | null; step?: number | null; responseTimeMs?: number | null; stepTimeMs?: number | null; timeToFirstOutputMs?: number | null; inputTokens?: number | null; outputTokens?: number | null; totalTokens?: number | null; cacheReadTokens?: number | null; cacheWriteTokens?: number | null; reasoningTokens?: number | null; cost?: null; tool?: string | null; toolKind?: "memory" | "web" | "browser" | "shell" | "schedule" | "other"; attempts?: number | null; reason?: | "tool-error" | "turn-cancelled" | "interrupted" | "incomplete" | "approval-denied" | null; taskId?: string | null; submissionId?: string | null; source?: "scheduled" | "manual"; claimedAt?: number | null; completedAt?: number | null; claimToCompletionMs?: number | null; code?: number | null; trigger?: | "ws-chat" | "rpc" | "submission" | "programmatic" | "agent-tool" | "unknown"; }; } export interface DiagnosticSnapshot { events: (DiagnosticEvent & { sequence: number })[]; oldestAt: number | null; newestAt: number | null; /** Cumulative pruning for this store, including scopes not selected here. */ prunedRows: number; omittedRows: number; available: boolean; } export interface DiagnosticExport { schemaVersion: 1; applicationVersion: string; sdkVersions: { agents: string; think: string; ai: string }; exportedAt: string; scope: { runtime: true; conversationId: string | null }; limits: typeof DIAGNOSTIC_LIMITS; availability: { history: "best-effort"; unfinishedStarts: "outcome-unknown"; usage: "reported-fields-only-workers-ai-zero-unavailable"; cost: "unavailable"; taskDuration: "claim-includes-queue-use-turn-duration-for-execution"; content: "excluded"; }; mcpConnections?: Array< Pick & { id: string | null; } >; runtime: DiagnosticSnapshot; conversation: DiagnosticSnapshot | null; }