/** Provider request/response capture middleware (plan 062, review §7 P1): * opt-in observation of already-normalized provider shapes — never raw HTTP. * * Request side rides the existing `provider_request` middleware hook; response * side rides the existing subscriber-event seam (`provider_turn_finished`, * which core already redacts). No new seam. Captured entries land in a capped * FIFO ring buffer (`maxEvents`, default 100). * * Privacy policy `redact` controls content retention: * - `"all"`: structure only — model id, counts, tool names, usage, latency. * - `"secrets"` (default): also drops message content (the privacy default: * captured buffers carry no conversation text unless the host opts in). * - `"none"`: retains message content for replay debugging. * Secret redaction is unconditional in every mode (replay-safe by * construction): retained material passes through the same `redactSecrets` * helper the logging seams use, so credentials never survive into a buffer * that a host might persist or replay. Provider request/response options and * headers are never captured at all — headers are where credentials ride. */ import type { AgentEvent, ProviderRequest } from "./contracts.js"; import type { Middleware } from "./middleware.js"; import { type SecretRedactor } from "./redaction.js"; export type CaptureRedaction = "secrets" | "all" | "none"; export interface ProviderCapturePolicy { /** Content-retention level; `"secrets"` (default) drops message content. */ readonly redact?: CaptureRedaction; /** Ring-buffer capacity; oldest entries evict first. Default 100. */ readonly maxEvents?: number; } export interface ProviderCaptureOptions { readonly policy?: ProviderCapturePolicy; /** Secrets redacted from every retained field, matching the logging seams. */ readonly secrets?: readonly (string | undefined)[]; readonly redactor?: SecretRedactor; readonly now?: () => number; } export interface ProviderCaptureEntry { readonly kind: "request" | "response"; readonly at: string; readonly redaction: CaptureRedaction; readonly provider?: string; readonly model?: string; readonly messageCount?: number; readonly toolNames?: readonly string[]; /** Message content — present only when the policy retains it (`"none"`), secrets redacted. */ readonly content?: unknown; /** Response entries: normalized usage numbers (never sensitive). */ readonly usage?: unknown; readonly latencyMs?: number; readonly error?: unknown; } export interface ProviderCapture { /** Register on the existing `provider_request` middleware hook. Passes the * request through untouched and records one entry per round. */ middleware(): Middleware; /** Feed `provider_turn_finished` events from the session's existing * subscriber loop (`session.subscribe()`) to record response entries. */ observeEvent(event: AgentEvent): void; /** Ring-buffer snapshot, oldest first. */ events(): readonly ProviderCaptureEntry[]; clear(): void; } export declare function createProviderCapture(options?: ProviderCaptureOptions): ProviderCapture;