feat(tui): add usage overlay and sidebar for displaying usage statistics and tasks

feat(tui): implement status bar with connection and turn state indicators
feat(tui): create workflow panel for agent status and progress visualization
feat(web): introduce web frontend interface with static file serving
feat(ws): add WebSocket interface for real-time communication and session management
This commit is contained in:
asepharyana
2026-07-20 09:04:57 +07:00
parent bceba665c0
commit da2ed6da25
454 changed files with 13979 additions and 29539 deletions
@@ -0,0 +1,65 @@
//! 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 })
}
}