diff --git a/entry b/entry index c00d251..dcf070e 100755 --- a/entry +++ b/entry @@ -38979,7 +38979,6 @@ var modes = [ description: "Implement, build, create, or develop code changes; make specific changes to files or features; execute a plan; or handle tasks with specific implementation details", prompt: `Follow these steps: 1. ${initialCommentInstruction} - 2. If the request requires understanding the codebase structure, dependencies, or conventions, gather relevant context (read AGENTS.md if it exists, understand how to install dependencies, run tests, run builds, and make changes according to best practices). Skip this step if the prompt is trivial and self-contained. 3. Understand the requirements and any existing plan 4. Make the necessary code changes @@ -39055,9 +39054,6 @@ Do not try to handle github auth- treat ${ghPullfrogMcpName} as a black box that When using ${ghPullfrogMcpName}, use the tools to comment and interact in a way that a real member of the team would. Ensure after your edits are done, your final comments do not contain intermediate reasoning or context, e.g. "I'll respond to the question." -For CI failures: -- Use ${ghPullfrogMcpName}/get_check_suite_logs with check_suite.id to get all failed workflow logs - ## Mode Selection Before starting any work, you must first determine which mode to use by examining the request and calling ${ghPullfrogMcpName}/select_mode. diff --git a/mcp-server b/mcp-server index b371114..c6b9754 100755 --- a/mcp-server +++ b/mcp-server @@ -107231,6 +107231,87 @@ var handleToolError = (error41) => { }; }; +// mcp/checkSuite.ts +var GetCheckSuiteLogs = type({ + check_suite_id: type.number.describe("the id from check_suite.id") +}); +var GetCheckSuiteLogsTool = tool({ + name: "get_check_suite_logs", + description: "get workflow run logs for a failed check suite. pass check_suite.id from the webhook payload.", + parameters: GetCheckSuiteLogs, + execute: contextualize(async ({ check_suite_id }, ctx) => { + const workflowRuns = await ctx.octokit.paginate( + ctx.octokit.rest.actions.listWorkflowRunsForRepo, + { + owner: ctx.owner, + repo: ctx.name, + check_suite_id, + per_page: 100 + } + ); + const failedRuns = workflowRuns.filter((run) => run.conclusion === "failure"); + if (failedRuns.length === 0) { + return { + check_suite_id, + message: "no failed workflow runs found for this check suite", + workflow_runs: [] + }; + } + const logsForRuns = await Promise.all( + failedRuns.map(async (run) => { + const jobs = await ctx.octokit.paginate(ctx.octokit.rest.actions.listJobsForWorkflowRun, { + owner: ctx.owner, + repo: ctx.name, + run_id: run.id + }); + const jobLogs = await Promise.all( + jobs.map(async (job) => { + try { + const logsResponse = await ctx.octokit.rest.actions.downloadJobLogsForWorkflowRun({ + owner: ctx.owner, + repo: ctx.name, + job_id: job.id + }); + const logsUrl = logsResponse.url; + const logsText = await fetch(logsUrl).then((r) => r.text()); + return { + job_id: job.id, + job_name: job.name, + status: job.status, + conclusion: job.conclusion, + started_at: job.started_at, + completed_at: job.completed_at, + logs: logsText + }; + } catch (error41) { + return { + job_id: job.id, + job_name: job.name, + status: job.status, + conclusion: job.conclusion, + started_at: job.started_at, + completed_at: job.completed_at, + error: `failed to fetch logs: ${error41}` + }; + } + }) + ); + return { + workflow_run_id: run.id, + workflow_name: run.name, + html_url: run.html_url, + conclusion: run.conclusion, + jobs: jobLogs + }; + }) + ); + return { + check_suite_id, + workflow_runs: logsForRuns + }; + }) +}); + // mcp/comment.ts var Comment = type({ issueNumber: type.number.describe("the issue number to comment on"), @@ -107335,86 +107416,6 @@ var UpdateWorkingCommentTool = tool({ }) }); -// mcp/checkSuite.ts -var GetCheckSuiteLogs = type({ - check_suite_id: type.number.describe("the id from check_suite.id") -}); -var GetCheckSuiteLogsTool = tool({ - name: "get_check_suite_logs", - description: "get workflow run logs for a failed check suite. pass check_suite.id from the webhook payload.", - parameters: GetCheckSuiteLogs, - execute: contextualize(async ({ check_suite_id }, ctx) => { - const runsResponse = await ctx.octokit.rest.actions.listWorkflowRunsForRepo({ - owner: ctx.owner, - repo: ctx.name, - check_suite_id, - per_page: 100 - }); - const failedRuns = runsResponse.data.workflow_runs.filter( - (run) => run.conclusion === "failure" - ); - if (failedRuns.length === 0) { - return { - check_suite_id, - message: "no failed workflow runs found for this check suite", - workflow_runs: [] - }; - } - const logsForRuns = await Promise.all( - failedRuns.map(async (run) => { - const jobsResponse = await ctx.octokit.rest.actions.listJobsForWorkflowRun({ - owner: ctx.owner, - repo: ctx.name, - run_id: run.id - }); - const jobLogs = await Promise.all( - jobsResponse.data.jobs.map(async (job) => { - try { - const logsResponse = await ctx.octokit.rest.actions.downloadJobLogsForWorkflowRun({ - owner: ctx.owner, - repo: ctx.name, - job_id: job.id - }); - const logsUrl = logsResponse.url; - const logsText = await fetch(logsUrl).then((r) => r.text()); - return { - job_id: job.id, - job_name: job.name, - status: job.status, - conclusion: job.conclusion, - started_at: job.started_at, - completed_at: job.completed_at, - logs: logsText - }; - } catch (error41) { - return { - job_id: job.id, - job_name: job.name, - status: job.status, - conclusion: job.conclusion, - started_at: job.started_at, - completed_at: job.completed_at, - error: `failed to fetch logs: ${error41}` - }; - } - }) - ); - return { - workflow_run_id: run.id, - workflow_name: run.name, - html_url: run.html_url, - conclusion: run.conclusion, - jobs: jobLogs - }; - }) - ); - return { - check_suite_id, - workflow_runs: logsForRuns - }; - }) -}); - // mcp/issue.ts var Issue = type({ title: type.string.describe("the title of the issue"), @@ -107510,7 +107511,7 @@ var PullRequestInfoTool = tool({ log.info(`Fetching PR branch: origin/${headBranch}`); execSync2(`git fetch origin ${headBranch}`, { stdio: "inherit" }); log.info(`Checking out PR branch: origin/${headBranch}`); - execSync2(`git checkout origin/${headBranch}`, { stdio: "inherit" }); + execSync2(`git checkout -B ${headBranch} origin/${headBranch}`, { stdio: "inherit" }); return { number: data.number, url: data.html_url, @@ -107592,6 +107593,74 @@ var ReviewTool = tool({ }) }); +// mcp/reviewComments.ts +var GetReviewComments = type({ + pull_number: type.number.describe("The pull request number"), + review_id: type.number.describe("The review ID to get comments for") +}); +var GetReviewCommentsTool = tool({ + name: "get_review_comments", + description: "Get all review comments for a specific pull request review. Returns line-by-line comments that were left on specific code locations.", + parameters: GetReviewComments, + execute: contextualize(async ({ pull_number, review_id }, ctx) => { + const comments = await ctx.octokit.paginate(ctx.octokit.rest.pulls.listCommentsForReview, { + owner: ctx.owner, + repo: ctx.name, + pull_number, + review_id + }); + return { + review_id, + pull_number, + comments: comments.map((comment) => ({ + id: comment.id, + body: comment.body, + path: comment.path, + line: comment.line, + side: comment.side, + start_line: comment.start_line, + start_side: comment.start_side, + user: typeof comment.user === "string" ? comment.user : comment.user?.login, + created_at: comment.created_at, + updated_at: comment.updated_at, + html_url: comment.html_url, + in_reply_to_id: comment.in_reply_to_id, + diff_hunk: comment.diff_hunk, + reactions: comment.reactions + })), + count: comments.length + }; + }) +}); +var ListPullRequestReviews = type({ + pull_number: type.number.describe("The pull request number to list reviews for") +}); +var ListPullRequestReviewsTool = tool({ + name: "list_pull_request_reviews", + description: "List all reviews for a pull request. Returns all reviews including approvals, request changes, and comments.", + parameters: ListPullRequestReviews, + execute: contextualize(async ({ pull_number }, ctx) => { + const reviews = await ctx.octokit.paginate(ctx.octokit.rest.pulls.listReviews, { + owner: ctx.owner, + repo: ctx.name, + pull_number + }); + return { + pull_number, + reviews: reviews.map((review) => ({ + id: review.id, + body: review.body, + state: review.state, + user: review.user?.login, + commit_id: review.commit_id, + submitted_at: review.submitted_at, + html_url: review.html_url + })), + count: reviews.length + }; + }) +}); + // mcp/selectMode.ts function getModes() { const modesJson = process.env.PULLFROG_MODES; @@ -107648,9 +107717,12 @@ addTools(server, [ CreateWorkingCommentTool, UpdateWorkingCommentTool, IssueTool, + // ListFilesTool, PullRequestTool, ReviewTool, PullRequestInfoTool, + GetReviewCommentsTool, + ListPullRequestReviewsTool, GetCheckSuiteLogsTool ]); server.start();