Clean up url resolution

This commit is contained in:
Colin McDonnell
2026-02-13 14:24:46 +00:00
committed by pullfrog[bot]
parent 267a4586ae
commit 78cf05f111
13 changed files with 211 additions and 146 deletions
+133 -113
View File
@@ -17639,12 +17639,12 @@ var require_lib = __commonJS({
throw new Error("Client has already been disposed.");
}
const parsedUrl = new URL(requestUrl);
let info2 = this._prepareRequest(verb, parsedUrl, headers);
let info3 = this._prepareRequest(verb, parsedUrl, headers);
const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1;
let numTries = 0;
let response;
do {
response = yield this.requestRaw(info2, data);
response = yield this.requestRaw(info3, data);
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
let authenticationHandler;
for (const handler2 of this.handlers) {
@@ -17654,7 +17654,7 @@ var require_lib = __commonJS({
}
}
if (authenticationHandler) {
return authenticationHandler.handleAuthentication(this, info2, data);
return authenticationHandler.handleAuthentication(this, info3, data);
} else {
return response;
}
@@ -17677,8 +17677,8 @@ var require_lib = __commonJS({
}
}
}
info2 = this._prepareRequest(verb, parsedRedirectUrl, headers);
response = yield this.requestRaw(info2, data);
info3 = this._prepareRequest(verb, parsedRedirectUrl, headers);
response = yield this.requestRaw(info3, data);
redirectsRemaining--;
}
if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) {
@@ -17707,7 +17707,7 @@ var require_lib = __commonJS({
* @param info
* @param data
*/
requestRaw(info2, data) {
requestRaw(info3, data) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve3, reject) => {
function callbackForResult(err, res) {
@@ -17719,7 +17719,7 @@ var require_lib = __commonJS({
resolve3(res);
}
}
this.requestRawWithCallback(info2, data, callbackForResult);
this.requestRawWithCallback(info3, data, callbackForResult);
});
});
}
@@ -17729,12 +17729,12 @@ var require_lib = __commonJS({
* @param data
* @param onResult
*/
requestRawWithCallback(info2, data, onResult) {
requestRawWithCallback(info3, data, onResult) {
if (typeof data === "string") {
if (!info2.options.headers) {
info2.options.headers = {};
if (!info3.options.headers) {
info3.options.headers = {};
}
info2.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
info3.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
}
let callbackCalled = false;
function handleResult2(err, res) {
@@ -17743,7 +17743,7 @@ var require_lib = __commonJS({
onResult(err, res);
}
}
const req = info2.httpModule.request(info2.options, (msg) => {
const req = info3.httpModule.request(info3.options, (msg) => {
const res = new HttpClientResponse(msg);
handleResult2(void 0, res);
});
@@ -17755,7 +17755,7 @@ var require_lib = __commonJS({
if (socket) {
socket.end();
}
handleResult2(new Error(`Request timeout: ${info2.options.path}`));
handleResult2(new Error(`Request timeout: ${info3.options.path}`));
});
req.on("error", function(err) {
handleResult2(err);
@@ -17791,27 +17791,27 @@ var require_lib = __commonJS({
return this._getProxyAgentDispatcher(parsedUrl, proxyUrl);
}
_prepareRequest(method, requestUrl, headers) {
const info2 = {};
info2.parsedUrl = requestUrl;
const usingSsl = info2.parsedUrl.protocol === "https:";
info2.httpModule = usingSsl ? https : http2;
const info3 = {};
info3.parsedUrl = requestUrl;
const usingSsl = info3.parsedUrl.protocol === "https:";
info3.httpModule = usingSsl ? https : http2;
const defaultPort = usingSsl ? 443 : 80;
info2.options = {};
info2.options.host = info2.parsedUrl.hostname;
info2.options.port = info2.parsedUrl.port ? parseInt(info2.parsedUrl.port) : defaultPort;
info2.options.path = (info2.parsedUrl.pathname || "") + (info2.parsedUrl.search || "");
info2.options.method = method;
info2.options.headers = this._mergeHeaders(headers);
info3.options = {};
info3.options.host = info3.parsedUrl.hostname;
info3.options.port = info3.parsedUrl.port ? parseInt(info3.parsedUrl.port) : defaultPort;
info3.options.path = (info3.parsedUrl.pathname || "") + (info3.parsedUrl.search || "");
info3.options.method = method;
info3.options.headers = this._mergeHeaders(headers);
if (this.userAgent != null) {
info2.options.headers["user-agent"] = this.userAgent;
info3.options.headers["user-agent"] = this.userAgent;
}
info2.options.agent = this._getAgent(info2.parsedUrl);
info3.options.agent = this._getAgent(info3.parsedUrl);
if (this.handlers) {
for (const handler2 of this.handlers) {
handler2.prepareRequest(info2.options);
handler2.prepareRequest(info3.options);
}
}
return info2;
return info3;
}
_mergeHeaders(headers) {
if (this.requestOptions && this.requestOptions.headers) {
@@ -19781,10 +19781,10 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
error49(message);
}
exports.setFailed = setFailed2;
function isDebug2() {
function isDebug3() {
return process.env["RUNNER_DEBUG"] === "1";
}
exports.isDebug = isDebug2;
exports.isDebug = isDebug3;
function debug2(message) {
(0, command_1.issueCommand)("debug", {}, message);
}
@@ -19801,10 +19801,10 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
(0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
}
exports.notice = notice;
function info2(message) {
function info3(message) {
process.stdout.write(message + os.EOL);
}
exports.info = info2;
exports.info = info3;
function startGroup3(name) {
(0, command_1.issue)("group", name);
}
@@ -39014,8 +39014,8 @@ var require_dataType = __commonJS({
return types;
}
exports.getSchemaTypes = getSchemaTypes;
function getJSONTypes(ts) {
const types = Array.isArray(ts) ? ts : ts ? [ts] : [];
function getJSONTypes(ts2) {
const types = Array.isArray(ts2) ? ts2 : ts2 ? [ts2] : [];
if (types.every(rules_1.isJSONType))
return types;
throw new Error("type must be JSONType or JSONType[]: " + types.join(","));
@@ -40057,18 +40057,18 @@ var require_validate = __commonJS({
});
narrowSchemaTypes(it, types);
}
function checkMultipleTypes(it, ts) {
if (ts.length > 1 && !(ts.length === 2 && ts.includes("null"))) {
function checkMultipleTypes(it, ts2) {
if (ts2.length > 1 && !(ts2.length === 2 && ts2.includes("null"))) {
strictTypesError(it, "use allowUnionTypes to allow union type keyword");
}
}
function checkKeywordTypes(it, ts) {
function checkKeywordTypes(it, ts2) {
const rules = it.self.RULES.all;
for (const keyword in rules) {
const rule = rules[keyword];
if (typeof rule == "object" && (0, applicability_1.shouldUseRule)(it.schema, rule)) {
const { type: type2 } = rule.definition;
if (type2.length && !type2.some((t) => hasApplicableType(ts, t))) {
if (type2.length && !type2.some((t) => hasApplicableType(ts2, t))) {
strictTypesError(it, `missing type "${type2.join(",")}" for keyword "${keyword}"`);
}
}
@@ -40077,18 +40077,18 @@ var require_validate = __commonJS({
function hasApplicableType(schTs, kwdT) {
return schTs.includes(kwdT) || kwdT === "number" && schTs.includes("integer");
}
function includesType(ts, t) {
return ts.includes(t) || t === "integer" && ts.includes("number");
function includesType(ts2, t) {
return ts2.includes(t) || t === "integer" && ts2.includes("number");
}
function narrowSchemaTypes(it, withTypes) {
const ts = [];
const ts2 = [];
for (const t of it.dataTypes) {
if (includesType(withTypes, t))
ts.push(t);
ts2.push(t);
else if (withTypes.includes("integer") && t === "number")
ts.push("integer");
ts2.push("integer");
}
it.dataTypes = ts;
it.dataTypes = ts2;
}
function strictTypesError(it, msg) {
const schemaPath = it.schemaEnv.baseId + it.errSchemaPath;
@@ -42088,7 +42088,7 @@ var require_core3 = __commonJS({
Object.defineProperty(exports, "__esModule", { value: true });
var id_1 = require_id();
var ref_1 = require_ref();
var core6 = [
var core7 = [
"$schema",
"$id",
"$defs",
@@ -42098,7 +42098,7 @@ var require_core3 = __commonJS({
id_1.default,
ref_1.default
];
exports.default = core6;
exports.default = core7;
}
});
@@ -45876,7 +45876,7 @@ var require_diagnostics = __commonJS({
pong: diagnosticsChannel.channel("undici:websocket:pong")
};
var isTrackingClientEvents = false;
function trackClientEvents(debugLog = undiciDebugLog) {
function trackClientEvents(debugLog2 = undiciDebugLog) {
if (isTrackingClientEvents) {
return;
}
@@ -45887,7 +45887,7 @@ var require_diagnostics = __commonJS({
const {
connectParams: { version: version3, protocol, port, host }
} = evt;
debugLog(
debugLog2(
"connecting to %s%s using %s%s",
host,
port ? `:${port}` : "",
@@ -45902,7 +45902,7 @@ var require_diagnostics = __commonJS({
const {
connectParams: { version: version3, protocol, port, host }
} = evt;
debugLog(
debugLog2(
"connected to %s%s using %s%s",
host,
port ? `:${port}` : "",
@@ -45918,7 +45918,7 @@ var require_diagnostics = __commonJS({
connectParams: { version: version3, protocol, port, host },
error: error49
} = evt;
debugLog(
debugLog2(
"connection to %s%s using %s%s errored - %s",
host,
port ? `:${port}` : "",
@@ -45934,12 +45934,12 @@ var require_diagnostics = __commonJS({
const {
request: { method, path: path3, origin }
} = evt;
debugLog("sending request to %s %s%s", method, origin, path3);
debugLog2("sending request to %s %s%s", method, origin, path3);
}
);
}
var isTrackingRequestEvents = false;
function trackRequestEvents(debugLog = undiciDebugLog) {
function trackRequestEvents(debugLog2 = undiciDebugLog) {
if (isTrackingRequestEvents) {
return;
}
@@ -45951,7 +45951,7 @@ var require_diagnostics = __commonJS({
request: { method, path: path3, origin },
response: { statusCode }
} = evt;
debugLog(
debugLog2(
"received response to %s %s%s - HTTP %d",
method,
origin,
@@ -45966,7 +45966,7 @@ var require_diagnostics = __commonJS({
const {
request: { method, path: path3, origin }
} = evt;
debugLog("trailers received from %s %s%s", method, origin, path3);
debugLog2("trailers received from %s %s%s", method, origin, path3);
}
);
diagnosticsChannel.subscribe(
@@ -45976,7 +45976,7 @@ var require_diagnostics = __commonJS({
request: { method, path: path3, origin },
error: error49
} = evt;
debugLog(
debugLog2(
"request to %s %s%s errored - %s",
method,
origin,
@@ -45987,7 +45987,7 @@ var require_diagnostics = __commonJS({
);
}
var isTrackingWebSocketEvents = false;
function trackWebSocketEvents(debugLog = websocketDebuglog) {
function trackWebSocketEvents(debugLog2 = websocketDebuglog) {
if (isTrackingWebSocketEvents) {
return;
}
@@ -45998,14 +45998,14 @@ var require_diagnostics = __commonJS({
const {
address: { address, port }
} = evt;
debugLog("connection opened %s%s", address, port ? `:${port}` : "");
debugLog2("connection opened %s%s", address, port ? `:${port}` : "");
}
);
diagnosticsChannel.subscribe(
"undici:websocket:close",
(evt) => {
const { websocket, code, reason } = evt;
debugLog(
debugLog2(
"closed connection to %s - %s %s",
websocket.url,
code,
@@ -46016,19 +46016,19 @@ var require_diagnostics = __commonJS({
diagnosticsChannel.subscribe(
"undici:websocket:socket_error",
(err) => {
debugLog("connection errored - %s", err.message);
debugLog2("connection errored - %s", err.message);
}
);
diagnosticsChannel.subscribe(
"undici:websocket:ping",
(evt) => {
debugLog("ping received");
debugLog2("ping received");
}
);
diagnosticsChannel.subscribe(
"undici:websocket:pong",
(evt) => {
debugLog("pong received");
debugLog2("pong received");
}
);
}
@@ -97611,7 +97611,7 @@ var require_semver2 = __commonJS({
});
// entry.ts
var core5 = __toESM(require_core(), 1);
var core6 = __toESM(require_core(), 1);
// node_modules/.pnpm/@ark+util@0.56.0/node_modules/@ark/util/out/arrays.js
var liftArray = (data) => Array.isArray(data) ? data : [data];
@@ -102706,25 +102706,25 @@ var Protocol = class {
});
}
_resetTimeout(messageId) {
const info2 = this._timeoutInfo.get(messageId);
if (!info2)
const info3 = this._timeoutInfo.get(messageId);
if (!info3)
return false;
const totalElapsed = Date.now() - info2.startTime;
if (info2.maxTotalTimeout && totalElapsed >= info2.maxTotalTimeout) {
const totalElapsed = Date.now() - info3.startTime;
if (info3.maxTotalTimeout && totalElapsed >= info3.maxTotalTimeout) {
this._timeoutInfo.delete(messageId);
throw McpError.fromError(ErrorCode.RequestTimeout, "Maximum total timeout exceeded", {
maxTotalTimeout: info2.maxTotalTimeout,
maxTotalTimeout: info3.maxTotalTimeout,
totalElapsed
});
}
clearTimeout(info2.timeoutId);
info2.timeoutId = setTimeout(info2.onTimeout, info2.timeout);
clearTimeout(info3.timeoutId);
info3.timeoutId = setTimeout(info3.onTimeout, info3.timeout);
return true;
}
_cleanupTimeout(messageId) {
const info2 = this._timeoutInfo.get(messageId);
if (info2) {
clearTimeout(info2.timeoutId);
const info3 = this._timeoutInfo.get(messageId);
if (info3) {
clearTimeout(info3.timeoutId);
this._timeoutInfo.delete(messageId);
}
}
@@ -121377,8 +121377,8 @@ var require_dataType2 = /* @__PURE__ */ __commonJSMin(((exports) => {
return types;
}
exports.getSchemaTypes = getSchemaTypes;
function getJSONTypes(ts) {
const types = Array.isArray(ts) ? ts : ts ? [ts] : [];
function getJSONTypes(ts2) {
const types = Array.isArray(ts2) ? ts2 : ts2 ? [ts2] : [];
if (types.every(rules_1$1.isJSONType)) return types;
throw new Error("type must be JSONType or JSONType[]: " + types.join(","));
}
@@ -122256,30 +122256,30 @@ var require_validate2 = /* @__PURE__ */ __commonJSMin(((exports) => {
});
narrowSchemaTypes(it, types);
}
function checkMultipleTypes(it, ts) {
if (ts.length > 1 && !(ts.length === 2 && ts.includes("null"))) strictTypesError(it, "use allowUnionTypes to allow union type keyword");
function checkMultipleTypes(it, ts2) {
if (ts2.length > 1 && !(ts2.length === 2 && ts2.includes("null"))) strictTypesError(it, "use allowUnionTypes to allow union type keyword");
}
function checkKeywordTypes(it, ts) {
function checkKeywordTypes(it, ts2) {
const rules = it.self.RULES.all;
for (const keyword in rules) {
const rule = rules[keyword];
if (typeof rule == "object" && (0, applicability_1.shouldUseRule)(it.schema, rule)) {
const { type: type2 } = rule.definition;
if (type2.length && !type2.some((t) => hasApplicableType(ts, t))) strictTypesError(it, `missing type "${type2.join(",")}" for keyword "${keyword}"`);
if (type2.length && !type2.some((t) => hasApplicableType(ts2, t))) strictTypesError(it, `missing type "${type2.join(",")}" for keyword "${keyword}"`);
}
}
}
function hasApplicableType(schTs, kwdT) {
return schTs.includes(kwdT) || kwdT === "number" && schTs.includes("integer");
}
function includesType(ts, t) {
return ts.includes(t) || t === "integer" && ts.includes("number");
function includesType(ts2, t) {
return ts2.includes(t) || t === "integer" && ts2.includes("number");
}
function narrowSchemaTypes(it, withTypes) {
const ts = [];
for (const t of it.dataTypes) if (includesType(withTypes, t)) ts.push(t);
else if (withTypes.includes("integer") && t === "number") ts.push("integer");
it.dataTypes = ts;
const ts2 = [];
for (const t of it.dataTypes) if (includesType(withTypes, t)) ts2.push(t);
else if (withTypes.includes("integer") && t === "number") ts2.push("integer");
it.dataTypes = ts2;
}
function strictTypesError(it, msg) {
const schemaPath = it.schemaEnv.baseId + it.errSchemaPath;
@@ -123968,7 +123968,7 @@ var require_core4 = /* @__PURE__ */ __commonJSMin(((exports) => {
Object.defineProperty(exports, "__esModule", { value: true });
const id_1 = require_id2();
const ref_1 = require_ref2();
const core6 = [
const core7 = [
"$schema",
"$id",
"$defs",
@@ -123978,7 +123978,7 @@ var require_core4 = /* @__PURE__ */ __commonJSMin(((exports) => {
id_1.default,
ref_1.default
];
exports.default = core6;
exports.default = core7;
}));
var require_limitNumber2 = /* @__PURE__ */ __commonJSMin(((exports) => {
Object.defineProperty(exports, "__esModule", { value: true });
@@ -135713,27 +135713,30 @@ function separator(length = 50) {
const separatorText = "\u2500".repeat(length);
core.info(separatorText);
}
function ts() {
return isDebugEnabled() ? `[${(/* @__PURE__ */ new Date()).toISOString()}] ` : "";
}
var log = {
/** Print info message */
info: (...args2) => {
core.info(formatArgs(args2));
core.info(`${ts()}${formatArgs(args2)}`);
},
/** Print warning message */
warning: (...args2) => {
core.warning(formatArgs(args2));
core.warning(`${ts()}${formatArgs(args2)}`);
},
/** Print error message */
error: (...args2) => {
core.error(formatArgs(args2));
core.error(`${ts()}${formatArgs(args2)}`);
},
/** Print success message */
success: (...args2) => {
core.info(`\xBB ${formatArgs(args2)}`);
core.info(`${ts()}\xBB ${formatArgs(args2)}`);
},
/** Print debug message (only if LOG_LEVEL=debug) */
debug: (...args2) => {
if (isDebugEnabled()) {
core.info(`[DEBUG] ${formatArgs(args2)}`);
core.info(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] ${formatArgs(args2)}`);
}
},
/** Print a formatted box with text */
@@ -135751,8 +135754,7 @@ var log = {
/** Log tool call information to console with formatted output */
toolCall: ({ toolName, input }) => {
const inputFormatted = formatJsonValue(input);
const timestamp = isDebugEnabled() ? ` [${(/* @__PURE__ */ new Date()).toISOString()}]` : "";
const output = inputFormatted !== "{}" ? `\xBB ${toolName}(${inputFormatted})${timestamp}` : `\xBB ${toolName}()${timestamp}`;
const output = inputFormatted !== "{}" ? `\xBB ${toolName}(${inputFormatted})` : `\xBB ${toolName}()`;
log.info(output.trimEnd());
}
};
@@ -135935,8 +135937,8 @@ function throttling(octokit, octokitOptions) {
"error",
(e) => octokit.log.warn("Error in throttling-plugin limit handler", e)
);
state.retryLimiter.on("failed", async function(error49, info2) {
const [state2, request2, options] = info2.args;
state.retryLimiter.on("failed", async function(error49, info3) {
const [state2, request2, options] = info3.args;
const { pathname } = new URL(options.url, "http://github.test");
const shouldRetryGraphQL = pathname.startsWith("/graphql") && error49.status !== 401;
if (!(shouldRetryGraphQL || error49.status === 403 || error49.status === 429)) {
@@ -139414,6 +139416,11 @@ var Octokit2 = Octokit.plugin(requestLog, legacyRestEndpointMethods, paginateRes
}
);
// utils/apiUrl.ts
function getApiUrl() {
return process.env.API_URL || "https://pullfrog.com";
}
// utils/retry.ts
var defaultShouldRetry = (error49) => {
if (!(error49 instanceof Error)) return false;
@@ -139451,7 +139458,7 @@ function isOIDCAvailable() {
}
async function acquireTokenViaOIDC(opts) {
const oidcToken = await core2.getIDToken("pullfrog-api");
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const params = new URLSearchParams();
const repos = [...opts?.repos ?? []];
const targetRepo = process.env.GITHUB_REPOSITORY?.split("/")[1];
@@ -140536,9 +140543,16 @@ import { spawn as nodeSpawn } from "node:child_process";
import { performance as performance3 } from "node:perf_hooks";
// utils/activity.ts
var core4 = __toESM(require_core(), 1);
import { performance as performance2 } from "node:perf_hooks";
var DEFAULT_ACTIVITY_TIMEOUT_MS = 6e4;
var DEFAULT_ACTIVITY_CHECK_INTERVAL_MS = 5e3;
function debugLog(msg) {
const isDebug3 = process.env.LOG_LEVEL === "debug" || process.env.ACTIONS_STEP_DEBUG === "true" || process.env.RUNNER_DEBUG === "1" || core4.isDebug();
if (isDebug3) {
core4.info(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] ${msg}`);
}
}
var _lastActivity = performance2.now();
function markActivity() {
_lastActivity = performance2.now();
@@ -140562,8 +140576,10 @@ function startProcessOutputMonitor(ctx) {
const originalStderrWrite = process.stderr.write.bind(process.stderr);
process.stdout.write = wrapWrite(originalStdoutWrite, markActivity);
process.stderr.write = wrapWrite(originalStderrWrite, markActivity);
debugLog(`process activity monitor started: timeout=${ctx.timeoutMs}ms`);
const intervalId = setInterval(() => {
const idleMs = getIdleMs();
debugLog(`process activity check: idle=${idleMs}ms / ${ctx.timeoutMs}ms`);
if (timedOut || idleMs <= ctx.timeoutMs) return;
timedOut = true;
ctx.onTimeout(idleMs);
@@ -140681,12 +140697,16 @@ async function spawn2(options) {
}, timeout);
}
if (activityTimeoutMs > 0) {
log.debug(`spawn activity timer: pid=${child.pid} cmd=${cmd} timeout=${activityTimeoutMs}ms`);
activityCheckIntervalId = setInterval(() => {
const idleMs = performance3.now() - lastActivityTime;
log.debug(
`spawn activity check: pid=${child.pid} idle=${Math.round(idleMs)}ms / ${activityTimeoutMs}ms`
);
if (idleMs > activityTimeoutMs) {
isActivityTimedOut = true;
const idleSec = Math.round(idleMs / 1e3);
log.error(`no output for ${idleSec}s, killing process`);
log.error(`no output for ${idleSec}s from pid=${child.pid} (${cmd}), killing process`);
child.kill("SIGKILL");
clearInterval(activityCheckIntervalId);
}
@@ -141283,7 +141303,7 @@ async function buildCommentFooter({
return buildPullfrogFooter(footerParams);
}
function buildImplementPlanLink(owner, repo, issueNumber, commentId) {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
return `[Implement plan \u2794](${apiUrl}/trigger/${owner}/${repo}/${issueNumber}?action=implement&comment_id=${commentId})`;
}
async function addFooter(ctx, body) {
@@ -143507,7 +143527,7 @@ function CreatePullRequestReviewTool(ctx) {
const reviewId = result.data.id;
const customParts = [];
if (comments.length > 0) {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const fixAllUrl = `${apiUrl}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${pull_number}?action=fix&review_id=${reviewId}`;
const fixApprovedUrl = `${apiUrl}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${pull_number}?action=fix-approved&review_id=${reviewId}`;
customParts.push(`[Fix all \u2794](${fixAllUrl})`, `[Fix \u{1F44D}s \u2794](${fixApprovedUrl})`);
@@ -143987,7 +144007,7 @@ function UploadFileTool(ctx) {
const contentLength = buffer.length;
const fileType = await fileTypeFromBuffer(buffer);
const contentType = fileType?.mime || "application/octet-stream";
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const response = await fetch(`${apiUrl}/api/upload/signed-url`, {
method: "POST",
headers: {
@@ -146236,7 +146256,7 @@ function resolveAgent(params) {
// utils/apiKeys.ts
function buildMissingApiKeyError(params) {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const settingsUrl = `${apiUrl}/console/${params.owner}/${params.name}`;
const githubRepoUrl = `https://github.com/${params.owner}/${params.name}`;
const githubSecretsUrl = `${githubRepoUrl}/settings/secrets/actions`;
@@ -146532,7 +146552,7 @@ function normalizeEnv() {
}
// utils/payload.ts
var core4 = __toESM(require_core(), 1);
var core5 = __toESM(require_core(), 1);
import { isAbsolute, resolve as resolve2 } from "node:path";
// utils/versioning.ts
@@ -146599,7 +146619,7 @@ function resolveCwd(cwd) {
return workspace ? resolve2(workspace, cwd) : cwd;
}
function resolvePromptInput() {
const prompt = core4.getInput("prompt", { required: true });
const prompt = core5.getInput("prompt", { required: true });
let parsed2;
try {
parsed2 = JSON.parse(prompt);
@@ -146615,14 +146635,14 @@ function resolvePromptInput() {
}
function resolveNonPromptInputs() {
return Inputs.omit("prompt").assert({
effort: core4.getInput("effort") || void 0,
timeout: core4.getInput("timeout") || void 0,
agent: core4.getInput("agent") || void 0,
cwd: core4.getInput("cwd") || void 0,
web: core4.getInput("web") || void 0,
search: core4.getInput("search") || void 0,
push: core4.getInput("push") || void 0,
bash: core4.getInput("bash") || void 0
effort: core5.getInput("effort") || void 0,
timeout: core5.getInput("timeout") || void 0,
agent: core5.getInput("agent") || void 0,
cwd: core5.getInput("cwd") || void 0,
web: core5.getInput("web") || void 0,
search: core5.getInput("search") || void 0,
push: core5.getInput("push") || void 0,
bash: core5.getInput("bash") || void 0
});
}
function resolvePayload(resolvedPromptInput, repoSettings) {
@@ -146698,7 +146718,7 @@ var defaultRunContext = {
apiToken: ""
};
async function fetchRunContext(params) {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const timeoutMs = 3e4;
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
@@ -147065,11 +147085,11 @@ async function run() {
throw new Error(result.error || "Agent execution failed");
}
if (result.result) {
core5.setOutput("result", result.result);
core6.setOutput("result", result.result);
}
} catch (error49) {
const errorMessage = error49 instanceof Error ? error49.message : "Unknown error occurred";
core5.setFailed(`Action failed: ${errorMessage}`);
core6.setFailed(`Action failed: ${errorMessage}`);
} finally {
await runCleanup();
}
+15 -8
View File
@@ -25626,27 +25626,30 @@ function separator(length = 50) {
const separatorText = "\u2500".repeat(length);
core.info(separatorText);
}
function ts() {
return isDebugEnabled() ? `[${(/* @__PURE__ */ new Date()).toISOString()}] ` : "";
}
var log = {
/** Print info message */
info: (...args) => {
core.info(formatArgs(args));
core.info(`${ts()}${formatArgs(args)}`);
},
/** Print warning message */
warning: (...args) => {
core.warning(formatArgs(args));
core.warning(`${ts()}${formatArgs(args)}`);
},
/** Print error message */
error: (...args) => {
core.error(formatArgs(args));
core.error(`${ts()}${formatArgs(args)}`);
},
/** Print success message */
success: (...args) => {
core.info(`\xBB ${formatArgs(args)}`);
core.info(`${ts()}\xBB ${formatArgs(args)}`);
},
/** Print debug message (only if LOG_LEVEL=debug) */
debug: (...args) => {
if (isDebugEnabled()) {
core.info(`[DEBUG] ${formatArgs(args)}`);
core.info(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] ${formatArgs(args)}`);
}
},
/** Print a formatted box with text */
@@ -25664,8 +25667,7 @@ var log = {
/** Log tool call information to console with formatted output */
toolCall: ({ toolName, input }) => {
const inputFormatted = formatJsonValue(input);
const timestamp = isDebugEnabled() ? ` [${(/* @__PURE__ */ new Date()).toISOString()}]` : "";
const output = inputFormatted !== "{}" ? `\xBB ${toolName}(${inputFormatted})${timestamp}` : `\xBB ${toolName}()${timestamp}`;
const output = inputFormatted !== "{}" ? `\xBB ${toolName}(${inputFormatted})` : `\xBB ${toolName}()`;
log.info(output.trimEnd());
}
};
@@ -25678,6 +25680,11 @@ function formatJsonValue(value) {
var core2 = __toESM(require_core(), 1);
import { createSign } from "node:crypto";
// utils/apiUrl.ts
function getApiUrl() {
return process.env.API_URL || "https://pullfrog.com";
}
// utils/retry.ts
var defaultShouldRetry = (error2) => {
if (!(error2 instanceof Error)) return false;
@@ -25715,7 +25722,7 @@ function isOIDCAvailable() {
}
async function acquireTokenViaOIDC(opts) {
const oidcToken = await core2.getIDToken("pullfrog-api");
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const params = new URLSearchParams();
const repos = [...opts?.repos ?? []];
const targetRepo = process.env.GITHUB_REPOSITORY?.split("/")[1];
+2 -1
View File
@@ -1,5 +1,6 @@
import { type } from "arktype";
import type { Agent } from "../agents/index.ts";
import { getApiUrl } from "../utils/apiUrl.ts";
import { buildPullfrogFooter, stripExistingFooter } from "../utils/buildPullfrogFooter.ts";
import { type OctokitWithPlugins, parseRepoContext } from "../utils/github.ts";
import type { ToolContext } from "./server.ts";
@@ -65,7 +66,7 @@ function buildImplementPlanLink(
issueNumber: number,
commentId: number
): string {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
return `[Implement plan ➔](${apiUrl}/trigger/${owner}/${repo}/${issueNumber}?action=implement&comment_id=${commentId})`;
}
+3 -2
View File
@@ -1,5 +1,6 @@
import type { RestEndpointMethodTypes } from "@octokit/rest";
import { type } from "arktype";
import { getApiUrl } from "../utils/apiUrl.ts";
import { buildPullfrogFooter } from "../utils/buildPullfrogFooter.ts";
import { log } from "../utils/cli.ts";
import { deleteProgressComment } from "./comment.ts";
@@ -115,7 +116,7 @@ export function CreatePullRequestReviewTool(ctx: ToolContext) {
// only include "Fix all" and "Fix 👍s" links if there are actual review comments
const customParts: string[] = [];
if (comments.length > 0) {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const fixAllUrl = `${apiUrl}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${pull_number}?action=fix&review_id=${reviewId}`;
const fixApprovedUrl = `${apiUrl}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${pull_number}?action=fix-approved&review_id=${reviewId}`;
customParts.push(`[Fix all ➔](${fixAllUrl})`, `[Fix 👍s ➔](${fixApprovedUrl})`);
@@ -410,7 +411,7 @@ export function SubmitReviewTool(ctx: ToolContext) {
);
// build quick links footer
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const fixAllUrl = `${apiUrl}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${ctx.toolState.issueNumber}?action=fix&review_id=${reviewId}`;
const fixApprovedUrl = `${apiUrl}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${ctx.toolState.issueNumber}?action=fix-approved&review_id=${reviewId}`;
+2 -1
View File
@@ -2,6 +2,7 @@ import * as fs from "node:fs";
import * as path from "node:path";
import { type } from "arktype";
import { fileTypeFromBuffer } from "file-type";
import { getApiUrl } from "../utils/apiUrl.ts";
import type { ToolContext } from "./server.ts";
import { execute, tool } from "./shared.ts";
@@ -24,7 +25,7 @@ export function UploadFileTool(ctx: ToolContext) {
const fileType = await fileTypeFromBuffer(buffer);
const contentType = fileType?.mime || "application/octet-stream";
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const response = await fetch(`${apiUrl}/api/upload/signed-url`, {
method: "POST",
+9 -7
View File
@@ -41094,27 +41094,30 @@ function separator(length = 50) {
const separatorText = "\u2500".repeat(length);
core.info(separatorText);
}
function ts() {
return isDebugEnabled() ? `[${(/* @__PURE__ */ new Date()).toISOString()}] ` : "";
}
var log = {
/** Print info message */
info: (...args2) => {
core.info(formatArgs(args2));
core.info(`${ts()}${formatArgs(args2)}`);
},
/** Print warning message */
warning: (...args2) => {
core.warning(formatArgs(args2));
core.warning(`${ts()}${formatArgs(args2)}`);
},
/** Print error message */
error: (...args2) => {
core.error(formatArgs(args2));
core.error(`${ts()}${formatArgs(args2)}`);
},
/** Print success message */
success: (...args2) => {
core.info(`\xBB ${formatArgs(args2)}`);
core.info(`${ts()}\xBB ${formatArgs(args2)}`);
},
/** Print debug message (only if LOG_LEVEL=debug) */
debug: (...args2) => {
if (isDebugEnabled()) {
core.info(`[DEBUG] ${formatArgs(args2)}`);
core.info(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] ${formatArgs(args2)}`);
}
},
/** Print a formatted box with text */
@@ -41132,8 +41135,7 @@ var log = {
/** Log tool call information to console with formatted output */
toolCall: ({ toolName, input }) => {
const inputFormatted = formatJsonValue(input);
const timestamp = isDebugEnabled() ? ` [${(/* @__PURE__ */ new Date()).toISOString()}]` : "";
const output = inputFormatted !== "{}" ? `\xBB ${toolName}(${inputFormatted})${timestamp}` : `\xBB ${toolName}()${timestamp}`;
const output = inputFormatted !== "{}" ? `\xBB ${toolName}(${inputFormatted})` : `\xBB ${toolName}()`;
log.info(output.trimEnd());
}
};
+16
View File
@@ -1,8 +1,21 @@
import { performance } from "node:perf_hooks";
import * as core from "@actions/core";
export const DEFAULT_ACTIVITY_TIMEOUT_MS = 60_000;
export const DEFAULT_ACTIVITY_CHECK_INTERVAL_MS = 5_000;
// inline debug check — can't import log.ts since activity.ts is a dependency of it
function debugLog(msg: string): void {
const isDebug =
process.env.LOG_LEVEL === "debug" ||
process.env.ACTIONS_STEP_DEBUG === "true" ||
process.env.RUNNER_DEBUG === "1" ||
core.isDebug();
if (isDebug) {
core.info(`[${new Date().toISOString()}] [DEBUG] ${msg}`);
}
}
type ActivityTimeoutContext = {
timeoutMs: number;
checkIntervalMs: number;
@@ -72,8 +85,11 @@ function startProcessOutputMonitor(ctx: OutputMonitorContext): OutputMonitor {
process.stdout.write = wrapWrite(originalStdoutWrite, markActivity);
process.stderr.write = wrapWrite(originalStderrWrite, markActivity);
debugLog(`process activity monitor started: timeout=${ctx.timeoutMs}ms`);
const intervalId = setInterval(() => {
const idleMs = getIdleMs();
debugLog(`process activity check: idle=${idleMs}ms / ${ctx.timeoutMs}ms`);
if (timedOut || idleMs <= ctx.timeoutMs) return;
timedOut = true;
ctx.onTimeout(idleMs);
+2 -1
View File
@@ -1,10 +1,11 @@
import type { Agent } from "../agents/index.ts";
import { getApiUrl } from "./apiUrl.ts";
/**
* Build a helpful error message for missing API key with links to repo settings
*/
function buildMissingApiKeyError(params: { agent: Agent; owner: string; name: string }): string {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const settingsUrl = `${apiUrl}/console/${params.owner}/${params.name}`;
const githubRepoUrl = `https://github.com/${params.owner}/${params.name}`;
+9
View File
@@ -0,0 +1,9 @@
/**
* resolve the Pullfrog API base URL.
*
* in the action: API_URL is not explicitly set, so this falls back to https://pullfrog.com.
* in local dev: API_URL=http://localhost:3000 (from .env).
*/
export function getApiUrl(): string {
return process.env.API_URL || "https://pullfrog.com";
}
+2 -1
View File
@@ -2,6 +2,7 @@ import { createSign } from "node:crypto";
import * as core from "@actions/core";
import { throttling } from "@octokit/plugin-throttling";
import { Octokit } from "@octokit/rest";
import { getApiUrl } from "./apiUrl.ts";
import { retry } from "./retry.ts";
export interface InstallationToken {
@@ -84,7 +85,7 @@ type AcquireTokenOptions = {
async function acquireTokenViaOIDC(opts?: AcquireTokenOptions): Promise<string> {
const oidcToken = await core.getIDToken("pullfrog-api");
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const params = new URLSearchParams();
// ensure the token covers GITHUB_REPOSITORY (may differ from OIDC claims repo)
+11 -10
View File
@@ -206,31 +206,36 @@ function separator(length: number = 50): void {
/**
* Main logging utility object - import this once and access all utilities
*/
/** timestamp prefix for debug mode — empty string when debug is off */
function ts(): string {
return isDebugEnabled() ? `[${new Date().toISOString()}] ` : "";
}
export const log = {
/** Print info message */
info: (...args: unknown[]): void => {
core.info(formatArgs(args));
core.info(`${ts()}${formatArgs(args)}`);
},
/** Print warning message */
warning: (...args: unknown[]): void => {
core.warning(formatArgs(args));
core.warning(`${ts()}${formatArgs(args)}`);
},
/** Print error message */
error: (...args: unknown[]): void => {
core.error(formatArgs(args));
core.error(`${ts()}${formatArgs(args)}`);
},
/** Print success message */
success: (...args: unknown[]): void => {
core.info(`» ${formatArgs(args)}`);
core.info(`${ts()}» ${formatArgs(args)}`);
},
/** Print debug message (only if LOG_LEVEL=debug) */
debug: (...args: unknown[]): void => {
if (isDebugEnabled()) {
core.info(`[DEBUG] ${formatArgs(args)}`);
core.info(`[${new Date().toISOString()}] [DEBUG] ${formatArgs(args)}`);
}
},
@@ -255,11 +260,7 @@ export const log = {
/** Log tool call information to console with formatted output */
toolCall: ({ toolName, input }: { toolName: string; input: unknown }): void => {
const inputFormatted = formatJsonValue(input);
const timestamp = isDebugEnabled() ? ` [${new Date().toISOString()}]` : "";
const output =
inputFormatted !== "{}"
? `» ${toolName}(${inputFormatted})${timestamp}`
: `» ${toolName}()${timestamp}`;
const output = inputFormatted !== "{}" ? `» ${toolName}(${inputFormatted})` : `» ${toolName}()`;
log.info(output.trimEnd());
},
+2 -1
View File
@@ -1,4 +1,5 @@
import type { AgentName, BashPermission, PushPermission, ToolPermission } from "../external.ts";
import { getApiUrl } from "./apiUrl.ts";
import type { RepoContext } from "./github.ts";
export interface Mode {
@@ -51,7 +52,7 @@ export async function fetchRunContext(params: {
token: string;
repoContext: RepoContext;
}): Promise<RunContext> {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
const apiUrl = getApiUrl();
const timeoutMs = 30000;
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
+5 -1
View File
@@ -148,12 +148,16 @@ export async function spawn(options: SpawnOptions): Promise<SpawnResult> {
// activity timeout: kill if no output for too long
if (activityTimeoutMs > 0) {
log.debug(`spawn activity timer: pid=${child.pid} cmd=${cmd} timeout=${activityTimeoutMs}ms`);
activityCheckIntervalId = setInterval(() => {
const idleMs = performance.now() - lastActivityTime;
log.debug(
`spawn activity check: pid=${child.pid} idle=${Math.round(idleMs)}ms / ${activityTimeoutMs}ms`
);
if (idleMs > activityTimeoutMs) {
isActivityTimedOut = true;
const idleSec = Math.round(idleMs / 1000);
log.error(`no output for ${idleSec}s, killing process`);
log.error(`no output for ${idleSec}s from pid=${child.pid} (${cmd}), killing process`);
child.kill("SIGKILL");
clearInterval(activityCheckIntervalId);
}