diff --git a/entry b/entry index fbb1e7d..faa00fa 100755 --- a/entry +++ b/entry @@ -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(); } diff --git a/get-installation-token/entry b/get-installation-token/entry index b7fdf10..d78fdb2 100755 --- a/get-installation-token/entry +++ b/get-installation-token/entry @@ -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]; diff --git a/mcp/comment.ts b/mcp/comment.ts index 71cd72b..029c8bf 100644 --- a/mcp/comment.ts +++ b/mcp/comment.ts @@ -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})`; } diff --git a/mcp/review.ts b/mcp/review.ts index b780a07..979b7ab 100644 --- a/mcp/review.ts +++ b/mcp/review.ts @@ -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}`; diff --git a/mcp/upload.ts b/mcp/upload.ts index 050e261..f195c8b 100644 --- a/mcp/upload.ts +++ b/mcp/upload.ts @@ -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", diff --git a/post b/post index aa0dcc9..fdb16c4 100755 --- a/post +++ b/post @@ -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()); } }; diff --git a/utils/activity.ts b/utils/activity.ts index 2e96c09..b528997 100644 --- a/utils/activity.ts +++ b/utils/activity.ts @@ -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); diff --git a/utils/apiKeys.ts b/utils/apiKeys.ts index a7afd16..d0b525f 100644 --- a/utils/apiKeys.ts +++ b/utils/apiKeys.ts @@ -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}`; diff --git a/utils/apiUrl.ts b/utils/apiUrl.ts new file mode 100644 index 0000000..4512c82 --- /dev/null +++ b/utils/apiUrl.ts @@ -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"; +} diff --git a/utils/github.ts b/utils/github.ts index 0dbd4f9..68becf5 100644 --- a/utils/github.ts +++ b/utils/github.ts @@ -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 { 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) diff --git a/utils/log.ts b/utils/log.ts index 9410fd1..df46fe4 100644 --- a/utils/log.ts +++ b/utils/log.ts @@ -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()); }, diff --git a/utils/runContext.ts b/utils/runContext.ts index 232faa7..04bab69 100644 --- a/utils/runContext.ts +++ b/utils/runContext.ts @@ -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 { - 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); diff --git a/utils/subprocess.ts b/utils/subprocess.ts index 6be0df4..ae2a371 100644 --- a/utils/subprocess.ts +++ b/utils/subprocess.ts @@ -148,12 +148,16 @@ export async function spawn(options: SpawnOptions): Promise { // 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); }