use std::collections::HashMap;
use car_ir::ProposalResult;
use car_multi::AgentOutput;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::types::{ApprovalField, Workflow};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowResult {
pub workflow_id: String,
pub workflow_name: String,
pub status: WorkflowStatus,
pub stages: Vec<StageResult>,
pub compensations: Vec<CompensationResult>,
pub duration_ms: f64,
pub timestamp: DateTime<Utc>,
#[serde(default)]
pub final_state: HashMap<String, Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub paused: Option<PausedWorkflow>,
}
impl WorkflowResult {
pub fn succeeded(&self) -> bool {
self.status == WorkflowStatus::Completed
}
pub fn is_paused(&self) -> bool {
self.status == WorkflowStatus::Paused
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum WorkflowStatus {
Completed,
Failed,
Compensated,
PartiallyCompensated,
Paused,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PausedWorkflow {
pub run_id: String,
pub workflow: Workflow,
pub paused_stage_id: String,
pub prompt: String,
pub fields: Vec<ApprovalField>,
pub output_key: String,
pub wf_state: HashMap<String, Value>,
pub stage_results: Vec<StageResult>,
pub completed_stage_ids: Vec<String>,
pub iterations: u32,
#[serde(default)]
pub prior_duration_ms: f64,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StageResult {
pub stage_id: String,
pub stage_name: String,
pub status: StageStatus,
pub output: StageOutput,
pub duration_ms: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum StageStatus {
Succeeded,
Failed,
Skipped,
Compensated,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum StageOutput {
Pattern {
outputs: Vec<AgentOutput>,
final_answer: String,
},
Proposal {
result: ProposalResult,
},
SubWorkflow {
result: Box<WorkflowResult>,
},
Approval {
response: Value,
},
Review {
passed: bool,
blocker_count: usize,
findings: Vec<car_multi::ReviewFinding>,
reviewer: AgentOutput,
},
Loop {
iterations: u32,
satisfied: bool,
iterations_output: Vec<Box<StageOutput>>,
},
ForEach {
items: Vec<String>,
outputs: Vec<Box<StageOutput>>,
},
Empty,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompensationResult {
pub for_stage_id: String,
pub status: StageStatus,
pub duration_ms: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}