/**
 * In-memory session DAG.
 *
 * {@link SessionGraph} holds the content-addressed nodes of one session and a
 * moving head. Appending a turn chains a fresh node onto the current head and
 * advances the head to it; branching points the head back at an older node so a
 * subsequent append forks a new line of history. The linear context handed to a
 * model is the path from a chosen leaf back to the root, reversed into
 * root→leaf order.
 */
import type { Turn } from "../../llmgateway/contract";
import type { SessionNode } from "../contract";
/** Source of wall-clock timestamps, injectable for deterministic tests. */
export type Clock = () => number;
/**
 * A mutable, branchable graph of {@link SessionNode}s for a single session.
 *
 * Nodes are immutable once added and keyed by their content hash. The graph
 * tracks a `head` — the node a fresh {@link SessionGraph.append} will chain
 * onto — which starts unset for an empty session.
 */
export declare class SessionGraph {
    readonly sessionId: string;
    private readonly nodes;
    private head;
    private readonly clock;
    constructor(sessionId: string, clock?: Clock);
    /**
     * Rebuild a graph from previously persisted nodes plus its leaf pointer.
     *
     * Nodes may arrive in any order; parents are not required to precede children.
     * The provided `leaf` becomes the head, or the loner node if exactly one
     * exists and no leaf is named.
     */
    static hydrate(sessionId: string, nodes: readonly SessionNode[], leaf: string | null, clock?: Clock): SessionGraph;
    /** The id of the node a fresh append will chain onto, or `null` if empty. */
    get leaf(): string | null;
    /** Total number of nodes across every branch. */
    get size(): number;
    /** Look up a node by its content hash. */
    get(nodeId: string): SessionNode | undefined;
    /** Every node in the graph, in insertion order. */
    all(): SessionNode[];
    /**
     * Chain a new turn onto the current head and advance the head to it.
     *
     * Returns the freshly minted node. If the content hash collides with an
     * existing node (identical lineage, turn, and timestamp), the head simply
     * advances to that node without duplicating it.
     */
    append(turn: Turn): SessionNode;
    /**
     * Move the head to an existing node so the next append forks from there.
     *
     * Throws if `nodeId` is not part of this graph.
     */
    branchFrom(nodeId: string): SessionNode;
    /**
     * Resolve the linear context ending at `leaf`, ordered root→leaf.
     *
     * Walks parent pointers from the leaf back to a root, then reverses. Throws if
     * `leaf` is unknown or the chain references a missing parent.
     */
    pathTo(leaf: string): Turn[];
    /**
     * Adopt `leaf` as the head and return its full root→leaf turn context.
     *
     * Convenience for re-entering a session at a chosen tip: combines {@link
     * branchFrom} (positioning) with {@link pathTo} (context).
     */
    resume(leaf: string): Turn[];
}
