/**
 * One row in `hdb_model_calls`. Field names are snake_case to match the table
 * schema. Numeric token counts are optional because not every backend reports
 * every metric.
 */
export interface ModelCallRecord {
    tenant?: string;
    app?: string;
    model?: string;
    backend: string;
    method: 'embed' | 'generate' | 'generateStream';
    adapter?: string;
    conversation_id?: string;
    prompt_tokens?: number;
    completion_tokens?: number;
    embedding_tokens?: number;
    gpu_ms?: number;
    latency_ms: number;
    success: boolean;
    /** Sanitized code (e.g. 'backend_error', 'aborted', 'capability_unsupported'). Never a raw upstream message. */
    error_code?: string;
}
/**
 * Lazy-getter for `hdb_model_calls`. Matches the convention used by
 * `getRawAnalyticsTable()` / `getAnalyticsTable()` in
 * `resources/analytics/write.ts:656-700` and the system-table declarations in
 * `server/DurableSubscriptionsSession.ts:14-50`.
 */
export declare function getModelCallsTable(): any;
export interface ModelCallAnalyticsWriterOpts {
    /** Default 10s. Buffer is flushed at this cadence regardless of size. */
    flushIntervalMs?: number;
    /** Default 1000. Reaching this size triggers an out-of-cadence flush. */
    maxBufferSize?: number;
    /** Default 1h. How often `cleanup()` runs to remove expired rows. */
    cleanupIntervalMs?: number;
    /** Default 90d. Rows older than this are removed by `cleanup()`. */
    retentionMs?: number;
    /** Override the table accessor. Tests inject a mock to avoid touching real LMDB. */
    getTable?: () => any;
}
/**
 * In-memory buffered writer for per-call model analytics. Rows are batched and
 * flushed periodically (or when the buffer is full) to keep the analytics path
 * off the hot model-call path. Shape mirrors the pattern in
 * `resources/analytics/write.ts` but writes per-call rows rather than
 * aggregating counters.
 *
 * The intervals are `.unref()`ed so they never hold the process open during
 * shutdown; rows buffered at shutdown are dropped (best-effort, same posture
 * as the existing analytics writer).
 */
export declare class ModelCallAnalyticsWriter {
    #private;
    constructor(opts?: ModelCallAnalyticsWriterOpts);
    write(record: ModelCallRecord): void;
    flush(): Promise<void>;
    cleanup(): Promise<void>;
    /** Stop the periodic timers. After stop, `write()` is a no-op and `flush()` still works. */
    stop(): void;
    /** Test-only: inspect current buffer size without flushing. */
    get bufferSize(): number;
}
/** Process-wide singleton writer. Constructed on first access. */
export declare function getModelCallAnalyticsWriter(): ModelCallAnalyticsWriter;
