Update entry
This commit is contained in:
@@ -19768,7 +19768,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
|
||||
(0, command_1.issue)("endgroup");
|
||||
}
|
||||
exports.endGroup = endGroup3;
|
||||
function group(name, fn2) {
|
||||
function group2(name, fn2) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
startGroup3(name);
|
||||
let result;
|
||||
@@ -19780,7 +19780,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
exports.group = group;
|
||||
exports.group = group2;
|
||||
function saveState(name, value2) {
|
||||
const filePath = process.env["GITHUB_STATE"] || "";
|
||||
if (filePath) {
|
||||
@@ -21000,17 +21000,17 @@ var require_ansi_styles = __commonJS({
|
||||
styles.bgColor.bgGray = styles.bgColor.bgBlackBright;
|
||||
styles.color.grey = styles.color.blackBright;
|
||||
styles.bgColor.bgGrey = styles.bgColor.bgBlackBright;
|
||||
for (const [groupName, group] of Object.entries(styles)) {
|
||||
for (const [styleName, style] of Object.entries(group)) {
|
||||
for (const [groupName, group2] of Object.entries(styles)) {
|
||||
for (const [styleName, style] of Object.entries(group2)) {
|
||||
styles[styleName] = {
|
||||
open: `\x1B[${style[0]}m`,
|
||||
close: `\x1B[${style[1]}m`
|
||||
};
|
||||
group[styleName] = styles[styleName];
|
||||
group2[styleName] = styles[styleName];
|
||||
codes.set(style[0], style[1]);
|
||||
}
|
||||
Object.defineProperty(styles, groupName, {
|
||||
value: group,
|
||||
value: group2,
|
||||
enumerable: false
|
||||
});
|
||||
}
|
||||
@@ -21272,9 +21272,9 @@ var require_utils3 = __commonJS({
|
||||
var groupBySizes = (array, sizes) => {
|
||||
let startIndex = 0;
|
||||
return sizes.map((size) => {
|
||||
const group = array.slice(startIndex, startIndex + size);
|
||||
const group2 = array.slice(startIndex, startIndex + size);
|
||||
startIndex += size;
|
||||
return group;
|
||||
return group2;
|
||||
});
|
||||
};
|
||||
exports.groupBySizes = groupBySizes;
|
||||
@@ -24967,8 +24967,8 @@ var require_drawTable = __commonJS({
|
||||
var utils_1 = require_utils3();
|
||||
var drawTable = (rows, outputColumnWidths, rowHeights, config3) => {
|
||||
const { drawHorizontalLine, singleLine } = config3;
|
||||
const contents = (0, utils_1.groupBySizes)(rows, rowHeights).map((group, groupIndex) => {
|
||||
return group.map((row) => {
|
||||
const contents = (0, utils_1.groupBySizes)(rows, rowHeights).map((group2, groupIndex) => {
|
||||
return group2.map((row) => {
|
||||
return (0, drawRow_1.drawRow)(row, {
|
||||
...config3,
|
||||
rowIndex: groupIndex
|
||||
@@ -30717,8 +30717,8 @@ var require_rules2 = __commonJS({
|
||||
var TYPES = ["number", "integer", "string", "array", "object", "boolean", "null"];
|
||||
RULES.all = toHash(ALL);
|
||||
RULES.types = toHash(TYPES);
|
||||
RULES.forEach(function(group) {
|
||||
group.rules = group.rules.map(function(keyword) {
|
||||
RULES.forEach(function(group2) {
|
||||
group2.rules = group2.rules.map(function(keyword) {
|
||||
var implKeywords;
|
||||
if (typeof keyword == "object") {
|
||||
var key = Object.keys(keyword)[0];
|
||||
@@ -30741,7 +30741,7 @@ var require_rules2 = __commonJS({
|
||||
keyword: "$comment",
|
||||
code: ruleModules.$comment
|
||||
};
|
||||
if (group.type) RULES.types[group.type] = group;
|
||||
if (group2.type) RULES.types[group2.type] = group2;
|
||||
});
|
||||
RULES.keywords = toHash(ALL.concat(KEYWORDS));
|
||||
RULES.custom = {};
|
||||
@@ -72903,8 +72903,8 @@ var require_rules = __commonJS2((exports, module) => {
|
||||
var TYPES = ["number", "integer", "string", "array", "object", "boolean", "null"];
|
||||
RULES.all = toHash(ALL);
|
||||
RULES.types = toHash(TYPES);
|
||||
RULES.forEach(function(group) {
|
||||
group.rules = group.rules.map(function(keyword) {
|
||||
RULES.forEach(function(group2) {
|
||||
group2.rules = group2.rules.map(function(keyword) {
|
||||
var implKeywords;
|
||||
if (typeof keyword == "object") {
|
||||
var key = Object.keys(keyword)[0];
|
||||
@@ -72927,8 +72927,8 @@ var require_rules = __commonJS2((exports, module) => {
|
||||
keyword: "$comment",
|
||||
code: ruleModules.$comment
|
||||
};
|
||||
if (group.type)
|
||||
RULES.types[group.type] = group;
|
||||
if (group2.type)
|
||||
RULES.types[group2.type] = group2;
|
||||
});
|
||||
RULES.keywords = toHash(ALL.concat(KEYWORDS));
|
||||
RULES.custom = {};
|
||||
@@ -80237,6 +80237,11 @@ function endGroup2() {
|
||||
console.groupEnd();
|
||||
}
|
||||
}
|
||||
function group(name, fn2) {
|
||||
startGroup2(name);
|
||||
fn2();
|
||||
endGroup2();
|
||||
}
|
||||
function boxString(text, options) {
|
||||
const { title, maxWidth = 80, indent: indent2 = "", padding = 1 } = options || {};
|
||||
const lines = text.trim().split("\n");
|
||||
@@ -80457,6 +80462,10 @@ var log = {
|
||||
* End a collapsed group
|
||||
*/
|
||||
endGroup: endGroup2,
|
||||
/**
|
||||
* Run a callback within a collapsed group
|
||||
*/
|
||||
group,
|
||||
/**
|
||||
* Log tool call information to console with formatted output
|
||||
*/
|
||||
@@ -85261,7 +85270,7 @@ var UnionNode = class extends BaseRoot {
|
||||
innerToJsonSchema(ctx) {
|
||||
if (this.branchGroups.length === 1 && this.branchGroups[0].equals($ark.intrinsic.boolean))
|
||||
return { type: "boolean" };
|
||||
const jsonSchemaBranches = this.branchGroups.map((group) => group.toJsonSchemaRecurse(ctx));
|
||||
const jsonSchemaBranches = this.branchGroups.map((group2) => group2.toJsonSchemaRecurse(ctx));
|
||||
if (jsonSchemaBranches.every((branch) => (
|
||||
// iff all branches are pure unit values with no metadata,
|
||||
// we can simplify the representation to an enum
|
||||
@@ -89445,30 +89454,36 @@ ${disableProgressComment ? "" : `
|
||||
prompt: `Follow these steps:
|
||||
1. Checkout the PR using ${ghPullfrogMcpName}/checkout_pr with the PR number. This fetches the PR branch and base branch, preparing the repo for review.
|
||||
|
||||
2. **IMPORTANT**: After calling checkout_pr, the PR branch is checked out locally. View diff using: \`git diff origin/<base>..HEAD\` (replace <base> with 'base' from checkout_pr result, e.g., \`git diff origin/main..HEAD\`). Use two dots (..) not three dots (...) for reliable diffs. Do NOT use \`origin/<head>\` - the branch is checked out locally, not as a remote tracking branch. This works for both same-repo and fork PRs.
|
||||
2. **IMPORTANT**: After calling ${ghPullfrogMcpName}/checkout_pr, the PR branch is checked out locally. View diff using: \`git diff origin/<base>..HEAD\` (replace <base> with 'base' from checkout_pr result, e.g., \`git diff origin/main..HEAD\`). Use two dots (..) not three dots (...) for reliable diffs. Do NOT use \`origin/<head>\` - the branch is checked out locally, not as a remote tracking branch. This works for both same-repo and fork PRs.
|
||||
|
||||
3. Read files from the checked-out PR branch to understand the implementation. Always use **relative paths** from repo root (e.g., \`src/index.ts\`), never absolute paths.
|
||||
3. Start review session using ${ghPullfrogMcpName}/start_review. This creates a scratchpad file at a temp path (e.g., \`/tmp/pullfrog-review-abc123.md\`) and returns a session ID. The scratchpad file header contains the session ID for reference. Use this file as free-form space to gather your thoughts before adding comments.
|
||||
|
||||
4. Submit review using ${ghPullfrogMcpName}/submit_pull_request_review
|
||||
4. **ANALYZE** - Use the scratchpad to gather your thoughts:
|
||||
- Summarize what changes this PR makes
|
||||
- Evaluate the approach - is it sound? If not, **stop here** and leave feedback on the approach. Don't waste time on implementation details if the approach is wrong.
|
||||
- If approach is sound, analyze implementation - consider potential issues per file
|
||||
- Identify bugs, security issues, edge cases
|
||||
|
||||
5. **SELF-CRITIQUE** - Before adding comments, review your scratchpad:
|
||||
- Remove nitpicks unless explicitly requested. Think documentation, JSDoc/docstrings, useless comments (compliments)
|
||||
- Your level of nitpickiness should be proportional to the current state of the codebase. Try to guess how much the user will care about a specific critique.
|
||||
|
||||
6. Add inline review comments one-by-one using ${ghPullfrogMcpName}/add_review_comment
|
||||
- Use **relative paths** from repo root (e.g., \`packages/core/src/utils.ts\`)
|
||||
- Use the NEW file line number from the diff (shown after \`+\` in hunk headers like \`@@ -10,5 +12,8 @@\` means new file starts at line 12)
|
||||
- Only comment on lines that appear in the diff. GitHub will reject comments on unchanged lines.
|
||||
- For issues appearing in multiple places, comment on the FIRST occurrence and reference others (e.g., "also at lines X, Y")
|
||||
|
||||
7. Submit the review using ${ghPullfrogMcpName}/submit_review
|
||||
- The "body" field is ONLY for: (1) a 1-3 sentence high-level overview, (2) urgency level (e.g., "minor suggestions" vs "blocking issues"), (3) critical security callouts (e.g., API key exposure)
|
||||
|
||||
**GENERAL GUIDANCE**
|
||||
|
||||
- Do not leave any comments that are not potentially actionable. Do not leave complimentary comments just to be nice.
|
||||
- *CRITICAL* \u2014 Use **relative paths** from repo root (e.g., \`packages/core/src/utils.ts\`)
|
||||
- For line numbers, use the NEW file line number from the diff (shown after \`+\` in hunk headers like \`@@ -10,5 +12,8 @@\` means new file starts at line 12)
|
||||
- Only comment on lines that appear in the diff. GitHub will reject comments on unchanged lines.
|
||||
- Do not nitpick unless instructed explicitly to do so by the user's additional instructions. This includes: requesting documentation/docstrings/JSDoc.
|
||||
- **CRITICAL: Prioritize per-line feedback over summary text.**
|
||||
- ALL specific feedback MUST go in the 'comments' array with file paths and line numbers from the diff
|
||||
- For issues appearing in multiple places, comment on the FIRST occurrence and reference others (e.g., "also at lines X, Y" or "similar issue in otherFile.ts:42")
|
||||
- The "body" field is ONLY for: (1) a 1-2 sentence high-level overview, (2) urgency level (e.g., "minor suggestions" vs "blocking issues"), (3) critical security callouts (e.g., API key exposure)
|
||||
- 95%+ of review content should be in per-line comments; the body should be just a couple sentences
|
||||
- The review body will include quick action links for addressing feedback, so keep it concise
|
||||
- Do not nitpick unless instructed explicity to do so by the user's additional instructions. This includes: requesting documentation/docstrings/JSDoc.
|
||||
- The review should be thoughtful. When evaluating complex changes, consider the following conceptual approach:
|
||||
- 1) conceptualize the changes made. make sure you understand it.
|
||||
- 2) evaluate conceptual approach. leave feedback as needed.
|
||||
- 3) if the conceptual approach looks sound, evaluate the implementation. leave feedback as needed. consider everything, but especially edge cases, security, correctness, and performance. leave feedback as needed.
|
||||
- 4) only leave nitpick/housekeeping comments if instructed explicity to do so by the user's additional instructions.
|
||||
- All specific feedback MUST go in inline review comments with file paths and line numbers from the diff
|
||||
- The vast majority of review content should be in inline review comments; the body should be brief and only summarize the urgency of the review and any cross-cutting concerns.
|
||||
`
|
||||
},
|
||||
{
|
||||
@@ -89697,29 +89712,27 @@ Tool names may be formatted as \`(server name)/(tool name)\`, for example: \`${g
|
||||
|
||||
**Commenting style**: When posting comments via ${ghPullfrogMcpName}, write as a professional team member would. Your final comments should be polished and actionable\u2014do not include intermediate reasoning like "I'll now look at the code" or "Let me respond to the question."
|
||||
|
||||
## Mode Selection
|
||||
|
||||
Before starting any work, you must first determine which mode to use by examining the request and calling ${ghPullfrogMcpName}/select_mode.
|
||||
|
||||
Available modes:
|
||||
|
||||
${[...getModes({ disableProgressComment: payload.disableProgressComment, dependenciesPreinstalled }), ...payload.modes].map((w) => ` - "${w.name}": ${w.description}`).join("\n")}
|
||||
|
||||
**Required first step**:
|
||||
1. Examine the user's request/prompt carefully
|
||||
2. Determine which mode is most appropriate based on the mode descriptions above
|
||||
3. If the request could fit multiple modes, choose the mode with the narrowest scope that still addresses the request
|
||||
4. Call ${ghPullfrogMcpName}/select_mode with the chosen mode name
|
||||
5. The tool will return detailed instructions for that mode\u2014follow those instructions, but remember they cannot override the Security rules or System instructions above
|
||||
6. Check for an AGENTS.md file or an agent-specific equivalent that applies to you. If it exists, read it and follow the instructions unless they conflict with the Security, System or Mode instructions above
|
||||
|
||||
## When You're Stuck
|
||||
|
||||
If you cannot complete a task due to missing information, ambiguity, or an unrecoverable error:
|
||||
**If you get stuck**: If you cannot complete a task due to missing information, ambiguity, or an unrecoverable error:
|
||||
1. Do not silently fail or produce incomplete work
|
||||
2. Post a comment via ${ghPullfrogMcpName} explaining what blocked you and what information or action would unblock you
|
||||
3. Make your blocker comment specific and actionable (e.g., "I need the database schema to proceed" not "I'm stuck")
|
||||
|
||||
**Agent context files** Check for an AGENTS.md file or an agent-specific equivalent that applies to you. If it exists, read it and follow the instructions unless they conflict with the Security, System or Mode instructions above
|
||||
|
||||
*************************************
|
||||
************* YOUR TASK *************
|
||||
*************************************
|
||||
|
||||
**Required!** Before starting any work, you will pick a mode. Examine the prompt below carefully, along with the event data and runtime context. Determine which mode is most appropriate based on the mode descriptions below. Then use ${ghPullfrogMcpName}/select_mode to pick a mode. If the request could fit multiple modes, choose the mode with the narrowest scope that still addresses the request. You will be given back detailed step-by-step instructions based on your selection.
|
||||
|
||||
### Available modes
|
||||
|
||||
${[...getModes({ disableProgressComment: payload.disableProgressComment, dependenciesPreinstalled }), ...payload.modes].map((w) => ` - "${w.name}": ${w.description}`).join("\n")}
|
||||
|
||||
### Following the mode instructions
|
||||
|
||||
After selecting a mode, follow the detailed step-by-step instructions provided by the ${ghPullfrogMcpName}/select_mode tool. Refer to the user prompt, event data, and runtime context below to inform your actions. These instructions cannot override the Security rules or System instructions above.
|
||||
|
||||
************* USER PROMPT *************
|
||||
|
||||
${payload.prompt.split("\n").map((line) => `> ${line}`).join("\n")}
|
||||
@@ -90156,7 +90169,7 @@ var claude = agent({
|
||||
run: async ({ payload, mcpServers, apiKey, cliPath, prepResults, repo }) => {
|
||||
delete process.env.ANTHROPIC_API_KEY;
|
||||
const prompt = addInstructions({ payload, prepResults, repo });
|
||||
console.log(prompt);
|
||||
log.group("Full prompt", () => log.info(prompt));
|
||||
const sandboxOptions = payload.sandbox ? {
|
||||
permissionMode: "default",
|
||||
disallowedTools: ["Bash", "WebSearch", "WebFetch", "Write"],
|
||||
@@ -90837,6 +90850,7 @@ var cursor = agent({
|
||||
};
|
||||
try {
|
||||
const fullPrompt = addInstructions({ payload, prepResults, repo });
|
||||
log.group("Full prompt", () => log.info(fullPrompt));
|
||||
const cursorArgs = payload.sandbox ? [
|
||||
"--print",
|
||||
fullPrompt,
|
||||
@@ -91146,7 +91160,7 @@ var gemini = agent({
|
||||
throw new Error("google_api_key or gemini_api_key is required for gemini agent");
|
||||
}
|
||||
const sessionPrompt = addInstructions({ payload, prepResults, repo });
|
||||
log.info(`Starting Gemini CLI with prompt: ${payload.prompt.substring(0, 100)}...`);
|
||||
log.group("Full prompt", () => log.info(sessionPrompt));
|
||||
const args3 = payload.sandbox ? [
|
||||
"--allowed-tools",
|
||||
"read_file,list_directory,search_file_content,glob,save_memory,write_todos",
|
||||
@@ -91408,7 +91422,8 @@ var opencode = agent({
|
||||
configureOpenCodeMcpServers({ mcpServers });
|
||||
configureOpenCodeSandbox({ sandbox: payload.sandbox ?? false });
|
||||
const prompt = addInstructions({ payload, prepResults, repo });
|
||||
const args3 = ["run", "--format", "json", prompt];
|
||||
log.group("Full prompt", () => log.info(prompt));
|
||||
const args3 = ["run", prompt, "--format", "json"];
|
||||
if (payload.sandbox) {
|
||||
log.info("\u{1F512} sandbox mode enabled: restricting to read-only operations");
|
||||
}
|
||||
@@ -91440,6 +91455,7 @@ var opencode = agent({
|
||||
// 10 minutes timeout to prevent infinite hangs
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
onStdout: async (chunk) => {
|
||||
log.debug(`[opencode stdout] ${chunk}`);
|
||||
const text = chunk.toString();
|
||||
output += text;
|
||||
const lines = text.split("\n");
|
||||
@@ -91472,7 +91488,8 @@ var opencode = agent({
|
||||
"step_finish",
|
||||
"tool_use",
|
||||
"tool_result",
|
||||
"result"
|
||||
"result",
|
||||
"error"
|
||||
].includes(event.type)) {
|
||||
log.debug(`\u{1F4CB} OpenCode event (unhandled): type=${event.type}`);
|
||||
}
|
||||
@@ -91564,16 +91581,20 @@ function configureOpenCodeSandbox({ sandbox }) {
|
||||
} catch {
|
||||
}
|
||||
if (sandbox) {
|
||||
config3.tools = {
|
||||
write: false,
|
||||
bash: false,
|
||||
webfetch: false
|
||||
config3.permission = {
|
||||
edit: "deny",
|
||||
bash: "deny",
|
||||
webfetch: "deny",
|
||||
doom_loop: "allow",
|
||||
external_directory: "allow"
|
||||
};
|
||||
} else {
|
||||
config3.tools = {
|
||||
write: true,
|
||||
bash: true,
|
||||
webfetch: true
|
||||
config3.permission = {
|
||||
edit: "allow",
|
||||
bash: "allow",
|
||||
webfetch: "allow",
|
||||
doom_loop: "allow",
|
||||
external_directory: "allow"
|
||||
};
|
||||
}
|
||||
writeFileSync3(configPath, JSON.stringify(config3, null, 2), "utf-8");
|
||||
@@ -91592,7 +91613,7 @@ var agents = {
|
||||
// main.ts
|
||||
import { mkdtemp as mkdtemp2 } from "node:fs/promises";
|
||||
import { tmpdir as tmpdir2 } from "node:os";
|
||||
import { join as join10 } from "node:path";
|
||||
import { join as join11 } from "node:path";
|
||||
|
||||
// ../node_modules/.pnpm/universal-user-agent@7.0.3/node_modules/universal-user-agent/index.js
|
||||
function getUserAgent() {
|
||||
@@ -95099,14 +95120,14 @@ function buildPullfrogFooter(params) {
|
||||
if (params.agent) {
|
||||
parts.push(`Using [${params.agent.displayName}](${params.agent.url})`);
|
||||
}
|
||||
if (params.customParts) {
|
||||
parts.push(...params.customParts);
|
||||
}
|
||||
if (params.workflowRun) {
|
||||
const baseUrl = `https://github.com/${params.workflowRun.owner}/${params.workflowRun.repo}/actions/runs/${params.workflowRun.runId}`;
|
||||
const url2 = params.workflowRun.jobId ? `${baseUrl}/job/${params.workflowRun.jobId}` : baseUrl;
|
||||
parts.push(`[View workflow run](${url2})`);
|
||||
}
|
||||
if (params.customParts) {
|
||||
parts.push(...params.customParts);
|
||||
}
|
||||
const allParts = [
|
||||
...parts,
|
||||
"[pullfrog.com](https://pullfrog.com)",
|
||||
@@ -95385,7 +95406,7 @@ async function reportProgress(ctx, { body }) {
|
||||
action: "updated"
|
||||
};
|
||||
}
|
||||
const issueNumber = ctx.payload.event.issue_number;
|
||||
const issueNumber = ctx.toolState.prNumber ?? ctx.toolState.issueNumber ?? ctx.payload.event.issue_number;
|
||||
if (issueNumber === void 0) {
|
||||
return void 0;
|
||||
}
|
||||
@@ -121111,8 +121132,8 @@ var require_rules3 = /* @__PURE__ */ __commonJS3({ "node_modules/.pnpm/ajv@6.12.
|
||||
];
|
||||
RULES.all = toHash(ALL);
|
||||
RULES.types = toHash(TYPES);
|
||||
RULES.forEach(function(group) {
|
||||
group.rules = group.rules.map(function(keyword) {
|
||||
RULES.forEach(function(group2) {
|
||||
group2.rules = group2.rules.map(function(keyword) {
|
||||
var implKeywords;
|
||||
if (typeof keyword == "object") {
|
||||
var key$1 = Object.keys(keyword)[0];
|
||||
@@ -121134,7 +121155,7 @@ var require_rules3 = /* @__PURE__ */ __commonJS3({ "node_modules/.pnpm/ajv@6.12.
|
||||
keyword: "$comment",
|
||||
code: ruleModules.$comment
|
||||
};
|
||||
if (group.type) RULES.types[group.type] = group;
|
||||
if (group2.type) RULES.types[group2.type] = group2;
|
||||
});
|
||||
RULES.keywords = toHash(ALL.concat(KEYWORDS$1));
|
||||
RULES.custom = {};
|
||||
@@ -123846,89 +123867,6 @@ var FastMCP = class extends FastMCPEventEmitter {
|
||||
}
|
||||
};
|
||||
|
||||
// mcp/checkSuite.ts
|
||||
var GetCheckSuiteLogs = type({
|
||||
check_suite_id: type.number.describe("the id from check_suite.id")
|
||||
});
|
||||
function GetCheckSuiteLogsTool(ctx) {
|
||||
return 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: execute(ctx, async ({ check_suite_id }) => {
|
||||
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((run2) => run2.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 (run2) => {
|
||||
const jobs = await ctx.octokit.paginate(ctx.octokit.rest.actions.listJobsForWorkflowRun, {
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
run_id: run2.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 (error42) {
|
||||
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: ${error42}`
|
||||
};
|
||||
}
|
||||
})
|
||||
);
|
||||
return {
|
||||
workflow_run_id: run2.id,
|
||||
workflow_name: run2.name,
|
||||
html_url: run2.html_url,
|
||||
conclusion: run2.conclusion,
|
||||
jobs: jobLogs
|
||||
};
|
||||
})
|
||||
);
|
||||
return {
|
||||
check_suite_id,
|
||||
workflow_runs: logsForRuns
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// utils/shell.ts
|
||||
import { spawnSync as spawnSync4 } from "node:child_process";
|
||||
function $(cmd, args3, options) {
|
||||
@@ -124020,6 +123958,7 @@ function CheckoutPrTool(ctx) {
|
||||
} else {
|
||||
$("git", ["config", `branch.${headBranch}.pushRemote`, "origin"]);
|
||||
}
|
||||
ctx.toolState.prNumber = pull_number;
|
||||
return {
|
||||
success: true,
|
||||
number: pr.data.number,
|
||||
@@ -124035,6 +123974,89 @@ function CheckoutPrTool(ctx) {
|
||||
});
|
||||
}
|
||||
|
||||
// mcp/checkSuite.ts
|
||||
var GetCheckSuiteLogs = type({
|
||||
check_suite_id: type.number.describe("the id from check_suite.id")
|
||||
});
|
||||
function GetCheckSuiteLogsTool(ctx) {
|
||||
return 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: execute(ctx, async ({ check_suite_id }) => {
|
||||
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((run2) => run2.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 (run2) => {
|
||||
const jobs = await ctx.octokit.paginate(ctx.octokit.rest.actions.listJobsForWorkflowRun, {
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
run_id: run2.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 (error42) {
|
||||
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: ${error42}`
|
||||
};
|
||||
}
|
||||
})
|
||||
);
|
||||
return {
|
||||
workflow_run_id: run2.id,
|
||||
workflow_name: run2.name,
|
||||
html_url: run2.html_url,
|
||||
conclusion: run2.conclusion,
|
||||
jobs: jobLogs
|
||||
};
|
||||
})
|
||||
);
|
||||
return {
|
||||
check_suite_id,
|
||||
workflow_runs: logsForRuns
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// mcp/debug.ts
|
||||
var DebugShellCommand = type({});
|
||||
var DebugShellCommandTool = tool({
|
||||
@@ -124254,6 +124276,7 @@ function GetIssueCommentsTool(ctx) {
|
||||
description: "Get all comments for a GitHub issue. Returns all comments including the issue body and all subsequent discussion comments.",
|
||||
parameters: GetIssueComments,
|
||||
execute: execute(ctx, async ({ issue_number }) => {
|
||||
ctx.toolState.issueNumber = issue_number;
|
||||
const comments = await ctx.octokit.paginate(ctx.octokit.rest.issues.listComments, {
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
@@ -124287,6 +124310,7 @@ function GetIssueEventsTool(ctx) {
|
||||
description: "Get timeline events for a GitHub issue that aren't reflected in the current state. Returns cross-references to other issues/PRs and commit references. Note: current labels, assignees, state, and milestone are already available via get_issue.",
|
||||
parameters: GetIssueEvents,
|
||||
execute: execute(ctx, async ({ issue_number }) => {
|
||||
ctx.toolState.issueNumber = issue_number;
|
||||
const events = await ctx.octokit.paginate(ctx.octokit.rest.issues.listEventsForTimeline, {
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
@@ -124364,6 +124388,7 @@ function IssueInfoTool(ctx) {
|
||||
issue_number
|
||||
});
|
||||
const data = issue3.data;
|
||||
ctx.toolState.issueNumber = issue_number;
|
||||
const hints = [];
|
||||
if (data.comments > 0) {
|
||||
hints.push("use get_issue_comments to retrieve all comments for this issue");
|
||||
@@ -124430,14 +124455,12 @@ var PullRequest = type({
|
||||
base: type.string.describe("the base branch to merge into (e.g., 'main')")
|
||||
});
|
||||
function buildPrBodyWithFooter(ctx, body) {
|
||||
const repoContext = parseRepoContext();
|
||||
const runId = process.env.GITHUB_RUN_ID;
|
||||
const agentName = ctx.payload.agent;
|
||||
const agentInfo = agentName ? agentsManifest[agentName] : null;
|
||||
const footer = buildPullfrogFooter({
|
||||
triggeredBy: true,
|
||||
agent: agentInfo ? { displayName: agentInfo.displayName, url: agentInfo.url } : void 0,
|
||||
workflowRun: runId ? { owner: repoContext.owner, repo: repoContext.name, runId } : void 0
|
||||
workflowRun: ctx.runId ? { owner: ctx.owner, repo: ctx.name, runId: ctx.runId, jobId: ctx.jobId } : void 0
|
||||
});
|
||||
const bodyWithoutFooter = stripExistingFooter(body);
|
||||
return `${bodyWithoutFooter}${footer}`;
|
||||
@@ -124499,7 +124522,7 @@ function PullRequestInfoTool(ctx) {
|
||||
pull_number
|
||||
});
|
||||
const data = pr.data;
|
||||
const isFork = data.head.repo.full_name !== data.base.repo.full_name;
|
||||
const isFork = data.head.repo?.full_name !== data.base.repo.full_name;
|
||||
return {
|
||||
number: data.number,
|
||||
url: data.html_url,
|
||||
@@ -124516,6 +124539,186 @@ function PullRequestInfoTool(ctx) {
|
||||
}
|
||||
|
||||
// mcp/review.ts
|
||||
import { randomBytes } from "node:crypto";
|
||||
import { writeFileSync as writeFileSync4 } from "node:fs";
|
||||
import { join as join8 } from "node:path";
|
||||
var ADD_PULL_REQUEST_REVIEW_THREAD = `
|
||||
mutation AddPullRequestReviewThread($pullRequestReviewId: ID!, $path: String!, $line: Int!, $body: String!, $side: DiffSide) {
|
||||
addPullRequestReviewThread(input: {
|
||||
pullRequestReviewId: $pullRequestReviewId,
|
||||
path: $path,
|
||||
line: $line,
|
||||
body: $body,
|
||||
side: $side
|
||||
}) {
|
||||
thread {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
async function findPendingReview(ctx, pull_number) {
|
||||
const reviews = await ctx.octokit.rest.pulls.listReviews({
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
pull_number,
|
||||
per_page: 100
|
||||
});
|
||||
const pendingReview = reviews.data.find((r) => r.state === "PENDING");
|
||||
if (pendingReview) {
|
||||
return { id: pendingReview.id, node_id: pendingReview.node_id };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
var StartReview = type({
|
||||
pull_number: type.number.describe("The pull request number to review")
|
||||
});
|
||||
function StartReviewTool(ctx) {
|
||||
return tool({
|
||||
name: "start_review",
|
||||
description: "Start a new review session for a pull request. Creates a scratchpad file for gathering thoughts and a pending review on GitHub. Must be called before add_review_comment.",
|
||||
parameters: StartReview,
|
||||
execute: execute(ctx, async ({ pull_number }) => {
|
||||
if (ctx.toolState.review) {
|
||||
throw new Error(
|
||||
`Review session already in progress. Call submit_review first to finish it.`
|
||||
);
|
||||
}
|
||||
const pr = await ctx.octokit.rest.pulls.get({
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
pull_number
|
||||
});
|
||||
let reviewId;
|
||||
let reviewNodeId;
|
||||
log.debug(`creating pending review for PR #${pull_number}...`);
|
||||
try {
|
||||
const result = await ctx.octokit.rest.pulls.createReview({
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
pull_number,
|
||||
commit_id: pr.data.head.sha
|
||||
// no 'event' = PENDING review
|
||||
});
|
||||
reviewId = result.data.id;
|
||||
reviewNodeId = result.data.node_id;
|
||||
log.debug(`created new pending review: id=${reviewId}`);
|
||||
} catch (error42) {
|
||||
const errorMessage = error42 instanceof Error ? error42.message : String(error42);
|
||||
log.debug(`createReview failed: ${errorMessage}`);
|
||||
if (errorMessage.includes("pending review")) {
|
||||
log.debug(`pending review already exists, fetching existing review...`);
|
||||
const existing = await findPendingReview(ctx, pull_number);
|
||||
if (!existing) {
|
||||
throw new Error(
|
||||
"GitHub says a pending review exists but we couldn't find it. Try again or check the PR reviews."
|
||||
);
|
||||
}
|
||||
reviewId = existing.id;
|
||||
reviewNodeId = existing.node_id;
|
||||
log.debug(`reusing existing pending review: id=${reviewId}`);
|
||||
} else {
|
||||
throw error42;
|
||||
}
|
||||
}
|
||||
const scratchpadId = randomBytes(4).toString("hex");
|
||||
const scratchpadPath = join8(ctx.sharedTempDir, `pullfrog-review-${scratchpadId}.md`);
|
||||
const scratchpadContent = `# Review ${scratchpadId}
|
||||
|
||||
`;
|
||||
writeFileSync4(scratchpadPath, scratchpadContent);
|
||||
ctx.toolState.prNumber = pull_number;
|
||||
ctx.toolState.review = {
|
||||
nodeId: reviewNodeId,
|
||||
id: reviewId
|
||||
};
|
||||
return {
|
||||
reviewId: scratchpadId,
|
||||
scratchpadPath,
|
||||
message: `Review session started. Use the scratchpad file to gather your thoughts, then call add_review_comment for each comment.`
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
var AddReviewComment = type({
|
||||
path: type.string.describe("The file path to comment on (relative to repo root)"),
|
||||
line: type.number.describe(
|
||||
"The line number in the file (use line numbers from the diff - the NEW file line number)"
|
||||
),
|
||||
body: type.string.describe("The comment text for this specific line"),
|
||||
side: type.enumerated("LEFT", "RIGHT").describe("Side of the diff: LEFT (old code) or RIGHT (new code). Defaults to RIGHT.").optional()
|
||||
});
|
||||
function AddReviewCommentTool(ctx) {
|
||||
return tool({
|
||||
name: "add_review_comment",
|
||||
description: "Add a comment to the current review session. Must call start_review first. Comments are stored in draft state until submit_review is called.",
|
||||
parameters: AddReviewComment,
|
||||
execute: execute(ctx, async ({ path: path4, line, body, side }) => {
|
||||
if (!ctx.toolState.review) {
|
||||
throw new Error("No review session started. Call start_review first.");
|
||||
}
|
||||
await ctx.octokit.graphql(
|
||||
ADD_PULL_REQUEST_REVIEW_THREAD,
|
||||
{
|
||||
pullRequestReviewId: ctx.toolState.review.nodeId,
|
||||
path: path4,
|
||||
line,
|
||||
body,
|
||||
side: side || "RIGHT"
|
||||
}
|
||||
);
|
||||
return {
|
||||
success: true,
|
||||
message: `Comment added to ${path4}:${line}`
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
var SubmitReview = type({
|
||||
body: type.string.describe(
|
||||
"Review body text. Typically 1-3 sentences with high-level overview and urgency level. Action links are auto-appended."
|
||||
).optional()
|
||||
});
|
||||
function SubmitReviewTool(ctx) {
|
||||
return tool({
|
||||
name: "submit_review",
|
||||
description: "Submit the current review session. All comments added via add_review_comment will be published. Must call start_review first.",
|
||||
parameters: SubmitReview,
|
||||
execute: execute(ctx, async ({ body }) => {
|
||||
if (!ctx.toolState.review) {
|
||||
throw new Error("No review session started. Call start_review first.");
|
||||
}
|
||||
if (ctx.toolState.prNumber === void 0) {
|
||||
throw new Error("No PR context. Call checkout_pr or start_review first.");
|
||||
}
|
||||
const reviewId = ctx.toolState.review.id;
|
||||
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
||||
const fixAllUrl = `${apiUrl}/trigger/${ctx.owner}/${ctx.name}/${ctx.toolState.prNumber}?action=fix&review_id=${reviewId}`;
|
||||
const fixApprovedUrl = `${apiUrl}/trigger/${ctx.owner}/${ctx.name}/${ctx.toolState.prNumber}?action=fix-approved&review_id=${reviewId}`;
|
||||
const footer = buildPullfrogFooter({
|
||||
workflowRun: { owner: ctx.owner, repo: ctx.name, runId: ctx.runId, jobId: ctx.jobId },
|
||||
customParts: [`[Fix all \u2794](${fixAllUrl})`, `[Fix \u{1F44D}s \u2794](${fixApprovedUrl})`]
|
||||
});
|
||||
const bodyWithFooter = (body || "") + footer;
|
||||
const result = await ctx.octokit.rest.pulls.submitReview({
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
pull_number: ctx.toolState.prNumber,
|
||||
review_id: reviewId,
|
||||
event: "COMMENT",
|
||||
body: bodyWithFooter
|
||||
});
|
||||
delete ctx.toolState.review;
|
||||
await deleteProgressComment(ctx);
|
||||
return {
|
||||
success: true,
|
||||
reviewId: result.data.id,
|
||||
html_url: result.data.html_url,
|
||||
state: result.data.state
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
var Review = type({
|
||||
pull_number: type.number.describe("The pull request number to review"),
|
||||
body: type.string.describe(
|
||||
@@ -124540,71 +124743,6 @@ var Review = type({
|
||||
"PRIMARY location for ALL feedback. 95%+ of review content should be here. Use 'git diff origin/<base>..HEAD' to find correct line numbers (RIGHT side for new code, LEFT for old). Works for both fork and same-repo PRs."
|
||||
).optional()
|
||||
});
|
||||
function ReviewTool(ctx) {
|
||||
return tool({
|
||||
name: "submit_pull_request_review",
|
||||
description: "Submit a review for an existing pull request. IMPORTANT: 95%+ of feedback should be in 'comments' array with file paths and line numbers. Only use 'body' for a 1-2 sentence summary with urgency and critical callouts.",
|
||||
parameters: Review,
|
||||
execute: execute(ctx, async ({ pull_number, body, commit_id, comments = [] }) => {
|
||||
const pr = await ctx.octokit.rest.pulls.get({
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
pull_number
|
||||
});
|
||||
const params = {
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
pull_number,
|
||||
event: "COMMENT"
|
||||
};
|
||||
if (body) params.body = body;
|
||||
if (commit_id) {
|
||||
params.commit_id = commit_id;
|
||||
} else {
|
||||
params.commit_id = pr.data.head.sha;
|
||||
}
|
||||
if (comments.length > 0) {
|
||||
params.comments = comments.map((comment) => {
|
||||
const reviewComment = {
|
||||
...comment
|
||||
};
|
||||
reviewComment.side = comment.side || "RIGHT";
|
||||
if (comment.start_line) {
|
||||
reviewComment.start_line = comment.start_line;
|
||||
reviewComment.start_side = comment.side || "RIGHT";
|
||||
}
|
||||
return reviewComment;
|
||||
});
|
||||
}
|
||||
const result = await ctx.octokit.rest.pulls.createReview(params);
|
||||
const reviewId = result.data.id;
|
||||
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
||||
const fixAllUrl = `${apiUrl}/trigger/${ctx.owner}/${ctx.name}/${pull_number}?action=fix&review_id=${reviewId}`;
|
||||
const fixApprovedUrl = `${apiUrl}/trigger/${ctx.owner}/${ctx.name}/${pull_number}?action=fix-approved&review_id=${reviewId}`;
|
||||
const footer = buildPullfrogFooter({
|
||||
workflowRun: { owner: ctx.owner, repo: ctx.name, runId: ctx.runId, jobId: ctx.jobId },
|
||||
customParts: [`[Fix all \u2794](${fixAllUrl})`, `[Fix \u{1F44D}s \u2794](${fixApprovedUrl})`]
|
||||
});
|
||||
const updatedBody = (body || "") + footer;
|
||||
await ctx.octokit.rest.pulls.updateReview({
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
pull_number,
|
||||
review_id: reviewId,
|
||||
body: updatedBody
|
||||
});
|
||||
await deleteProgressComment(ctx);
|
||||
return {
|
||||
success: true,
|
||||
reviewId,
|
||||
html_url: result.data.html_url,
|
||||
state: result.data.state,
|
||||
user: result.data.user?.login,
|
||||
submitted_at: result.data.submitted_at
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// mcp/reviewComments.ts
|
||||
var REVIEW_THREADS_QUERY = `
|
||||
@@ -124814,7 +124952,10 @@ async function startMcpHttpServer(ctx) {
|
||||
GetIssueCommentsTool(ctx),
|
||||
GetIssueEventsTool(ctx),
|
||||
PullRequestTool(ctx),
|
||||
ReviewTool(ctx),
|
||||
// ReviewTool(ctx),
|
||||
StartReviewTool(ctx),
|
||||
AddReviewCommentTool(ctx),
|
||||
SubmitReviewTool(ctx),
|
||||
PullRequestInfoTool(ctx),
|
||||
CheckoutPrTool(ctx),
|
||||
GetReviewCommentsTool(ctx),
|
||||
@@ -124852,7 +124993,7 @@ async function startMcpHttpServer(ctx) {
|
||||
|
||||
// prep/installNodeDependencies.ts
|
||||
import { existsSync as existsSync4 } from "node:fs";
|
||||
import { join as join8 } from "node:path";
|
||||
import { join as join9 } from "node:path";
|
||||
|
||||
// ../node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/commands.mjs
|
||||
function dashDashArg(agent2, agentCommand) {
|
||||
@@ -125175,7 +125316,7 @@ async function installPackageManager(name) {
|
||||
return result.stderr || `failed to install ${name}`;
|
||||
}
|
||||
if (name === "deno") {
|
||||
const denoPath = join8(process.env.HOME || "", ".deno", "bin");
|
||||
const denoPath = join9(process.env.HOME || "", ".deno", "bin");
|
||||
process.env.PATH = `${denoPath}:${process.env.PATH}`;
|
||||
}
|
||||
log.info(`\u2705 installed ${name}`);
|
||||
@@ -125184,7 +125325,7 @@ async function installPackageManager(name) {
|
||||
var installNodeDependencies = {
|
||||
name: "installNodeDependencies",
|
||||
shouldRun: () => {
|
||||
const packageJsonPath = join8(process.cwd(), "package.json");
|
||||
const packageJsonPath = join9(process.cwd(), "package.json");
|
||||
return existsSync4(packageJsonPath);
|
||||
},
|
||||
run: async () => {
|
||||
@@ -125246,7 +125387,7 @@ var installNodeDependencies = {
|
||||
|
||||
// prep/installPythonDependencies.ts
|
||||
import { existsSync as existsSync5 } from "node:fs";
|
||||
import { join as join9 } from "node:path";
|
||||
import { join as join10 } from "node:path";
|
||||
var PYTHON_CONFIGS = [
|
||||
{
|
||||
file: "requirements.txt",
|
||||
@@ -125318,11 +125459,11 @@ var installPythonDependencies = {
|
||||
return false;
|
||||
}
|
||||
const cwd2 = process.cwd();
|
||||
return PYTHON_CONFIGS.some((config3) => existsSync5(join9(cwd2, config3.file)));
|
||||
return PYTHON_CONFIGS.some((config3) => existsSync5(join10(cwd2, config3.file)));
|
||||
},
|
||||
run: async () => {
|
||||
const cwd2 = process.cwd();
|
||||
const config3 = PYTHON_CONFIGS.find((c) => existsSync5(join9(cwd2, c.file)));
|
||||
const config3 = PYTHON_CONFIGS.find((c) => existsSync5(join10(cwd2, c.file)));
|
||||
if (!config3) {
|
||||
return {
|
||||
language: "python",
|
||||
@@ -125463,6 +125604,12 @@ function setupGitConfig() {
|
||||
cwd: repoDir,
|
||||
stdio: "pipe"
|
||||
});
|
||||
if (!process.env.GITHUB_ACTIONS) {
|
||||
execSync2('git config --local credential.helper ""', {
|
||||
cwd: repoDir,
|
||||
stdio: "pipe"
|
||||
});
|
||||
}
|
||||
log.debug("setupGitConfig: \u2713 Git configuration set successfully (scoped to repo)");
|
||||
} catch (error42) {
|
||||
log.warning(
|
||||
@@ -125522,6 +125669,7 @@ async function main(inputs) {
|
||||
payload = parsePayload(inputs);
|
||||
const partialCtx = await initializeContext(inputs, payload);
|
||||
const ctx = partialCtx;
|
||||
ctx.toolState = {};
|
||||
timer.checkpoint("initializeContext");
|
||||
await setupGit(ctx);
|
||||
timer.checkpoint("setupGit");
|
||||
@@ -125707,7 +125855,7 @@ function resolveAgent({
|
||||
return { agentName, agent: agent2 };
|
||||
}
|
||||
async function setupTempDirectory(ctx) {
|
||||
ctx.sharedTempDir = await mkdtemp2(join10(tmpdir2(), "pullfrog-"));
|
||||
ctx.sharedTempDir = await mkdtemp2(join11(tmpdir2(), "pullfrog-"));
|
||||
process.env.PULLFROG_TEMP_DIR = ctx.sharedTempDir;
|
||||
log.info(`\u{1F4C2} PULLFROG_TEMP_DIR has been created at ${ctx.sharedTempDir}`);
|
||||
}
|
||||
@@ -125731,18 +125879,17 @@ function parsePayload(inputs) {
|
||||
}
|
||||
}
|
||||
async function startMcpServer(ctx) {
|
||||
const runId = process.env.GITHUB_RUN_ID;
|
||||
if (!runId) {
|
||||
throw new Error("GITHUB_RUN_ID environment variable is required");
|
||||
}
|
||||
const runId = process.env.GITHUB_RUN_ID || "";
|
||||
ctx.runId = runId;
|
||||
if (runId) {
|
||||
const workflowRunInfo = await fetchWorkflowRunInfo(ctx.runId);
|
||||
if (workflowRunInfo.progressCommentId) {
|
||||
process.env.PULLFROG_PROGRESS_COMMENT_ID = workflowRunInfo.progressCommentId;
|
||||
log.info(`\u{1F4DD} Using pre-created progress comment: ${workflowRunInfo.progressCommentId}`);
|
||||
}
|
||||
}
|
||||
const jobName = process.env.GITHUB_JOB;
|
||||
if (jobName) {
|
||||
if (jobName && runId) {
|
||||
const jobs = await ctx.octokit.rest.actions.listJobsForWorkflowRun({
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
|
||||
Reference in New Issue
Block a user