Skip to main content

RunState

Struct RunState 

Source
pub struct RunState { /* private fields */ }
Expand description

Durable state derived by replaying one run’s ordered event ledger.

The state machine performs no IO. Hosts inspect Self::pending_command for requested effects and Self::pending_compaction_turn for the narrow post-compaction context gate, then apply the resulting recorded event. A HarnessEvent::ModelFailed restores the identical pending model command without advancing its step.

§Examples

A tool turn advances only after the proposed call is validated, approved, executed, and recorded:

use platonic_core::*;
use serde_json::json;

let run_id = RunId::new("run-1")?;
let turn_id = TurnId::new("turn-1")?;
let call_id = ToolCallId::new("call-1")?;
let tool = ToolName::new("file.write")?;
let input = json!({"path": "note.txt", "content": "done"});
let proposal = ToolProposal {
    tool: tool.clone(),
    input: input.clone(),
};
let call = ToolCall {
    id: call_id.clone(),
    tool,
    effect: EffectClass::WorkspaceWrite,
    input,
};

let events = vec![
    HarnessEvent::RunStarted {
        run_id: run_id.clone(),
        agent_id: AgentId::new("agent-1")?,
    },
    HarnessEvent::ContextBuilt {
        run_id: run_id.clone(),
        turn_id: turn_id.clone(),
        context: ContextPack { token_budget: 10, fragments: vec![] },
    },
    HarnessEvent::ModelRequested {
        run_id: run_id.clone(),
        turn_id: turn_id.clone(),
        step: 0,
        model: ModelName::new("model-1")?,
    },
    HarnessEvent::ModelResponded {
        run_id: run_id.clone(),
        turn_id: turn_id.clone(),
        step: 0,
        output: Message {
            role: MessageRole::Assistant,
            content: "I will write the file.".into(),
        },
        proposed_calls: vec![proposal],
        served_model: None,
        usage: Some(ModelUsage { input_tokens: 3, output_tokens: 5 }),
    },
    HarnessEvent::ToolCallProposed {
        run_id: run_id.clone(),
        turn_id,
        call: call.clone(),
    },
    HarnessEvent::PolicyEvaluated {
        run_id: run_id.clone(),
        call_id: call_id.clone(),
        decision: PolicyDecision::RequireApproval {
            reason: "workspace write".into(),
        },
    },
    HarnessEvent::ApprovalGranted {
        run_id: run_id.clone(),
        call_id: call_id.clone(),
        actor_id: ActorId::new("human-1")?,
    },
    HarnessEvent::ToolStarted {
        run_id: run_id.clone(),
        call_id: call_id.clone(),
    },
    HarnessEvent::ToolFinished {
        run_id: run_id.clone(),
        result: ToolResult {
            call_id,
            summary: "wrote note.txt".into(),
            data: json!({}),
            artifacts: vec![],
            visibility: ResultVisibility::Both,
        },
    },
    HarnessEvent::RunFinished { run_id },
];

let mut state = RunState::new();
for (seq, event) in events.into_iter().enumerate() {
    state.apply(&RecordedEvent {
        seq: seq as u64,
        occurred_at_ms: 0,
        event,
    })?;
    if seq == 5 {
        assert!(matches!(state.pending_command(), Some(RunCommand::AwaitApproval { .. })));
    }
    if seq == 6 {
        assert!(matches!(state.pending_command(), Some(RunCommand::ExecuteTool { .. })));
    }
}
assert_eq!(state.phase(), &RunPhase::Finished);

Implementations§

Source§

impl RunState

Source

pub fn new() -> Self

Creates an unbound state expecting sequence zero and run_started.

Source

pub fn run_id(&self) -> Option<&RunId>

Returns the bound run id, or None before run_started is applied.

Source

pub fn next_seq(&self) -> u64

Returns the next contiguous per-run sequence number.

Source

pub fn phase(&self) -> &RunPhase

Returns the phase derived from all successfully applied events.

Source

pub fn pending_compaction_turn(&self) -> Option<&TurnId>

Returns the turn whose compacted context must be built next.

After an accepted HarnessEvent::ContextCompacted, Self::phase intentionally remains the surrounding stable phase and Self::pending_command returns None. While this returns Some, only a matching HarnessEvent::ContextBuilt or terminal HarnessEvent::RunFailed can be accepted. Either accepted event clears the pending turn.

Source

pub fn pending_command(&self) -> Option<RunCommand>

Derives the pending host IO command without mutating run state.

Source

pub fn apply(&mut self, record: &RecordedEvent) -> Result<(), Error>

Validates and applies one event, advancing the sequence only on success.

Trait Implementations§

Source§

impl Clone for RunState

Source§

fn clone(&self) -> RunState

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for RunState

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for RunState

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl PartialEq for RunState

Source§

fn eq(&self, other: &RunState) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for RunState

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.