Skip to main content

systemprompt_sync/export/
agents.rs

1//! Serialise an [`Agent`] into the disk layout expected by `AgentsLocalSync`
2//! (one directory per agent, containing `config.yaml` and an optional
3//! `system_prompt.md`).
4
5use super::escape_yaml;
6use crate::error::SyncResult;
7use std::fs;
8use std::path::Path;
9use systemprompt_agent::models::Agent;
10
11pub fn generate_agent_system_prompt(agent: &Agent) -> Option<String> {
12    agent.system_prompt.as_ref().map(|sp| {
13        format!(
14            "---\ndescription: \"{}\"\n---\n\n{}",
15            escape_yaml(&agent.description),
16            sp
17        )
18    })
19}
20
21pub fn generate_agent_config(agent: &Agent) -> String {
22    let tags_yaml = if agent.tags.is_empty() {
23        "[]".to_string()
24    } else {
25        agent
26            .tags
27            .iter()
28            .map(|t| format!("  - {}", t))
29            .collect::<Vec<_>>()
30            .join("\n")
31    };
32
33    let mcp_servers_yaml = if agent.mcp_servers.is_empty() {
34        "[]".to_string()
35    } else {
36        agent
37            .mcp_servers
38            .iter()
39            .map(|s| format!("  - {}", s))
40            .collect::<Vec<_>>()
41            .join("\n")
42    };
43
44    let skills_yaml = if agent.skills.is_empty() {
45        "[]".to_string()
46    } else {
47        agent
48            .skills
49            .iter()
50            .map(|s| format!("  - {}", s))
51            .collect::<Vec<_>>()
52            .join("\n")
53    };
54
55    format!(
56        r#"id: {}
57name: "{}"
58display_name: "{}"
59description: "{}"
60version: "{}"
61enabled: {}
62port: {}
63tags:
64{}
65mcp_servers:
66{}
67skills:
68{}"#,
69        agent.id.as_str(),
70        escape_yaml(&agent.name),
71        escape_yaml(&agent.display_name),
72        escape_yaml(&agent.description),
73        escape_yaml(&agent.version),
74        agent.enabled,
75        agent.port,
76        tags_yaml,
77        mcp_servers_yaml,
78        skills_yaml
79    )
80}
81
82pub fn export_agent_to_disk(agent: &Agent, base_path: &Path) -> SyncResult<()> {
83    let agent_dir = base_path.join(&agent.name);
84    fs::create_dir_all(&agent_dir)?;
85
86    let config_content = generate_agent_config(agent);
87    fs::write(agent_dir.join("config.yaml"), config_content)?;
88
89    if let Some(system_prompt) = generate_agent_system_prompt(agent) {
90        fs::write(agent_dir.join("system_prompt.md"), system_prompt)?;
91    }
92
93    Ok(())
94}