use serde::{Deserialize, Serialize};
use crate::platform::container::handoff::HandoffRecord;
use crate::platform::container::planning::TaskPlan;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaladinResult {
pub output: String,
pub token_count: u32,
pub execution_time_ms: u64,
pub loop_count: u32,
pub stop_reason: StopReason,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub plan: Option<TaskPlan>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub handoff_history: Vec<HandoffRecord>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum StopReason {
MaxLoops,
StopWord(String),
Completed,
Timeout,
}
impl StopReason {
pub fn is_successful(&self) -> bool {
matches!(self, StopReason::Completed | StopReason::StopWord(_))
}
pub fn is_limit(&self) -> bool {
matches!(self, StopReason::MaxLoops | StopReason::Timeout)
}
}
impl Default for PaladinResult {
fn default() -> Self {
Self {
output: String::new(),
token_count: 0,
execution_time_ms: 0,
loop_count: 0,
stop_reason: StopReason::Completed,
plan: None,
handoff_history: Vec::new(),
}
}
}
impl PaladinResult {
pub fn new(
output: String,
token_count: u32,
execution_time_ms: u64,
loop_count: u32,
stop_reason: StopReason,
) -> Self {
Self {
output,
token_count,
execution_time_ms,
loop_count,
stop_reason,
plan: None,
handoff_history: Vec::new(),
}
}
pub fn has_plan(&self) -> bool {
self.plan.is_some()
}
pub fn has_handoffs(&self) -> bool {
!self.handoff_history.is_empty()
}
pub fn handoff_count(&self) -> usize {
self.handoff_history.len()
}
}