deepseek-rust-cli 1.20.7

A lightweight, high-speed autonomous CLI system agent port of DeepSeek CLI.
Documentation
use std::{collections::HashMap, path::Path};

use anyhow::Result;
use async_trait::async_trait;
use serde_json::Value;

use crate::{agent::types::UndoAction, tools, tools::base::Tool};

pub struct GithubRepoInfoTool;
#[async_trait]
impl Tool for GithubRepoInfoTool {
    fn name(&self) -> &str {
        "github_repo_info"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        tools::github_ops::github_repo_info(repo).await
    }
}

pub struct GithubRepoListIssuesTool;
#[async_trait]
impl Tool for GithubRepoListIssuesTool {
    fn name(&self) -> &str {
        "github_repo_list_issues"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        let state = args.get("state").and_then(|v| v.as_str());
        let limit = args
            .get("limit")
            .and_then(|v| v.as_u64())
            .map(|v| v as usize);
        tools::github_ops::github_repo_list_issues(repo, state, limit).await
    }
}

pub struct GithubIssueCreateTool;
#[async_trait]
impl Tool for GithubIssueCreateTool {
    fn name(&self) -> &str {
        "github_issue_create"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        let title = args
            .get("title")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'title'"))?;
        let body = args.get("body").and_then(|v| v.as_str());
        let labels = args.get("labels").and_then(|v| v.as_str());
        tools::github_ops::github_issue_create(repo, title, body, labels).await
    }
}

pub struct GithubIssueUpdateTool;
#[async_trait]
impl Tool for GithubIssueUpdateTool {
    fn name(&self) -> &str {
        "github_issue_update"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        let issue_number = args
            .get("issue_number")
            .and_then(|v| v.as_u64())
            .ok_or_else(|| anyhow::anyhow!("Missing 'issue_number'"))?;
        let title = args.get("title").and_then(|v| v.as_str());
        let body = args.get("body").and_then(|v| v.as_str());
        let state = args.get("state").and_then(|v| v.as_str());
        tools::github_ops::github_issue_update(repo, issue_number, title, body, state).await
    }
}

pub struct GithubPrListTool;
#[async_trait]
impl Tool for GithubPrListTool {
    fn name(&self) -> &str {
        "github_pr_list"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        let state = args.get("state").and_then(|v| v.as_str());
        let limit = args
            .get("limit")
            .and_then(|v| v.as_u64())
            .map(|v| v as usize);
        tools::github_ops::github_pr_list(repo, state, limit).await
    }
}

pub struct GithubPrCreateTool;
#[async_trait]
impl Tool for GithubPrCreateTool {
    fn name(&self) -> &str {
        "github_pr_create"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        let title = args
            .get("title")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'title'"))?;
        let head = args
            .get("head")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'head'"))?;
        let base = args
            .get("base")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'base'"))?;
        let body = args.get("body").and_then(|v| v.as_str());
        let draft = args.get("draft").and_then(|v| v.as_bool()).unwrap_or(false);
        tools::github_ops::github_pr_create(repo, title, head, base, body, draft).await
    }
}

pub struct GithubPrInfoTool;
#[async_trait]
impl Tool for GithubPrInfoTool {
    fn name(&self) -> &str {
        "github_pr_info"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        let pr_number = args
            .get("pr_number")
            .and_then(|v| v.as_u64())
            .ok_or_else(|| anyhow::anyhow!("Missing 'pr_number'"))?;
        tools::github_ops::github_pr_info(repo, pr_number).await
    }
}

pub struct GithubPrMergeTool;
#[async_trait]
impl Tool for GithubPrMergeTool {
    fn name(&self) -> &str {
        "github_pr_merge"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        let pr_number = args
            .get("pr_number")
            .and_then(|v| v.as_u64())
            .ok_or_else(|| anyhow::anyhow!("Missing 'pr_number'"))?;
        let method = args.get("method").and_then(|v| v.as_str());
        tools::github_ops::github_pr_merge(repo, pr_number, method).await
    }
}

pub struct GithubSearchCodeTool;
#[async_trait]
impl Tool for GithubSearchCodeTool {
    fn name(&self) -> &str {
        "github_search_code"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let query = args
            .get("query")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'query'"))?;
        let repo = args.get("repo").and_then(|v| v.as_str());
        let limit = args
            .get("limit")
            .and_then(|v| v.as_u64())
            .map(|v| v as usize);
        tools::github_ops::github_search_code(query, repo, limit).await
    }
}

pub struct GithubSearchReposTool;
#[async_trait]
impl Tool for GithubSearchReposTool {
    fn name(&self) -> &str {
        "github_search_repos"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let query = args
            .get("query")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'query'"))?;
        let limit = args
            .get("limit")
            .and_then(|v| v.as_u64())
            .map(|v| v as usize);
        tools::github_ops::github_search_repos(query, limit).await
    }
}

pub struct GithubGetFileTool;
#[async_trait]
impl Tool for GithubGetFileTool {
    fn name(&self) -> &str {
        "github_get_file"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        let path = args
            .get("path")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'path'"))?;
        let ref_ = args.get("ref").and_then(|v| v.as_str());
        tools::github_ops::github_get_file(repo, path, ref_).await
    }
}

pub struct GithubWorkflowListTool;
#[async_trait]
impl Tool for GithubWorkflowListTool {
    fn name(&self) -> &str {
        "github_workflow_list"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        tools::github_ops::github_workflow_list(repo).await
    }
}

pub struct GithubWorkflowRunsTool;
#[async_trait]
impl Tool for GithubWorkflowRunsTool {
    fn name(&self) -> &str {
        "github_workflow_runs"
    }
    async fn execute(
        &self,
        args: &HashMap<String, Value>,
        _undo: &mut Vec<UndoAction>,
        _cwd: Option<&Path>,
    ) -> Result<String> {
        let repo = args
            .get("repo")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow::anyhow!("Missing 'repo'"))?;
        let workflow_id = args.get("workflow_id").and_then(|v| v.as_str());
        let limit = args
            .get("limit")
            .and_then(|v| v.as_u64())
            .map(|v| v as usize);
        tools::github_ops::github_workflow_runs(repo, workflow_id, limit).await
    }
}