Skip to main content

deepseek_rust_cli/tools/
github_tools.rs

1use std::{collections::HashMap, path::Path};
2
3use anyhow::Result;
4use async_trait::async_trait;
5use serde_json::Value;
6
7use crate::{agent::types::UndoAction, tools, tools::base::Tool};
8
9pub struct GithubRepoInfoTool;
10#[async_trait]
11impl Tool for GithubRepoInfoTool {
12    fn name(&self) -> &str {
13        "github_repo_info"
14    }
15    async fn execute(
16        &self,
17        args: &HashMap<String, Value>,
18        _undo: &mut Vec<UndoAction>,
19        _cwd: Option<&Path>,
20    ) -> Result<String> {
21        let repo = args
22            .get("repo")
23            .and_then(|v| v.as_str())
24            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
25        tools::github_ops::github_repo_info(repo).await
26    }
27}
28
29pub struct GithubRepoListIssuesTool;
30#[async_trait]
31impl Tool for GithubRepoListIssuesTool {
32    fn name(&self) -> &str {
33        "github_repo_list_issues"
34    }
35    async fn execute(
36        &self,
37        args: &HashMap<String, Value>,
38        _undo: &mut Vec<UndoAction>,
39        _cwd: Option<&Path>,
40    ) -> Result<String> {
41        let repo = args
42            .get("repo")
43            .and_then(|v| v.as_str())
44            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
45        let state = args.get("state").and_then(|v| v.as_str());
46        let limit = args
47            .get("limit")
48            .and_then(|v| v.as_u64())
49            .map(|v| v as usize);
50        tools::github_ops::github_repo_list_issues(repo, state, limit).await
51    }
52}
53
54pub struct GithubIssueCreateTool;
55#[async_trait]
56impl Tool for GithubIssueCreateTool {
57    fn name(&self) -> &str {
58        "github_issue_create"
59    }
60    async fn execute(
61        &self,
62        args: &HashMap<String, Value>,
63        _undo: &mut Vec<UndoAction>,
64        _cwd: Option<&Path>,
65    ) -> Result<String> {
66        let repo = args
67            .get("repo")
68            .and_then(|v| v.as_str())
69            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
70        let title = args
71            .get("title")
72            .and_then(|v| v.as_str())
73            .ok_or_else(|| anyhow::anyhow!("Missing 'title'"))?;
74        let body = args.get("body").and_then(|v| v.as_str());
75        let labels = args.get("labels").and_then(|v| v.as_str());
76        tools::github_ops::github_issue_create(repo, title, body, labels).await
77    }
78}
79
80pub struct GithubIssueUpdateTool;
81#[async_trait]
82impl Tool for GithubIssueUpdateTool {
83    fn name(&self) -> &str {
84        "github_issue_update"
85    }
86    async fn execute(
87        &self,
88        args: &HashMap<String, Value>,
89        _undo: &mut Vec<UndoAction>,
90        _cwd: Option<&Path>,
91    ) -> Result<String> {
92        let repo = args
93            .get("repo")
94            .and_then(|v| v.as_str())
95            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
96        let issue_number = args
97            .get("issue_number")
98            .and_then(|v| v.as_u64())
99            .ok_or_else(|| anyhow::anyhow!("Missing 'issue_number'"))?;
100        let title = args.get("title").and_then(|v| v.as_str());
101        let body = args.get("body").and_then(|v| v.as_str());
102        let state = args.get("state").and_then(|v| v.as_str());
103        tools::github_ops::github_issue_update(repo, issue_number, title, body, state).await
104    }
105}
106
107pub struct GithubPrListTool;
108#[async_trait]
109impl Tool for GithubPrListTool {
110    fn name(&self) -> &str {
111        "github_pr_list"
112    }
113    async fn execute(
114        &self,
115        args: &HashMap<String, Value>,
116        _undo: &mut Vec<UndoAction>,
117        _cwd: Option<&Path>,
118    ) -> Result<String> {
119        let repo = args
120            .get("repo")
121            .and_then(|v| v.as_str())
122            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
123        let state = args.get("state").and_then(|v| v.as_str());
124        let limit = args
125            .get("limit")
126            .and_then(|v| v.as_u64())
127            .map(|v| v as usize);
128        tools::github_ops::github_pr_list(repo, state, limit).await
129    }
130}
131
132pub struct GithubPrCreateTool;
133#[async_trait]
134impl Tool for GithubPrCreateTool {
135    fn name(&self) -> &str {
136        "github_pr_create"
137    }
138    async fn execute(
139        &self,
140        args: &HashMap<String, Value>,
141        _undo: &mut Vec<UndoAction>,
142        _cwd: Option<&Path>,
143    ) -> Result<String> {
144        let repo = args
145            .get("repo")
146            .and_then(|v| v.as_str())
147            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
148        let title = args
149            .get("title")
150            .and_then(|v| v.as_str())
151            .ok_or_else(|| anyhow::anyhow!("Missing 'title'"))?;
152        let head = args
153            .get("head")
154            .and_then(|v| v.as_str())
155            .ok_or_else(|| anyhow::anyhow!("Missing 'head'"))?;
156        let base = args
157            .get("base")
158            .and_then(|v| v.as_str())
159            .ok_or_else(|| anyhow::anyhow!("Missing 'base'"))?;
160        let body = args.get("body").and_then(|v| v.as_str());
161        let draft = args.get("draft").and_then(|v| v.as_bool()).unwrap_or(false);
162        tools::github_ops::github_pr_create(repo, title, head, base, body, draft).await
163    }
164}
165
166pub struct GithubPrInfoTool;
167#[async_trait]
168impl Tool for GithubPrInfoTool {
169    fn name(&self) -> &str {
170        "github_pr_info"
171    }
172    async fn execute(
173        &self,
174        args: &HashMap<String, Value>,
175        _undo: &mut Vec<UndoAction>,
176        _cwd: Option<&Path>,
177    ) -> Result<String> {
178        let repo = args
179            .get("repo")
180            .and_then(|v| v.as_str())
181            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
182        let pr_number = args
183            .get("pr_number")
184            .and_then(|v| v.as_u64())
185            .ok_or_else(|| anyhow::anyhow!("Missing 'pr_number'"))?;
186        tools::github_ops::github_pr_info(repo, pr_number).await
187    }
188}
189
190pub struct GithubPrMergeTool;
191#[async_trait]
192impl Tool for GithubPrMergeTool {
193    fn name(&self) -> &str {
194        "github_pr_merge"
195    }
196    async fn execute(
197        &self,
198        args: &HashMap<String, Value>,
199        _undo: &mut Vec<UndoAction>,
200        _cwd: Option<&Path>,
201    ) -> Result<String> {
202        let repo = args
203            .get("repo")
204            .and_then(|v| v.as_str())
205            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
206        let pr_number = args
207            .get("pr_number")
208            .and_then(|v| v.as_u64())
209            .ok_or_else(|| anyhow::anyhow!("Missing 'pr_number'"))?;
210        let method = args.get("method").and_then(|v| v.as_str());
211        tools::github_ops::github_pr_merge(repo, pr_number, method).await
212    }
213}
214
215pub struct GithubSearchCodeTool;
216#[async_trait]
217impl Tool for GithubSearchCodeTool {
218    fn name(&self) -> &str {
219        "github_search_code"
220    }
221    async fn execute(
222        &self,
223        args: &HashMap<String, Value>,
224        _undo: &mut Vec<UndoAction>,
225        _cwd: Option<&Path>,
226    ) -> Result<String> {
227        let query = args
228            .get("query")
229            .and_then(|v| v.as_str())
230            .ok_or_else(|| anyhow::anyhow!("Missing 'query'"))?;
231        let repo = args.get("repo").and_then(|v| v.as_str());
232        let limit = args
233            .get("limit")
234            .and_then(|v| v.as_u64())
235            .map(|v| v as usize);
236        tools::github_ops::github_search_code(query, repo, limit).await
237    }
238}
239
240pub struct GithubSearchReposTool;
241#[async_trait]
242impl Tool for GithubSearchReposTool {
243    fn name(&self) -> &str {
244        "github_search_repos"
245    }
246    async fn execute(
247        &self,
248        args: &HashMap<String, Value>,
249        _undo: &mut Vec<UndoAction>,
250        _cwd: Option<&Path>,
251    ) -> Result<String> {
252        let query = args
253            .get("query")
254            .and_then(|v| v.as_str())
255            .ok_or_else(|| anyhow::anyhow!("Missing 'query'"))?;
256        let limit = args
257            .get("limit")
258            .and_then(|v| v.as_u64())
259            .map(|v| v as usize);
260        tools::github_ops::github_search_repos(query, limit).await
261    }
262}
263
264pub struct GithubGetFileTool;
265#[async_trait]
266impl Tool for GithubGetFileTool {
267    fn name(&self) -> &str {
268        "github_get_file"
269    }
270    async fn execute(
271        &self,
272        args: &HashMap<String, Value>,
273        _undo: &mut Vec<UndoAction>,
274        _cwd: Option<&Path>,
275    ) -> Result<String> {
276        let repo = args
277            .get("repo")
278            .and_then(|v| v.as_str())
279            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
280        let path = args
281            .get("path")
282            .and_then(|v| v.as_str())
283            .ok_or_else(|| anyhow::anyhow!("Missing 'path'"))?;
284        let ref_ = args.get("ref").and_then(|v| v.as_str());
285        tools::github_ops::github_get_file(repo, path, ref_).await
286    }
287}
288
289pub struct GithubWorkflowListTool;
290#[async_trait]
291impl Tool for GithubWorkflowListTool {
292    fn name(&self) -> &str {
293        "github_workflow_list"
294    }
295    async fn execute(
296        &self,
297        args: &HashMap<String, Value>,
298        _undo: &mut Vec<UndoAction>,
299        _cwd: Option<&Path>,
300    ) -> Result<String> {
301        let repo = args
302            .get("repo")
303            .and_then(|v| v.as_str())
304            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
305        tools::github_ops::github_workflow_list(repo).await
306    }
307}
308
309pub struct GithubWorkflowRunsTool;
310#[async_trait]
311impl Tool for GithubWorkflowRunsTool {
312    fn name(&self) -> &str {
313        "github_workflow_runs"
314    }
315    async fn execute(
316        &self,
317        args: &HashMap<String, Value>,
318        _undo: &mut Vec<UndoAction>,
319        _cwd: Option<&Path>,
320    ) -> Result<String> {
321        let repo = args
322            .get("repo")
323            .and_then(|v| v.as_str())
324            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
325        let workflow_id = args.get("workflow_id").and_then(|v| v.as_str());
326        let limit = args
327            .get("limit")
328            .and_then(|v| v.as_u64())
329            .map(|v| v as usize);
330        tools::github_ops::github_workflow_runs(repo, workflow_id, limit).await
331    }
332}