pub struct ReplayRecord {Show 24 fields
pub turn_id: TurnId,
pub conversation_id: ConversationId,
pub account_id: AccountId,
pub phase: TurnPhase,
pub workflow_versions: Vec<WorkflowVersionRecord>,
pub loaded_cases: Vec<CaseRef>,
pub understanding: Option<Understanding>,
pub plan_hash: Option<Digest>,
pub act_outcomes: Vec<String>,
pub reduction_plan_hash: Option<Digest>,
pub target_resolutions: Vec<TargetResolutionRecord>,
pub policy_decisions: Vec<PolicyDecision>,
pub command_outcomes: Vec<CommandOutcomeRecord>,
pub interactions_created: Vec<InteractionId>,
pub event_ids: Vec<EventId>,
pub response_block_ids: Vec<BlockId>,
pub outbox_ids: Vec<OutboxId>,
pub reconciliation_attempt_ids: Vec<AttemptId>,
pub provider_attempts: Vec<ProviderAttemptRecord>,
pub prompt_refs: Vec<PromptRef>,
pub tasks: Vec<TaskRecord>,
pub budget: Option<BudgetReport>,
pub effort: Effort,
pub recorded_at: DateTime<Utc>,
}Expand description
Everything needed to replay a turn (I20).
Spec §26.1 asks that one turn be traceable end to end, which includes the
external effects it started: the outbox rows it enqueued and the attempts
whose outcome is not yet known. Those live in outbox_ids and
reconciliation_attempt_ids, so an auditor holding nothing but this
record can ask the outbox what became of the turn’s side effects instead of
inferring it from the transcript.
Compared with PartialEq only, because ProviderAttemptRecord carries
a float; see that type.
Fields§
§turn_id: TurnIdThe turn.
conversation_id: ConversationIdThe conversation.
account_id: AccountIdThe tenant.
phase: TurnPhaseLast persisted phase.
workflow_versions: Vec<WorkflowVersionRecord>Workflow versions in force.
loaded_cases: Vec<CaseRef>Cases and revisions loaded at the start of the turn.
understanding: Option<Understanding>What the turn was understood to say: the reducer’s input.
plan_hash: Option<Digest>Hash of the understanding.
act_outcomes: Vec<String>What the reduction decided about each act, by index, as
crate::reduce::PlannedActResult::name.
The hash below identifies a plan; this says what happened in it. A measurement that wants to know how often the structure refused a reading cannot get there from the command count: an act that changes nothing and one that is waiting for a confirmation both journal zero commands and neither was refused, while a plan holding one refusal beside one write journals a command and hides the refusal entirely.
reduction_plan_hash: Option<Digest>Hash of the reduction plan.
target_resolutions: Vec<TargetResolutionRecord>Target resolutions per act.
policy_decisions: Vec<PolicyDecision>Policy decisions per command.
command_outcomes: Vec<CommandOutcomeRecord>Command outcomes.
interactions_created: Vec<InteractionId>Interactions created by the turn.
event_ids: Vec<EventId>Events committed by the turn.
response_block_ids: Vec<BlockId>Block ids of the assistant turn, in order.
outbox_ids: Vec<OutboxId>Outbox rows the turn enqueued, in the order they were enqueued (spec §16.4, §26.1).
Each identifies a row in the dispatch queue, so the record names the turn’s external effects even before any of them has been dispatched. Empty for a turn with no external effect, which is the common case; the field defaults on deserialization, so records written before it existed still load.
reconciliation_attempt_ids: Vec<AttemptId>Attempts at external effects that the turn left unsettled, in the order they were made (spec §16.5, I15).
An attempt lands here when the request was transmitted and the outcome
never came back: it may or may not have taken effect, so it is neither
a success to claim nor a failure to retry blindly, and a poller or a
callback has to settle it against the remote system. Reading them
together with the ones implied by
CommandOutcome::OutcomeUnknown is
what pending_reconciliations
is for. Defaults on deserialization.
provider_attempts: Vec<ProviderAttemptRecord>Every provider attempt.
prompt_refs: Vec<PromptRef>Every prompt a configured prompt source supplied for this turn, in the order the stages asked for them and without repeats.
ProviderAttemptRecord::prompt_ref answers “which prompt produced
this call”; this list answers “which prompts were in force for the
turn at all”, which is the question an audit of a released prompt
version asks. It stays empty for an application that has configured no
prompt source, which is the recommended default, and it defaults on
deserialization so records written before it existed still load.
tasks: Vec<TaskRecord>Every model task the turn ran, repairs, votes and escalations included.
budget: Option<BudgetReport>What the turn’s model calls spent, and the bound that stopped them if one did.
effort: EffortThe effort the turn ran at.
recorded_at: DateTime<Utc>When the record was last written.
Implementations§
Source§impl ReplayRecord
impl ReplayRecord
Sourcepub fn received(
turn_id: TurnId,
conversation_id: ConversationId,
account_id: AccountId,
now: DateTime<Utc>,
) -> Self
pub fn received( turn_id: TurnId, conversation_id: ConversationId, account_id: AccountId, now: DateTime<Utc>, ) -> Self
A record for a turn that was just received.
Sourcepub fn discarded_answers(&self) -> Vec<DiscardedAnswer>
pub fn discarded_answers(&self) -> Vec<DiscardedAnswer>
Every answer a check refused whole, in the order the tasks ran.
Sourcepub fn pending_reconciliations(&self) -> Vec<AttemptId>
pub fn pending_reconciliations(&self) -> Vec<AttemptId>
Every attempt at an external effect this record says is unsettled, in record order and without repeats.
Two places name one: the explicit
reconciliation_attempt_ids,
which a dispatcher adds to as it retries, and
CommandOutcome::OutcomeUnknown, which execution writes against the
command that caused it. A reconciler wants the union of the two and
wants it once each, so it does not query the remote system twice for the
same attempt.
The command outcomes come first, because they carry the attempt the turn itself observed.