/**
 * hosting/envelope — pack a session for storage, and refuse to unpack one you
 * cannot read.
 *
 * One rule, and everything here is a consequence of it: **an envelope this
 * runtime cannot read is refused BY NAME, never guessed at.** A store outlives
 * the code that wrote to it. Somebody will deploy a newer runtime, it will write
 * a newer format, and an older instance still running will read it. The only
 * honest thing that older instance can do is say which format it found, which
 * ones it knows, and stop — because "restore what I can and hope" means an agent
 * answering from a session that is missing whatever the older reader did not
 * understand.
 *
 * ── Two formats, two readers, and why they refuse each other ─────────────────
 * `readEnvelope` unpacks a CONVERSATION; `readPausedRun` unpacks a PAUSED RUN.
 * Each refuses the other's format by name and points at its sibling. That looks
 * fussy until you notice the alternative: one reader that quietly returned the
 * conversation inside a paused run would hand back a session that LOOKS finished
 * while a person is still waiting on a question nobody mentioned. That is a
 * half-restore wearing a happy path, which is the exact failure the format field
 * exists to prevent.
 *
 * ── The same rule one step earlier: unreadable ≠ absent ──────────────────────
 * A format nobody knows is one way a store can hand back something unusable.
 * The other is bytes that are not an envelope at all — a store that kept its own
 * encoding and gave back its host language's `toString()` of the object rather
 * than the object, say. **An unreadable stored conversation and an absent one
 * are different facts, and only one of them is safe to answer with a fresh
 * start.** Absent is ordinary. Unreadable means a conversation EXISTS and this
 * runtime cannot see it, and answering that with a fresh start is invisible from
 * the outside — it looks exactly like a new user — until a deployment boundary
 * hands somebody a blank slate where their conversation was.
 *
 * So {@link readFormat} — the ONE place a stored value is inspected, and
 * therefore the place every reader and every store adapter inherits from —
 * raises {@link UnreadableEnvelopeError} by name, with the session and a short
 * prefix of what it found. Decoding is an adapter's business (only the adapter
 * knows its transport's encoding); "these bytes are nobody's readable session"
 * is everybody's, so it is refused here, once.
 */
import { type AgentRunCheckpoint } from '../core/runCheckpoint.js';
import type { CheckpointEnvelope, ConversationEnvelope, PausedRun, PausedRunEnvelope } from './types.js';
import type { TranscriptMessage } from './sessionWire.js';
/**
 * Pack a conversation checkpoint for storage.
 *
 * @example
 *   const conversation = agent.checkpoint();
 *   if (conversation) await sessions.persist(sessionId, toEnvelope(conversation));
 */
export declare function toEnvelope(checkpoint: AgentRunCheckpoint): ConversationEnvelope;
/**
 * Pack a paused run for storage — the engine checkpoint, the conversation as of
 * the pause, and the question it is waiting on.
 *
 * Store it anywhere that speaks JSON. Note what JSON does and does not preserve
 * here: `agent.resume()` reads `checkpoint.sharedState`, which round-trips
 * unchanged; the engine's diagnostic halves lose their explicitly-`undefined`
 * properties, because that is what `JSON.stringify` does to them. See
 * {@link PausedRun}.
 *
 * @example
 *   const outcome = await agent.run({ message });
 *   if (isPaused(outcome)) {
 *     await sessions.persist(sessionId, toPausedEnvelope({
 *       checkpoint: outcome.checkpoint,
 *       conversation: agent.checkpoint()!,
 *       pending: { pauseData: outcome.pauseData },
 *     }));
 *   }
 */
export declare function toPausedEnvelope(paused: PausedRun): PausedRunEnvelope;
/**
 * Unpack a stored envelope back into a conversation checkpoint.
 *
 * Takes `unknown` on purpose: what comes back from a store is bytes somebody
 * else wrote, in a format this runtime may not know, and typing the parameter
 * as the happy shape would be assuming the very thing that needs checking.
 *
 * @throws UnreadableEnvelopeError when what came back is present but is not an
 *   envelope at all — bytes a store kept in its own encoding, say. Never
 *   `undefined`: a conversation that exists and cannot be read is not the same
 *   fact as one that was never there.
 * @throws TypeError naming the format when it is one this runtime cannot read;
 *   naming the missing field when the conversation inside is malformed; and
 *   pointing at {@link readPausedRun} when the envelope holds a paused run,
 *   which is a session with a question outstanding rather than a conversation.
 */
export declare function readEnvelope(envelope: unknown): AgentRunCheckpoint;
/**
 * Unpack a stored envelope back into a paused run.
 *
 * It hands back the record as stored, MARK INCLUDED: a pause whose resume
 * failed and may have used its decision carries `answered`
 * (`PausedRun.answered`), and code that continues sessions must not resume one
 * — continue its `conversation` with the next message instead. The library's own doors read stored sessions
 * through one reader that does exactly that (`answeredPause.ts`).
 *
 * @throws TypeError naming the format when it is one this runtime cannot read;
 *   pointing at {@link readEnvelope} when the envelope holds a plain
 *   conversation; and naming the missing field when the paused run inside is
 *   malformed.
 */
export declare function readPausedRun(envelope: unknown): PausedRun;
/**
 * Check that an envelope is one this runtime can read, and hand it back
 * unchanged — without committing to which half you wanted.
 *
 * This is what a STORE wants. A store's job is to notice that the bytes it is
 * about to hand over are unreadable, so the refusal names the store that
 * produced them rather than whoever read them next; it has no business caring
 * whether the session inside is mid-conversation or mid-question.
 *
 * Pass `sessionId` and the refusal names the conversation, which is what turns
 * a log line into an incident somebody can act on. Pass it whenever you have it
 * — a store always does.
 *
 * @throws UnreadableEnvelopeError when the stored value is present but is not an
 *   envelope at all. That is the case a store must NOT answer with `undefined`:
 *   see the module header.
 * @throws TypeError naming the format when this runtime cannot read it, or the
 *   missing field when the payload is malformed.
 *
 * @example
 *   async hydrate(sessionId) {
 *     const stored = await myStore.get(sessionId);
 *     return stored === undefined ? undefined : checkEnvelope(stored, sessionId);
 *   }
 */
export declare function checkEnvelope(envelope: unknown, sessionId?: string): CheckpointEnvelope;
/**
 * WHO a stored session belongs to — the `principal` on the conversation the
 * envelope carries, or `undefined` when it names nobody (9.26.0).
 *
 * The ONE derivation, so a store's owner index and the composer's ownership
 * check can never disagree about what "belongs to" means. It is read from the
 * conversation's own identity — the tuple `standingAgent` composed from the
 * request's verified user — and NOT from anything a caller supplied at persist
 * time: a store that indexed on a claimed owner would be a store where owning
 * a session is a matter of asking.
 *
 * A conversation that ran anonymously, or under a derived session-namespace
 * rung with no principal, has no owner. That is a FACT, not a gap to fill: a
 * session nobody signed for is a session nobody can list, and inventing an
 * owner would be inventing an entitlement.
 *
 * **Status: the CONTRACT is field-validated — an independent field trial,
 * 2026-08-13.** A live multi-user run against a real Firestore: an owner
 * written once and never moved, a cross-user transcript answering the same
 * not-found a missing session gets, one caller's own two sessions listed over
 * two pages, `listByUser` / `ownerOf` feature detection, and `mayOpenSession`
 * refusing an ordinary turn on somebody else's conversation. The store
 * underneath was **the trial's own Firestore `SessionLifecycle`**, not one this
 * package ships — so the rung belongs to this derivation and the rules above
 * it, and no shipped Google adapter may borrow the credit.
 *
 * Reads both formats, so a session that is mid-question is owned exactly as
 * firmly as one that is finished. Returns `undefined` rather than throwing on
 * a shape it cannot read — an index is a convenience, and refusing to WRITE a
 * conversation because its owner could not be derived would be the tail
 * wagging the dog. (Every reader of the index still checks ownership itself.)
 */
export declare function envelopeOwner(envelope: unknown): string | undefined;
/**
 * The stored conversation's messages, projected to what a person may read back
 * (9.26.0): user and assistant TEXT, in stored order.
 *
 * Everything else is deliberately dropped — see {@link TranscriptMessage} for
 * the full list and the reason. Non-string content (a provider's structured
 * block) is dropped rather than stringified: a transcript is what was said, and
 * `[object Object]` is not something anybody said.
 */
export declare function envelopeTranscript(envelope: unknown): readonly TranscriptMessage[];
