use oneagentgraph::config::ConfigRef;
use onevcs::registry::{RepoType, Workflow};
use onevcs::MergePolicy;
use serde::{Deserialize, Serialize};
pub const PLAN_SCHEMA_VERSION: u32 = 1;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Plan {
pub schema_version: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub goal: Option<Goal>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default = "default_concurrency")]
pub concurrency: u32,
pub tasks: Vec<Node>,
}
fn default_concurrency() -> u32 {
4
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Goal {
pub text: String,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum NodeKind {
#[default]
Agent,
Human,
}
impl NodeKind {
fn is_agent(&self) -> bool {
matches!(self, Self::Agent)
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Node {
pub id: String,
#[serde(default, skip_serializing_if = "NodeKind::is_agent")]
pub kind: NodeKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub task: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub persona: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub deps: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub done_when: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_turns: Option<u32>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub expects_no_diff: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub context: Option<String>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub parked: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub executor: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent_graph: Option<ConfigRef>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub repo: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub repo_type: Option<RepoType>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub workflow: Option<Workflow>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub merge_policy: Option<MergePolicy>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub base_branch: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub branch: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub execution_checkout: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub verify_via_ci: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub steps: Option<Vec<Step>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub resume: Option<Resume>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Step {
pub id: String,
#[serde(default, skip_serializing_if = "NodeKind::is_agent")]
pub kind: NodeKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub task: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub persona: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub deps: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub done_when: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_turns: Option<u32>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub expects_no_diff: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub executor: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent_graph: Option<ConfigRef>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Resume {
pub branch: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub checkpoint: Option<String>,
}