Automation

This commit is contained in:
Alex Emmet 2026-06-07 16:06:39 +02:00
commit e45a8063e3
6 changed files with 1022 additions and 4 deletions

41
src/agents.rs Normal file
View file

@ -0,0 +1,41 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum AgentType {
Planner,
DocAgent,
BuildAgent,
ChatAgent,
TestJudge,
}
impl AgentType {
pub fn as_str(&self) -> &'static str {
match self {
AgentType::Planner => "planner",
AgentType::DocAgent => "doc_agent",
AgentType::BuildAgent => "build_agent",
AgentType::ChatAgent => "chat",
AgentType::TestJudge => "test_judge",
}
}
pub fn from_str(s: &str) -> Option<Self> {
match s {
"planner" => Some(AgentType::Planner),
"doc_agent" => Some(AgentType::DocAgent),
"build_agent" => Some(AgentType::BuildAgent),
"chat" => Some(AgentType::ChatAgent),
"test_judge" => Some(AgentType::TestJudge),
_ => None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum ApprovalMode {
Batch,
PerTool,
}

View file

@ -8,6 +8,9 @@ pub enum ToDoStatus {
Completed,
Blocked,
ReadyForAgent,
Delegated,
Failed,
PendingApproval,
}
impl Default for ToDoStatus {
@ -24,6 +27,9 @@ impl fmt::Display for ToDoStatus {
ToDoStatus::Completed => write!(f, "completed"),
ToDoStatus::Blocked => write!(f, "blocked"),
ToDoStatus::ReadyForAgent => write!(f, "ready_for_agent"),
ToDoStatus::Delegated => write!(f, "delegated"),
ToDoStatus::Failed => write!(f, "failed"),
ToDoStatus::PendingApproval => write!(f, "pending_approval"),
}
}
}
@ -37,6 +43,9 @@ impl std::str::FromStr for ToDoStatus {
"completed" => Ok(ToDoStatus::Completed),
"blocked" => Ok(ToDoStatus::Blocked),
"ready_for_agent" => Ok(ToDoStatus::ReadyForAgent),
"delegated" => Ok(ToDoStatus::Delegated),
"failed" => Ok(ToDoStatus::Failed),
"pending_approval" => Ok(ToDoStatus::PendingApproval),
_ => Err(format!("unknown status: {}", s)),
}
}
@ -191,3 +200,51 @@ pub enum TaskResultType {
Error,
Split,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ToDoSource {
User,
Planner,
Automation,
Delegation,
}
impl Default for ToDoSource {
fn default() -> Self {
ToDoSource::User
}
}
impl std::fmt::Display for ToDoSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ToDoSource::User => write!(f, "user"),
ToDoSource::Planner => write!(f, "planner"),
ToDoSource::Automation => write!(f, "automation"),
ToDoSource::Delegation => write!(f, "delegation"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TestStrategy {
Unit,
Integration,
E2e,
Property,
Manual,
}
impl std::fmt::Display for TestStrategy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TestStrategy::Unit => write!(f, "unit"),
TestStrategy::Integration => write!(f, "integration"),
TestStrategy::E2e => write!(f, "e2e"),
TestStrategy::Property => write!(f, "property"),
TestStrategy::Manual => write!(f, "manual"),
}
}
}

View file

@ -2,6 +2,7 @@ pub use chrono::{DateTime, Utc};
pub use stp_core::{CommunicationType, CommunicationValue, DataTypes, DataValue};
pub use uuid::Uuid;
pub mod agents;
pub mod ai_response;
pub mod coral;
pub mod enums;
@ -12,6 +13,7 @@ pub mod task;
pub mod todo;
pub mod tools;
pub use agents::{AgentType, ApprovalMode};
pub use ai_response::{Conversation, Message};
pub use coral::{Coral, CoralId};
pub use enums::*;
@ -22,5 +24,5 @@ pub use task::{Task, TaskResult};
pub use todo::ToDo;
pub use tools::{
format_tool_error, format_tool_result, parse_tool_call_blocks, parse_tool_call_stream,
ParsedToolCall, ToolDefinition, ToolParser,
tool_definitions, ParsedToolCall, ToolDefinition, ToolParser,
};

View file

@ -2,7 +2,8 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::enums::{TaskResultType, TaskStatus};
use crate::agents::AgentType;
use crate::enums::{TaskResultType, TaskStatus, TestStrategy};
use crate::todo::ToDo;
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -146,6 +147,10 @@ pub struct TestCase {
pub name: String,
pub command: String,
pub expected_output: Option<String>,
#[serde(default)]
pub test_strategy: Option<TestStrategy>,
#[serde(default)]
pub suggested_test_files: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -156,6 +161,12 @@ pub struct ResourceLimits {
pub timeout_seconds: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionBudget {
pub max_tool_calls: u32,
pub max_tokens: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileRange {
pub path: String,
@ -177,6 +188,12 @@ pub struct AgentTaskSpec {
pub token_budget: usize,
pub resource_limits: ResourceLimits,
pub parent_task_id: Option<Uuid>,
pub pre_approved_plan_id: Option<Uuid>,
pub execution_token: Option<Uuid>,
pub session_budget: Option<SessionBudget>,
pub agent_type: Option<AgentType>,
#[serde(default)]
pub suggested_test_files: Vec<String>,
}
impl AgentTaskSpec {
@ -199,6 +216,11 @@ impl AgentTaskSpec {
timeout_seconds: 3600, // 1 hour
},
parent_task_id: None,
pre_approved_plan_id: None,
execution_token: None,
session_budget: None,
agent_type: None,
suggested_test_files: Vec::new(),
}
}
}

View file

@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::enums::ToDoStatus;
use crate::enums::{ToDoSource, ToDoStatus};
use crate::errors::ValidationError;
use crate::{CommunicationType, CommunicationValue, DataTypes, DataValue};
@ -24,6 +24,12 @@ pub struct ToDo {
pub updated_at: DateTime<Utc>,
pub created_by: Uuid,
pub project_id: Option<Uuid>,
pub parent_todo_id: Option<Uuid>,
pub subtask_ids: Vec<Uuid>,
pub affected_files: Vec<String>,
pub source: ToDoSource,
pub automation_chain_id: Option<Uuid>,
pub tags: Vec<String>,
}
impl Default for ToDo {
@ -40,6 +46,12 @@ impl Default for ToDo {
updated_at: now,
created_by: Uuid::nil(),
project_id: None,
parent_todo_id: None,
subtask_ids: Vec::new(),
affected_files: Vec::new(),
source: ToDoSource::User,
automation_chain_id: None,
tags: Vec::new(),
}
}
}
@ -58,6 +70,12 @@ impl ToDo {
updated_at: now,
created_by,
project_id: None,
parent_todo_id: None,
subtask_ids: Vec::new(),
affected_files: Vec::new(),
source: ToDoSource::User,
automation_chain_id: None,
tags: Vec::new(),
}
}
@ -112,6 +130,15 @@ impl ToDo {
(ToDoStatus::ReadyForAgent, ToDoStatus::InProgress) => true,
(ToDoStatus::ReadyForAgent, ToDoStatus::Pending) => true,
(ToDoStatus::ReadyForAgent, ToDoStatus::Blocked) => true,
(ToDoStatus::InProgress, ToDoStatus::Delegated) => true,
(ToDoStatus::InProgress, ToDoStatus::Failed) => true,
(ToDoStatus::InProgress, ToDoStatus::PendingApproval) => true,
(ToDoStatus::Delegated, ToDoStatus::InProgress) => true,
(ToDoStatus::Delegated, ToDoStatus::Completed) => true,
(ToDoStatus::Delegated, ToDoStatus::Blocked) => true,
(ToDoStatus::Failed, ToDoStatus::Pending) => true,
(ToDoStatus::PendingApproval, ToDoStatus::InProgress) => true,
(ToDoStatus::PendingApproval, ToDoStatus::Blocked) => true,
_ => self.status == status,
};

View file

@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolDefinition {
#[serde(default)]
pub id: String,
@ -19,6 +19,30 @@ pub struct ToolDefinition {
/// Project-scoped tools are filtered out when no project is selected.
#[serde(default)]
pub project_scoped: bool,
/// Maximum execution time in milliseconds. Defaults to 30000 (30s).
#[serde(default = "default_timeout_ms")]
pub timeout_ms: u64,
}
const fn default_timeout_ms() -> u64 {
30000
}
impl Default for ToolDefinition {
fn default() -> Self {
Self {
id: String::new(),
name: String::new(),
description: String::new(),
category: String::new(),
parameters: serde_json::Value::Null,
dangerous: false,
requires_approval: false,
version: String::new(),
project_scoped: false,
timeout_ms: default_timeout_ms(),
}
}
}
impl ToolDefinition {
@ -277,6 +301,851 @@ pub struct ToolErrorInfo {
pub message: String,
}
macro_rules! tool {
($name:expr, $desc:expr, $cat:expr, $dangerous:expr, $approval:expr, $scoped:expr, $params:expr) => {
ToolDefinition {
id: $name.to_string(),
name: $name.to_string(),
description: $desc.to_string(),
category: $cat.to_string(),
parameters: $params,
dangerous: $dangerous,
requires_approval: $approval,
version: "1.0.0".to_string(),
project_scoped: $scoped,
timeout_ms: default_timeout_ms(),
}
};
($name:expr, $desc:expr, $cat:expr, $dangerous:expr, $approval:expr, $scoped:expr, $params:expr, $timeout:expr) => {
ToolDefinition {
id: $name.to_string(),
name: $name.to_string(),
description: $desc.to_string(),
category: $cat.to_string(),
parameters: $params,
dangerous: $dangerous,
requires_approval: $approval,
version: "1.0.0".to_string(),
project_scoped: $scoped,
timeout_ms: $timeout,
}
};
}
/// Returns all built-in tool definitions across all categories.
pub fn tool_definitions() -> Vec<ToolDefinition> {
vec![
// ========================
// Filesystem Tools
// ========================
tool!(
"read_file",
"Read the content of a file with optional pagination",
"filesystem",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"path": { "type": "string", "description": "Path to the file to read" },
"offset": { "type": "number", "description": "Line number to start reading from (1-based)" },
"limit": { "type": "number", "description": "Maximum number of lines to read" }
},
"required": ["path"]
})
),
tool!(
"write_file",
"Create or overwrite a file with content",
"filesystem",
true, true, false,
serde_json::json!({
"type": "object",
"properties": {
"path": { "type": "string", "description": "Path to the file to write" },
"content": { "type": "string", "description": "Content to write to the file" },
"create_dirs": { "type": "boolean", "description": "Create parent directories if they don't exist" }
},
"required": ["path", "content"]
})
),
tool!(
"list_directory",
"List directory contents with optional filtering",
"filesystem",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"path": { "type": "string", "description": "Path to the directory to list" },
"include_hidden": { "type": "boolean", "description": "Include hidden files (starting with .)" },
"recursive": { "type": "boolean", "description": "List subdirectories recursively" }
},
"required": ["path"]
})
),
tool!(
"edit_file",
"Edit file contents with line-based operations (replace, insert, delete)",
"filesystem",
true, true, false,
serde_json::json!({
"type": "object",
"properties": {
"path": { "type": "string", "description": "Path to the file to edit" },
"edits": {
"type": "array",
"description": "Array of edit operations: {start_line, end_line (optional), new_content (optional), operation: 'replace'|'insert'|'delete'}",
"items": {
"type": "object",
"properties": {
"start_line": { "type": "number" },
"end_line": { "type": "number" },
"new_content": { "type": "string" },
"operation": { "type": "string", "enum": ["replace", "insert", "delete"] }
},
"required": ["start_line", "operation"]
}
}
},
"required": ["path", "edits"]
})
),
tool!(
"search_files",
"Search for text patterns in files (grep-like)",
"filesystem",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"path": { "type": "string", "description": "Directory path to search in" },
"pattern": { "type": "string", "description": "Search pattern (regex supported)" },
"file_pattern": { "type": "string", "description": "File pattern to match (e.g., *.rs, *.ts)" }
},
"required": ["path", "pattern"]
})
),
// ========================
// Execution Tools
// ========================
tool!(
"bash",
"Execute a shell command and capture output",
"execution",
true, true, false,
serde_json::json!({
"type": "object",
"properties": {
"command": { "type": "string", "description": "The shell command to execute" },
"cwd": { "type": "string", "description": "Working directory for the command" },
"timeout_ms": { "type": "number", "description": "Timeout in milliseconds" }
},
"required": ["command"]
})
),
// ========================
// Git Tools
// ========================
tool!(
"git_status",
"Show working tree status in a git repository",
"git",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"repo_path": { "type": "string", "description": "Path to the git repository" },
"short": { "type": "boolean", "description": "Use short format" }
}
})
),
tool!(
"git_diff",
"Show changes between commits, commit and working tree, etc.",
"git",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"repo_path": { "type": "string", "description": "Path to the git repository" },
"target": { "type": "string", "description": "Diff target (e.g., HEAD, HEAD~1, branch name)" },
"file": { "type": "string", "description": "Only show diff for specific file" }
}
})
),
tool!(
"git_log",
"Show commit history in a git repository",
"git",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"repo_path": { "type": "string", "description": "Path to the git repository" },
"max_count": { "type": "number", "description": "Maximum number of commits to show" }
}
})
),
tool!(
"git_branch",
"List or manage git branches",
"git",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"repo_path": { "type": "string", "description": "Path to the git repository" },
"all": { "type": "boolean", "description": "List all branches including remote" }
}
})
),
// ========================
// Build & Test Tools
// ========================
tool!(
"cargo_check",
"Run cargo check on a Rust project to verify compilation",
"build",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"project_path": { "type": "string", "description": "Path to the Rust project (default: cwd)" },
"manifest_path": { "type": "string", "description": "Path to Cargo.toml" }
}
})
),
tool!(
"npm_build",
"Run npm build script in a JavaScript/TypeScript project",
"build",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"project_path": { "type": "string", "description": "Path to the npm project" },
"script": { "type": "string", "description": "Script to run (default: build)" }
}
})
),
tool!(
"python_check",
"Check Python syntax or run linting on a Python file",
"build",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"project_path": { "type": "string", "description": "Path to Python project" }
},
"required": ["project_path"]
})
),
tool!(
"test_runner",
"Run project tests with a test runner like pytest",
"build",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"project_path": { "type": "string", "description": "Path to the project" },
"test_command": { "type": "string", "description": "Command to run tests" },
"test_path": { "type": "string", "description": "Specific test path to run" }
}
})
),
// ========================
// Network Tools
// ========================
tool!(
"web_search",
"Search the web for information using a search provider",
"network",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"query": { "type": "string", "description": "The search query" },
"provider": { "type": "string", "description": "Search provider (exa, google, bing)" },
"num_results": { "type": "number", "description": "Number of results to return" }
},
"required": ["query"]
})
),
tool!(
"web_fetch",
"Fetch and parse web pages from URLs",
"network",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"url": { "type": "string", "description": "URL to fetch" },
"format": { "type": "string", "description": "Response format: text, markdown, html" }
},
"required": ["url"]
})
),
tool!(
"web_api",
"Make HTTP API requests to external services",
"network",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"url": { "type": "string", "description": "API endpoint URL" },
"method": { "type": "string", "description": "HTTP method (GET, POST, PUT, DELETE, PATCH)" },
"body": { "type": "string", "description": "Request body (JSON)" }
},
"required": ["url", "method"]
})
),
// ========================
// Workspace Tools
// ========================
tool!(
"create_workspace",
"Create an ephemeral workspace directory for isolated operations",
"workspace",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"name": { "type": "string", "description": "Optional workspace name (auto-generated if not provided)" },
"base_path": { "type": "string", "description": "Base path for workspaces (default: /tmp)" }
}
})
),
tool!(
"delete_workspace",
"Delete an ephemeral workspace and all its contents",
"workspace",
true, true, false,
serde_json::json!({
"type": "object",
"properties": {
"path": { "type": "string", "description": "Path to the workspace to delete" },
"force": { "type": "boolean", "description": "Force deletion without confirmation" }
},
"required": ["path"]
})
),
tool!(
"create_venv",
"Create a Python virtual environment",
"workspace",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"path": { "type": "string", "description": "Path where to create the venv" },
"name": { "type": "string", "description": "Name of virtual environment (default: venv)" }
},
"required": ["path"]
})
),
tool!(
"install_dependencies",
"Install Python dependencies from requirements.txt or specified packages",
"workspace",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"path": { "type": "string", "description": "Path to project with requirements.txt" },
"package": { "type": "string", "description": "Specific package to install" }
},
"required": ["path"]
})
),
tool!(
"workspace_info",
"Get information and statistics about a workspace directory",
"workspace",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"path": { "type": "string", "description": "Path to the workspace" }
},
"required": ["path"]
})
),
// ========================
// Kanban Tools
// ========================
tool!(
"kanban_list_board",
"List all columns and todos in the Kanban board",
"kanban",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" }
},
"required": ["project_id"]
})
),
tool!(
"kanban_create_todo",
"Create a new todo item in a Kanban column",
"kanban",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" },
"column_id": { "type": "string", "description": "Column ID to place the todo" },
"title": { "type": "string", "description": "Title of the todo" },
"description": { "type": "string", "description": "Optional description" },
"priority": { "type": "number", "description": "Priority (1-1000)" },
"deploy_agent": { "type": "boolean", "description": "Whether to deploy an agent for this todo" },
"agent_prompt": { "type": "string", "description": "Optional agent prompt if deploy_agent is true" },
"agent_task_details": { "type": "string", "description": "Optional agent task details" }
},
"required": ["project_id", "column_id", "title"]
})
),
tool!(
"kanban_update_todo",
"Update a todo item's title, description, status, or priority",
"kanban",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" },
"todo_id": { "type": "string", "description": "ID of the todo to update" },
"title": { "type": "string", "description": "New title" },
"description": { "type": "string", "description": "New description" },
"status": { "type": "string", "description": "New status (pending, in_progress, completed, blocked)" },
"priority": { "type": "number", "description": "New priority" }
},
"required": ["project_id", "todo_id"]
})
),
tool!(
"kanban_delete_todo",
"Delete a todo item from the Kanban board",
"kanban",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" },
"todo_id": { "type": "string", "description": "ID of the todo to delete" }
},
"required": ["project_id", "todo_id"]
})
),
tool!(
"kanban_move_todo",
"Move a todo to a different column or reorder it",
"kanban",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" },
"todo_id": { "type": "string", "description": "ID of the todo to move" },
"column_id": { "type": "string", "description": "Target column ID" },
"task_order": { "type": "number", "description": "New order position" }
},
"required": ["project_id", "todo_id", "column_id"]
})
),
tool!(
"kanban_create_task",
"Create a sub-task within a todo",
"kanban",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" },
"todo_id": { "type": "string", "description": "ID of the parent todo" },
"title": { "type": "string", "description": "Title of the task" },
"description": { "type": "string", "description": "Optional description" }
},
"required": ["project_id", "todo_id", "title"]
})
),
tool!(
"kanban_update_task",
"Update a sub-task's title, description, or status",
"kanban",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" },
"task_id": { "type": "string", "description": "ID of the task to update" },
"title": { "type": "string", "description": "New title" },
"description": { "type": "string", "description": "New description" },
"status": { "type": "string", "description": "New status" }
},
"required": ["project_id", "task_id"]
})
),
tool!(
"kanban_add_tag",
"Add a tag to a todo item",
"kanban",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" },
"todo_id": { "type": "string", "description": "ID of the todo" },
"tag_name": { "type": "string", "description": "Tag name" },
"tag_color": { "type": "string", "description": "Tag color (hex, default: #6366f1)" }
},
"required": ["project_id", "todo_id", "tag_name"]
})
),
tool!(
"kanban_create_column",
"Create a new column in the Kanban board",
"kanban",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" },
"name": { "type": "string", "description": "Column name" },
"column_order": { "type": "number", "description": "Display order" }
},
"required": ["project_id", "name"]
})
),
// ========================
// Documentation Tools
// ========================
tool!(
"document_file",
"Analyze and generate documentation for a file",
"documentation",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string" },
"file_id": { "type": "string" }
},
"required": ["project_id", "file_id"]
})
),
tool!(
"document_project",
"Generate a comprehensive summary of all project files",
"documentation",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string" }
},
"required": ["project_id"]
})
),
tool!(
"find_references",
"Find all references to a symbol across the project",
"documentation",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string" },
"file_path": { "type": "string", "description": "Path to find all references for" },
"symbol_name": { "type": "string", "description": "Specific symbol name to find" },
"type": { "type": "string", "enum": ["function", "struct", "enum", "trait", "module", "type_alias"], "description": "Filter by symbol type" }
},
"required": ["project_id"]
})
),
tool!(
"file_dependencies",
"Get incoming or outgoing dependencies for a file",
"documentation",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string" },
"file_path": { "type": "string" },
"direction": { "type": "string", "enum": ["incoming", "outgoing", "both"], "description": "Direction of dependencies (default: both)" }
},
"required": ["project_id", "file_path"]
})
),
tool!(
"documentation_tree",
"Build a directory tree showing documentation coverage",
"documentation",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string" },
"root": { "type": "string", "description": "Optional root path to limit the tree" }
},
"required": ["project_id"]
})
),
tool!(
"verify_documentation",
"Verify documentation freshness and compute coverage stats",
"documentation",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string" }
},
"required": ["project_id"]
})
),
tool!(
"document_folder",
"Document all files within a folder",
"documentation",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string" },
"folder_path": { "type": "string", "description": "Relative folder path to document" }
},
"required": ["project_id", "folder_path"]
})
),
tool!(
"store_file_doc",
"Store documentation for a file",
"documentation",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string" },
"file_path": { "type": "string", "description": "Relative file path" },
"doc": {
"type": "object",
"description": "FileDoc-compatible documentation payload",
"properties": {
"summary": { "type": "string" },
"functions": { "type": "array", "items": { "type": "object" } },
"structs": { "type": "array", "items": { "type": "object" } }
}
}
},
"required": ["project_id", "file_path", "doc"]
})
),
tool!(
"get_documentation_context",
"Get the documentation context for a file",
"documentation",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string" },
"file_path": { "type": "string", "description": "Relative file path to get context for" }
},
"required": ["project_id", "file_path"]
})
),
// ========================
// File Tools
// ========================
tool!(
"list_files",
"List all files in a project",
"files",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string" },
"path_prefix": { "type": "string", "description": "Optional path prefix to filter files" }
},
"required": ["project_id"]
})
),
// ========================
// Strategic Tools
// ========================
tool!(
"propose_strategic_item",
"Propose a new high-level strategic goal or todo",
"strategic",
false, true, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" },
"title": { "type": "string", "description": "Title of the strategic item" },
"description": { "type": "string", "description": "Detailed description" },
"rationale": { "type": "string", "description": "Why this item is important" },
"proposer_id": { "type": "string", "description": "Unique ID to prevent duplicates" }
},
"required": ["project_id", "title", "description", "rationale", "proposer_id"]
})
),
tool!(
"change_planner_mode",
"Suggest switching the Planner's personality mode",
"strategic",
false, true, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" },
"mode": { "type": "string", "enum": ["cooperative", "critical", "red_team", "socratic"], "description": "The planner mode to switch to" },
"rationale": { "type": "string", "description": "Why this mode change is beneficial" }
},
"required": ["project_id", "mode", "rationale"]
})
),
tool!(
"audit_assumptions",
"List the user's current assumptions about the project and identify the weakest ones",
"strategic",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" }
},
"required": ["project_id"]
})
),
tool!(
"identify_blind_spots",
"Query project data for missing dependency chains, undocumented risks, and recurring blockers",
"strategic",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" }
},
"required": ["project_id"]
})
),
tool!(
"check_dependencies",
"Analyze todo dependency chains for circular or missing dependencies",
"strategic",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" }
},
"required": ["project_id"]
})
),
tool!(
"evaluate_plan_risk",
"Score the current plan for feasibility, edge-case coverage, and alignment",
"strategic",
false, false, true,
serde_json::json!({
"type": "object",
"properties": {
"project_id": { "type": "string", "description": "Project ID" }
},
"required": ["project_id"]
})
),
tool!(
"compare_project_patterns",
"Compare kanban structures across projects to detect inconsistencies",
"strategic",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"project_ids": { "type": "array", "items": { "type": "string" }, "description": "Optional list of project IDs to compare" }
}
})
),
tool!(
"find_similar_risks",
"Search across projects for similar risk patterns",
"strategic",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"risk_type": { "type": "string", "description": "Type of risk (dependency, testing, security)" },
"project_ids": { "type": "array", "items": { "type": "string" }, "description": "Optional list of project IDs" }
}
})
),
// ========================
// Agent Tools
// ========================
tool!(
"report_completion",
"Report completion status of a todo back to the Bridge",
"agent",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"todo_id": { "type": "string", "description": "ID of the todo being reported" },
"status": { "type": "string", "enum": ["done", "failed", "delegated", "needs_retry", "pending_approval"], "description": "Completion status" },
"summary": { "type": "string", "description": "Summary of what was done (max 3 sentences)" },
"artifact_refs": { "type": "array", "items": { "type": "string" }, "description": "File paths, test logs" },
"retry_plan": { "type": "string", "description": "Optional retry plan if status is needs_retry" },
"subtask_ids": { "type": "array", "items": { "type": "string" }, "description": "Subtask IDs if status is delegated" }
},
"required": ["todo_id", "status"]
})
),
tool!(
"submit_batch_plan",
"Submit a batch plan of mutations for pre-approval before execution",
"agent",
false, false, false,
serde_json::json!({
"type": "object",
"properties": {
"plan_id": { "type": "string", "description": "Auto-generated plan ID" },
"steps": { "type": "array", "description": "List of mutation steps", "items": {
"type": "object",
"properties": {
"tool": { "type": "string", "description": "Tool name (write_file, edit_file, bash)" },
"arguments": { "type": "object", "description": "Tool arguments" },
"expected_files": { "type": "array", "items": { "type": "string" }, "description": "Files expected to be modified" }
},
"required": ["tool", "arguments"]
}},
"rationale": { "type": "string", "description": "Why this batch of changes is needed" }
},
"required": ["plan_id", "steps", "rationale"]
})
),
]
}
#[cfg(test)]
mod tests {
use super::*;