use std::fmt::Write as _;
#[derive(Debug, Clone, Copy)]
struct RecipeStep {
tool: &'static str,
note: &'static str,
}
#[derive(Debug, Clone, Copy)]
struct Recipe {
key: &'static str,
title: &'static str,
issue: &'static str,
route: &'static str,
steps: &'static [RecipeStep],
}
const RECIPES: &[Recipe] = &[
Recipe {
key: "formalize",
title: "Formalize a text into a knowledge base",
issue: "#468",
route: "formaliz / knowledge base / fisherman",
steps: &[
RecipeStep {
tool: "web_search",
note: "find the source text",
},
RecipeStep {
tool: "web_fetch",
note: "read it; a tool error falls back to the canonical synopsis",
},
RecipeStep {
tool: "write_file",
note: "formalize prose into Links Notation",
},
RecipeStep {
tool: "run_command",
note: "cat the file to verify the write landed",
},
],
},
Recipe {
key: "meaning",
title: "Make a meaning more detailed",
issue: "#538",
route: "more detailed / grammatical number / a known concept",
steps: &[
RecipeStep {
tool: "web_search",
note: "find the concept's Wikidata lexemes",
},
RecipeStep {
tool: "web_fetch",
note: "read the forms; recover the missing plural",
},
RecipeStep {
tool: "write_file",
note: "re-derive the grounded block, byte-for-byte the seed",
},
RecipeStep {
tool: "run_command",
note: "cat the block to verify",
},
],
},
Recipe {
key: "diagram",
title: "Generate these diagrams",
issue: "#538",
route: "mermaid / diagram / visual overview",
steps: &[
RecipeStep {
tool: "write_file",
note: "render the mermaid parts from the recipe table",
},
RecipeStep {
tool: "run_command",
note: "cat the document to verify",
},
],
},
Recipe {
key: "self_ast",
title: "Store the CST/AST of the meta algorithm",
issue: "#538",
route: "cst/ast / abstract-syntax / reason about itself",
steps: &[
RecipeStep {
tool: "write_file",
note: "parse the planner via meta-language; write the AST node census",
},
RecipeStep {
tool: "run_command",
note: "cat the census to verify",
},
],
},
];
pub const DIAGRAM_TASK: &str = "Generate the mermaid diagrams of our agentic recipes, split into \
parts, as a visual overview of how Formal AI drives its own tools.";
pub const DIAGRAM_PATH: &str = "agentic-recipes.md";
const DIAGRAM_KEYWORDS: [&str; 4] = ["mermaid", "diagram", "visual overview", "flowchart"];
#[must_use]
pub fn is_diagram_task(prompt: &str) -> bool {
let lower = prompt.to_lowercase();
DIAGRAM_KEYWORDS
.iter()
.any(|keyword| lower.contains(keyword))
}
fn render_overview(out: &mut String) {
let _ = writeln!(out, "## Part 1 — Overview: how a task is routed\n");
let _ = writeln!(out, "```mermaid");
let _ = writeln!(out, "flowchart TD");
let _ = writeln!(
out,
" user[\"user task\"] --> router{{\"plan_chat_step<br/>routes by keywords\"}}"
);
for recipe in RECIPES {
let _ = writeln!(
out,
" router -->|\"{route}\"| {key}[\"{title} ({issue})\"]",
route = recipe.route,
key = recipe.key,
title = recipe.title,
issue = recipe.issue,
);
}
let _ = writeln!(
out,
" router -->|\"otherwise\"| solver[\"ordinary solver text\"]"
);
let _ = writeln!(out, "```\n");
}
fn render_recipe(out: &mut String, part: usize, recipe: &Recipe) {
let _ = writeln!(
out,
"## Part {part} — Recipe: {title} ({issue})\n",
title = recipe.title,
issue = recipe.issue,
);
let _ = writeln!(out, "```mermaid");
let _ = writeln!(out, "flowchart LR");
let mut previous = format!("{}_task", recipe.key);
let _ = writeln!(
out,
" {previous}[\"user task<br/>({route})\"]",
route = recipe.route
);
for (index, step) in recipe.steps.iter().enumerate() {
let node = format!("{}_{}", recipe.key, index);
let _ = writeln!(
out,
" {previous} --> {node}[\"{number}. {tool}<br/>{note}\"]",
number = index + 1,
tool = step.tool,
note = step.note,
);
previous = node;
}
let final_node = format!("{}_final", recipe.key);
let _ = writeln!(
out,
" {previous} --> {final_node}([\"final answer<br/>the artifact inline\"])"
);
let _ = writeln!(out, "```\n");
}
#[must_use]
pub fn render_document() -> String {
let mut out = String::new();
let _ = writeln!(out, "# Formal AI agentic recipes (generated)\n");
let _ = writeln!(
out,
"<!-- Generated by the Formal AI Agent CLI (`formal-ai agent`) from the planner's own"
);
let _ = writeln!(
out,
" recipe table (src/agentic_coding/diagram.rs). Do not hand-edit; regenerate. -->\n"
);
let _ = writeln!(
out,
"A high-level, split-into-parts visual overview of how Formal AI drives its own agentic\n\
CLI to complete a task. Part 1 shows how a request is routed to a recipe; each later part\n\
details what happens for input handled by that recipe — the deterministic\n\
`search -> fetch -> write -> verify -> final` state machine in `src/agentic_coding/`.\n"
);
render_overview(&mut out);
for (offset, recipe) in RECIPES.iter().enumerate() {
render_recipe(&mut out, offset + 2, recipe);
}
format!("{}\n", out.trim_end())
}
#[must_use]
pub fn final_answer(document: &str) -> String {
format!(
"Generated the agentic-recipe mermaid diagrams, split into {parts} parts, from the \
planner's own recipe table — a visual overview of how Formal AI drives its own tools.\n\n\
Generated document ({DIAGRAM_PATH}):\n\n{document}",
parts = RECIPES.len() + 1,
document = document.trim_end(),
)
}