use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct EnvContext {
pub step_info: Option<StepInfo>,
pub task_description: Option<String>,
pub journal_summary: Option<JournalSummary>,
pub redesign_count: usize,
pub strategy_phase: Option<String>,
}
impl EnvContext {
pub fn new() -> Self {
Self::default()
}
pub fn with_step_info(mut self, info: StepInfo) -> Self {
self.step_info = Some(info);
self
}
pub fn with_task_description(mut self, description: impl Into<String>) -> Self {
self.task_description = Some(description.into());
self
}
pub fn with_journal_summary(mut self, summary: JournalSummary) -> Self {
self.journal_summary = Some(summary);
self
}
pub fn with_redesign_count(mut self, count: usize) -> Self {
self.redesign_count = count;
self
}
pub fn with_strategy_phase(mut self, phase: impl Into<String>) -> Self {
self.strategy_phase = Some(phase.into());
self
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StepInfo {
pub step_id: String,
pub description: String,
pub assigned_agent: String,
pub expected_output: Option<String>,
}
impl StepInfo {
pub fn new(
step_id: impl Into<String>,
description: impl Into<String>,
assigned_agent: impl Into<String>,
) -> Self {
Self {
step_id: step_id.into(),
description: description.into(),
assigned_agent: assigned_agent.into(),
expected_output: None,
}
}
pub fn with_expected_output(mut self, output: impl Into<String>) -> Self {
self.expected_output = Some(output.into());
self
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct JournalSummary {
pub total_steps: usize,
pub failed_steps: usize,
pub success_rate: f64,
pub consecutive_failures: usize,
}
impl JournalSummary {
pub fn new(total_steps: usize, failed_steps: usize) -> Self {
let success_rate = if total_steps > 0 {
1.0 - (failed_steps as f64 / total_steps as f64)
} else {
1.0
};
Self {
total_steps,
failed_steps,
success_rate,
consecutive_failures: 0,
}
}
pub fn with_consecutive_failures(mut self, count: usize) -> Self {
self.consecutive_failures = count;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_env_context_builder() {
let ctx = EnvContext::new()
.with_step_info(StepInfo::new("step_1", "Test step", "TestAgent"))
.with_task_description("Test task")
.with_redesign_count(2);
assert_eq!(ctx.step_info.as_ref().unwrap().step_id, "step_1");
assert_eq!(ctx.task_description, Some("Test task".to_string()));
assert_eq!(ctx.redesign_count, 2);
}
#[test]
fn test_journal_summary_success_rate() {
let summary = JournalSummary::new(10, 3);
assert_eq!(summary.total_steps, 10);
assert_eq!(summary.failed_steps, 3);
assert!((summary.success_rate - 0.7).abs() < 0.01);
}
#[test]
fn test_journal_summary_empty() {
let summary = JournalSummary::new(0, 0);
assert_eq!(summary.success_rate, 1.0);
}
}