pub const TOOL_SEARCH_NAME: &str = "tool_search";
pub const LAZY_TOOLS_PROMPT: &str = "\n\n--- Tool Access ---\n\
You have a CORE set of tools always available (file read/write/edit, bash, ls/glob/grep, \
web/exa/memory search, task/context/plan, http, the brain-file loader, config, session). \
You do NOT see every tool by default. For anything else — browsing or clicking web pages, \
sending channel messages (Telegram/Discord/Slack/WhatsApp), spawning sub-agents or teams, \
generating or analyzing images/video, creating real documents (Excel with live \
formulas, Word, PDF, PowerPoint via generate_document), parsing documents, cron jobs, \
self-improvement/rebuild/evolve — call \
`tool_search` FIRST with a short description of what you need. It returns the exact tool's \
schema and makes it callable for the rest of the session. NEVER say you can't do something \
before searching for the tool.\n";
pub const CORE_TOOLS: &[&str] = &[
"read_file",
"write_file",
"edit_file",
"hashline_edit",
"bash",
"ls",
"glob",
"grep",
"web_search",
"exa_search",
"memory_search",
"task",
"context",
"plan",
"http_client",
"load_brain_file",
"write_opencrabs_file",
"config_tool",
"slash_command",
"rename_session",
"follow_up_question",
"analyze_image",
"analyze_video",
TOOL_SEARCH_NAME,
];
pub fn is_core(name: &str) -> bool {
CORE_TOOLS.contains(&name)
}
pub const EXTENDED_TOOL_INVENTORY: &[(&str, &[&str])] = &[
(
"channels",
&[
"telegram_send",
"telegram_connect",
"discord_send",
"discord_connect",
"slack_send",
"slack_connect",
"whatsapp_send",
"whatsapp_connect",
"trello_send",
"trello_connect",
"cowork_connect",
],
),
(
"browser",
&[
"browser_navigate",
"browser_click",
"browser_type",
"browser_eval",
"browser_content",
"browser_screenshot",
"browser_wait",
"browser_find",
"browser_close",
],
),
(
"agents",
&[
"spawn_agent",
"wait_agent",
"send_input",
"close_agent",
"resume_agent",
],
),
("media", &["generate_image", "provider_vision"]),
(
"documents",
&["generate_document", "parse_document", "pdf_to_images"],
),
(
"system",
&[
"self_improve",
"rebuild",
"evolve",
"tool_manage",
"feedback_analyze",
"feedback_record",
],
),
(
"utility",
&[
"cron_manage",
"goal_manage",
"session_search",
"channel_search",
"mission_control_report",
"a2a_send",
"execute_code",
"notebook_edit",
"web_scrape",
],
),
];
pub fn tool_inventory_prompt() -> String {
let mut out = String::from(
"\nAVAILABLE EXTENDED TOOLS — you have these too, their schemas just aren't loaded yet. \
Pick the name and `tool_search` it to activate; NEVER claim one of these is missing \
without searching first:\n",
);
for (category, names) in EXTENDED_TOOL_INVENTORY {
out.push_str(" ");
out.push_str(category);
out.push_str(": ");
out.push_str(&names.join(", "));
out.push('\n');
}
out.push_str(
"Plus any project dynamic tools (tools.toml) and skills listed under \
\"Available Commands & Skills\". Names only here — `tool_search` returns the schema.\n",
);
out
}
pub fn tool_access_prompt() -> String {
format!("{LAZY_TOOLS_PROMPT}{}", tool_inventory_prompt())
}
pub fn is_protected_builtin(name: &str) -> bool {
is_core(name)
|| matches!(
name,
"telegram_send"
| "whatsapp_send"
| "discord_send"
| "slack_send"
| "trello_send"
| "telegram_connect"
| "whatsapp_connect"
| "discord_connect"
| "slack_connect"
| "trello_connect"
| "cowork_connect"
| "cron_manage"
| "goal_manage"
| "session_search"
| "channel_search"
| "mission_control_report"
| "a2a_send"
| "tool_manage"
| "execute_code"
| "notebook_edit"
| "parse_document"
| "pdf_to_images"
| "browser_navigate"
| "browser_click"
| "browser_type"
| "browser_eval"
| "browser_content"
| "browser_screenshot"
| "browser_wait"
| "browser_find"
| "browser_close"
)
}
pub fn tool_category(name: &str) -> &'static str {
if is_core(name) {
return "core";
}
match name {
n if n.starts_with("browser_") => "browser",
n if n.starts_with("telegram_")
|| n.starts_with("whatsapp_")
|| n.starts_with("discord_")
|| n.starts_with("slack_")
|| n.starts_with("trello_") =>
{
"channels"
}
n if n.starts_with("spawn_agent")
|| n.starts_with("wait_agent")
|| n.starts_with("send_input")
|| n.starts_with("close_agent")
|| n.starts_with("resume_agent")
|| n.starts_with("team_") =>
{
"agents"
}
n if n.starts_with("analyze_image")
|| n.starts_with("analyze_video")
|| n.starts_with("generate_image")
|| n.starts_with("provider_vision") =>
{
"media"
}
n if n.starts_with("feedback_")
|| n == "self_improve"
|| n == "rebuild"
|| n == "evolve"
|| n == "tool_manage" =>
{
"system"
}
n if n == "generate_document" || n == "parse_document" || n == "pdf_to_images" => {
"documents"
}
n if n == "cron_manage"
|| n == "goal_manage"
|| n == "session_search"
|| n == "channel_search"
|| n == "a2a_send" =>
{
"utility"
}
"web_scrape" => "web",
_ => "other",
}
}