Skip to main content

ai_agent/tools/remote_trigger/
mod.rs

1// Source: ~/claudecode/openclaudecode/src/tools/RemoteTriggerTool/RemoteTriggerTool.ts
2use crate::error::AgentError;
3use crate::types::*;
4
5pub const REMOTE_TRIGGER_TOOL_NAME: &str = "RemoteTrigger";
6
7pub const DESCRIPTION: &str =
8    "Manage scheduled remote Claude Code agents (triggers) via the claude.ai CCR API";
9
10/// RemoteTrigger tool - manage remote agent triggers via API
11pub struct RemoteTriggerTool;
12
13impl RemoteTriggerTool {
14    pub fn new() -> Self {
15        Self
16    }
17
18    pub fn name(&self) -> &str {
19        REMOTE_TRIGGER_TOOL_NAME
20    }
21
22    pub fn description(&self) -> &str {
23        DESCRIPTION
24    }
25
26    pub fn user_facing_name(&self, _input: Option<&serde_json::Value>) -> String {
27        "RemoteTrigger".to_string()
28    }
29
30    pub fn get_tool_use_summary(&self, input: Option<&serde_json::Value>) -> Option<String> {
31        input.and_then(|inp| inp["action"].as_str().map(String::from))
32    }
33
34    pub fn render_tool_result_message(
35        &self,
36        content: &serde_json::Value,
37    ) -> Option<String> {
38        content["content"].as_str().map(|s| s.to_string())
39    }
40
41    pub fn input_schema(&self) -> ToolInputSchema {
42        ToolInputSchema {
43            schema_type: "object".to_string(),
44            properties: serde_json::json!({
45                "action": {
46                    "type": "string",
47                    "enum": ["list", "get", "create", "update", "run"],
48                    "description": "The action to perform"
49                },
50                "trigger_id": {
51                    "type": "string",
52                    "description": "Required for get, update, and run"
53                },
54                "body": {
55                    "type": "object",
56                    "description": "JSON body for create and update"
57                }
58            }),
59            required: Some(vec!["action".to_string()]),
60        }
61    }
62
63    pub async fn execute(
64        &self,
65        input: serde_json::Value,
66        _context: &ToolContext,
67    ) -> Result<ToolResult, AgentError> {
68        let action = input["action"]
69            .as_str()
70            .ok_or_else(|| AgentError::Tool("Missing action parameter".to_string()))?;
71
72        let trigger_id = input["trigger_id"].as_str();
73        let body = input.get("body");
74
75        // Build the API URL and method based on action
76        let base_url = "https://api.claude.ai/v1/code/triggers";
77        let (method, url, request_body) = match action {
78            "list" => ("GET", base_url.to_string(), None),
79            "get" => {
80                let tid = trigger_id.ok_or_else(|| {
81                    AgentError::Tool("get action requires trigger_id".to_string())
82                })?;
83                ("GET", format!("{}/{}", base_url, tid), None)
84            }
85            "create" => {
86                let b = body
87                    .ok_or_else(|| AgentError::Tool("create action requires body".to_string()))?;
88                ("POST", base_url.to_string(), Some(b.clone()))
89            }
90            "update" => {
91                let tid = trigger_id.ok_or_else(|| {
92                    AgentError::Tool("update action requires trigger_id".to_string())
93                })?;
94                let b = body
95                    .ok_or_else(|| AgentError::Tool("update action requires body".to_string()))?;
96                ("POST", format!("{}/{}", base_url, tid), Some(b.clone()))
97            }
98            "run" => {
99                let tid = trigger_id.ok_or_else(|| {
100                    AgentError::Tool("run action requires trigger_id".to_string())
101                })?;
102                (
103                    "POST",
104                    format!("{}/run", base_url),
105                    Some(serde_json::json!({})),
106                )
107            }
108            _ => return Err(AgentError::Tool(format!("Unknown action: {}", action))),
109        };
110
111        // Note: In a full implementation, this would make the actual HTTP request
112        // with OAuth authentication. For now, return a not-implemented response.
113        let result = serde_json::json!({
114            "status": 501,
115            "json": {
116                "message": "RemoteTrigger tool requires OAuth authentication with claude.ai. This feature is not available in the current build.",
117                "action": action,
118                "url": url,
119                "method": method
120            }
121        });
122
123        Ok(ToolResult {
124            result_type: "text".to_string(),
125            tool_use_id: "".to_string(),
126            content: serde_json::to_string_pretty(&result).unwrap_or_default(),
127            is_error: None,
128            was_persisted: None,
129        })
130    }
131}
132
133impl Default for RemoteTriggerTool {
134    fn default() -> Self {
135        Self::new()
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    fn test_remote_trigger_tool_name() {
145        let tool = RemoteTriggerTool::new();
146        assert_eq!(tool.name(), REMOTE_TRIGGER_TOOL_NAME);
147    }
148
149    #[test]
150    fn test_remote_trigger_tool_schema() {
151        let tool = RemoteTriggerTool::new();
152        let schema = tool.input_schema();
153        assert_eq!(schema.schema_type, "object");
154        assert_eq!(schema.required, Some(vec!["action".to_string()]));
155    }
156}