use std::fmt::Display;
use std::ops::Deref;
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use super::WorkflowSchema;
use super::diagnose::*;
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AgentRuntime {
Codex,
ClaudeCode,
}
impl AsRef<str> for AgentRuntime {
fn as_ref(&self) -> &str {
match self {
AgentRuntime::Codex => "codex",
AgentRuntime::ClaudeCode => "claude_code",
}
}
}
impl Display for AgentRuntime {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_ref())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentProfileSchema {
pub runtime: AgentRuntime,
pub model: String,
#[serde(default, skip_serializing_if = "serde_yaml::Mapping::is_empty")]
pub args: serde_yaml::Mapping,
#[serde(flatten)]
unknown_fields: serde_yaml::Mapping,
}
#[cfg(test)]
impl AgentProfileSchema {
pub fn new(runtime: AgentRuntime, model: String) -> Self {
Self {
runtime,
model,
args: serde_yaml::Mapping::new(),
unknown_fields: serde_yaml::Mapping::new(),
}
}
pub fn with_args(mut self, args: serde_yaml::Mapping) -> Self {
self.args = args;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentProfilesSchema(IndexMap<String, AgentProfileSchema>);
impl Diagnose for AgentProfileSchema {
fn diagnose(&self, _: &WorkflowSchema) -> Diagnostics {
let mut diagnostics = Diagnostics::new();
diagnostics.error_if_empty_str("model", &self.model);
diagnostics.warn_unknown_fields(&self.unknown_fields);
diagnostics
}
}
impl Diagnose for AgentProfilesSchema {
fn diagnose(&self, workflow: &WorkflowSchema) -> Diagnostics {
let mut diagnostics = Diagnostics::new();
diagnostics.error_if_empty_map_here(self.is_empty());
self.0.iter().for_each(|(profile_name, profile)| {
diagnostics.extends_with_pointer(profile_name, profile.diagnose(workflow));
});
diagnostics
}
}
impl Deref for AgentProfilesSchema {
type Target = IndexMap<String, AgentProfileSchema>;
fn deref(&self) -> &Self::Target {
&self.0
}
}