use std::collections::HashMap;
use crate::error::ZigError;
pub mod templates {
use std::sync::LazyLock;
pub fn create() -> &'static str {
static STRIPPED: LazyLock<&'static str> =
LazyLock::new(|| super::strip_front_matter(include_str!("../prompts/create/2_1.md")));
*STRIPPED
}
pub fn update() -> &'static str {
static STRIPPED: LazyLock<&'static str> =
LazyLock::new(|| super::strip_front_matter(include_str!("../prompts/update/1_2.md")));
*STRIPPED
}
pub fn config_sidecar() -> &'static str {
static STRIPPED: LazyLock<&'static str> = LazyLock::new(|| {
super::strip_front_matter(include_str!("../prompts/config-sidecar/1_3.md"))
});
*STRIPPED
}
pub mod examples {
pub const SEQUENTIAL: &str = include_str!("../prompts/examples/sequential.zwf");
pub const FAN_OUT: &str = include_str!("../prompts/examples/fan-out.zwf");
pub const GENERATOR_CRITIC: &str = include_str!("../prompts/examples/generator-critic.zwf");
pub const COORDINATOR_DISPATCHER: &str =
include_str!("../prompts/examples/coordinator-dispatcher.zwf");
pub const HIERARCHICAL_DECOMPOSITION: &str =
include_str!("../prompts/examples/hierarchical-decomposition.zwf");
pub const HUMAN_IN_THE_LOOP: &str =
include_str!("../prompts/examples/human-in-the-loop.zwf");
pub const INTER_AGENT_COMMUNICATION: &str =
include_str!("../prompts/examples/inter-agent-communication.zwf");
}
}
const EXAMPLE_DESCRIPTIONS: &[(&str, &str)] = &[
(
"sequential.zwf",
"Sequential Pipeline — blog post workflow (research → draft → edit → SEO)",
),
(
"fan-out.zwf",
"Fan-Out / Gather — PR review with parallel security/performance/design reviewers and synthesis",
),
(
"generator-critic.zwf",
"Generator / Critic — landing page copy with iterative quality scoring loop",
),
(
"coordinator-dispatcher.zwf",
"Coordinator / Dispatcher — support ticket classification routed to specialist handlers",
),
(
"hierarchical-decomposition.zwf",
"Hierarchical Decomposition — feature spec broken into parallel analysis tracks",
),
(
"human-in-the-loop.zwf",
"Human-in-the-Loop — database migration plan with approval gates",
),
(
"inter-agent-communication.zwf",
"Inter-Agent Communication — RFC review with advocate/skeptic/moderator roles",
),
];
pub fn example_for_pattern(pattern: &str) -> Option<&'static str> {
match pattern {
"sequential" => Some(templates::examples::SEQUENTIAL),
"fan-out" => Some(templates::examples::FAN_OUT),
"generator-critic" => Some(templates::examples::GENERATOR_CRITIC),
"coordinator-dispatcher" => Some(templates::examples::COORDINATOR_DISPATCHER),
"hierarchical-decomposition" => Some(templates::examples::HIERARCHICAL_DECOMPOSITION),
"human-in-the-loop" => Some(templates::examples::HUMAN_IN_THE_LOOP),
"inter-agent-communication" => Some(templates::examples::INTER_AGENT_COMMUNICATION),
_ => None,
}
}
pub fn all_examples() -> Vec<(&'static str, &'static str)> {
vec![
("sequential.zwf", templates::examples::SEQUENTIAL),
("fan-out.zwf", templates::examples::FAN_OUT),
(
"generator-critic.zwf",
templates::examples::GENERATOR_CRITIC,
),
(
"coordinator-dispatcher.zwf",
templates::examples::COORDINATOR_DISPATCHER,
),
(
"hierarchical-decomposition.zwf",
templates::examples::HIERARCHICAL_DECOMPOSITION,
),
(
"human-in-the-loop.zwf",
templates::examples::HUMAN_IN_THE_LOOP,
),
(
"inter-agent-communication.zwf",
templates::examples::INTER_AGENT_COMMUNICATION,
),
]
}
pub fn strip_front_matter(content: &str) -> &str {
let rest = if let Some(r) = content.strip_prefix("---\n") {
r
} else if let Some(r) = content.strip_prefix("---\r\n") {
r
} else {
return content;
};
let mut offset = 0;
while offset <= rest.len() {
let remainder = &rest[offset..];
let (line, advance) = match remainder.find('\n') {
Some(nl) => (&remainder[..nl], nl + 1),
None => (remainder, remainder.len()),
};
let trimmed = line.strip_suffix('\r').unwrap_or(line);
if trimmed == "---" {
let body_start = offset + advance;
let body = &rest[body_start..];
return body
.strip_prefix("\r\n")
.or_else(|| body.strip_prefix('\n'))
.unwrap_or(body);
}
if advance == 0 {
break;
}
offset += advance;
}
content
}
pub fn examples_reference_block() -> String {
let mut out = String::new();
out.push_str(
"Here are examples of agent orchestration patterns, for reference. \
Read the relevant file(s) before designing or editing a workflow so \
the structure matches a proven pattern:\n\n",
);
for (filename, description) in EXAMPLE_DESCRIPTIONS {
out.push_str("- `~/.zig/examples/");
out.push_str(filename);
out.push_str("` — ");
out.push_str(description);
out.push('\n');
}
out
}
pub fn write_examples_to_global_dir() -> Result<(), ZigError> {
let dir = crate::paths::ensure_global_examples_dir()?;
for (filename, content) in all_examples() {
let path = dir.join(filename);
std::fs::write(&path, content)
.map_err(|e| ZigError::Io(format!("failed to write {}: {e}", path.display())))?;
}
Ok(())
}
pub fn render(template: &str, vars: &HashMap<&str, &str>) -> String {
let mut result = template.to_string();
for (&key, &value) in vars {
let placeholder = format!("{{{{{key}}}}}");
result = result.replace(&placeholder, value);
}
result
}
#[cfg(test)]
#[path = "prompt_tests.rs"]
mod tests;