pub struct AgentState {
pub messages: Vec<Message>,
pub iteration: usize,
pub stop_reason: Option<StopReason>,
pub tool_results: Vec<ToolResult>,
pub total_tokens: usize,
pub input_tokens: usize,
pub output_tokens: usize,
pub last_input_tokens: Option<usize>,
pub last_estimate_at_report: Option<usize>,
pub last_estimate_divergence: Option<f64>,
}Expand description
Tracks the full lifecycle of an agent conversation including messages, token usage, tool results, and iteration progress.
Derives Serialize/Deserialize for session persistence and
cross-process state transfer (e.g. oxios supervisor serialization).
Fields§
§messages: Vec<Message>Conversation message history (user, assistant, and tool-result messages).
iteration: usizeCurrent agent loop iteration (incremented after each assistant turn).
stop_reason: Option<StopReason>The reason the last turn stopped, if any.
tool_results: Vec<ToolResult>Accumulated results from tool executions in the current conversation.
total_tokens: usizeCumulative token count (input + output) across all turns.
input_tokens: usizeCumulative prompt / input tokens across all turns.
output_tokens: usizeCumulative completion / output tokens across all turns.
last_input_tokens: Option<usize>Most-recent reported input-token count from a single LLM response.
Unlike Self::input_tokens (which is cumulative across all turns),
this is overwritten on every ProviderEvent::Done with the count
that turn actually sent to the model. It is the ground-truth signal
used by compaction when available — see Self::current_token_source.
None until the first Done event has been observed.
last_estimate_at_report: Option<usize>Heuristic token estimate (bytes/4) that was current when
last_input_tokens was last set. Used to detect the bytes/4 drift
described in #28 and surface it as a warning.
last_estimate_divergence: Option<f64>Divergence factor (reported / estimate) at the time of the last
Done. Surfaced in logs so the operator can see how badly the
bytes/4 heuristic is undercounting on token-dense workloads.
None until first divergence observation.
Implementations§
Source§impl AgentState
impl AgentState
Sourcepub fn new() -> AgentState
pub fn new() -> AgentState
Create a new, default-initialized agent state.
Sourcepub fn add_user_message(&mut self, content: String)
pub fn add_user_message(&mut self, content: String)
Add a user message
Sourcepub fn add_assistant_message(&mut self, content: String)
pub fn add_assistant_message(&mut self, content: String)
Add an assistant message
Sourcepub fn add_tool_result(&mut self, tool_call_id: String, content: String)
pub fn add_tool_result(&mut self, tool_call_id: String, content: String)
Add a tool result message to both the message history and the tool results list.
Sourcepub fn increment_iteration(&mut self)
pub fn increment_iteration(&mut self)
Increment the iteration counter after an assistant turn completes.
Sourcepub fn set_stop_reason(&mut self, reason: StopReason)
pub fn set_stop_reason(&mut self, reason: StopReason)
Record the reason the last turn stopped.
Sourcepub fn record_usage(&mut self, input: usize, output: usize)
pub fn record_usage(&mut self, input: usize, output: usize)
Accumulate token usage from a completed LLM call.
input is the input-token count for the just-completed turn —
NOT a per-turn delta. The provider reports a fresh per-turn
usage.input_tokens on every Done; we accumulate it into
Self::input_tokens for lifetime accounting and also cache
it as the most-recent observation via Self::record_provider_turn.
Sourcepub fn record_provider_turn(
&mut self,
input_tokens: usize,
estimate_at_report: usize,
)
pub fn record_provider_turn( &mut self, input_tokens: usize, estimate_at_report: usize, )
Record the most recent provider-reported input-token count and the heuristic estimate that was current at the time of the report, so the loop can use the real count for compaction decisions and surface drift (issue #28 gap 2).
input_tokens is the value from ProviderEvent::Done.message.usage.input.
estimate_at_report is the bytes/4 estimate taken at the same moment
(i.e. the value the legacy path would have used for compaction).
Sourcepub fn current_token_source(&self) -> TokenSource
pub fn current_token_source(&self) -> TokenSource
Current best estimate of context size, tagged with its source.
Real(n)if the last completed turn reportedusage.input_tokens.Heuristic(n)only before the firstDoneis observed (cold start).Noneif there are no messages yet.
Callers (notably maybe_compact) should prefer Real and only
fall back to Heuristic on cold start. See issue #28.
Sourcepub fn replace_messages(&mut self, messages: Vec<Message>)
pub fn replace_messages(&mut self, messages: Vec<Message>)
Replace the entire message history (used after context compaction).
Sourcepub fn estimate_tokens(&self) -> usize
pub fn estimate_tokens(&self) -> usize
Rough token-count estimate based on the serialized message JSON length.
Sourcepub fn is_complete(&self) -> bool
pub fn is_complete(&self) -> bool
Returns true if the agent has signaled a stop reason.
Trait Implementations§
Source§impl Clone for AgentState
impl Clone for AgentState
Source§fn clone(&self) -> AgentState
fn clone(&self) -> AgentState
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for AgentState
impl Debug for AgentState
Source§impl Default for AgentState
impl Default for AgentState
Source§fn default() -> AgentState
fn default() -> AgentState
Source§impl<'de> Deserialize<'de> for AgentState
impl<'de> Deserialize<'de> for AgentState
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<AgentState, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<AgentState, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl Serialize for AgentState
impl Serialize for AgentState
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Auto Trait Implementations§
impl Freeze for AgentState
impl RefUnwindSafe for AgentState
impl Send for AgentState
impl Sync for AgentState
impl Unpin for AgentState
impl UnsafeUnpin for AgentState
impl UnwindSafe for AgentState
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.