/**
 * proxy.ts
 *
 * A lightweight HTTP recording proxy that captures all outbound requests
 * made by an AI agent during evaluation. Instead of being an actual network
 * proxy (which requires HTTPS MITM certificates), this module provides:
 *
 *   1. A `fetch` wrapper that records every request/response
 *   2. A session manager that groups observations by test case
 *
 * This design works with any agent framework that uses `fetch` or can be
 * configured to use a custom HTTP client. For agents that use a real browser,
 * see the Chrome DevTools Protocol integration (future work).
 *
 * Usage:
 *   const recorder = new RequestRecorder()
 *   recorder.start('session-123')
 *
 *   // The agent makes requests through the recorder's fetch wrapper
 *   const response = await recorder.fetch('https://sanity.io/docs/groq')
 *
 *   const log = recorder.stop()
 *   // → AgentBehaviorLog with all requests classified
 *
 * W0133 — per-class preview byte caps
 *
 * `responsePreview` is capped at `previewLimits.default` (4 KB) for most
 * responses, with per-class overrides for two payloads whose contents are
 * the ground truth for trace audits:
 *
 *   - `previewLimits.search` (16 KB) — Jina-wrapped DuckDuckGo, Google CSE,
 *     bing.com/search, duckduckgo.com, google.com/search responses. Captures
 *     the full result list (typical 8–10 KB) so trace audits can resolve
 *     which result the model fetched next.
 *   - `previewLimits.llmsTxt` (128 KB) — `/llms.txt` responses. The Sanity
 *     index is ~110 KB. Capturing the full body lets trace audits
 *     distinguish "model fetched a path that wasn't in the index" from
 *     "model fetched a path that was in the index but the page is missing".
 *
 * The slim Content Lake report (W0051) does not inline previews — they
 * live in the GCS `traces` NDJSON artifact only, so bumping these caps
 * has no effect on the 10 MB Sanity document budget.
 */
import type { ObservedRequest, AgentBehaviorLog } from "./types.js";
export interface RecorderOptions {
    /** Headers to capture from requests (case-insensitive). Default: common ones */
    captureHeaders?: string[];
    /** Whether to capture response body previews. Default: true */
    captureResponsePreview?: boolean;
    /** Filter: skip requests matching these URL patterns. Default: skip none.
     *  Accepts RegExp or string (strings are auto-converted to case-insensitive RegExp). */
    excludePatterns?: (RegExp | string)[];
    /** Filter: only fully record requests matching these URL patterns. Default: record all fully.
     *  When `statusOnlyForUnmatched` is true (default), unmatched URLs still emit a slim
     *  status-only observation. Accepts RegExp or string (strings are auto-converted to
     *  case-insensitive RegExp). */
    includePatterns?: (RegExp | string)[];
    /** Maximum request body bytes to capture. Default: 4096 */
    maxBodyBytes?: number;
    /**
     * Default response preview byte cap. Default: 4096.
     *
     * Per-class overrides in `previewLimits` may extend this for specific
     * URL patterns. If `previewLimits` is set, `previewLimits.default` wins
     * over `maxPreviewBytes`.
     */
    maxPreviewBytes?: number;
    /**
     * Per-class response preview byte caps (W0133). Lets the recorder
     * capture larger previews for response classes whose contents are the
     * ground truth for trace audits, without inflating preview size for
     * generic responses.
     *
     * - `default` — used when no other class matches. Falls back to
     *   `maxPreviewBytes` when omitted (defaults to 4 KB).
     * - `search` — Jina-wrapped DuckDuckGo, Google CSE, bing/duckduckgo,
     *   google.com/search responses. Default: 16 KB.
     * - `llmsTxt` — `/llms.txt` responses. Default: 128 KB.
     */
    previewLimits?: {
        default?: number;
        llmsTxt?: number;
        search?: number;
    };
    /**
     * When a URL fails `includePatterns` but passes `excludePatterns`, emit a
     * slim observation (url/method/statusCode/latencyMs/timestamp/seq, with
     * `capture: "status-only"`) instead of dropping it entirely. Default: true.
     *
     * Setting to `false` restores strict-allowlist behavior — unmatched URLs
     * are dropped, leaving no record of the call. The default exists so
     * model-side traffic to api.openai.com / api.anthropic.com /
     * googleapis.com is visible in run artifacts without recording prompts,
     * completions, or API keys. See W0132.
     */
    statusOnlyForUnmatched?: boolean;
}
export declare class RequestRecorder {
    private observations;
    private options;
    private provider;
    private running;
    private seq;
    private sessionId;
    private startTime;
    private taskDescription;
    constructor(options?: RecorderOptions);
    /**
     * A `fetch`-compatible wrapper that records the request and response,
     * then returns the real response unmodified.
     *
     * Drop-in replacement: `const response = await recorder.fetch(url, init)`
     */
    fetch(input: Request | string | URL, init?: RequestInit): Promise<Response>;
    /**
     * Whether the recorder is currently active.
     */
    isRunning(): boolean;
    /**
     * Get current observations without stopping the recorder.
     */
    peek(): ObservedRequest[];
    /**
     * Record an externally-observed request/response pair.
     *
     * Use this when you can't wrap `fetch` directly but can observe traffic
     * (e.g., via browser DevTools Protocol, mitmproxy logs, etc.).
     *
     * Filter behavior (W0132):
     * - `excludePatterns` always drops the observation entirely.
     * - `includePatterns` mismatch produces a slim `capture: "status-only"`
     *   record when `statusOnlyForUnmatched` is true (default), or drops it
     *   when false.
     * - The discriminator on the input is honored: callers that already
     *   know they're emitting a slim record (e.g., the fetch wrapper) can
     *   set `capture: "status-only"` themselves.
     */
    record(observation: Omit<ObservedRequest, "seq">): void;
    /**
     * Resolve the preview byte cap for a given URL using per-class overrides
     * (W0133). Order of preference:
     *   1. `previewLimits.llmsTxt` for `/llms.txt` URLs.
     *   2. `previewLimits.search` for known search providers.
     *   3. `previewLimits.default`.
     */
    private resolvePreviewBytes;
    /**
     * Decide how to record a URL given the current filter configuration.
     *
     * - `"drop"` — `excludePatterns` matched, or `includePatterns` failed
     *   and `statusOnlyForUnmatched` is false.
     * - `"status-only"` — `includePatterns` failed but
     *   `statusOnlyForUnmatched` is true (default). Skip body/headers.
     * - `"full"` — record everything.
     *
     * See W0132.
     */
    private classifyCaptureMode;
    /**
     * Reset the recorder for reuse without creating a new instance.
     */
    reset(): void;
    /**
     * Start a new recording session. Call this before the agent runs a task.
     */
    start(sessionId: string, provider: string, taskDescription: string): void;
    /**
     * Stop recording and return the complete behavior log with
     * classified observations and summary statistics.
     */
    stop(): AgentBehaviorLog;
    private computeSummary;
    private extractBody;
    private extractHeaders;
    private redactSensitive;
}
