import { SecureContextOptions } from 'node:tls';

type EventType = 'network' | 'console' | 'session' | 'state' | 'render' | 'dom_snapshot' | 'performance' | 'database' | 'custom' | 'navigation' | 'ui' | 'recon_metadata' | 'recon_design_tokens' | 'recon_fonts' | 'recon_layout_tree' | 'recon_accessibility' | 'recon_computed_styles' | 'recon_element_snapshot' | 'recon_asset_inventory';
interface BaseEvent {
    eventId: string;
    sessionId: string;
    timestamp: number;
    eventType: EventType;
}
interface GraphQLOperation {
    type: 'query' | 'mutation' | 'subscription';
    name: string;
}
interface NetworkEvent extends BaseEvent {
    eventType: 'network';
    url: string;
    method: string;
    status: number;
    requestHeaders: Record<string, string>;
    responseHeaders: Record<string, string>;
    requestBodySize: number;
    responseBodySize: number;
    duration: number;
    ttfb: number;
    graphqlOperation?: GraphQLOperation;
    requestBody?: string;
    responseBody?: string;
    errorPhase?: 'error' | 'abort' | 'timeout';
    errorMessage?: string;
    source?: 'fetch' | 'xhr' | 'node-http' | 'node-https' | 'workers';
}
type ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug' | 'trace';
interface ConsoleEvent extends BaseEvent {
    eventType: 'console';
    level: ConsoleLevel;
    message: string;
    args: unknown[];
    stackTrace?: string;
    sourceFile?: string;
    /** Where this log originated: browser, server (Node.js), or workers (Cloudflare) */
    source?: 'browser' | 'server' | 'workers';
}
interface BuildMeta {
    gitCommit?: string;
    gitBranch?: string;
    buildTime?: string;
    deployId?: string;
}
interface UserContext {
    id?: string;
    email?: string;
    name?: string;
    [key: string]: unknown;
}
interface SessionEvent extends BaseEvent {
    eventType: 'session';
    appName: string;
    connectedAt: number;
    sdkVersion: string;
    buildMeta?: BuildMeta;
    user?: UserContext;
    projectId?: string;
}
interface StateEvent extends BaseEvent {
    eventType: 'state';
    storeId: string;
    library: 'zustand' | 'redux' | 'unknown';
    phase: 'init' | 'update';
    state: unknown;
    previousState?: unknown;
    diff?: Record<string, {
        from: unknown;
        to: unknown;
    }>;
    action?: {
        type: string;
        payload?: unknown;
    };
    stackTrace?: string;
}
interface RenderComponentProfile {
    componentName: string;
    renderCount: number;
    totalDuration: number;
    avgDuration: number;
    lastRenderPhase: 'mount' | 'update' | 'unmount';
    lastRenderCause?: 'props' | 'state' | 'context' | 'parent' | 'unknown';
    renderVelocity: number;
    suspicious: boolean;
}
interface RenderEvent extends BaseEvent {
    eventType: 'render';
    profiles: RenderComponentProfile[];
    snapshotWindowMs: number;
    totalRenders: number;
    suspiciousComponents: string[];
}
interface DomSnapshotEvent extends BaseEvent {
    eventType: 'dom_snapshot';
    html: string;
    url: string;
    viewport: {
        width: number;
        height: number;
    };
    scrollPosition: {
        x: number;
        y: number;
    };
    elementCount: number;
    truncated: boolean;
}
type WebVitalRating = 'good' | 'needs-improvement' | 'poor';
type ServerMetricName = 'memory.rss' | 'memory.heapUsed' | 'memory.heapTotal' | 'memory.external' | 'eventloop.lag.mean' | 'eventloop.lag.p99' | 'eventloop.lag.max' | 'gc.pause.major' | 'gc.pause.minor' | 'cpu.user' | 'cpu.system' | 'handles.active' | 'requests.active';
type PerformanceMetricName = 'LCP' | 'FCP' | 'CLS' | 'TTFB' | 'FID' | 'INP' | ServerMetricName;
interface PerformanceEvent extends BaseEvent {
    eventType: 'performance';
    metricName: PerformanceMetricName;
    value: number;
    rating?: WebVitalRating;
    unit?: 'bytes' | 'ms' | 'percent' | 'count' | 'score';
    element?: string;
    entries?: unknown[];
}
type DatabaseOperation = 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE' | 'OTHER';
type DatabaseSource = 'prisma' | 'drizzle' | 'knex' | 'pg' | 'mysql2' | 'better-sqlite3' | 'd1' | 'kv' | 'r2' | 'generic';
interface DatabaseEvent extends BaseEvent {
    eventType: 'database';
    query: string;
    normalizedQuery: string;
    duration: number;
    rowsReturned?: number;
    rowsAffected?: number;
    tablesAccessed: string[];
    operation: DatabaseOperation;
    source: DatabaseSource;
    stackTrace?: string;
    label?: string;
    error?: string;
    params?: string;
}
interface NavigationEvent extends BaseEvent {
    eventType: 'navigation';
    from: string;
    to: string;
    trigger: 'pushState' | 'replaceState' | 'popstate' | 'hashchange' | 'initial';
}
interface CustomEvent extends BaseEvent {
    eventType: 'custom';
    name: string;
    properties?: Record<string, unknown>;
}
type UIInteractionAction = 'click' | 'breadcrumb';
interface UIInteractionEvent extends BaseEvent {
    eventType: 'ui';
    action: UIInteractionAction;
    /** CSS selector or element description */
    target: string;
    /** Visible text (button label, link text) */
    text?: string;
    /** Optional extra context */
    data?: Record<string, unknown>;
}
interface UIInteractionFilter {
    action?: UIInteractionAction;
    sinceSeconds?: number;
    sessionId?: string;
    projectId?: string;
}
interface CustomEventFilter {
    name?: string;
    sinceSeconds?: number;
    sessionId?: string;
    projectId?: string;
}
type DetectedFramework = 'react' | 'vue' | 'angular' | 'svelte' | 'solid' | 'preact' | 'htmx' | 'unknown';
type DetectedMetaFramework = 'nextjs' | 'nuxt' | 'sveltekit' | 'remix' | 'astro' | 'gatsby' | 'unknown';
type DetectedUILibrary = 'tailwind' | 'mui' | 'chakra' | 'shadcn' | 'bootstrap' | 'antd' | 'radix' | 'unknown';
type DetectedBuildTool = 'webpack' | 'vite' | 'turbopack' | 'esbuild' | 'parcel' | 'rollup' | 'unknown';
type DetectedHosting = 'vercel' | 'netlify' | 'cloudflare' | 'aws' | 'firebase' | 'railway' | 'unknown';
interface TechStackDetection {
    name: string;
    confidence: 'high' | 'medium' | 'low';
    version?: string;
    evidence: string[];
}
interface ReconMetadataEvent extends BaseEvent {
    eventType: 'recon_metadata';
    url: string;
    title: string;
    viewport: {
        width: number;
        height: number;
    };
    documentLang?: string;
    metaTags: Record<string, string>;
    techStack: {
        framework: TechStackDetection;
        metaFramework?: TechStackDetection;
        uiLibrary?: TechStackDetection;
        buildTool?: TechStackDetection;
        hosting?: TechStackDetection;
        stateManagement?: TechStackDetection;
        additional: TechStackDetection[];
    };
    externalStylesheets: {
        href: string;
        crossOrigin: boolean;
    }[];
    externalScripts: {
        src: string;
        async: boolean;
        defer: boolean;
        type?: string;
    }[];
    preloads: {
        href: string;
        as: string;
    }[];
}
interface CSSCustomProperty {
    name: string;
    value: string;
    source: string;
}
interface ColorToken {
    value: string;
    hex: string;
    usageCount: number;
    properties: string[];
    sampleSelectors: string[];
}
interface TypographyToken {
    fontFamily: string;
    fontSize: string;
    fontWeight: string;
    lineHeight: string;
    letterSpacing: string;
    usageCount: number;
    sampleSelectors: string[];
}
interface SpacingValue {
    value: string;
    pixels: number;
    usageCount: number;
    properties: string[];
}
type CSSArchitecture = 'tailwind' | 'css-modules' | 'styled-components' | 'css-in-js' | 'bem' | 'atomic' | 'vanilla' | 'unknown';
interface ReconDesignTokensEvent extends BaseEvent {
    eventType: 'recon_design_tokens';
    url: string;
    customProperties: CSSCustomProperty[];
    colors: ColorToken[];
    typography: TypographyToken[];
    spacing: SpacingValue[];
    borderRadii: {
        value: string;
        usageCount: number;
    }[];
    boxShadows: {
        value: string;
        usageCount: number;
    }[];
    cssArchitecture: CSSArchitecture;
    classNamingPatterns: string[];
    sampleClassNames: string[];
}
interface FontFaceInfo {
    family: string;
    weight: string;
    style: string;
    src: string;
    display?: string;
    unicodeRange?: string;
}
interface FontUsage {
    family: string;
    weight: string;
    style: string;
    usageCount: number;
    sampleSelectors: string[];
}
interface ReconFontsEvent extends BaseEvent {
    eventType: 'recon_fonts';
    url: string;
    fontFaces: FontFaceInfo[];
    fontsUsed: FontUsage[];
    iconFonts: {
        family: string;
        glyphsUsed: {
            codepoint: string;
            selector: string;
        }[];
    }[];
    loadingStrategy: string;
}
interface LayoutNode {
    tag: string;
    id?: string;
    classList: string[];
    role?: string;
    ariaLabel?: string;
    dataAttributes: Record<string, string>;
    boundingRect: {
        x: number;
        y: number;
        width: number;
        height: number;
    };
    display: string;
    position: string;
    flexDirection?: string;
    justifyContent?: string;
    alignItems?: string;
    flexWrap?: string;
    gap?: string;
    gridTemplateColumns?: string;
    gridTemplateRows?: string;
    overflow?: string;
    zIndex?: string;
    opacity?: string;
    children: LayoutNode[];
    childCount: number;
    textContent?: string;
}
interface ReconLayoutTreeEvent extends BaseEvent {
    eventType: 'recon_layout_tree';
    url: string;
    viewport: {
        width: number;
        height: number;
    };
    scrollHeight: number;
    rootSelector?: string;
    tree: LayoutNode;
    totalElements: number;
    maxDepth: number;
}
interface HeadingInfo {
    level: number;
    text: string;
    selector: string;
}
interface LandmarkInfo {
    role: string;
    label?: string;
    selector: string;
}
interface FormFieldInfo {
    tag: string;
    type?: string;
    name?: string;
    label?: string;
    required: boolean;
    ariaDescribedBy?: string;
    selector: string;
}
interface InteractiveElementInfo {
    tag: string;
    role?: string;
    text: string;
    ariaLabel?: string;
    href?: string;
    tabIndex?: number;
    selector: string;
}
interface ReconAccessibilityEvent extends BaseEvent {
    eventType: 'recon_accessibility';
    url: string;
    headings: HeadingInfo[];
    landmarks: LandmarkInfo[];
    formFields: FormFieldInfo[];
    links: InteractiveElementInfo[];
    buttons: InteractiveElementInfo[];
    images: {
        src: string;
        alt: string;
        hasAlt: boolean;
        selector: string;
    }[];
    issues: string[];
}
interface ComputedStyleEntry {
    selector: string;
    matchCount: number;
    styles: Record<string, string>;
    variations?: {
        property: string;
        values: {
            value: string;
            count: number;
        }[];
    }[];
}
interface ReconComputedStylesEvent extends BaseEvent {
    eventType: 'recon_computed_styles';
    url: string;
    selector: string;
    propertyFilter?: string[];
    entries: ComputedStyleEntry[];
}
interface ElementSnapshotNode {
    tag: string;
    id?: string;
    classList: string[];
    attributes: Record<string, string>;
    textContent?: string;
    boundingRect: {
        x: number;
        y: number;
        width: number;
        height: number;
    };
    computedStyles: Record<string, string>;
    children: ElementSnapshotNode[];
}
interface ReconElementSnapshotEvent extends BaseEvent {
    eventType: 'recon_element_snapshot';
    url: string;
    selector: string;
    depth: number;
    root: ElementSnapshotNode;
    totalNodes: number;
}
interface ImageAsset {
    src: string;
    alt?: string;
    width: number;
    height: number;
    naturalWidth?: number;
    naturalHeight?: number;
    format?: string;
    loading?: string;
    selector: string;
}
interface SpriteFrame {
    selector: string;
    cropX: number;
    cropY: number;
    cropWidth: number;
    cropHeight: number;
    extractedDataUrl?: string;
}
interface BackgroundSpriteSheet {
    sheetUrl: string;
    sheetWidth?: number;
    sheetHeight?: number;
    frames: SpriteFrame[];
}
interface SVGSpriteSymbol {
    id: string;
    viewBox?: string;
    paths: string;
    referencedBy: string[];
}
interface IconFontInfo {
    fontFamily: string;
    fontFaceUrl?: string;
    glyphs: {
        codepoint: string;
        pseudoElement: string;
        selector: string;
        renderedSize: number;
    }[];
}
interface InlineSVGAsset {
    selector: string;
    viewBox?: string;
    width?: number;
    height?: number;
    source: string;
}
interface MaskSpriteSheet {
    sheetUrl: string;
    sheetWidth?: number;
    sheetHeight?: number;
    frames: SpriteFrame[];
}
interface ReconAssetInventoryEvent extends BaseEvent {
    eventType: 'recon_asset_inventory';
    url: string;
    images: ImageAsset[];
    inlineSVGs: InlineSVGAsset[];
    svgSprites: SVGSpriteSymbol[];
    backgroundSprites: BackgroundSpriteSheet[];
    maskSprites: MaskSpriteSheet[];
    iconFonts: IconFontInfo[];
    totalAssets: number;
}
interface ReconFilter {
    reconType?: ReconEventType;
    sinceSeconds?: number;
    sessionId?: string;
    projectId?: string;
    url?: string;
}
type ReconEventType = 'recon_metadata' | 'recon_design_tokens' | 'recon_fonts' | 'recon_layout_tree' | 'recon_accessibility' | 'recon_computed_styles' | 'recon_element_snapshot' | 'recon_asset_inventory';
type RuntimeEvent = NetworkEvent | ConsoleEvent | SessionEvent | StateEvent | RenderEvent | DomSnapshotEvent | PerformanceEvent | DatabaseEvent | NavigationEvent | CustomEvent | UIInteractionEvent | ReconMetadataEvent | ReconDesignTokensEvent | ReconFontsEvent | ReconLayoutTreeEvent | ReconAccessibilityEvent | ReconComputedStylesEvent | ReconElementSnapshotEvent | ReconAssetInventoryEvent;
interface NetworkFilter {
    sinceSeconds?: number;
    urlPattern?: string;
    status?: number;
    method?: string;
    sessionId?: string;
    projectId?: string;
}
interface ConsoleFilter {
    level?: string;
    sinceSeconds?: number;
    search?: string;
    sessionId?: string;
    projectId?: string;
}
interface StateFilter {
    storeId?: string;
    sinceSeconds?: number;
    sessionId?: string;
    projectId?: string;
}
interface RenderFilter {
    componentName?: string;
    sinceSeconds?: number;
    sessionId?: string;
    projectId?: string;
}
interface PerformanceFilter {
    metricName?: string;
    sinceSeconds?: number;
    sessionId?: string;
    projectId?: string;
}
interface DatabaseFilter {
    sinceSeconds?: number;
    table?: string;
    minDurationMs?: number;
    search?: string;
    operation?: DatabaseOperation;
    source?: DatabaseSource;
    sessionId?: string;
    projectId?: string;
}
interface HistoricalFilter {
    project?: string;
    sessionId?: string;
    eventTypes?: EventType[];
    since?: number;
    until?: number;
    limit?: number;
    offset?: number;
    endpoint?: string;
    component?: string;
    storeId?: string;
}
interface ToolResponse<T = unknown> {
    summary: string;
    data: T;
    issues: string[];
    metadata: {
        timeRange: {
            from: number;
            to: number;
        };
        eventCount: number;
        sessionId: string | null;
        projectId?: string | null;
    };
}
interface SessionInfo {
    sessionId: string;
    appName: string;
    connectedAt: number;
    sdkVersion: string;
    eventCount: number;
    isConnected: boolean;
    projectId?: string;
}
interface SessionInfoExtended extends SessionInfo {
    project: string;
    projectId?: string;
    disconnectedAt?: number;
    buildMeta?: BuildMeta;
}
interface SessionMetrics {
    sessionId: string;
    project: string;
    connectedAt: number;
    disconnectedAt: number;
    totalEvents: number;
    errorCount: number;
    endpoints: Record<string, {
        avgLatency: number;
        errorRate: number;
        callCount: number;
    }>;
    components: Record<string, {
        renderCount: number;
        avgDuration: number;
    }>;
    stores: Record<string, {
        updateCount: number;
    }>;
    webVitals: Record<string, {
        value: number;
        rating: WebVitalRating;
    }>;
    queries: Record<string, {
        avgDuration: number;
        callCount: number;
    }>;
}
interface MetricDelta {
    key: string;
    before: number;
    after: number;
    delta: number;
    percentChange: number;
    classification: 'regression' | 'improvement' | 'unchanged';
}
interface SessionDiffResult {
    sessionA: string;
    sessionB: string;
    endpointDeltas: MetricDelta[];
    componentDeltas: MetricDelta[];
    storeDeltas: MetricDelta[];
    webVitalDeltas: MetricDelta[];
    queryDeltas: MetricDelta[];
    overallDelta: {
        errorCountDelta: number;
        totalEventsDelta: number;
    };
}
interface SessionSnapshot {
    id?: number;
    sessionId: string;
    project: string;
    label?: string;
    metrics: SessionMetrics;
    buildMeta?: BuildMeta;
    createdAt: number;
}
interface WSMessage {
    type: 'event' | 'handshake' | 'heartbeat' | 'command' | 'command_response';
    payload: unknown;
    timestamp: number;
    sessionId: string;
}
interface HandshakePayload {
    appName: string;
    sdkVersion: string;
    sessionId: string;
    authToken?: string;
    projectId?: string;
}
interface EventBatchPayload {
    events: RuntimeEvent[];
}
type ServerCommand = {
    command: 'capture_dom_snapshot';
    requestId: string;
    params?: {
        maxSize?: number;
    };
} | {
    command: 'capture_performance_metrics';
    requestId: string;
} | {
    command: 'clear_renders';
    requestId: string;
} | {
    command: 'recon_scan';
    requestId: string;
    params?: {
        categories?: ReconEventType[];
    };
} | {
    command: 'recon_computed_styles';
    requestId: string;
    params: {
        selector: string;
        properties?: string[];
    };
} | {
    command: 'recon_element_snapshot';
    requestId: string;
    params: {
        selector: string;
        depth?: number;
    };
} | {
    command: 'recon_layout_tree';
    requestId: string;
    params?: {
        selector?: string;
        maxDepth?: number;
    };
};
interface CommandResponse {
    type: 'command_response';
    requestId: string;
    command: string;
    payload: unknown;
    timestamp: number;
    sessionId: string;
}
interface TimelineFilter {
    sinceSeconds?: number;
    eventTypes?: EventType[];
    sessionId?: string;
    projectId?: string;
}
type IssueSeverity = 'high' | 'medium' | 'low';
interface DetectedIssue {
    id: string;
    pattern: string;
    severity: IssueSeverity;
    title: string;
    description: string;
    evidence: string[];
    suggestion?: string;
}
interface AuthInfo {
    type: 'bearer' | 'basic' | 'api_key' | 'cookie' | 'none';
    headerName?: string;
}
interface ApiContractField {
    path: string;
    type: string;
    nullable: boolean;
    example?: unknown;
}
interface ApiContract {
    requestFields?: ApiContractField[];
    responseFields: ApiContractField[];
    sampleCount: number;
}
interface ApiEndpoint {
    normalizedPath: string;
    method: string;
    baseUrl: string;
    service: string;
    callCount: number;
    firstSeen: number;
    lastSeen: number;
    auth: AuthInfo;
    contract?: ApiContract;
    graphqlOperation?: GraphQLOperation;
}
interface ApiEndpointHealth {
    normalizedPath: string;
    method: string;
    service: string;
    callCount: number;
    successRate: number;
    avgLatency: number;
    p50Latency: number;
    p95Latency: number;
    errorRate: number;
    errorCodes: Record<number, number>;
}
interface ServiceInfo {
    name: string;
    baseUrl: string;
    endpointCount: number;
    totalCalls: number;
    avgLatency: number;
    errorRate: number;
    auth: AuthInfo;
    detectedPlatform?: string;
}
interface ApiChangeRecord {
    normalizedPath: string;
    method: string;
    changeType: 'added' | 'removed' | 'modified';
    fieldChanges?: {
        path: string;
        change: 'added' | 'removed' | 'type_changed';
        oldType?: string;
        newType?: string;
    }[];
}
interface NormalizedQueryStats {
    normalizedQuery: string;
    tables: string[];
    operation: DatabaseOperation;
    callCount: number;
    avgDuration: number;
    maxDuration: number;
    p95Duration: number;
    totalDuration: number;
    avgRowsReturned: number;
}
interface IndexSuggestion {
    table: string;
    columns: string[];
    reason: string;
    estimatedImpact: 'high' | 'medium' | 'low';
    queryPattern: string;
}
interface DatabaseConnectionConfig {
    id: string;
    type: 'postgres' | 'mysql' | 'sqlite';
    connectionString?: string;
    label?: string;
    projectRef?: string;
    serviceKey?: string;
}
interface SchemaColumn {
    name: string;
    type: string;
    nullable: boolean;
    defaultValue?: string;
    isPrimaryKey: boolean;
}
interface SchemaForeignKey {
    column: string;
    referencedTable: string;
    referencedColumn: string;
}
interface SchemaIndex {
    name: string;
    columns: string[];
    unique: boolean;
}
interface SchemaTable {
    name: string;
    columns: SchemaColumn[];
    foreignKeys: SchemaForeignKey[];
    indexes: SchemaIndex[];
    rowCount?: number;
}
interface DatabaseSchema {
    connectionId: string;
    tables: SchemaTable[];
    fetchedAt: number;
}
type DevProcessType = 'next' | 'vite' | 'webpack' | 'wrangler' | 'prisma' | 'docker' | 'postgres' | 'mysql' | 'redis' | 'node' | 'bun' | 'deno' | 'python' | 'unknown';
interface DevProcess {
    pid: number;
    command: string;
    type: DevProcessType;
    cpuPercent: number;
    memoryMB: number;
    ports: number[];
    cwd?: string;
    project?: string;
    uptime?: number;
    isOrphaned: boolean;
}
interface PortUsage {
    port: number;
    pid: number;
    process: string;
    type: DevProcessType;
    project?: string;
}
interface DeployLog {
    id: string;
    platform: string;
    project: string;
    status: 'building' | 'ready' | 'error' | 'canceled';
    url?: string;
    branch?: string;
    commit?: string;
    createdAt: number;
    readyAt?: number;
    errorMessage?: string;
}
interface RuntimeLog {
    timestamp: number;
    level: 'info' | 'warn' | 'error' | 'debug';
    message: string;
    source?: string;
    platform: string;
}
interface BuildStatus {
    platform: string;
    project: string;
    latestDeployId: string;
    status: 'building' | 'ready' | 'error' | 'canceled';
    url?: string;
    lastDeployed: number;
}
interface InfraOverview {
    project: string;
    platforms: {
        name: string;
        configured: boolean;
        deployCount: number;
        lastDeploy?: number;
        status?: string;
    }[];
    detectedFromTraffic: string[];
}

interface SqliteStoreOptions {
    dbPath: string;
    walMode?: boolean;
    flushIntervalMs?: number;
    batchSize?: number;
}
declare class SqliteStore {
    private db;
    private writeBuffer;
    private flushTimer;
    private readonly batchSize;
    private readonly dbPath;
    private static readonly MAX_SNAPSHOTS_PER_SESSION;
    private insertEventStmt;
    private insertSessionStmt;
    private updateSessionDisconnectedStmt;
    constructor(options: SqliteStoreOptions);
    private openDatabase;
    private prepareStatements;
    private createSchema;
    addEvent(event: RuntimeEvent, project: string): void;
    flush(): void;
    saveSession(info: SessionInfoExtended): void;
    /**
     * Read every session record stored for a project. Used by the in-memory
     * EventStore at startup to rehydrate the session→projectId map after a
     * crash, so post-recovery `?project_id=...` queries return the right rows.
     * Each row is returned as a `SessionInfo` shape compatible with EventStore.
     */
    getStoredSessions(project: string): SessionInfoExtended[];
    updateSessionDisconnected(sessionId: string, disconnectedAt: number): void;
    saveSessionMetrics(sessionId: string, project: string, metrics: unknown, label?: string): void;
    /** Remove oldest snapshots for a session beyond the retention limit */
    private pruneSnapshots;
    /**
     * Return the most recent `limit` events for a project, in chronological
     * order (oldest-first). Used at startup to warm the in-memory ring buffer
     * so MCP tools see recent activity immediately after a collector restart.
     */
    getRecentEvents(project: string, limit: number): RuntimeEvent[];
    getEvents(filter: HistoricalFilter): RuntimeEvent[];
    getEventCount(filter: HistoricalFilter): number;
    getSessions(project: string, limit?: number): SessionInfoExtended[];
    getSessionMetrics(sessionId: string): SessionMetrics | null;
    getSessionSnapshots(sessionId: string): SessionSnapshot[];
    getSnapshotById(snapshotId: number): SessionSnapshot | null;
    getEventsByType(project: string, eventType: EventType, sinceMs?: number): RuntimeEvent[];
    private migrateSessionMetrics;
    deleteOldEvents(beforeTimestamp: number): number;
    vacuum(): void;
    /**
     * Atomically copy the live database to `targetPath` using SQLite's
     * `VACUUM INTO`. The destination is a self-contained, defragmented copy of
     * the DB at the moment the statement runs — no readers are blocked beyond
     * the duration of the copy, and the WAL/journal contents are folded in.
     * The target file must not already exist; SQLite refuses to overwrite.
     *
     * Returns the size in bytes of the resulting file.
     */
    snapshotTo(targetPath: string): number;
    close(): void;
}

interface RedactionRule {
    name: string;
    pattern: RegExp;
    replacement: string;
}
interface RedactorConfig {
    enabled?: boolean;
    useBuiltIn?: boolean;
    rules?: RedactionRule[];
    /** Redact JSON object keys matching these patterns (case-insensitive). */
    sensitiveKeys?: string[];
}
/** Built-in patterns for common secret/PII formats. */
declare const BUILT_IN_RULES: RedactionRule[];
declare class Redactor {
    private rules;
    private sensitiveKeyPattern;
    private enabled;
    constructor(config?: RedactorConfig);
    isEnabled(): boolean;
    /** Apply all redaction rules to a string value. */
    redactString(value: string): string;
    /**
     * Deep-walk an event and redact all string fields.
     * Returns a new event object (does not mutate the original).
     */
    redactEvent(event: RuntimeEvent): RuntimeEvent;
    private deepRedact;
}

declare class EventStore {
    private buffer;
    private sessions;
    private sqliteStore;
    private currentProject;
    private onEventCallbacks;
    private redactor;
    constructor(capacity?: number);
    setRedactor(redactor: Redactor): void;
    get eventCount(): number;
    setSqliteStore(store: SqliteStore, project: string): void;
    /**
     * Drop the SQLite pointer if it matches the given project. Called by the
     * collector's idle-store eviction timer so the store doesn't try to write
     * through a closed handle after eviction. The next `setSqliteStore` (from
     * the next event for this project) restores the binding.
     */
    clearSqliteStoreIfMatches(project: string): void;
    /**
     * Pre-load recent events from a SqliteStore into the in-memory ring buffer.
     * Used at collector startup to make MCP tools immediately useful after a
     * restart — without this, the buffer is empty until the SDK reconnects and
     * generates new traffic.
     *
     * Also rehydrates the session→projectId map from SqliteStore's `sessions`
     * table. Without this, queries filtered by `project_id` after a crash
     * return nothing because the in-memory map is empty: events are tagged
     * by sessionId, and matchesProjectId() looks up the session record to
     * find the project. (Pre-fix: only sessions whose `session` event happens
     * to be in the warmed window got rehydrated, which is rare in long runs.)
     *
     * Does NOT propagate to SqliteStore (we just read FROM it). Ring-buffer
     * eviction handles overflow naturally if multiple projects are warmed.
     */
    warmFromSqlite(sqliteStore: SqliteStore, project: string, limit: number): void;
    onEvent(callback: (event: RuntimeEvent) => void): void;
    removeEventListener(callback: (event: RuntimeEvent) => void): void;
    addEvent(event: RuntimeEvent): void;
    getNetworkRequests(filter?: NetworkFilter): NetworkEvent[];
    getConsoleMessages(filter?: ConsoleFilter): ConsoleEvent[];
    getSessionInfo(): SessionInfo[];
    /**
     * Fast O(sessions) event count for a specific projectId. Callers that just
     * want to know "have any events arrived for project X yet?" should use this
     * instead of `getAllEvents(..., projectId).length`, which allocates and
     * filters the entire 10K-event ring buffer on every call.
     */
    eventCountForProject(projectId: string): number;
    markDisconnected(sessionId: string): void;
    getEventTimeline(filter?: TimelineFilter): RuntimeEvent[];
    getAllEvents(sinceSeconds?: number, sessionId?: string, projectId?: string): RuntimeEvent[];
    getSessionIdsForProject(appName: string): string[];
    getSessionIdsForProjectId(projectId: string): string[];
    /** Re-tag all sessions with oldProjectId to use newProjectId. */
    retagSessions(oldProjectId: string, newProjectId: string): void;
    /** Check if an event belongs to the given projectId (via its session). */
    private matchesProjectId;
    getStateEvents(filter?: StateFilter): StateEvent[];
    getRenderEvents(filter?: RenderFilter): RenderEvent[];
    getPerformanceMetrics(filter?: PerformanceFilter): PerformanceEvent[];
    getDatabaseEvents(filter?: DatabaseFilter): DatabaseEvent[];
    getCustomEvents(filter?: CustomEventFilter): CustomEvent[];
    getUIInteractions(filter?: UIInteractionFilter): UIInteractionEvent[];
    private getLatestReconEvent;
    private getReconEvents;
    getReconMetadata(filter?: ReconFilter): ReconMetadataEvent | null;
    getReconDesignTokens(filter?: ReconFilter): ReconDesignTokensEvent | null;
    getReconFonts(filter?: ReconFilter): ReconFontsEvent | null;
    getReconLayoutTree(filter?: ReconFilter): ReconLayoutTreeEvent | null;
    getReconAccessibility(filter?: ReconFilter): ReconAccessibilityEvent | null;
    getReconComputedStyles(filter?: ReconFilter): ReconComputedStylesEvent[];
    getReconElementSnapshots(filter?: ReconFilter): ReconElementSnapshotEvent[];
    getReconAssetInventory(filter?: ReconFilter): ReconAssetInventoryEvent | null;
    clear(): {
        clearedCount: number;
    };
}

interface ApiKeyEntry {
    key: string;
    label: string;
    project?: string;
    createdAt: number;
}
interface AuthConfig {
    enabled: boolean;
    apiKeys: ApiKeyEntry[];
}
declare class AuthManager {
    private keys;
    private enabled;
    constructor(config?: Partial<AuthConfig>);
    isEnabled(): boolean;
    /** Validate an API key. Returns the entry if valid, null if invalid. */
    validate(key: string | undefined): ApiKeyEntry | null;
    /** Check if request is authorized. Returns true if auth is disabled or key is valid. */
    isAuthorized(key: string | undefined): boolean;
    /** Extract bearer token from Authorization header value. */
    static extractBearer(header: string | undefined): string | undefined;
    /** Constant-time string comparison to prevent timing attacks. */
    private safeCompare;
}
/** Generate a cryptographically secure API key (64 hex chars = 32 bytes). */
declare function generateApiKey(label: string, project?: string): ApiKeyEntry;

interface GlobalConfig {
    defaultPort: number;
    bufferSize: number;
    httpPort: number;
    /** Authentication configuration */
    auth?: {
        enabled: boolean;
        apiKeys: ApiKeyEntry[];
    };
    /** TLS certificate paths */
    tls?: {
        certPath: string;
        keyPath: string;
        caPath?: string;
    };
    /** CORS allowed origins (defaults to '*' when not set) */
    corsOrigins?: string[];
    /** Rate limiting configuration */
    rateLimits?: {
        maxEventsPerSecond?: number;
        maxEventsPerMinute?: number;
    };
    /** Payload redaction configuration */
    redaction?: {
        enabled: boolean;
        rules?: {
            name: string;
            pattern: string;
            replacement: string;
        }[];
    };
}
interface ProjectConfig {
    name: string;
    createdAt: string;
    sdkVersion?: string;
    projectId?: string;
    settings: {
        bufferSize?: number;
        retentionDays?: number;
    };
}
interface InfrastructureConfig {
    project?: string;
    databases?: Record<string, {
        type: string;
        connection_string?: string;
        project_ref?: string;
        service_key?: string;
        label?: string;
    }>;
    deployments?: Record<string, {
        platform: string;
        project_id?: string;
        team_id?: string;
        worker_name?: string;
        account_id?: string;
    }>;
    services?: Record<string, string>;
}
/** Minimal interface for PmStore used by rebuildAppIndex (avoids circular deps). */
interface PmStoreIndexSource {
    listProjects(): Array<{
        runtimeApps?: string[];
        runtimeProjectId?: string;
        path?: string;
    }>;
}
declare class ProjectManager {
    private readonly baseDir;
    private appProjectIndex;
    constructor(baseDir?: string);
    get rootDir(): string;
    getProjectDir(projectName: string): string;
    getProjectDbPath(projectName: string): string;
    ensureGlobalDir(): void;
    ensureProjectDir(projectName: string): void;
    getGlobalConfig(): GlobalConfig;
    saveGlobalConfig(config: GlobalConfig): void;
    getProjectConfig(projectName: string): ProjectConfig | null;
    saveProjectConfig(projectName: string, config: ProjectConfig): void;
    getInfrastructureConfig(projectName: string): InfrastructureConfig | null;
    getClaudeInstructions(projectName: string): string | null;
    listProjects(): string[];
    projectExists(projectName: string): boolean;
    /** Look up the stored projectId for an appName. Returns null if none set. */
    getProjectIdForApp(appName: string): string | null;
    /** Persist a projectId for an appName in its project config. */
    setProjectIdForApp(appName: string, projectId: string): void;
    /** Resolve a projectId to an appName by scanning all project configs. Returns null if not found. */
    getAppForProjectId(projectId: string): string | null;
    /**
     * Build reverse index: appName -> projectId.
     * Scans all project configs, PM projects with runtimeApps + runtimeProjectId,
     * and project-level .runtimescope/config.json files from PM project paths.
     */
    rebuildAppIndex(pmStore?: PmStoreIndexSource): void;
    /** O(1) lookup from the cached index. */
    resolveAppProjectId(appName: string): string | null;
    resolveEnvVars(value: string): string;
    private mkdirp;
    private readJson;
    private writeJson;
    private resolveConfigEnvVars;
    /**
     * Minimal YAML parser for simple infrastructure config files.
     * Handles flat key-value pairs and one level of nesting.
     * For full YAML support, install js-yaml.
     */
    private parseSimpleYaml;
}

/** Minimal interface for PmStore to avoid circular dependencies. */
interface PmStoreLike {
    findProjectIdByApp(appName: string): string | null;
    getWorkspaceByApiKey?(key: string): {
        id: string;
        slug: string;
        name: string;
    } | null;
    listProjects?(): Array<{
        id: string;
        runtimeProjectId?: string;
        workspaceId?: string;
    }>;
    setProjectWorkspace?(projectId: string, workspaceId: string): void;
    autoLinkApp?(appName: string, projectId?: string): string | null;
}
/** Generate a new project ID (proj_ + 12 random alphanumeric chars). */
declare function generateProjectId(): string;
/** Validate that a string is a well-formed project ID. */
declare function isValidProjectId(id: string): boolean;
/**
 * Look up or create a project ID for a given appName.
 * Persists the ID in the ProjectManager config so the same appName
 * always returns the same project ID (idempotent).
 */
declare function getOrCreateProjectId(projectManager: ProjectManager, appName: string): string;

/**
 * Minimal Prometheus-compatible metrics registry. Zero dependencies — the
 * exposition format is small enough that pulling in `prom-client` would be
 * heavier than just emitting the text ourselves.
 *
 * Two metric kinds are supported:
 *   - Counter (monotonic) for things like total events, dropped events.
 *   - Gauge (point-in-time) for things like current sessions connected,
 *     ring-buffer occupancy. Gauges accept a `collect` callback so they
 *     compute their value at scrape time rather than tracking state.
 *
 * Spec reference: https://prometheus.io/docs/instrumenting/exposition_formats/
 */
type LabelValues = Record<string, string>;
interface Sample {
    labels: LabelValues;
    value: number;
}
declare abstract class Metric {
    readonly name: string;
    readonly help: string;
    readonly labelNames: string[];
    constructor(name: string, help: string, labelNames?: string[]);
    abstract type(): 'counter' | 'gauge';
    abstract collect(): Sample[];
}
declare class Counter extends Metric {
    private values;
    type(): 'counter';
    inc(value?: number, labels?: LabelValues): void;
    reset(): void;
    collect(): Sample[];
}
declare class Gauge extends Metric {
    private values;
    private collectFn;
    type(): 'gauge';
    /**
     * Set a fixed value for the given label set. Per the Prometheus spec, gauges
     * may take any numeric value including +Inf / -Inf / NaN — the renderer
     * handles formatting. Only actually-not-a-number inputs (`undefined`, etc.)
     * are silently dropped.
     */
    set(value: number, labels?: LabelValues): void;
    /**
     * Compute the gauge dynamically at scrape time. Useful for things like
     * "currently-connected sessions" where caching a stale value is wrong.
     * Mutually exclusive with `set()` — last writer wins.
     */
    setCollect(fn: () => number | Sample[]): void;
    collect(): Sample[];
}
declare class MetricsRegistry {
    private metrics;
    counter(name: string, help: string, labelNames?: string[]): Counter;
    gauge(name: string, help: string, labelNames?: string[]): Gauge;
    /** Serialize every registered metric in Prometheus exposition format. */
    render(): string;
}

/**
 * OpenTelemetry exporter — one-way bridge from RuntimeScope events to OTLP/HTTP.
 *
 * Each RuntimeScope event maps to one OTel signal:
 *   - `network`     → trace span (HTTP client, kind=CLIENT)
 *   - `database`    → trace span (DB client, kind=CLIENT)
 *   - `render`      → trace span (kind=INTERNAL, attr `react.component`)
 *   - `console`     → log record. `level=error` is severity=ERROR, with the
 *                     stack trace as an `exception.stacktrace` attribute.
 *   - `performance` → gauge metric (Web Vitals: LCP / FCP / CLS / INP / TTFB).
 *
 * State, session, ui-interaction, dom_snapshot, custom, navigation, and recon
 * events have no clean OTel mapping and are skipped — downstream tools can
 * still see everything via the RuntimeScope HTTP API directly.
 *
 * Session = trace. All events for one `sessionId` share a deterministic 16-byte
 * trace ID derived from `sha256(sessionId)`, so a downstream OTel UI groups
 * them. Span IDs are random per event.
 *
 * Wire format is OTLP/HTTP with JSON encoding — chosen specifically because it
 * needs no Protobuf compiler, no deps, and is supported by every modern
 * collector (otel-collector, Honeycomb refinery, Vector, Datadog, Tempo, etc.).
 *
 * Configuration is opt-in via env vars:
 *   - RUNTIMESCOPE_OTEL_ENDPOINT       — e.g. "http://localhost:4318" (no path)
 *   - RUNTIMESCOPE_OTEL_HEADERS        — "k1=v1,k2=v2" — for bearer tokens etc.
 *   - RUNTIMESCOPE_OTEL_SERVICE_NAME   — defaults to "runtimescope-collector"
 *
 * Failure semantics: best-effort. We batch in memory, flush on a timer or
 * size threshold, and drop on POST failure (logging at most once per failure).
 * If the OTel endpoint is down, RuntimeScope itself is unaffected — that's
 * the whole point of running this as a sidecar exporter.
 */

interface OtelExporterOptions {
    /** Base URL of the OTel collector — no path. e.g. "http://localhost:4318". */
    endpoint: string;
    /** `service.name` resource attribute. Default "runtimescope-collector". */
    serviceName?: string;
    /** `service.namespace` resource attribute — useful for projectId. */
    serviceNamespace?: string;
    /** Extra HTTP headers (auth tokens, tenant IDs, etc.). */
    headers?: Record<string, string>;
    /** Force flush after this many milliseconds even if the buffer is small. Default 10s. */
    flushIntervalMs?: number;
    /** Force flush once we've accumulated this many signals. Default 1000. */
    maxBatchSize?: number;
}
declare class OtelExporter {
    private spans;
    private logs;
    private metrics;
    private flushTimer;
    private closed;
    private lastFailureLog;
    private readonly endpoint;
    private readonly serviceName;
    private readonly serviceNamespace;
    private readonly headers;
    private readonly maxBatchSize;
    constructor(options: OtelExporterOptions);
    /** Convert a RuntimeScope event to its OTel signal(s) and buffer. */
    ingest(event: RuntimeEvent): void;
    /** POST any buffered signals to the OTLP endpoint. */
    flush(): Promise<void>;
    close(): Promise<void>;
    private networkToSpan;
    private databaseToSpan;
    /**
     * Render events bundle multiple component profiles in one event. We emit
     * one span per profile so the OTel UI can show each component's render
     * timing independently — sharing the same trace via the sessionId.
     */
    private renderToSpans;
    /**
     * `console` events with `level: 'error'` carry stack traces; we surface them
     * via OTel's exception attributes so log-search backends can show them
     * inline. Lower-severity console events become plain log records.
     */
    private consoleToLog;
    private performanceToMetric;
    private resourceAttributes;
    private wrapSpans;
    private wrapLogs;
    private wrapMetrics;
    private send;
    /** Rate-limit failure logs to once every 60s — don't spam stderr. */
    private logFailure;
}
/**
 * Build a deterministic 16-byte trace ID from the sessionId so every event
 * for one session belongs to the same trace in the downstream UI.
 */
declare function traceIdFromSession(sessionId: string): string;
declare function randomSpanId(): string;
/** Parse `RUNTIMESCOPE_OTEL_HEADERS="k1=v1,k2=v2"` into a header map. */
declare function parseOtelHeaders(raw: string | undefined): Record<string, string>;
/** Build options from environment variables. Returns null if OTel is not configured. */
declare function otelOptionsFromEnv(): OtelExporterOptions | null;

interface RateLimitConfig {
    maxEventsPerSecond?: number;
    maxEventsPerMinute?: number;
}
declare class SessionRateLimiter {
    private windows;
    private maxPerSecond;
    private maxPerMinute;
    private _droppedTotal;
    constructor(config?: RateLimitConfig);
    get droppedTotal(): number;
    isEnabled(): boolean;
    /** Returns true if the event should be accepted, false if rate-limited. */
    allow(sessionId: string): boolean;
    /** Allow a batch of N events. Returns the number accepted. */
    allowBatch(sessionId: string, count: number): number;
    /** Remove tracking for sessions that haven't been seen in maxAgeMs. */
    prune(maxAgeMs?: number): void;
    private maybeWarn;
}

interface TlsConfig {
    certPath: string;
    keyPath: string;
    caPath?: string;
}
/**
 * Load TLS certificate files and return options suitable for
 * https.createServer() or tls.createSecureContext().
 */
declare function loadTlsOptions(config: TlsConfig): SecureContextOptions;
/**
 * Resolve TLS config from environment variables.
 * Returns null if TLS is not configured.
 */
declare function resolveTlsConfig(): TlsConfig | null;

interface SnapshotResult {
    /** Absolute path to the snapshot directory. */
    path: string;
    /** ISO-like timestamp embedded in the directory name. */
    timestamp: string;
    /** Per-project sizes + event counts. */
    projects: {
        name: string;
        sqliteBytes: number;
        walBytes: number;
        eventCount: number;
    }[];
    /** Total bytes written across all projects. */
    totalBytes: number;
}

interface CollectorServerOptions {
    port?: number;
    host?: string;
    bufferSize?: number;
    maxRetries?: number;
    retryDelayMs?: number;
    projectManager?: ProjectManager;
    authManager?: AuthManager;
    rateLimits?: RateLimitConfig;
    tls?: TlsConfig;
    /**
     * Optional OpenTelemetry exporter config. When set (or when
     * `RUNTIMESCOPE_OTEL_ENDPOINT` is in the environment), every event the
     * store accepts is converted into an OTLP signal and shipped to the
     * configured endpoint. Failures are logged but never break ingestion.
     */
    otel?: OtelExporterOptions;
    /**
     * Skip the synchronous startup recovery pass (WAL replay + SQLite warm).
     * The MCP server uses this when an existing healthy collector is already
     * holding port 6768: in that case the in-process collector receives zero
     * SDK events (SDKs talk to the launchd collector instead), so warming
     * 40+ SQLite stores during boot is pure cost — and it pushes the MCP
     * transport-ready time past Claude Code's plugin reconnect timeout.
     * Recovery still runs lazily on the first SDK connection per project.
     */
    skipRecovery?: boolean;
}
declare class CollectorServer {
    private wss;
    private store;
    private projectManager;
    private authManager;
    private rateLimiter;
    private clients;
    private pendingHandshakes;
    private pendingCommands;
    private sqliteStores;
    private sqliteStoreLastAccess;
    private wals;
    private walsLastAccess;
    private ready;
    private metrics;
    private startedAt;
    private counters;
    private otelExporter;
    private connectCallbacks;
    private disconnectCallbacks;
    private pruneTimer;
    private heartbeatTimer;
    private sqliteEvictTimer;
    private tlsConfig;
    private pmStore;
    constructor(options?: CollectorServerOptions);
    /** Public access to the metrics registry — HttpServer renders this at /metrics. */
    getMetricsRegistry(): MetricsRegistry;
    getStore(): EventStore;
    getPort(): number | null;
    getClientCount(): number;
    getProjectManager(): ProjectManager | null;
    getSqliteStore(projectName: string): SqliteStore | undefined;
    getSqliteStores(): Map<string, SqliteStore>;
    /**
     * Diagnostic counters for currently-open per-project resource handles
     * and pending bidirectional commands. Exposed for tests + future
     * tray-app health surfaces.
     *
     * - `sqliteStores` / `wals`: open handle counts. The eviction sweep
     *   (5-minute idle in production, env-overridable for tests) drives
     *   these down to zero for idle projects and back up on reconnect.
     * - `pendingCommands`: in-flight WS commands (server → SDK). Settles
     *   on response or via the per-command timeout — see audit F5.
     */
    getOpenHandleCounts(): {
        sqliteStores: number;
        wals: number;
        pendingCommands: number;
    };
    getRateLimiter(): SessionRateLimiter;
    /** Set the PmStore for project ID resolution (called after construction when PmStore is available). */
    setPmStore(pmStore: PmStoreLike | null): void;
    onConnect(cb: (sessionId: string, projectName: string, projectId?: string) => void): void;
    onDisconnect(cb: (sessionId: string, projectName: string, projectId?: string) => void): void;
    /** True after start() finishes recovery. False during startup or after stop(). */
    isReady(): boolean;
    /**
     * Snapshot every project's SQLite DB and WAL into a fresh directory under
     * `<runtimescope-root>/snapshots/<ISO>/`. Atomic via SQLite's `VACUUM INTO`;
     * non-blocking for ongoing event ingestion (the live DB keeps accepting
     * writes during the copy).
     *
     * Returns metadata for the admin endpoint to serialize.
     */
    createSnapshot(): SnapshotResult;
    start(options?: CollectorServerOptions): Promise<void>;
    /**
     * Close SQLite stores that haven't been accessed in IDLE_TIMEOUT_MS. Any
     * subsequent `ensureSqliteStore(name)` call will transparently re-open the
     * store from disk, so eviction is invisible to callers — they just see a
     * brief warm-up the next time they touch a project.
     *
     * We deliberately do NOT evict stores belonging to currently-connected
     * SDK clients, since those are guaranteed to write again soon and closing
     * + reopening on every event would be expensive.
     */
    private startSqliteEvictionTimer;
    /**
     * On collector startup, for each known project:
     *   1. Replay any sealed/active WAL files into SqliteStore (mirror of the
     *      lazy recovery in `ensureWal`, but proactive — handles the case where
     *      a crashed project never reconnects).
     *   2. Warm the in-memory ring buffer with recent events from SqliteStore so
     *      MCP tools see history immediately, not just events from the next
     *      session that connects.
     *
     * Runs synchronously — better-sqlite3 is sync — so callers can `await
     * collector.start()` and trust the buffer is hot when it returns.
     */
    private runStartupRecovery;
    private tryStart;
    private handleStartError;
    private ensureSqliteStore;
    private walDirFor;
    /**
     * Open (or return) the WAL for a project. Every event ingested for this
     * project is first appended + fsync'd here before being pushed to the ring
     * buffer and SqliteStore, so a crash between receipt and SqliteStore flush
     * doesn't lose acknowledged events.
     */
    private ensureWal;
    /**
     * Replay any sealed or non-empty active WAL files into SqliteStore, then
     * delete them. Called lazily the first time a project's WAL is opened — if
     * the prior collector crashed mid-batch, those events survive in the WAL
     * and we'd otherwise leave them stranded on disk forever.
     */
    private recoverWalForProject;
    /**
     * Rotate the project's WAL, flush SqliteStore so the rotated file's events
     * are persisted, then delete the sealed file. Called when the active file
     * has grown past its rotate threshold.
     */
    private checkpointWal;
    /** Catch runtime errors on the WSS so an unhandled error doesn't crash the process */
    private setupPersistentErrorHandler;
    /** Ping all connected clients every 15s — terminate those that don't respond */
    private startHeartbeat;
    private setupConnectionHandler;
    private handleMessage;
    /** Find the WebSocket for a given sessionId */
    private findWsBySessionId;
    /** Get the first connected session ID (for single-app use) */
    getFirstSessionId(): string | undefined;
    /** Get the project name for a session */
    getProjectForSession(sessionId: string): string | undefined;
    /** Get all connected session IDs with their project names */
    getConnectedSessions(): {
        sessionId: string;
        projectName: string;
        projectId?: string;
    }[];
    /** Send a command to the SDK and await the response */
    sendCommand(sessionId: string, command: {
        command: string;
        requestId: string;
        params?: Record<string, unknown>;
    }, timeoutMs?: number): Promise<unknown>;
    stop(): void;
}

/**
 * Fixed-size circular buffer. When full, new items overwrite the oldest.
 * Optimized for append-heavy workloads with periodic filtered scans.
 */
declare class RingBuffer<T> {
    private capacity;
    private buffer;
    private head;
    private _count;
    constructor(capacity: number);
    get count(): number;
    push(item: T): void;
    /** Returns all items from oldest to newest. */
    toArray(): T[];
    /** Returns matching items from newest to oldest (most recent first). */
    query(predicate: (item: T) => boolean): T[];
    clear(): void;
}

/**
 * Runs all pattern detectors against a set of events and returns
 * prioritized issues sorted by severity (high → medium → low).
 */
declare function detectIssues(events: RuntimeEvent[]): DetectedIssue[];

interface RuntimeScopeProjectConfig {
    /** Stable project identifier (proj_xxx). Groups all SDKs for this project. */
    projectId: string;
    /** DSN connection string: runtimescope://<projectId>@<host>:<port>/<appName> */
    dsn?: string;
    /** Human-readable project name. */
    appName: string;
    /** Optional description for dashboard/reports. */
    description?: string;
    /** SDKs installed in this project. Each entry is a target (browser, server, worker, etc.). */
    sdks: SdkEntry[];
    /** Default capture settings. Used by /setup to generate snippets and by server-sdk for auto-config. */
    capture: CaptureConfig;
    /** Project phase for CapEx tracking. */
    phase?: 'preliminary' | 'application_development' | 'post_implementation';
    /** Category for grouping in dashboard (e.g., "work", "personal", "internal"). */
    category?: string;
    /** Infrastructure references (no tokens — those live in ~/.runtimescope/config.json). */
    infra?: {
        vercel?: {
            projectId?: string;
        };
        cloudflare?: {
            workerName?: string;
            accountId?: string;
        };
        railway?: {
            projectId?: string;
        };
    };
}
interface SdkEntry {
    /** Which SDK is installed. */
    type: 'browser' | 'server' | 'workers';
    /** Where the SDK init code lives (e.g., "src/main.tsx", "src/server.ts"). */
    entryFile?: string;
    /** Framework detected during setup. */
    framework?: string;
    /** The appName used in this SDK's init (can differ from project appName for multi-SDK). */
    appName?: string;
}
interface CaptureConfig {
    network?: boolean;
    console?: boolean;
    xhr?: boolean;
    body?: boolean;
    performance?: boolean;
    renders?: boolean;
    navigation?: boolean;
    clicks?: boolean;
    /** Server SDK specific */
    http?: boolean;
    errors?: boolean;
    stackTraces?: boolean;
}
/** Read .runtimescope/config.json from a project directory. Returns null if not found. */
declare function readProjectConfig(projectDir: string): RuntimeScopeProjectConfig | null;
/** Write .runtimescope/config.json to a project directory. Creates the directory if needed. */
declare function writeProjectConfig(projectDir: string, config: RuntimeScopeProjectConfig): void;
/**
 * Scaffold the .runtimescope/ directory for a project.
 * Creates config.json with a generated projectId and default capture settings.
 * If config already exists, returns the existing one (idempotent).
 */
declare function scaffoldProjectConfig(projectDir: string, opts: {
    appName: string;
    framework?: string;
    sdkType?: SdkEntry['type'];
    description?: string;
    category?: string;
}): RuntimeScopeProjectConfig;
/**
 * Resolve all appNames associated with a project config.
 * Returns the main appName plus any SDK-specific appNames.
 */
declare function resolveProjectAppNames(config: RuntimeScopeProjectConfig): string[];
interface MigratablePmStore {
    listProjects(): Array<{
        id: string;
        name: string;
        path?: string;
        runtimeApps?: string[];
        runtimeProjectId?: string;
    }>;
    updateProject(id: string, updates: Record<string, unknown>): void;
}
interface MigrationResult {
    unified: number;
    skipped: number;
    details: string[];
}
/**
 * Scan PM projects with multiple runtimeApps and ensure all their
 * appNames share the same canonical projectId (from .runtimescope/config.json).
 */
declare function migrateProjectIds(projectManager: ProjectManager, pmStore?: MigratablePmStore | null): MigrationResult;

/**
 * Write-ahead log for the collector. One WAL directory per project, holding
 * an append-only JSONL file (`active.jsonl`) plus zero or more sealed files
 * that have been rotated out. The durability contract is:
 *
 *   append(events) + commit() → events are on disk (fsync'd).
 *
 * `append` buffers into the OS file table (a plain `write` syscall); `commit`
 * calls `fsync` to force the bytes to stable storage. Callers should batch
 * appends within a single SDK message and call `commit` once per batch.
 *
 * On rotation, the active file is renamed to `sealed-<ts>-<seq>.jsonl` and a
 * fresh active file is opened. Sealed files stay on disk until the collector
 * confirms the corresponding events are durable in SqliteStore, at which
 * point they're safe to delete.
 *
 * On crash + restart, any remaining sealed or active files are evidence of
 * events that may not have reached SqliteStore. Replay feeds them back into
 * the store path, then deletes the WAL files.
 */

interface WalOptions {
    /** Directory to hold WAL files — created if missing. */
    dir: string;
    /** Rotate the active file once it grows past this size in bytes. */
    rotateSizeBytes?: number;
}
declare class Wal {
    private dir;
    private rotateSize;
    private fd;
    private activeSize;
    private seq;
    private closed;
    constructor(options: WalOptions);
    private openActive;
    private activePath;
    /**
     * Buffer events into the active file. Not durable yet — must be followed by
     * `commit()` before the caller treats the events as persisted.
     */
    append(events: RuntimeEvent[]): void;
    /** fsync the active file. Durability contract: returns only after bytes are on stable storage. */
    commit(): void;
    /** True if the active file has exceeded the rotate threshold. */
    shouldRotate(): boolean;
    /**
     * Rotate the active file: fsync, close, rename to `sealed-<ts>-<seq>.jsonl`,
     * then open a fresh active file. Returns the sealed path so the caller can
     * schedule deletion after confirming persistence elsewhere.
     */
    rotate(): string | null;
    /** Remove a sealed file once its events are durable in the downstream store. */
    static deleteSealed(path: string): void;
    /** List sealed files in this WAL's directory, sorted oldest-first. */
    listSealed(): string[];
    /**
     * Parse a WAL file back into its events, skipping any corrupt or truncated
     * trailing line. A crash mid-append can leave a partial line; the parser
     * tolerates it because fsync had never completed for that line, which means
     * the event was never treated as durable.
     */
    static readFile(path: string): RuntimeEvent[];
    /**
     * List the WAL files that need recovery for a project: any sealed files
     * plus the active file if it has content. Returned in ingestion order
     * (sealed oldest-first, then active last).
     */
    static listRecoveryFiles(dir: string): string[];
    close(): void;
    /**
     * Copy the active file (post-fsync) and any sealed files into `targetDir`.
     * Returns the total bytes copied. Used by snapshot endpoints — pairing the
     * SQLite snapshot with the WAL means a restore captures any events that
     * hadn't yet been drained into SQLite at snapshot time.
     */
    snapshotTo(targetDir: string): number;
}

declare function isSqliteAvailable(): boolean;

declare const safeLog: {
    error(...args: unknown[]): void;
    warn(...args: unknown[]): void;
};

declare class ApiDiscoveryEngine {
    private endpoints;
    private store;
    private lastRebuildEventCount;
    private isDirty;
    constructor(store: EventStore);
    /** Mark the cache dirty so the next read triggers a rebuild */
    markDirty(): void;
    rebuild(): void;
    private ingestEvent;
    private refineEndpoints;
    /**
     * Resolve a projectId to the set of sessionIds that belong to it. Returns
     * null when no projectId is supplied (caller should skip filtering). Returns
     * an empty set when the projectId has no known sessions — in that case
     * every endpoint should be excluded from results.
     *
     * The endpoints map is global (built from all network events across every
     * project), so any project-scoped read MUST filter ep.events by sessionId
     * to avoid bleeding traffic from one project into another's tool output.
     */
    private resolveProjectSessionIds;
    getCatalog(filter?: {
        service?: string;
        minCalls?: number;
        projectId?: string;
    }): ApiEndpoint[];
    getHealth(filter?: {
        endpoint?: string;
        sinceSeconds?: number;
        projectId?: string;
    }): ApiEndpointHealth[];
    getDocumentation(filter?: {
        service?: string;
        format?: string;
        projectId?: string;
    }): string;
    getServiceMap(filter?: {
        projectId?: string;
    }): ServiceInfo[];
    getApiChanges(sessionA: string, sessionB: string): ApiChangeRecord[];
    private buildCatalogFromEvents;
    detectIssues(projectId?: string): DetectedIssue[];
}

declare function aggregateQueryStats(events: DatabaseEvent[]): NormalizedQueryStats[];
declare function detectN1Queries(events: DatabaseEvent[]): DetectedIssue[];
declare function detectSlowQueries(events: DatabaseEvent[], thresholdMs?: number): DetectedIssue[];
declare function suggestIndexes(events: DatabaseEvent[]): IndexSuggestion[];
declare function detectOverfetching(events: DatabaseEvent[]): DetectedIssue[];

interface ManagedConnection {
    config: DatabaseConnectionConfig;
    client: unknown;
    isHealthy: boolean;
    lastChecked: number;
}
declare class ConnectionManager {
    private connections;
    addConnection(config: DatabaseConnectionConfig): Promise<void>;
    getConnection(id: string): ManagedConnection | undefined;
    listConnections(): {
        id: string;
        type: string;
        label?: string;
        isHealthy: boolean;
    }[];
    healthCheck(id: string): Promise<boolean>;
    closeConnection(id: string): Promise<void>;
    closeAll(): Promise<void>;
    private dynamicRequire;
    private createClient;
}

declare class SchemaIntrospector {
    introspect(connection: ManagedConnection, tableName?: string): Promise<DatabaseSchema>;
    private introspectPostgres;
    private introspectMysql;
    private introspectSqlite;
}

interface ReadOptions {
    table: string;
    limit?: number;
    offset?: number;
    where?: string;
    orderBy?: string;
}
interface ReadResult {
    rows: Record<string, unknown>[];
    total: number;
    limit: number;
    offset: number;
}
interface WriteOptions {
    table: string;
    operation: 'insert' | 'update' | 'delete';
    data?: Record<string, unknown>;
    where?: string;
}
interface WriteResult {
    success: boolean;
    affectedRows: number;
    error?: string;
}
declare class DataBrowser {
    read(connection: ManagedConnection, options: ReadOptions): Promise<ReadResult>;
    write(connection: ManagedConnection, options: WriteOptions): Promise<WriteResult>;
    private assertLocalhost;
    private readPostgres;
    private writePostgres;
    private readMysql;
    private writeMysql;
    private readSqlite;
    private writeSqlite;
}

declare class ProcessMonitor {
    private store;
    private scanInterval;
    private processes;
    private lastActivity;
    constructor(store: EventStore);
    start(intervalMs?: number): void;
    stop(): void;
    scan(): void;
    getProcesses(filter?: {
        project?: string;
        type?: DevProcessType;
    }): DevProcess[];
    killProcess(pid: number, signal?: 'SIGTERM' | 'SIGKILL'): {
        success: boolean;
        error?: string;
    };
    getPortUsage(port?: number): PortUsage[];
    detectIssues(): DetectedIssue[];
}

declare class InfraConnector {
    private store;
    private clients;
    constructor(store: EventStore);
    loadFromConfig(projectManager: ProjectManager, projectName: string): void;
    getDeployLogs(project: string, platform?: string, deployId?: string): Promise<DeployLog[]>;
    getRuntimeLogs(project: string, opts?: {
        platform?: string;
        since?: number;
        level?: string;
    }): Promise<RuntimeLog[]>;
    getBuildStatus(project: string): Promise<BuildStatus[]>;
    getInfraOverview(project?: string): InfraOverview[];
}

declare class SessionManager {
    private projectManager;
    private sqliteStores;
    private store;
    constructor(projectManager: ProjectManager, sqliteStores: Map<string, SqliteStore>, store: EventStore);
    computeMetrics(sessionId: string, project: string, events: RuntimeEvent[]): SessionMetrics;
    createSnapshot(sessionId: string, project: string, label?: string): SessionSnapshot;
    getSessionSnapshots(project: string, sessionId: string): SessionSnapshot[];
    getSnapshotById(project: string, snapshotId: number): SessionSnapshot | null;
    getSessionHistory(project: string, limit?: number): SessionSnapshot[];
}

declare function compareSessions(metricsA: SessionMetrics, metricsB: SessionMetrics): SessionDiffResult;

/**
 * A workspace is the top-level tenancy boundary. Every project belongs to
 * exactly one workspace, and every API key is scoped to one workspace.
 * On single-user installs a "personal" workspace is auto-created and is
 * invisible to users until they create a second one.
 */
interface PmWorkspace {
    id: string;
    name: string;
    slug: string;
    description?: string;
    createdAt: number;
    updatedAt: number;
    isDefault?: boolean;
}
/**
 * Workspace-scoped API key. SDKs authenticate with a key, the collector
 * looks up its workspace, and only projects in that workspace can accept
 * events from that key.
 */
interface PmApiKey {
    /**
     * Raw secret. Populated ONLY by `createApiKey()`'s return value — the caller
     * must store it on the spot. Every subsequent read (list/get) returns this
     * field as an empty string; the server stores a SHA-256 hash, not the
     * plaintext, so there is no way to recover it later.
     */
    key: string;
    /** User-visible identifier — first ~11 chars of the raw token, e.g. "tk_9f2a1c3b". Safe to log. */
    keyPrefix: string;
    /** Last 4 chars of the raw token — for visual confirmation ("...a4f1"). */
    keyLast4: string;
    workspaceId: string;
    label: string;
    createdAt: number;
    lastUsedAt?: number;
    expiresAt?: number;
    revokedAt?: number;
}
type ProjectPhase = 'preliminary' | 'application_development' | 'post_implementation';
type ProjectStatus = 'active' | 'suspended' | 'abandoned';
interface PmProject {
    id: string;
    workspaceId?: string;
    name: string;
    path?: string;
    claudeProjectKey?: string;
    runtimescopeProject?: string;
    runtimeProjectId?: string;
    runtimeApps?: string[];
    phase: ProjectPhase;
    managementAuthorized: boolean;
    probableToComplete: boolean;
    projectStatus: ProjectStatus;
    category?: string;
    sdkInstalled?: boolean;
    createdAt: number;
    updatedAt: number;
    metadata?: Record<string, unknown>;
}
type TaskStatus = 'todo' | 'in_progress' | 'done';
type TaskPriority = 'low' | 'medium' | 'high' | 'urgent';
type TaskSource = 'manual' | 'claude_session' | 'github_issue';
interface PmTask {
    id: string;
    projectId?: string;
    title: string;
    description?: string;
    status: TaskStatus;
    priority: TaskPriority;
    labels: string[];
    source: TaskSource;
    sourceRef?: string;
    sortOrder: number;
    assignedTo?: string;
    dueDate?: string;
    createdAt: number;
    updatedAt: number;
    completedAt?: number;
}
interface PmSession {
    id: string;
    projectId: string;
    jsonlPath: string;
    jsonlSize?: number;
    firstPrompt?: string;
    summary?: string;
    slug?: string;
    model?: string;
    version?: string;
    gitBranch?: string;
    messageCount: number;
    userMessageCount: number;
    assistantMessageCount: number;
    totalInputTokens: number;
    totalOutputTokens: number;
    totalCacheCreationTokens: number;
    totalCacheReadTokens: number;
    costMicrodollars: number;
    startedAt: number;
    endedAt?: number;
    activeMinutes: number;
    compactionCount: number;
    preCompactionTokens?: number;
    permissionMode?: string;
    createdAt: number;
    updatedAt: number;
}
interface SessionStats {
    totalSessions: number;
    totalActiveMinutes: number;
    totalCostMicrodollars: number;
    totalInputTokens: number;
    totalOutputTokens: number;
    avgSessionMinutes: number;
    modelBreakdown: {
        model: string;
        sessions: number;
        cost: number;
    }[];
}
interface PmNote {
    id: string;
    projectId?: string;
    sessionId?: string;
    title: string;
    content: string;
    pinned: boolean;
    tags: string[];
    createdAt: number;
    updatedAt: number;
}
type CapexClassification = 'capitalizable' | 'expensed';
type WorkType = 'coding' | 'testing' | 'design' | 'planning' | 'maintenance' | 'bug_fix';
interface PmCapexEntry {
    id: string;
    projectId: string;
    sessionId: string;
    classification: CapexClassification;
    workType?: WorkType;
    activeMinutes: number;
    costMicrodollars: number;
    adjustmentFactor: number;
    adjustedCostMicrodollars: number;
    confirmed: boolean;
    confirmedAt?: number;
    confirmedBy?: string;
    notes?: string;
    period: string;
    createdAt: number;
    updatedAt: number;
}
interface CapexSummary {
    projectId: string;
    period?: {
        start: string;
        end: string;
    };
    totalSessions: number;
    totalActiveMinutes: number;
    totalCostMicrodollars: number;
    capitalizableCostMicrodollars: number;
    expensedCostMicrodollars: number;
    confirmedCount: number;
    unconfirmedCount: number;
    byMonth: {
        period: string;
        capitalizable: number;
        expensed: number;
        activeMinutes: number;
    }[];
}
type GitFileStatus = 'M' | 'A' | 'D' | 'R' | '?' | 'C' | 'U';
interface GitFileChange {
    path: string;
    status: GitFileStatus;
    oldPath?: string;
}
interface GitStatus {
    branch: string;
    staged: GitFileChange[];
    unstaged: GitFileChange[];
    untracked: GitFileChange[];
    isGitRepo: boolean;
}
interface GitCommit {
    hash: string;
    shortHash: string;
    subject: string;
    message: string;
    author: string;
    relativeDate: string;
    refs: string;
}
interface MemoryFile {
    filename: string;
    content: string;
    sizeBytes: number;
}
interface RulesFiles {
    global: {
        path: string;
        content: string;
        exists: boolean;
    };
    project: {
        path: string;
        content: string;
        exists: boolean;
    };
    local: {
        path: string;
        content: string;
        exists: boolean;
    };
}

interface PmStoreOptions {
    dbPath: string;
    walMode?: boolean;
}
declare class PmStore {
    private db;
    constructor(options: PmStoreOptions);
    private createSchema;
    private runMigrations;
    /**
     * Ensure a default "personal" workspace exists and every project has a
     * workspace_id. Runs on every startup — idempotent.
     */
    private ensureDefaultWorkspace;
    upsertProject(project: PmProject): void;
    getProject(id: string): PmProject | null;
    listProjects(): PmProject[];
    updateProject(id: string, updates: Partial<PmProject>): void;
    /**
     * Auto-link an SDK appName to a PM project.
     * Matches by: exact name, directory basename, runtimescopeProject, or existing runtimeApps.
     * Returns the project ID if linked, null if no match found.
     */
    autoLinkApp(appName: string, projectId?: string): string | null;
    /** Find a project's runtimeProjectId by checking if appName appears in any project's runtimeApps. */
    findProjectIdByApp(appName: string): string | null;
    listCategories(): string[];
    listWorkspaces(): PmWorkspace[];
    getWorkspace(id: string): PmWorkspace | null;
    getWorkspaceBySlug(slug: string): PmWorkspace | null;
    getDefaultWorkspace(): PmWorkspace;
    createWorkspace(input: {
        name: string;
        slug?: string;
        description?: string;
    }): PmWorkspace;
    updateWorkspace(id: string, updates: Partial<Pick<PmWorkspace, 'name' | 'slug' | 'description'>>): void;
    deleteWorkspace(id: string): void;
    /** Move a project between workspaces. */
    setProjectWorkspace(projectId: string, workspaceId: string): void;
    createApiKey(workspaceId: string, label: string, expiresAt?: number): PmApiKey;
    listApiKeys(workspaceId: string): PmApiKey[];
    /** Revoke by the public prefix (what the dashboard shows), not the raw secret. */
    revokeApiKey(prefix: string): void;
    /** Look up an API key's workspace by its public prefix. Used for per-workspace authorization on the revoke route. */
    findApiKeyByPrefix(prefix: string): PmApiKey | null;
    /**
     * True if any non-revoked workspace API key exists. The HTTP auth gate uses
     * this to enforce auth whenever workspace keys are in play, even when the
     * global AuthManager has no keys configured. Without this check, a user who
     * creates a workspace key expecting it to gate access gets no auth at all
     * (the H5 bypass).
     */
    hasActiveApiKeys(): boolean;
    /**
     * Given a runtime projectId (proj_xxx), return the workspaceId it belongs to,
     * or null if the projectId isn't registered with any PM project. Used to
     * enforce per-workspace isolation on event-read routes — the caller can only
     * query events from runtime projects owned by their workspace.
     */
    getWorkspaceIdByRuntimeProjectId(runtimeProjectId: string): string | null;
    getWorkspaceByApiKey(rawKey: string): PmWorkspace | null;
    private mapProjectRow;
    createTask(task: PmTask): PmTask;
    updateTask(id: string, updates: Partial<PmTask>): void;
    deleteTask(id: string): void;
    listTasks(projectId?: string, status?: TaskStatus): PmTask[];
    reorderTask(id: string, status: TaskStatus, sortOrder: number): void;
    private mapTaskRow;
    upsertSession(session: PmSession): void;
    getSession(id: string): PmSession | null;
    listSessions(projectId?: string, opts?: {
        limit?: number;
        offset?: number;
        startDate?: string;
        endDate?: string;
        hideEmpty?: boolean;
    }): PmSession[];
    getSessionStats(projectId?: string, opts?: {
        startDate?: string;
        endDate?: string;
        hideEmpty?: boolean;
    }): SessionStats;
    getProjectSummaries(opts?: {
        startDate?: string;
        endDate?: string;
        hideEmpty?: boolean;
    }): ProjectSummaryRow[];
    private mapSessionRow;
    createNote(note: PmNote): PmNote;
    updateNote(id: string, updates: Partial<PmNote>): void;
    deleteNote(id: string): void;
    listNotes(opts?: {
        projectId?: string;
        pinned?: boolean;
    }): PmNote[];
    private mapNoteRow;
    upsertCapexEntry(entry: PmCapexEntry): void;
    listCapexEntries(projectId: string, opts?: {
        month?: string;
        confirmed?: boolean;
    }): PmCapexEntry[];
    updateCapexEntry(id: string, updates: Partial<PmCapexEntry>): void;
    confirmCapexEntry(id: string, confirmedBy?: string): void;
    getCapexSummary(projectId: string, opts?: {
        startDate?: string;
        endDate?: string;
    }): CapexSummary;
    exportCapexCsv(projectId: string, opts?: {
        startDate?: string;
        endDate?: string;
    }): string;
    exportCapexXlsx(projectId: string, opts?: {
        startDate?: string;
        endDate?: string;
    }): Promise<Buffer>;
    exportCapexXlsxAll(opts?: {
        startDate?: string;
        endDate?: string;
        category?: string;
    }): Promise<Buffer>;
    private mapCapexRow;
    deleteProject(id: string): void;
    isDeletedPath(path: string): boolean;
    recoverProject(path: string): void;
    listDeletedProjects(): Array<{
        path: string;
        name: string;
        deletedAt: number;
    }>;
    close(): void;
}
interface ProjectSummaryRow {
    id: string;
    name: string;
    path: string | null;
    category: string | null;
    sdk_installed: number;
    runtimescope_project: string | null;
    runtime_apps: string | null;
    session_count: number;
    total_cost: number;
    total_active_minutes: number;
    last_session_at: number | null;
    total_messages: number;
}

interface DiscoveryResult {
    projectsDiscovered: number;
    projectsUpdated: number;
    sessionsDiscovered: number;
    sessionsUpdated: number;
    errors: string[];
}
declare class ProjectDiscovery {
    private pmStore;
    private projectManager;
    private readonly claudeBaseDir;
    constructor(pmStore: PmStore, projectManager: ProjectManager, claudeBaseDir?: string);
    /**
     * Run full discovery: Claude Code projects + RuntimeScope projects.
     * Never throws — all errors are captured in the result.
     */
    discoverAll(): Promise<DiscoveryResult>;
    /**
     * Discover Claude Code projects from ~/.claude/projects/.
     */
    discoverClaudeProjects(): Promise<Partial<DiscoveryResult>>;
    /**
     * Discover RuntimeScope projects from ~/.runtimescope/projects/.
     */
    discoverRuntimeScopeProjects(): Promise<Partial<DiscoveryResult>>;
    /**
     * Index all sessions for a given project.
     * Returns the number of sessions indexed (new or updated).
     */
    indexProjectSessions(projectId: string): Promise<number>;
    /**
     * Process a single Claude project directory key.
     */
    private processClaudeProject;
    /**
     * Try to resolve the filesystem path from the sessions-index.json projectPath field.
     */
    private resolvePathFromIndex;
    /**
     * Index sessions for a Claude project directly (used during discovery).
     * Returns counts of discovered and updated sessions.
     */
    private indexSessionsForClaudeProject;
    /**
     * Build a PmSession from the fast sessions-index.json entry.
     * Token counts and cost are zeroed since the index doesn't contain them;
     * they will be populated on a subsequent full parse if needed.
     */
    private buildSessionFromIndex;
    /**
     * Build a PmSession by fully parsing a .jsonl file.
     */
    private buildSessionFromJsonl;
    /**
     * Create or update a CapEx entry stub for a session.
     * Defaults to 'expensed' classification, unconfirmed.
     */
    private upsertCapexStub;
}

interface HttpServerOptions {
    port?: number;
    host?: string;
    authManager?: AuthManager;
    allowedOrigins?: string[];
    tls?: TlsConfig;
}
declare class HttpServer {
    private server;
    private wss;
    private store;
    private processMonitor;
    private authManager;
    private allowedOrigins;
    private rateLimiter;
    private dashboardClients;
    private eventListener;
    private routes;
    private pmRouter;
    private sdkBundlePath;
    private activePort;
    private startedAt;
    private connectedSessionsGetter;
    private pmStore;
    private projectManager;
    private isReadyGetter;
    private snapshotFn;
    private lastSnapshotAt;
    private renderMetricsFn;
    constructor(store: EventStore, processMonitor?: ProcessMonitor, options?: {
        authManager?: AuthManager;
        allowedOrigins?: string[];
        rateLimiter?: SessionRateLimiter;
        pmStore?: PmStore;
        discovery?: ProjectDiscovery;
        getConnectedSessions?: () => {
            sessionId: string;
            projectName: string;
        }[];
        projectManager?: ProjectManager;
        /**
         * Returns true once the collector has finished startup recovery
         * (WAL replay + ring-buffer warm). Drives the `/readyz` probe — load
         * balancers and attach-mode detection should wait for ready before
         * routing traffic.
         */
        isReady?: () => boolean;
        /**
         * Called by `POST /api/v1/admin/snapshot`. Implementations should copy
         * every project's SQLite + WAL into a fresh directory and return a
         * manifest. Admin-only on the route side; rate-limited to prevent
         * snapshot loops.
         */
        createSnapshot?: () => {
            path: string;
            timestamp: string;
            projects: {
                name: string;
                sqliteBytes: number;
                walBytes: number;
                eventCount: number;
            }[];
            totalBytes: number;
        };
        /**
         * Returns the Prometheus exposition body for `GET /metrics`. Public
         * (no auth) so a Prometheus scraper can hit it without configuring a
         * bearer token — that's the standard pattern. Opt out via the
         * `RUNTIMESCOPE_DISABLE_METRICS=1` env var.
         */
        renderMetrics?: () => string;
    });
    private registerRoutes;
    /**
     * Resolve the SDK IIFE bundle path.
     * Tries multiple locations for monorepo and installed-package scenarios.
     */
    private resolveSdkPath;
    /**
     * Resolve the directory containing the built dashboard SPA. The tsup
     * onSuccess hook copies packages/dashboard/dist/ into the collector's
     * dist/dashboard-assets/ so the dashboard ships inside the @runtimescope/
     * collector npm package. Cached after first resolution.
     */
    private dashboardAssetsRoot;
    private resolveDashboardAssets;
    getPort(): number;
    /**
     * Validate the `project_id` query parameter against the caller's workspace.
     *
     * Returns:
     *   - `string`  — the caller is authorized; pass to store.
     *   - `undefined` — caller is admin and didn't specify a project_id (all projects allowed).
     *   - `false`   — not authorized (a 400 or 403 response has already been written); the handler must return immediately.
     *
     * Callers with a workspace-scoped token MUST provide `project_id`, and it
     * must resolve to a PM project in the caller's workspace. Runtime projectIds
     * without a PM record (never registered via setup_project) fall through to
     * admin-only; workspace-scoped callers get 403.
     */
    private authorizeProjectIdParam;
    start(options?: HttpServerOptions): Promise<void>;
    private tryStart;
    stop(): Promise<void>;
    broadcastEvent(event: RuntimeEvent): void;
    broadcastSessionChange(type: 'session_connected' | 'session_disconnected', sessionId: string, appName: string): void;
    private broadcastDevServer;
    private handleRequest;
    private setCorsHeaders;
    private readBody;
    private json;
}

interface ParseResult {
    session: Partial<PmSession>;
    messageTimestamps: number[];
}
/**
 * Sum gaps between consecutive timestamps where gap < idle threshold.
 * Returns total active time in minutes.
 */
declare function calculateActiveMinutes(timestamps: number[], idleThresholdMs?: number): number;
/**
 * Calculate cost in microdollars from token counts and model name.
 * Formula: (input * pricing.input + output * pricing.output
 *           + cacheCreation * pricing.cacheWrite + cacheRead * pricing.cacheRead) / 1_000_000
 */
declare function calculateCostMicrodollars(model: string, inputTokens: number, outputTokens: number, cacheCreationTokens: number, cacheReadTokens: number): number;
/**
 * Stream-parse a Claude Code session JSONL file and extract metadata.
 *
 * Uses Node.js readline + createReadStream for memory-safe line-by-line
 * parsing of files up to ~192 MB. Each line is independently JSON.parse'd;
 * malformed lines are silently skipped.
 */
declare function parseSessionJsonl(jsonlPath: string, sessionId: string, projectId: string): Promise<ParseResult>;

/** Find PIDs listening on `port`. Cross-platform. */
declare function getPidsOnPort(port: number): number[];
/** Find which ports a PID is listening on. Cross-platform. */
declare function getListenPorts(pid: number): number[];
/** Get the working directory of a process. Returns undefined on Windows or failure. */
declare function getProcessCwd(pid: number): string | undefined;
/** Find PIDs with open files/cwd in a directory. Best-effort on Windows (returns []). */
declare function findPidsInDirectory(dir: string): number[];
interface ProcessInfo {
    pid: number;
    cpu: number;
    mem: number;
    command: string;
}
/** List all running processes. Cross-platform. */
declare function parseProcessList(): ProcessInfo[];
/** Get RSS memory in MB for a given PID. Cross-platform. */
declare function getProcessMemoryMB(pid: number): number;

export { type ApiChangeRecord, type ApiContract, type ApiContractField, ApiDiscoveryEngine, type ApiEndpoint, type ApiEndpointHealth, type ApiKeyEntry, type AuthConfig, type AuthInfo, AuthManager, BUILT_IN_RULES, type BackgroundSpriteSheet, type BaseEvent, type BuildMeta, type BuildStatus, type CSSArchitecture, type CSSCustomProperty, type CapexClassification, type CapexSummary, type CaptureConfig, CollectorServer, type CollectorServerOptions, type ColorToken, type CommandResponse, type ComputedStyleEntry, ConnectionManager, type ConsoleEvent, type ConsoleFilter, type ConsoleLevel, Counter, type CustomEvent, type CustomEventFilter, DataBrowser, type DatabaseConnectionConfig, type DatabaseEvent, type DatabaseFilter, type DatabaseOperation, type DatabaseSchema, type DatabaseSource, type DeployLog, type DetectedBuildTool, type DetectedFramework, type DetectedHosting, type DetectedIssue, type DetectedMetaFramework, type DetectedUILibrary, type DevProcess, type DevProcessType, type DomSnapshotEvent, type ElementSnapshotNode, type EventBatchPayload, EventStore, type EventType, type FontFaceInfo, type FontUsage, type FormFieldInfo, Gauge, type GitCommit, type GitFileChange, type GitFileStatus, type GitStatus, type GlobalConfig, type GraphQLOperation, type HandshakePayload, type HeadingInfo, type HistoricalFilter, HttpServer, type HttpServerOptions, type IconFontInfo, type ImageAsset, type IndexSuggestion, InfraConnector, type InfraOverview, type InfrastructureConfig, type InlineSVGAsset, type InteractiveElementInfo, type IssueSeverity, type LabelValues, type LandmarkInfo, type LayoutNode, type ManagedConnection, type MaskSpriteSheet, type MemoryFile, type MetricDelta, MetricsRegistry, type NavigationEvent, type NetworkEvent, type NetworkFilter, type NormalizedQueryStats, OtelExporter, type OtelExporterOptions, type PerformanceEvent, type PerformanceFilter, type PerformanceMetricName, type PmApiKey, type PmCapexEntry, type PmNote, type PmProject, type PmSession, PmStore, type PmStoreIndexSource, type PmTask, type PmWorkspace, type PortUsage, type ProcessInfo, ProcessMonitor, type ProjectConfig, ProjectDiscovery, ProjectManager, type ProjectPhase, type ProjectStatus, type RateLimitConfig, type ReadOptions, type ReadResult, type ReconAccessibilityEvent, type ReconAssetInventoryEvent, type ReconComputedStylesEvent, type ReconDesignTokensEvent, type ReconElementSnapshotEvent, type ReconEventType, type ReconFilter, type ReconFontsEvent, type ReconLayoutTreeEvent, type ReconMetadataEvent, type RedactionRule, Redactor, type RedactorConfig, type RenderComponentProfile, type RenderEvent, type RenderFilter, RingBuffer, type RulesFiles, type RuntimeEvent, type RuntimeLog, type RuntimeScopeProjectConfig, type SVGSpriteSymbol, type SchemaColumn, type SchemaForeignKey, type SchemaIndex, SchemaIntrospector, type SchemaTable, type SdkEntry, type ServerCommand, type ServerMetricName, type ServiceInfo, type SessionDiffResult, type SessionEvent, type SessionInfo, type SessionInfoExtended, SessionManager, type SessionMetrics, SessionRateLimiter, type SessionSnapshot, type SessionStats, type SnapshotResult, type SpacingValue, type SpriteFrame, SqliteStore, type SqliteStoreOptions, type StateEvent, type StateFilter, type TaskPriority, type TaskSource, type TaskStatus, type TechStackDetection, type TimelineFilter, type TlsConfig, type ToolResponse, type TypographyToken, type UIInteractionAction, type UIInteractionEvent, type UIInteractionFilter, type UserContext, type WSMessage, Wal, type WalOptions, type WebVitalRating, type WorkType, type WriteOptions, type WriteResult, aggregateQueryStats, calculateActiveMinutes, calculateCostMicrodollars, compareSessions, detectIssues, detectN1Queries, detectOverfetching, detectSlowQueries, findPidsInDirectory, generateApiKey, generateProjectId, getListenPorts, getOrCreateProjectId, getPidsOnPort, getProcessCwd, getProcessMemoryMB, isSqliteAvailable, isValidProjectId, loadTlsOptions, migrateProjectIds, otelOptionsFromEnv, parseOtelHeaders, parseProcessList, parseSessionJsonl, randomSpanId, readProjectConfig, resolveProjectAppNames, resolveTlsConfig, safeLog, scaffoldProjectConfig, suggestIndexes, traceIdFromSession, writeProjectConfig };
