/**
 * hosting/sessionWire — the wire grammar for "show me my own conversations",
 * owned once.
 *
 * A hosted agent stores conversations so a person can come back to one. Until
 * now the only way back was to already know the session id: the host could
 * hydrate what you named and nothing else. That is fine for a client that
 * remembers, and useless for the screen everyone actually builds — a sidebar of
 * your past chats.
 *
 * Two operations answer it, and the shape of the pair is the security design:
 *
 *   `{ op: 'session-list' }`                      → the VERIFIED caller's own
 *                                                    sessions, newest first
 *   `{ op: 'session-transcript', sessionId }`     → that session's messages,
 *                                                    IF the verified caller
 *                                                    owns it
 *
 * ── Why both REQUIRE verified identity ───────────────────────────────────────
 * `HostRequest.userId` is caller data — a string anybody can send, as the port
 * has said since 9.12. Listing "your" sessions from an unverified header is
 * enumeration with a friendly interface: guess an id, read a stranger's
 * conversations. So these ops are refused outright at a door that does not
 * verify ({@link SessionOpNeedsIdentityError}) rather than served under a name
 * nobody proved. This is the one place in the hosting layer where a feature is
 * gated on a SECURITY control being present, and it is gated because the
 * feature without the control is a vulnerability rather than a smaller feature.
 *
 * ── Why a foreign transcript is a 404 and not a 403 ──────────────────────────
 * "That session exists but is not yours" tells an attacker which ids are real.
 * A session that does not exist, one that exists and belongs to somebody else,
 * and one whose store lost it are ONE answer here, byte-identical but for the
 * id the caller already knew. The same law the artifact wire's not-found
 * follows, for the same reason.
 *
 * ── What a transcript actually contains ──────────────────────────────────────
 * The stored envelope's own messages, read through the envelope readers — the
 * `LLMMessage[]` an agent conversation IS. Roles and text, projected: no tool
 * arguments, no tool results, no system prompt. That projection is stated on
 * {@link TranscriptMessage} rather than implied, because a transcript that
 * looked complete while silently dropping the tool leg would be a transcript
 * somebody reconstructs a decision from and gets wrong.
 */
/** The wire spelling of "my sessions". */
export declare const SESSION_LIST_OP: "session-list";
/** The wire spelling of "one owned session's messages". */
export declare const SESSION_TRANSCRIPT_OP: "session-transcript";
export declare const SESSION_PENDING_OP: "session-pending";
/**
 * One session-history operation, as a request carries it — the port-side shape
 * behind the wire's `{ op, sessionId? }`.
 *
 * `op` is the port's own verb vocabulary (`list` | `transcript`), not the wire
 * spelling, for the same reason the artifact request's is: the wire says
 * `'session-list'` because a body field named `op` has to say which domain it
 * belongs to; the port already knows.
 */
export type SessionWireRequest = {
    readonly op: 'list';
} | {
    readonly op: 'transcript';
    readonly sessionId: string;
} | {
    readonly op: 'pending';
    readonly sessionId: string;
};
/** One row in a listing — everything a sidebar draws, and nothing from inside
 *  the conversation. */
export interface SessionSummary {
    readonly sessionId: string;
    /** Unix ms of the last write, straight off the stored envelope. */
    readonly savedAt: number;
    /** What the session IS for a listing (`listedFormatOf`): `'flowchart-v1'`
     *  only for a session still waiting on somebody's answer, `'conversation-v1'`
     *  for one that is not — a finished turn, a pause whose decision a resume
     *  already used (`PausedRun.answered`), or a pause no answer can reach any
     *  more. A sidebar that wants to badge "awaiting you" reads this and needs
     *  nothing else. It is not always the stored envelope's own `format`: an
     *  answered pause is still stored as a paused run, and `hydrate` hands it
     *  back as stored. */
    readonly format: string;
    /** How many messages the transcript would carry. A count is safe in a
     *  listing; content is not, so none rides here. */
    readonly messageCount: number;
}
/**
 * One message, projected for reading.
 *
 * **What is here:** the role and the text, in stored order.
 *
 * **What is deliberately NOT here:** tool call arguments, tool results, tool
 * names and ids, and the system prompt. A transcript is what the two parties
 * SAID, and the tool leg is neither — it is the run's internals, it routinely
 * carries resolved credentials and raw records, and a screen that rendered it
 * would be publishing the inside of the agent to whoever is signed in. The gap
 * is stated because a transcript that quietly dropped a step is one somebody
 * reconstructs a decision from and gets wrong: the count on
 * {@link SessionSummary} counts what THIS projection carries.
 */
export interface TranscriptMessage {
    readonly role: 'user' | 'assistant';
    readonly content: string;
}
/** What a resolved session operation hands the reply. Exactly one arm. */
export type SessionWireResult = {
    readonly op: 'pending';
    readonly pending: import('./types.js').PendingAsk | null;
} | {
    readonly op: 'list';
    readonly sessions: readonly SessionSummary[];
} | {
    readonly op: 'transcript';
    readonly sessionId: string;
    readonly messages: readonly TranscriptMessage[];
};
/**
 * Read a session-history operation out of a request body, if the body names
 * one.
 *
 * Returns `undefined` for a body with no `op`, and for an op that belongs to
 * another domain's reader (the artifact ops) — declining is not refusing. An
 * op nobody speaks raises the ONE shared refusal, so the answer is the same
 * whichever reader a dialect happens to call first.
 *
 * Exported for custom {@link import('./httpHost.js').HttpWire} dialects.
 */
export declare function readSessionWireOp(body: Readonly<Record<string, unknown>>): SessionWireRequest | undefined;
/**
 * The standard reply body for a resolved session operation:
 * `{ sessions: [...] }` for a list, `{ transcript: { sessionId, messages } }`
 * for a transcript.
 *
 * Authored once so every dialect answers byte-compatibly; a dialect that must
 * add its own envelope fields spreads this and adds them beside (the managed
 * runtime adds its own `status`) — the `artifactWireBody` precedent, verb for
 * verb.
 */
export declare function sessionWireBody(result: SessionWireResult): Readonly<Record<string, unknown>>;
