use crate::model::{Agent, Mode, Rule, Skill, ToolCap};
use anyhow::{Context, Result};
use serde_yaml_ng::{Mapping, Value};
pub fn skill_frontmatter(skill: &Skill) -> Result<String> {
super::build_skill_frontmatter(skill, skill.opencode.as_ref())
}
pub fn rule_frontmatter(rule: &Rule) -> Result<String> {
let mut map = Mapping::new();
map.insert(Value::from("name"), Value::from(rule.name.clone()));
map.insert(
Value::from("description"),
Value::from(rule.description.clone()),
);
if let Some(Value::Mapping(pt)) = rule.opencode.as_ref() {
for (k, v) in pt {
map.insert(k.clone(), v.clone());
}
}
serde_yaml_ng::to_string(&map).context("serializing opencode rule frontmatter")
}
pub fn agent_frontmatter(agent: &Agent) -> Result<String> {
let mut map = Mapping::new();
map.insert(Value::from("name"), Value::from(agent.name.clone()));
map.insert(
Value::from("description"),
Value::from(agent.description.clone()),
);
let mode = agent.mode.unwrap_or(Mode::Subagent);
map.insert(Value::from("mode"), Value::from(mode_str(mode)));
if let Some(model) = &agent.model {
map.insert(Value::from("model"), Value::from(model.clone()));
}
let mut perms = Mapping::new();
for tool in &agent.tools {
let key = Value::from(permission_key(*tool));
if !perms.contains_key(&key) {
perms.insert(key, Value::from("allow"));
}
}
if !perms.is_empty() {
map.insert(Value::from("permission"), Value::Mapping(perms));
}
if let Some(Value::Mapping(pt)) = agent.opencode.as_ref() {
for (k, v) in pt {
map.insert(k.clone(), v.clone());
}
}
serde_yaml_ng::to_string(&map).context("serializing opencode agent frontmatter")
}
fn mode_str(m: Mode) -> &'static str {
match m {
Mode::Primary => "primary",
Mode::Subagent => "subagent",
Mode::All => "all",
}
}
fn permission_key(t: ToolCap) -> &'static str {
match t {
ToolCap::Read => "read",
ToolCap::Write => "edit",
ToolCap::Edit => "edit",
ToolCap::Bash => "bash",
ToolCap::Grep => "grep",
ToolCap::Glob => "glob",
ToolCap::WebFetch => "webfetch",
ToolCap::WebSearch => "websearch",
}
}