import { ModelName } from "smoltalk";
import { JSONEdge } from "./types.js";
export declare const STATELOG_FORMAT_VERSION = 1;
export type SpanType = "agentRun" | "nodeExecution" | "llmCall" | "toolExecution" | "forkAll" | "race" | "handlerChain" | "embedding" | "memoryRemember" | "memoryRecall" | "memoryForget" | "memoryCompaction";
export type SpanContext = {
    spanId: string;
    parentSpanId: string | null;
    spanType: SpanType;
    startTime: number;
};
export type RunMetadata = {
    tags?: string[];
    environment?: string;
    userId?: string;
    agentVersion?: string;
    custom?: Record<string, string>;
};
export type StatelogConfig = {
    host: string;
    traceId?: string;
    apiKey: string;
    projectId: string;
    debugMode: boolean;
    metadata?: RunMetadata;
    observability?: boolean;
    logFile?: string;
    /**
     * Per-request timeout (milliseconds) applied to the remote http POST.
     * Prevents a slow/unreachable statelog host from wedging the agent's
     * end-of-run cleanup. Default: 1500ms.
     */
    requestTimeoutMs?: number;
};
export type TokenUsage = {
    inputTokens?: number;
    outputTokens?: number;
    cachedInputTokens?: number;
    totalTokens?: number;
};
export type TokenCost = {
    inputCost?: number;
    outputCost?: number;
    totalCost?: number;
};
export declare class StatelogClient {
    private host;
    private debugMode;
    private traceId;
    private apiKey;
    private projectId;
    private logFile?;
    private enabled;
    private remoteEnabled;
    private rootStack;
    private spanStorage;
    private metadata?;
    private requestTimeoutMs;
    constructor(config: StatelogConfig);
    private currentStack;
    snapshotStack(): SpanContext[];
    runInBranchContext<T>(parentStack: SpanContext[], fn: () => Promise<T>): Promise<T>;
    startSpan(type: SpanType): string | undefined;
    endSpan(spanId?: string): SpanContext | undefined;
    get currentSpan(): SpanContext | undefined;
    toJSON(): {
        traceId: string;
        projectId: string;
        host: string;
        debugMode: boolean;
    };
    debug(message: string, data: any): Promise<void>;
    graph({ nodes, edges, startNode, }: {
        nodes: string[];
        edges: Record<string, JSONEdge>;
        startNode?: string;
    }): Promise<void>;
    enterNode({ nodeId, data, }: {
        nodeId: string;
        data: any;
    }): Promise<void>;
    exitNode({ nodeId, data, timeTaken, }: {
        nodeId: string;
        data: any;
        timeTaken?: number;
    }): Promise<void>;
    beforeHook({ nodeId, startData, endData, timeTaken, }: {
        nodeId: string;
        startData: any;
        endData: any;
        timeTaken?: number;
    }): Promise<void>;
    afterHook({ nodeId, startData, endData, timeTaken, }: {
        nodeId: string;
        startData: any;
        endData: any;
        timeTaken?: number;
    }): Promise<void>;
    followEdge({ fromNodeId, toNodeId, isConditionalEdge, data, }: {
        fromNodeId: string;
        toNodeId: string;
        isConditionalEdge: boolean;
        data: any;
    }): Promise<void>;
    promptCompletion({ messages, completion, model, timeTaken, tools, responseFormat, usage, cost, finishReason, stream, }: {
        messages: any[];
        completion: any;
        model?: ModelName | string;
        timeTaken?: number;
        tools?: {
            name: string;
            description?: string;
            schema: any;
        }[];
        responseFormat?: any;
        usage?: TokenUsage;
        cost?: TokenCost;
        finishReason?: string;
        stream?: boolean;
    }): Promise<void>;
    /**
     * Emit an `embedCompletion` event. Mirrors `promptCompletion` so the
     * viewer can render the two with a shared formatter, but keeps the
     * embedding-specific bits (dimensions, phase tag) separate.
     *
     * `inputPreview` is intentionally a short slice of the source text —
     * the full text is kept off the wire so a transcript-with-PII never
     * ends up in a remote sink by accident. Vectors are NEVER logged
     * (only their length, via `dimensions`).
     */
    embedCompletion({ inputPreview, inputCount, model, dimensions, timeTaken, usage, cost, phase, }: {
        /** First ~200 chars of the embedded text, for human-readable tracing. */
        inputPreview: string;
        /** Number of input strings in the batch. Currently always 1 from
         *  memory; left as a count so future batching changes don't
         *  require a schema bump. */
        inputCount: number;
        /** Embedding model name (e.g. "text-embedding-3-small"). */
        model?: string;
        /** Vector length. Useful for catching index-vs-query model
         *  mismatches at trace time without comparing the full vectors. */
        dimensions?: number;
        /** Wall-clock latency in ms (caller measures via `performance.now`). */
        timeTaken?: number;
        /** Optional provider-reported usage. Not all embed providers
         *  return these; absent values stay undefined. */
        usage?: TokenUsage;
        cost?: TokenCost;
        /** Free-form tag identifying the caller — e.g. "recall-query",
         *  "new-observation". Lets a viewer filter "embed for recall"
         *  vs "embed for storage" without parsing the parent span tree. */
        phase?: string;
    }): Promise<void>;
    /**
     * Memory umbrella-span marker events.
     *
     * Why these exist: the logs viewer infers span types from EVENT
     * types (see `lib/logsViewer/tree.ts#inferSpanLabel`). A span that
     * never has an event posted with its own `span_id` is invisible to
     * the viewer — its children get re-parented to the trace root.
     *
     * Calling `startSpan("memoryRemember")` only sets up the AsyncLocal-
     * Storage stack; on its own it produces no event. These methods
     * post a tiny marker event right after `startSpan` so the span
     * materializes in the tree with the right label, and the inner
     * `llmCall` / `embedding` spans nest under it. The payload is also
     * useful in its own right (content/query preview, memoryId).
     */
    memoryRemember({ contentPreview, memoryId, }: {
        /** First ~N chars of the content being remembered. */
        contentPreview: string;
        /** Active memory scope (from `setMemoryId`, defaults to "default"). */
        memoryId: string;
    }): Promise<void>;
    memoryRecall({ queryPreview, memoryId, phase, }: {
        /** First ~N chars of the recall query. */
        queryPreview: string;
        memoryId: string;
        /** "recall" for the user-facing tier-3 call, "recallForInjection"
         *  for the auto-injection variant. Lets the viewer distinguish
         *  the two without inspecting the parent span tree. */
        phase: "recall" | "recallForInjection";
    }): Promise<void>;
    memoryForget({ queryPreview, memoryId, }: {
        queryPreview: string;
        memoryId: string;
    }): Promise<void>;
    memoryCompaction({ memoryId, messageCount, threshold, }: {
        memoryId: string;
        /** Number of messages in the thread that triggered compaction. */
        messageCount: number;
        /** Threshold the count was checked against (so a viewer can show
         *  how close to the trigger this run was). */
        threshold: number;
    }): Promise<void>;
    toolCall({ toolName, args, output, model, timeTaken, }: {
        toolName: string;
        args: any;
        output: any;
        model?: ModelName;
        timeTaken?: number;
    }): Promise<void>;
    diff({ itemA, itemB, message, }: {
        itemA: any;
        itemB: any;
        message?: string;
    }): Promise<void>;
    runMetadata(metadata: RunMetadata & {
        moduleName?: string;
        entryNode?: string;
    }): Promise<void>;
    agentStart({ entryNode, args, }: {
        entryNode: string;
        args?: any;
    }): Promise<void>;
    agentEnd({ entryNode, result, timeTaken, tokenStats, }: {
        entryNode: string;
        result?: any;
        timeTaken: number;
        tokenStats?: {
            usage: TokenUsage;
            cost: TokenCost;
        };
    }): Promise<void>;
    interruptThrown({ interruptId, interruptData, }: {
        interruptId: string;
        interruptData: any;
    }): Promise<void>;
    handlerDecision({ interruptId, handlerIndex, decision, value, }: {
        interruptId: string;
        handlerIndex: number;
        decision: "approve" | "reject" | "propagate" | "none";
        value?: any;
    }): Promise<void>;
    interruptResolved({ interruptId, outcome, resolvedBy, timeTaken, }: {
        interruptId: string;
        outcome: "approved" | "rejected" | "propagated";
        resolvedBy: "handler" | "user" | "policy" | "ipc";
        timeTaken?: number;
    }): Promise<void>;
    checkpointCreated({ checkpointId, reason, sourceLocation, }: {
        checkpointId: number;
        reason: "interrupt" | "explicit" | "failure" | "fork" | "race";
        sourceLocation?: {
            moduleId: string;
            scopeName: string;
            stepPath: string;
        };
    }): Promise<void>;
    checkpointRestored({ checkpointId, restoreCount, maxRestores, overrides, }: {
        checkpointId: number;
        restoreCount: number;
        maxRestores?: number;
        overrides?: {
            args?: boolean;
            globals?: boolean;
            locals?: boolean;
        };
    }): Promise<void>;
    forkStart({ forkId, mode, branchCount, }: {
        forkId: string;
        mode: "all" | "race";
        branchCount: number;
    }): Promise<void>;
    forkBranchEnd({ forkId, branchIndex, outcome, timeTaken, }: {
        forkId: string;
        branchIndex: number;
        outcome: "success" | "failure" | "interrupted" | "aborted";
        timeTaken: number;
    }): Promise<void>;
    forkEnd({ forkId, mode, timeTaken, winnerIndex, }: {
        forkId: string;
        mode: "all" | "race";
        timeTaken: number;
        winnerIndex?: number;
    }): Promise<void>;
    threadCreated({ threadId, threadType, parentThreadId, }: {
        threadId: string;
        threadType: "thread" | "subthread";
        parentThreadId?: string;
    }): Promise<void>;
    /** Fired when a previously-closed thread is re-activated via
     *  `ThreadStore.resumeExisting()` (i.e. by `thread(continue: id)`
     *  or `thread(session: name)` on second+ entry). Mirrors
     *  `threadCreated` so trace consumers can distinguish first-entry
     *  from resumption. */
    threadResumed({ threadId, }: {
        threadId: string;
    }): Promise<void>;
    /** Fired when the `onThreadEnd` callback dispatcher itself throws
     *  inside the `Runner.thread` finally block. Individual callback
     *  errors are caught and logged by `fireWithGuard`; this event
     *  covers the rarer case where the dispatcher loop itself blew up
     *  (e.g. a malformed registration). Emitted in lieu of the
     *  previous `console.error` so the failure is observable in
     *  traces. */
    threadEndHookError({ threadId, error, }: {
        threadId: string;
        error: string;
    }): Promise<void>;
    error({ errorType, message, functionName, retryable, sourceLocation, }: {
        errorType: "toolError" | "llmError" | "runtimeError" | "validationError" | "limitExceeded";
        message: string;
        functionName?: string;
        retryable?: boolean;
        sourceLocation?: {
            moduleId: string;
            line?: number;
        };
    }): Promise<void>;
    post(body: Record<string, any>, options?: {
        /**
         * When true, fire the remote http POST without awaiting its
         * result. The synchronous file/stdout sinks still run inline so
         * the event ordering they care about is preserved; only the
         * network round-trip is detached. Used for end-of-run events
         * (e.g. `agentEnd`) where nothing useful can be done with the
         * response and waiting would just delay process exit.
         */
        noWait?: boolean;
    }): Promise<void>;
}
export declare function getStatelogClient(config: {
    host: string;
    traceId?: string;
    projectId: string;
    debugMode?: boolean;
    observability?: boolean;
    logFile?: string;
}): StatelogClient;
