• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dcdpr / jp / 18002699183

25 Sep 2025 09:11AM UTC coverage: 43.653% (-0.007%) from 43.66%
18002699183

push

github

web-flow
chore(tools): Add `git` and `web` tools and simplified file modification (#247)

This commit introduces two new tool categories and improves the existing
file system tools. The `git_commit` tool enables committing staged
changes directly from conversations, while `web_fetch` allows retrieving
web page contents. The file modification interface has been simplified
from complex change objects to simpler string replacement, to increase
success rate for LLMs.

The `fs_modify_file` tool now accepts `string_to_replace` and
`new_string` parameters instead of structured change objects, making it
more accessible. It includes fuzzy matching to handle whitespace
variations and provides better error messages.

Additional improvements include better empty result handling in
`fs_list_files` (showing "No files found" instead of empty arrays),
enhanced `cargo_check` output formatting, and more accurate git status
messaging.

Signed-off-by: Jean Mertz <git@jeanmertz.com>

79 of 176 new or added lines in 13 files covered. (44.89%)

2 existing lines in 2 files now uncovered.

5430 of 12439 relevant lines covered (43.65%)

6.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/.config/jp/tools/src/github.rs
1
use crate::{Error, Tool, Workspace};
2

3
mod create_issue_bug;
4
mod create_issue_enhancement;
5
mod issues;
6
mod pulls;
7
mod repo;
8

9
use create_issue_bug::github_create_issue_bug;
10
use create_issue_enhancement::github_create_issue_enhancement;
11
use issues::github_issues;
12
use pulls::github_pulls;
13
use repo::{github_code_search, github_read_file};
14

15
const ORG: &str = "dcdpr";
16
const REPO: &str = "jp";
17

18
pub async fn run(_: Workspace, t: Tool) -> std::result::Result<String, Error> {
×
19
    match t.name.trim_start_matches("github_") {
×
NEW
20
        "issues" => github_issues(t.opt_or_empty("number")?).await,
×
21
        "create_issue_bug" => {
×
22
            github_create_issue_bug(
×
23
                t.req("title")?,
×
24
                t.req("description")?,
×
25
                t.req("expected_behavior")?,
×
26
                t.req("actual_behavior")?,
×
27
                t.req("complexity")?,
×
28
                t.opt("reproduce")?,
×
29
                t.opt("proposed_solution")?,
×
30
                t.opt("tasks")?,
×
31
                t.opt("resource_links")?,
×
32
                t.opt("labels")?,
×
33
                t.opt("assignees")?,
×
34
            )
35
            .await
×
36
        }
37
        "create_issue_enhancement" => {
×
38
            github_create_issue_enhancement(
×
39
                t.req("title")?,
×
40
                t.req("description")?,
×
41
                t.req("context")?,
×
42
                t.req("complexity")?,
×
43
                t.opt("alternatives")?,
×
44
                t.opt("proposed_implementation")?,
×
45
                t.opt("tasks")?,
×
46
                t.opt("resource_links")?,
×
47
                t.opt("labels")?,
×
48
                t.opt("assignees")?,
×
49
            )
50
            .await
×
51
        }
52
        "pulls" => github_pulls(t.opt("number")?, t.opt("state")?, t.opt("file_diffs")?).await,
×
53
        "code_search" => github_code_search(t.opt("repository")?, t.req("query")?).await,
×
54
        "read_file" => github_read_file(t.opt("repository")?, t.req("path")?).await,
×
55
        _ => Err(format!("Unknown tool '{}'", t.name).into()),
×
56
    }
57
}
×
58

59
async fn auth() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
×
60
    let token = std::env::var("JP_GITHUB_TOKEN")
×
61
        .or_else(|_| std::env::var("GITHUB_TOKEN"))
×
62
        .map_err(|_| {
×
63
            "unable to get auth token. Set `JP_GITHUB_TOKEN` or `GITHUB_TOKEN` to a valid token."
×
64
        })?;
×
65

66
    let octocrab = octocrab::Octocrab::builder()
×
67
        .personal_token(token)
×
68
        .build()
×
69
        .map_err(|err| format!("unable to create github client: {err:#}"))?;
×
70

71
    octocrab::initialise(octocrab);
×
72

73
    if octocrab::instance().current().user().await.is_err() {
×
74
        return Err(
×
75
            "Unable to authenticate with github. This might be because the token is expired. \
×
76
             Either set `JP_GITHUB_TOKEN` or `GITHUB_TOKEN` to a valid token."
×
77
                .into(),
×
78
        );
×
79
    }
×
80

81
    Ok(())
×
82
}
×
83

84
fn handle_404(error: octocrab::Error, msg: impl Into<String>) -> Error {
×
85
    match error {
×
86
        octocrab::Error::GitHub { source, .. } if source.status_code.as_u16() == 404 => {
×
87
            msg.into().into()
×
88
        }
89
        _ => Box::new(error) as Error,
×
90
    }
91
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc