PicoBot/src/agent/builtin.rs
xiaoxixi 78d6e29672 feat: enable bash delegation, drop legacy anonymous general agent, ship built-in general-purpose Agent
- bash is now Delegatable so named Agents may run shell commands
- remove the legacy anonymous 'general' path entirely: SubAgentManager
  run_background/run_foreground_batch/run_inline/run_foreground,
  filter_tools/get_skills_prompt, TaskNotification direct delivery,
  DelegateContext task-local, background_permits/admission, and the
  delegate tool's check_task/cancel_task/list_tasks actions (agent_task
  replaces them); /stop and todo migrate off the task-local bridge
- stop writing the legacy background_tasks table (read-only transition);
  /api/tasks union still renders historical records
- ship a built-in general-purpose Agent definition (resources/agents)
  released to ~/.picobot/agents on first run like built-in skills, with
  bash/read-only/search/web/calculator/sleep tools; root_delegates now
  defaults to it so orchestration works out of the box
- update AGENTS/README/architecture/config/db-schema docs accordingly
2026-08-13 08:50:22 +08:00

53 lines
2.2 KiB
Rust

//! Built-in Agent definitions, released to the user config directory on
//! first run just like built-in skills. A released definition is a regular
//! user-editable file afterwards; the installer never overwrites it.
use std::path::Path;
use crate::config::LLMProviderConfig;
mod embedded {
include!(concat!(env!("OUT_DIR"), "/embedded_agents.rs"));
}
/// Install built-in Agent definitions into `<config_dir>/agents/`. Files
/// that already exist (user-modified or user-created) are left untouched.
pub fn install_builtin_agents(config_dir: &Path, profiles: &std::collections::HashMap<String, LLMProviderConfig>) {
let agents_dir = config_dir.join("agents");
if let Err(error) = std::fs::create_dir_all(&agents_dir) {
tracing::warn!(dir = %agents_dir.display(), error = %error, "Failed to create agents directory");
return;
}
for agent in embedded::EMBEDDED_AGENTS {
let path = agents_dir.join(format!("{}.md", agent.name));
if path.exists() {
continue;
}
if let Err(error) = std::fs::write(&path, agent.content) {
tracing::warn!(name = agent.name, error = %error, "Failed to install built-in Agent definition");
continue;
}
let profile = match profiles.get("default").cloned() {
Some(profile) => profile,
None => {
tracing::warn!(
name = agent.name,
"Skipping built-in Agent validation: no 'default' provider profile configured"
);
continue;
}
};
// Validate the released file immediately so a future catalog load
// cannot fail on a broken built-in. Validation failure keeps the
// file (the user can edit it) but logs loudly.
match super::definition::parse_definition(&path, std::sync::Arc::new(profile)) {
Ok(_) => {
tracing::info!(name = agent.name, dir = %path.display(), "Installed built-in Agent definition");
}
Err(error) => {
tracing::warn!(name = agent.name, error = %error, "Installed built-in Agent definition failed validation");
}
}
}
}