/**
 * serializer — one run's served agentfootprint events → AG-UI events.
 *
 * Pattern: a per-run state machine (`RunTranslation`), pure — no I/O, no clock,
 *          no import of `@ag-ui/*`. Frames are the framing strategy's job
 *          (`framing.ts`); reading a request is the adapter's (`adapter.ts`).
 * Role:    the Lens over a run for an AG-UI reader. It composes what that reader
 *          is served, from the RECORD only: every value it writes comes from a
 *          served event (the placeholder wherever a redaction policy selected a
 *          value), from the record's address (`meta.runtimeStageId`,
 *          `meta.subflowPath` — never selected by a policy), or from the
 *          AG-UI request's own ids. It never reads the run's live values, so
 *          nothing a policy hides can reach an AG-UI event. The record's own
 *          run id is never written: it counts every run the process made.
 *
 * THE MAPPING
 *   agent.turn_start (nested)          → SUBAGENT_STARTED      (a sub-agent's turn)
 *   agent.turn_end                     → SUBAGENT_FINISHED / the root answer
 *   agent.iteration_start/_end         → STEP_STARTED/_FINISHED  `iteration <n>`
 *   composition.enter/exit             → STEP_STARTED/_FINISHED  `<Kind>[:<mount>]`
 *   stream.token                       → TEXT_MESSAGE_START/CONTENT/END
 *   stream.llm_end (no agent around)   → one whole TEXT message (an LLM call that streams nothing)
 *   stream.thinking_delta/_end         → REASONING_START … REASONING_END   (only with `reasoning: true`)
 *   stream.tool_start                  → TOOL_CALL_START + TOOL_CALL_ARGS + TOOL_CALL_END
 *   stream.tool_end                    → TOOL_CALL_RESULT
 *   pause.request + settle('paused')   → RUN_FINISHED { outcome: interrupt }
 *   settle('paused', awaiting caller)  → RUN_FINISHED { outcome: success, pendingToolCallIds }
 *                                        (a tool the client runs: its call is left to answer)
 *   error.fatal + settle('failed')     → RUN_ERROR — the served error.fatal's words when they
 *                                        are a fixed sentence, else "The run failed."
 *   an allow-listed event              → CUSTOM { name: <event type>, value: <its listed fields> }
 *   anything else                      → nothing
 *
 * WHAT LEAVES THE PROCESS. An AG-UI stream goes to a browser, so nothing goes
 * out by default that a person is not meant to read. Every value comes from a
 * served payload; `CUSTOM` carries only the event types on an allow-list, each
 * with the fields its projection picks ({@link AG_UI_CUSTOM_EVENTS} — the whole
 * record, such as `context.injected`'s assembled prompt or `error.retried`'s
 * raw error, stays off the wire unless the app lists it); the model's
 * reasoning goes out only when the app says so; and a failure is described by
 * the record, never by the thrown value. Identity on the meta (`principal`,
 * `tenant`, `sessionId`) is never written.
 *
 * WHO OWNS AN EVENT. Each agent's turn opens a SCOPE at its mount — the
 * subflow path its `turn_start` fired at (`[]` for the root agent, `step-p/x`
 * for an agent in a parallel branch). An event belongs to the deepest open scope
 * whose mount prefixes its own subflow path, segment by segment, and carries
 * that scope's `subagentRunId`. Parallel branches have different mounts, so
 * their interleaved events can never be attributed to each other.
 *
 * A RUN THAT CONTINUES A PAUSE. A paused run hands back `suspension()` — the
 * ids it gave the client (the interrupt, the open call) and every scope and
 * step open at the pause. The run that continues it passes that as `resume`:
 * the same sub-agents re-open (AG-UI: "a later run may continue the same
 * invocation"), their steps re-open, and the first result in the paused call's
 * scope answers that call under its own id — or, for a tool the client ran, is
 * not written at all, because the client holds the result it sent.
 *
 * TEXT. The reply is what the record streamed (`stream.token`) — the channel
 * `toSSE({ format: 'text' })` and a hosted reply read. An agent turn whose
 * answer streamed no token (a provider without `stream()`) is written whole
 * from `turn_end.finalContent`, unless the record marks it refused. An
 * agent's `llm_end.content` is a DRAFT the library may be holding back
 * (answer validation, an output policy) and is never written.
 */
import type { AgentfootprintEvent } from '../events/registry.js';
import type { RunTranslation } from '../hosting/protocolAdapter.js';
import { type AgUiEvent, type AgUiSuspension } from './types.js';
/** What a CUSTOM projection is told beside the payload: where the event landed. */
export interface AgUiCustomContext {
    /** The AG-UI id of the tool call open where the event happened, when one is. */
    readonly toolCallId?: string;
}
/**
 * One allow-listed event's `CUSTOM` value: the fields of its SERVED payload
 * that go out (the payload is the one every listener receives — the
 * placeholder wherever a redaction policy selected a value). Return only what
 * a person using the frontend is meant to read.
 */
export type AgUiCustomProjection = (payload: Readonly<Record<string, unknown>>, at: AgUiCustomContext) => unknown;
/**
 * The agentfootprint events that go out as AG-UI `CUSTOM` by default, each with
 * the fields it carries: progress (which call, which iteration), spend, the
 * loop's route, the answer's standing and a provider's retries — counts and the
 * library's own words. Content (a tool's own progress `payload`,
 * `context.injected`'s assembled prompt, `error.retried`'s raw error, memory,
 * permission and credential facts) stays off the wire unless an app lists it:
 * `agUiSerializer({ ..., custom: { ...AG_UI_CUSTOM_EVENTS, [type]: projection } })`.
 */
export declare const AG_UI_CUSTOM_EVENTS: Readonly<Record<string, AgUiCustomProjection>>;
/** Options for {@link agUiSerializer}. */
export interface AgUiSerializerOptions {
    /** The conversation this run belongs to — `RunAgentInput.threadId`. */
    readonly threadId: string;
    /** This run's AG-UI id — `RunAgentInput.runId`. Every id the run mints is under it. */
    readonly runId: string;
    /**
     * The events with no AG-UI equivalent that go out as `CUSTOM`, keyed by event
     * type, each with the projection that picks its fields. Default
     * {@link AG_UI_CUSTOM_EVENTS}; `{}` sends none. An event not listed sends
     * nothing. Events the mapping consumes (tokens, tool calls, turns,
     * iterations, compositions, the pause and the fatal error) are never CUSTOM.
     */
    readonly custom?: Readonly<Record<string, AgUiCustomProjection>>;
    /**
     * Write the model's reasoning — `REASONING_*` events from the served
     * `stream.thinking_*` events. Default `false`: a model's chain of thought is
     * shown to a person only when the app decides it is.
     */
    readonly reasoning?: boolean;
    /**
     * What a FAILED tool call's result says. Default `'withheld'`: the fixed words
     * "The tool failed." — the record's result for a failed call is the thrown
     * text, which may hold a connection string, a path or a provider's response.
     * `'served'` sends the record's own result (still the served value: the
     * placeholder wherever a redaction policy selected one).
     */
    readonly toolErrors?: 'withheld' | 'served';
    /**
     * Which served events are this run's. Default: the events of the first run
     * an event names (plus events that name no run). Pass it when the listener
     * can hear more than one run — an instance several callers share — so the
     * translation never binds to whichever run spoke first.
     */
    readonly owns?: (event: AgentfootprintEvent) => boolean;
    /**
     * The paused run this one continues — what that run's translation returned
     * from `suspension()` after it settled `'paused'`. Its suspended sub-agents
     * and open steps re-open under the same ids, and the call it stopped in is
     * answered under its own id (or, for a frontend tool, not at all: the client
     * already holds the result it sent).
     */
    readonly resume?: AgUiSuspension;
}
/** One run's AG-UI translation — and, once it pauses, what its continuation needs. */
export interface AgUiTranslation extends RunTranslation<AgUiEvent> {
    /**
     * The record to `resume` from. Before settling, what a `'paused'` settlement
     * with the same `awaiting` will hand out (keep it first, then settle); after
     * `settle({ kind: 'paused' })`, what it handed out; after any other ending,
     * `undefined`.
     */
    suspension(awaiting?: 'person' | 'caller'): AgUiSuspension | undefined;
}
/** Said by `TOOL_CALL_RESULT` for a failed call, unless `toolErrors: 'served'`. */
export declare const AG_UI_TOOL_FAILED = "The tool failed.";
/** Said by `RUN_ERROR` when the run's `error.fatal` is not one of the record's fixed sentences. */
export declare const AG_UI_RUN_FAILED = "The run failed.";
/**
 * Said by `RUN_ERROR` (with `code: 'ERR_ANSWER_VALIDATION'`) when an enforcing
 * `.answerValidation()` withheld the answer: a refusal, not a crash.
 */
export declare const AG_UI_ANSWER_WITHHELD = "The answer was withheld: it did not pass the app's answer checks.";
/** Said by `SUBAGENT_ERROR` for a sub-agent whose turn ended without an answer. */
export declare const AG_UI_SUBAGENT_UNFINISHED = "The sub-agent's turn ended without an answer.";
/** Said by `SUBAGENT_ERROR` for a sub-agent still running when its run was cancelled. */
export declare const AG_UI_SUBAGENT_CANCELLED = "The run was cancelled before this sub-agent finished.";
/**
 * The AG-UI serializer for ONE run: feed it every served agentfootprint event
 * of the run, in order, then settle it once. `RUN_STARTED` comes before the
 * first event it returns; `RUN_FINISHED` or `RUN_ERROR` is the last thing
 * `settle` returns, with everything still open closed before it.
 *
 * @example
 * ```ts
 * const ag = agUiSerializer({ threadId, runId });
 * const off = agent.on('*', (event) => send(ag.event(event)));
 * try {
 *   const out = await agent.run({ message });
 *   send(ag.settle({ kind: isPaused(out) ? 'paused' : 'finished' }));
 * } catch (error) {
 *   // A withheld answer is a refusal, named by its code (`RUN_ERROR.code`);
 *   // anything else is described by the record, never by the thrown value.
 *   send(
 *     ag.settle(
 *       error instanceof AnswerValidationError
 *         ? { kind: 'failed', refusal: 'ERR_ANSWER_VALIDATION' }
 *         : { kind: 'failed' },
 *     ),
 *   );
 * } finally {
 *   off();
 * }
 * ```
 */
export declare function agUiSerializer(options: AgUiSerializerOptions): AgUiTranslation;
//# sourceMappingURL=serializer.d.ts.map