agent_base/tool/
auto_continue.rs1use async_trait::async_trait;
2use serde_json::{Value, json};
3
4use crate::tool::{Content, Tool, ToolContext};
5use crate::types::AgentResult;
6
7#[derive(Clone, Debug, Default)]
14pub struct AutoContinueTool;
15
16impl AutoContinueTool {
17 pub fn new() -> Self {
18 Self
19 }
20}
21
22#[async_trait]
23impl Tool for AutoContinueTool {
24 fn name(&self) -> &'static str {
25 "request_auto_continue"
26 }
27
28 fn description(&self) -> &'static str {
29 "When you encounter an error in the previous tool execution and have found a solution or retry strategy, or when you need to execute multiple long tasks in sequence, call this tool to request the system to automatically continue to the next turn instead of stopping and waiting for user reply. This tool is only for making the request; you still need to describe your solution in the prompt."
30 }
31
32 fn schema(&self) -> Value {
33 json!({
34 "type": "object",
35 "properties": {
36 "reason": {
37 "type": "string",
38 "description": "A brief reason for requesting auto-continue, e.g. 'network error, trying alternative source'"
39 }
40 },
41 "required": ["reason"]
42 })
43 }
44
45 fn metadata(&self) -> crate::tool::ToolMetadata {
46 crate::tool::ToolMetadata {
47 name: self.name().to_string(),
48 description:
49 "Request automatic continuation to the next turn without waiting for user input."
50 .to_string(),
51 origin: "agent-base".to_string(),
52 version: env!("CARGO_PKG_VERSION").to_string(),
53 requirements: vec![],
54 }
55 }
56
57 async fn call(&self, args: &Value, _ctx: &ToolContext) -> AgentResult<Vec<Content>> {
58 let reason = args
59 .get("reason")
60 .and_then(Value::as_str)
61 .unwrap_or("no reason provided");
62
63 Ok(vec![Content::text(format!(
64 "Auto-continue request received. Reason: {}",
65 reason
66 ))])
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use crate::tool::content_text;
74 use serde_json::json;
75
76 #[test]
77 fn name_is_stable() {
78 assert_eq!(AutoContinueTool::new().name(), "request_auto_continue");
79 }
80
81 #[test]
82 fn schema_requires_reason() {
83 let schema = AutoContinueTool::new().schema();
84 assert_eq!(schema["type"], "object");
85 assert!(schema["properties"]["reason"].is_object());
86 assert_eq!(schema["required"], json!(["reason"]));
87 }
88
89 #[test]
90 fn metadata_origin_is_agent_base() {
91 let m = AutoContinueTool::new().metadata();
92 assert_eq!(m.origin, "agent-base");
93 assert_eq!(m.name, "request_auto_continue");
94 }
95
96 #[tokio::test]
97 async fn call_with_reason_echoes_reason() {
98 let tool = AutoContinueTool::new();
99 let ctx = ToolContext::for_test();
100 let out = tool
101 .call(&json!({"reason": "retry after network error"}), &ctx)
102 .await
103 .unwrap();
104 assert!(content_text(&out).contains("retry after network error"));
105 }
106
107 #[tokio::test]
108 async fn call_without_reason_uses_default() {
109 let tool = AutoContinueTool::new();
110 let ctx = ToolContext::for_test();
111 let out = tool.call(&json!({}), &ctx).await.unwrap();
112 assert!(content_text(&out).contains("no reason provided"));
113 }
114}