summaryrefslogtreecommitdiff
path: root/makima/src/llm/mesh_tools.rs
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/llm/mesh_tools.rs')
-rw-r--r--makima/src/llm/mesh_tools.rs331
1 files changed, 331 insertions, 0 deletions
diff --git a/makima/src/llm/mesh_tools.rs b/makima/src/llm/mesh_tools.rs
index 1d12c66..ec9dd01 100644
--- a/makima/src/llm/mesh_tools.rs
+++ b/makima/src/llm/mesh_tools.rs
@@ -418,6 +418,140 @@ pub static MESH_TOOLS: once_cell::sync::Lazy<Vec<Tool>> = once_cell::sync::Lazy:
"required": ["questions"]
}),
},
+ // =============================================================================
+ // Supervisor Tools (only available to supervisor tasks)
+ // =============================================================================
+ Tool {
+ name: "get_all_contract_tasks".to_string(),
+ description: "Get status of all tasks in the contract tree. Only available to supervisor tasks.".to_string(),
+ parameters: json!({
+ "type": "object",
+ "properties": {
+ "contract_id": {
+ "type": "string",
+ "description": "ID of the contract to query tasks for"
+ }
+ },
+ "required": ["contract_id"]
+ }),
+ },
+ Tool {
+ name: "wait_for_task_completion".to_string(),
+ description: "Block until a task completes or timeout. Only available to supervisor tasks.".to_string(),
+ parameters: json!({
+ "type": "object",
+ "properties": {
+ "task_id": {
+ "type": "string",
+ "description": "ID of the task to wait for"
+ },
+ "timeout_seconds": {
+ "type": "integer",
+ "description": "Maximum time to wait in seconds (default: 300)",
+ "default": 300
+ }
+ },
+ "required": ["task_id"]
+ }),
+ },
+ Tool {
+ name: "read_task_worktree".to_string(),
+ description: "Read a file from any task's worktree. Only available to supervisor tasks.".to_string(),
+ parameters: json!({
+ "type": "object",
+ "properties": {
+ "task_id": {
+ "type": "string",
+ "description": "ID of the task whose worktree to read from"
+ },
+ "file_path": {
+ "type": "string",
+ "description": "Path to the file within the worktree"
+ }
+ },
+ "required": ["task_id", "file_path"]
+ }),
+ },
+ Tool {
+ name: "spawn_task".to_string(),
+ description: "Create and start a child task (fire and forget). Only available to supervisor tasks.".to_string(),
+ parameters: json!({
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the task"
+ },
+ "plan": {
+ "type": "string",
+ "description": "Detailed instructions/plan for what the task should accomplish"
+ },
+ "parent_task_id": {
+ "type": "string",
+ "description": "Optional parent task to branch from"
+ },
+ "checkpoint_sha": {
+ "type": "string",
+ "description": "Optional checkpoint SHA to branch from"
+ },
+ "repository_url": {
+ "type": "string",
+ "description": "Git repository URL (optional - inherits from contract if not provided)"
+ },
+ "base_branch": {
+ "type": "string",
+ "description": "Optional base branch to start from"
+ }
+ },
+ "required": ["name", "plan"]
+ }),
+ },
+ Tool {
+ name: "create_checkpoint".to_string(),
+ description: "Create a git checkpoint (commit) in the current task's worktree. Only available to supervisor tasks.".to_string(),
+ parameters: json!({
+ "type": "object",
+ "properties": {
+ "task_id": {
+ "type": "string",
+ "description": "ID of the task to checkpoint"
+ },
+ "message": {
+ "type": "string",
+ "description": "Commit message for the checkpoint"
+ }
+ },
+ "required": ["task_id", "message"]
+ }),
+ },
+ Tool {
+ name: "list_task_checkpoints".to_string(),
+ description: "List all checkpoints for a task.".to_string(),
+ parameters: json!({
+ "type": "object",
+ "properties": {
+ "task_id": {
+ "type": "string",
+ "description": "ID of the task to list checkpoints for"
+ }
+ },
+ "required": ["task_id"]
+ }),
+ },
+ Tool {
+ name: "get_task_tree".to_string(),
+ description: "Get the full task tree starting from a specific task.".to_string(),
+ parameters: json!({
+ "type": "object",
+ "properties": {
+ "task_id": {
+ "type": "string",
+ "description": "ID of the root task"
+ }
+ },
+ "required": ["task_id"]
+ }),
+ },
]
});
@@ -506,6 +640,37 @@ pub enum MeshToolRequest {
task_id: Uuid,
mode: String,
},
+
+ // Supervisor tools (only for supervisor tasks)
+ GetAllContractTasks {
+ contract_id: Uuid,
+ },
+ WaitForTaskCompletion {
+ task_id: Uuid,
+ timeout_seconds: i32,
+ },
+ ReadTaskWorktree {
+ task_id: Uuid,
+ file_path: String,
+ },
+ SpawnTask {
+ name: String,
+ plan: String,
+ parent_task_id: Option<Uuid>,
+ checkpoint_sha: Option<String>,
+ repository_url: Option<String>,
+ base_branch: Option<String>,
+ },
+ CreateCheckpoint {
+ task_id: Uuid,
+ message: String,
+ },
+ ListTaskCheckpoints {
+ task_id: Uuid,
+ },
+ GetTaskTree {
+ task_id: Uuid,
+ },
}
/// Result from executing a mesh tool
@@ -560,6 +725,15 @@ pub fn parse_mesh_tool_call(
// Interactive tools
"ask_user" => parse_ask_user(call),
+ // Supervisor tools
+ "get_all_contract_tasks" => parse_get_all_contract_tasks(call),
+ "wait_for_task_completion" => parse_wait_for_task_completion(call),
+ "read_task_worktree" => parse_read_task_worktree(call),
+ "spawn_task" => parse_spawn_task(call),
+ "create_checkpoint" => parse_create_checkpoint(call),
+ "list_task_checkpoints" => parse_list_task_checkpoints(call),
+ "get_task_tree" => parse_get_task_tree(call),
+
_ => MeshToolExecutionResult {
success: false,
message: format!("Unknown mesh tool: {}", call.name),
@@ -1059,6 +1233,163 @@ fn parse_ask_user(call: &super::tools::ToolCall) -> MeshToolExecutionResult {
}
// =============================================================================
+// Supervisor Tool Parsing Functions
+// =============================================================================
+
+fn parse_get_all_contract_tasks(call: &super::tools::ToolCall) -> MeshToolExecutionResult {
+ let Some(contract_id) = parse_uuid_arg(call, "contract_id") else {
+ return error_result("Missing or invalid contract_id");
+ };
+
+ MeshToolExecutionResult {
+ success: true,
+ message: "Querying all contract tasks...".to_string(),
+ data: None,
+ request: Some(MeshToolRequest::GetAllContractTasks { contract_id }),
+ pending_questions: None,
+ }
+}
+
+fn parse_wait_for_task_completion(call: &super::tools::ToolCall) -> MeshToolExecutionResult {
+ let Some(task_id) = parse_uuid_arg(call, "task_id") else {
+ return error_result("Missing or invalid task_id");
+ };
+
+ let timeout_seconds = call
+ .arguments
+ .get("timeout_seconds")
+ .and_then(|v| v.as_i64())
+ .map(|v| v as i32)
+ .unwrap_or(300);
+
+ MeshToolExecutionResult {
+ success: true,
+ message: format!("Waiting for task completion (timeout: {}s)...", timeout_seconds),
+ data: None,
+ request: Some(MeshToolRequest::WaitForTaskCompletion {
+ task_id,
+ timeout_seconds,
+ }),
+ pending_questions: None,
+ }
+}
+
+fn parse_read_task_worktree(call: &super::tools::ToolCall) -> MeshToolExecutionResult {
+ let Some(task_id) = parse_uuid_arg(call, "task_id") else {
+ return error_result("Missing or invalid task_id");
+ };
+
+ let Some(file_path) = call.arguments.get("file_path").and_then(|v| v.as_str()) else {
+ return error_result("Missing required parameter: file_path");
+ };
+
+ MeshToolExecutionResult {
+ success: true,
+ message: format!("Reading file from task worktree: {}", file_path),
+ data: None,
+ request: Some(MeshToolRequest::ReadTaskWorktree {
+ task_id,
+ file_path: file_path.to_string(),
+ }),
+ pending_questions: None,
+ }
+}
+
+fn parse_spawn_task(call: &super::tools::ToolCall) -> MeshToolExecutionResult {
+ let Some(name) = call.arguments.get("name").and_then(|v| v.as_str()) else {
+ return error_result("Missing required parameter: name");
+ };
+
+ let Some(plan) = call.arguments.get("plan").and_then(|v| v.as_str()) else {
+ return error_result("Missing required parameter: plan");
+ };
+
+ let parent_task_id = parse_uuid_arg(call, "parent_task_id");
+
+ let checkpoint_sha = call
+ .arguments
+ .get("checkpoint_sha")
+ .and_then(|v| v.as_str())
+ .map(|s| s.to_string());
+
+ let repository_url = call
+ .arguments
+ .get("repository_url")
+ .and_then(|v| v.as_str())
+ .map(|s| s.to_string());
+
+ let base_branch = call
+ .arguments
+ .get("base_branch")
+ .and_then(|v| v.as_str())
+ .map(|s| s.to_string());
+
+ MeshToolExecutionResult {
+ success: true,
+ message: format!("Spawning task: {}", name),
+ data: None,
+ request: Some(MeshToolRequest::SpawnTask {
+ name: name.to_string(),
+ plan: plan.to_string(),
+ parent_task_id,
+ checkpoint_sha,
+ repository_url,
+ base_branch,
+ }),
+ pending_questions: None,
+ }
+}
+
+fn parse_create_checkpoint(call: &super::tools::ToolCall) -> MeshToolExecutionResult {
+ let Some(task_id) = parse_uuid_arg(call, "task_id") else {
+ return error_result("Missing or invalid task_id");
+ };
+
+ let Some(message) = call.arguments.get("message").and_then(|v| v.as_str()) else {
+ return error_result("Missing required parameter: message");
+ };
+
+ MeshToolExecutionResult {
+ success: true,
+ message: format!("Creating checkpoint: {}", message),
+ data: None,
+ request: Some(MeshToolRequest::CreateCheckpoint {
+ task_id,
+ message: message.to_string(),
+ }),
+ pending_questions: None,
+ }
+}
+
+fn parse_list_task_checkpoints(call: &super::tools::ToolCall) -> MeshToolExecutionResult {
+ let Some(task_id) = parse_uuid_arg(call, "task_id") else {
+ return error_result("Missing or invalid task_id");
+ };
+
+ MeshToolExecutionResult {
+ success: true,
+ message: "Listing task checkpoints...".to_string(),
+ data: None,
+ request: Some(MeshToolRequest::ListTaskCheckpoints { task_id }),
+ pending_questions: None,
+ }
+}
+
+fn parse_get_task_tree(call: &super::tools::ToolCall) -> MeshToolExecutionResult {
+ let Some(task_id) = parse_uuid_arg(call, "task_id") else {
+ return error_result("Missing or invalid task_id");
+ };
+
+ MeshToolExecutionResult {
+ success: true,
+ message: "Getting task tree...".to_string(),
+ data: None,
+ request: Some(MeshToolRequest::GetTaskTree { task_id }),
+ pending_questions: None,
+ }
+}
+
+// =============================================================================
// Helper Functions
// =============================================================================