Run process state with reducer-owned projection fields.
:run_deadline_ms is the total wall-clock budget for the whole run, armed
once the backend has started. Unlike :stream_timeout_ms it never re-arms,
so a backend that keeps emitting events still terminates.
Summary
Types
@type cost_totals() :: %{ input_tokens: non_neg_integer(), output_tokens: non_neg_integer(), cost_usd: number() }
@type run_deadline() :: pos_integer() | :infinity
@type status() :: :initializing | :running | :completed | :failed | :interrupted
@type t() :: %ASM.Run.State{ approval_timeout_ms: pos_integer(), approval_timers: %{optional(String.t()) => reference()}, backend: module() | nil, backend_info: ASM.ProviderBackend.Info.t() | nil, backend_opts: keyword(), backend_pid: pid() | nil, backend_ref: reference() | nil, backend_subscription_ref: reference() | nil, codex_materialized_runtime: term(), continuation: map() | nil, cost: cost_totals(), deadline_timer_ref: reference() | nil, error: ASM.Error.t() | nil, events: [ASM.Event.t()], events_rev: [ASM.Event.t()], execution_config: ASM.Execution.Config.t() | nil, finished_at: DateTime.t() | nil, lane: :core | :sdk | nil, messages_acc: [term()], messages_rev: [term()], metadata: map(), pending_approvals: %{optional(String.t()) => term()}, pipeline: [term()], pipeline_ctx: map(), prompt: String.t() | nil, provider: atom(), provider_opts: keyword(), result: ASM.Result.t() | nil, run_deadline_ms: run_deadline(), run_id: String.t(), sequence: non_neg_integer(), session_id: String.t(), session_pid: pid() | nil, started_at: DateTime.t(), status: status(), subscriber: pid() | nil, text_acc: String.t(), text_chunks_rev: [String.t()], tools: %{optional(String.t()) => term()} }