import type { LucidClientLike, LucidRawRunner } from '../stores/lucid.js';
/**
 * A2A conversation state the agent tables do not carry: who a `contextId` belongs to, and the reply
 * each `messageId` got (PACT §4.2, §4.3).
 *
 * A context belongs to a brand (the exposed agent) and to one personal-agent user — the pair
 * `(agent issuer, sub)`. Once a turn in it has run under a delegation, it is also bound to that
 * account: a token for another account is refused there, so one conversation never mixes two users'
 * data (§5.5).
 */
export interface A2aContext {
    /** The `contextId` — the agent thread's id. */
    id: string;
    /** The exposed agent (the "brand" in `/a2a/{brand}`). */
    brand: string;
    agentIssuer: string;
    agentSub: string;
    /** The account a delegated turn ran as; `null` until one does. */
    accountRef: string | null;
}
/** Where a `messageId` stands: never seen (now claimed), still running, or answered. */
export type MessageClaim = {
    status: 'claimed';
} | {
    status: 'pending';
} | {
    status: 'done';
    reply: unknown;
};
export interface A2aStore {
    getContext(id: string): Promise<A2aContext | null>;
    createContext(context: A2aContext): Promise<void>;
    /**
     * Bind the context to `accountRef` unless it is already bound. `true` when it is now bound to
     * `accountRef` (either way), `false` when it was bound to someone else.
     */
    bindAccount(id: string, accountRef: string): Promise<boolean>;
    /** Claim `messageId` in the context — atomically, so two deliveries of one message run once. */
    claimMessage(contextId: string, messageId: string): Promise<MessageClaim>;
    /** Store the reply a claimed message got, for its retries. */
    completeMessage(contextId: string, messageId: string, reply: unknown): Promise<void>;
    /** Drop a claim whose turn failed, so a retry runs it again instead of finding nothing. */
    releaseMessage(contextId: string, messageId: string): Promise<void>;
}
/** Process-local {@link A2aStore} — tests and single-instance dev. */
export declare class InMemoryA2aStore implements A2aStore {
    #private;
    getContext(id: string): Promise<A2aContext | null>;
    createContext(context: A2aContext): Promise<void>;
    bindAccount(id: string, accountRef: string): Promise<boolean>;
    claimMessage(contextId: string, messageId: string): Promise<MessageClaim>;
    completeMessage(contextId: string, messageId: string, reply: unknown): Promise<void>;
    releaseMessage(contextId: string, messageId: string): Promise<void>;
}
export declare const A2A_TABLES: {
    readonly contexts: 'agent_a2a_context';
    readonly messages: 'agent_a2a_message';
};
/**
 * `CREATE TABLE IF NOT EXISTS` DDL for the two A2A tables — same portable dialect as the agent
 * tables (quoted identifiers, epoch-ms `BIGINT`, `TEXT` JSON). The message table's primary key IS the
 * idempotency lock: two deliveries of one `messageId` race on the insert and one loses.
 */
export declare function a2aTableStatements(): string[];
/** Create the A2A tables if missing. Idempotent. */
export declare function ensureA2aTables(db: LucidRawRunner): Promise<void>;
/** {@link A2aStore} over Lucid (any of SQLite / Postgres / MySQL). */
export declare class LucidA2aStore implements A2aStore {
    #private;
    private readonly db;
    constructor(db: LucidClientLike);
    getContext(id: string): Promise<A2aContext | null>;
    createContext(context: A2aContext): Promise<void>;
    bindAccount(id: string, accountRef: string): Promise<boolean>;
    claimMessage(contextId: string, messageId: string): Promise<MessageClaim>;
    completeMessage(contextId: string, messageId: string, reply: unknown): Promise<void>;
    releaseMessage(contextId: string, messageId: string): Promise<void>;
}
//# sourceMappingURL=store.d.ts.map