Skip to main content

agentforge_parser/formats/
mod.rs

1pub mod anthropic;
2pub mod copilot;
3pub mod crewai;
4pub mod native;
5pub mod openai;
6
7use agentforge_core::{AgentFile, AgentFileFormat, Result};
8
9/// Convert a raw parsed value into the canonical `AgentFile` representation.
10///
11/// For `CopilotAgentMd` the `raw` source is passed so we can extract the Markdown body
12/// (everything after the closing `---` frontmatter delimiter) as the system prompt.
13pub fn normalize(
14    format: &AgentFileFormat,
15    value: &serde_json::Value,
16    raw: &str,
17) -> Result<AgentFile> {
18    match format {
19        AgentFileFormat::NativeYaml => native::normalize(value),
20        AgentFileFormat::OpenaiJson => openai::normalize(value),
21        AgentFileFormat::AnthropicJson => anthropic::normalize(value),
22        AgentFileFormat::CrewaiYaml => crewai::normalize(value),
23        AgentFileFormat::LangchainYaml => {
24            // LangChain: fall back to native normalization
25            native::normalize(value)
26        }
27        AgentFileFormat::CopilotAgentMd => {
28            // The system prompt is the Markdown body after the closing ---
29            let body = extract_markdown_body(raw);
30            copilot::normalize(value, body)
31        }
32    }
33}
34
35/// Extract the Markdown body that follows the YAML frontmatter block.
36/// Given `---\nfrontmatter\n---\nbody`, returns the `body` part.
37fn extract_markdown_body(raw: &str) -> &str {
38    let trimmed = raw.trim();
39    if !trimmed.starts_with("---") {
40        return trimmed;
41    }
42    // Split on first two `---` occurrences: [empty, frontmatter, body]
43    let mut parts = trimmed.splitn(3, "---");
44    parts.next(); // before first ---
45    parts.next(); // frontmatter
46    parts.next().map(|s| s.trim()).unwrap_or("")
47}