From 87044a747b47bd83249d61a45842c7f7b2eae56d Mon Sep 17 00:00:00 2001 From: soryu Date: Sun, 11 Jan 2026 05:52:14 +0000 Subject: Contract system --- makima/src/llm/mesh_tools.rs | 331 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) (limited to 'makima/src/llm/mesh_tools.rs') 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> = 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, + checkpoint_sha: Option, + repository_url: Option, + base_branch: Option, + }, + 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), @@ -1058,6 +1232,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 // ============================================================================= -- cgit v1.2.3