Files
zesdex/apps/infrastructure/src/workflow/script.rs
T

66 lines
1.9 KiB
Rust
Raw Normal View History

//! Workflow script — parse and execute user-defined workflow scripts.
use anyhow::Result;
use tracing::info;
/// A single phase in a parsed workflow script.
#[derive(Debug, Clone)]
pub struct WorkflowPhase {
pub name: String,
pub directive: String,
}
/// A parsed workflow script with named phases.
#[derive(Debug, Clone)]
pub struct WorkflowScript {
pub name: String,
pub phases: Vec<WorkflowPhase>,
}
impl WorkflowScript {
/// Parse a YAML string into a WorkflowScript.
///
/// Expected format:
/// ```yaml
/// name: my-workflow
/// phases:
/// - name: research
/// directive: "Explore the codebase..."
/// - name: implement
/// directive: "Implement the changes..."
/// ```
pub fn parse(yaml: &str) -> Result<Self> {
let parsed: serde_json::Value = serde_yaml_ng::from_str(yaml)
.map_err(|e| anyhow::anyhow!("Failed to parse workflow YAML: {e}"))?;
let name = parsed
.get("name")
.and_then(|v| v.as_str())
.unwrap_or("unnamed")
.to_string();
let mut phases = Vec::new();
if let Some(phases_arr) = parsed.get("phases").and_then(|v| v.as_array()) {
for phase_val in phases_arr {
let phase_name = phase_val
.get("name")
.and_then(|v| v.as_str())
.unwrap_or("phase")
.to_string();
let directive = phase_val
.get("directive")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();
phases.push(WorkflowPhase {
name: phase_name,
directive,
});
}
}
info!("Parsed workflow script: {name} ({} phases)", phases.len());
Ok(WorkflowScript { name, phases })
}
}