Skip to main content

tycode_core/spawn/
complete_task.rs

1//! Complete task tool - signals task completion and pops the agent stack.
2
3use crate::chat::events::{ToolRequest as ToolRequestEvent, ToolRequestType};
4use crate::tools::r#trait::{ToolCallHandle, ToolCategory, ToolExecutor, ToolOutput, ToolRequest};
5use crate::tools::ToolName;
6use anyhow::Result;
7use serde::{Deserialize, Serialize};
8use serde_json::{json, Value};
9
10#[derive(Debug, Serialize, Deserialize)]
11struct CompleteTaskParams {
12    result: String,
13    success: bool,
14}
15
16pub struct CompleteTask;
17
18impl CompleteTask {
19    pub fn tool_name() -> ToolName {
20        ToolName::new("complete_task")
21    }
22
23    /// Creates a standalone CompleteTask for use outside SpawnModule context
24    pub fn standalone() -> Self {
25        Self
26    }
27}
28
29struct CompleteTaskHandle {
30    success: bool,
31    result: String,
32    tool_use_id: String,
33}
34
35#[async_trait::async_trait(?Send)]
36impl ToolCallHandle for CompleteTaskHandle {
37    fn tool_request(&self) -> ToolRequestEvent {
38        ToolRequestEvent {
39            tool_call_id: self.tool_use_id.clone(),
40            tool_name: "complete_task".to_string(),
41            tool_type: ToolRequestType::Other {
42                args: json!({
43                    "success": self.success,
44                    "result": self.result,
45                }),
46            },
47        }
48    }
49
50    async fn execute(self: Box<Self>) -> ToolOutput {
51        ToolOutput::PopAgent {
52            success: self.success,
53            result: self.result,
54        }
55    }
56}
57
58#[async_trait::async_trait(?Send)]
59impl ToolExecutor for CompleteTask {
60    fn name(&self) -> String {
61        "complete_task".to_string()
62    }
63
64    fn description(&self) -> String {
65        "Signal task completion (success or failure) and return control to parent agent. \
66         FAIL a task when: \
67         • Required resources/files don't exist \
68         • The task requirements are unclear or contradictory \
69         • You encounter errors you cannot resolve \
70         • The requested change would break existing functionality \
71         • You lack necessary permissions or access \
72         SUCCEED when: \
73         • All requested changes are implemented \
74         • The task objectives are met \
75         NOTE: Sub-agents must use this with failure instead of spawning more agents when stuck. \
76         Parent agents have more context to handle failures properly."
77            .to_string()
78    }
79
80    fn input_schema(&self) -> Value {
81        json!({
82            "type": "object",
83            "required": ["result", "success"],
84            "properties": {
85                "result": {
86                    "type": "string",
87                    "description": "Result of the task - summary of what was accomplished, failure details, code outline, or any other output"
88                },
89                "success": {
90                    "type": "boolean",
91                    "description": "Whether the task completed successfully"
92                }
93            }
94        })
95    }
96
97    fn category(&self) -> ToolCategory {
98        ToolCategory::Meta
99    }
100
101    async fn process(&self, request: &ToolRequest) -> Result<Box<dyn ToolCallHandle>> {
102        let params: CompleteTaskParams = serde_json::from_value(request.arguments.clone())?;
103
104        Ok(Box::new(CompleteTaskHandle {
105            success: params.success,
106            result: params.result,
107            tool_use_id: request.tool_use_id.clone(),
108        }))
109    }
110}