pullfrog 0.1.49 → 0.1.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.mjs +306 -238
- package/dist/external.d.ts +11 -1
- package/dist/index.js +305 -237
- package/dist/internal/index.d.ts +2 -1
- package/dist/internal.js +15 -2
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/similarIssues.d.ts +11 -0
- package/dist/models.d.ts +10 -0
- package/dist/utils/activity.d.ts +33 -0
- package/dist/utils/agentHangReport.d.ts +13 -0
- package/dist/utils/instructions.d.ts +3 -0
- package/dist/utils/isPullfrog.d.ts +4 -0
- package/dist/utils/payload.d.ts +0 -6
- package/dist/utils/runContext.d.ts +1 -0
- package/dist/utils/runStatusCheck.d.ts +9 -4
- package/dist/utils/statusChecks.d.ts +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -100541,14 +100541,18 @@ function formatMcpToolRef(agentId, toolName) {
|
|
|
100541
100541
|
return agentId;
|
|
100542
100542
|
}
|
|
100543
100543
|
}
|
|
100544
|
+
function hasSimilarIssues(params) {
|
|
100545
|
+
return params.repoIntelligence && !!params.event.issue_number && !params.event.is_pr;
|
|
100546
|
+
}
|
|
100544
100547
|
|
|
100545
100548
|
// utils/activity.ts
|
|
100546
100549
|
import { performance as performance2 } from "node:perf_hooks";
|
|
100547
|
-
function
|
|
100550
|
+
function isDebugEnabled() {
|
|
100548
100551
|
return process.env.ACTIONS_STEP_DEBUG === "true" || process.env.RUNNER_DEBUG === "1" || process.env.LOG_LEVEL === "debug";
|
|
100549
100552
|
}
|
|
100550
100553
|
var DEFAULT_ACTIVITY_TIMEOUT_MS = 3e5;
|
|
100551
100554
|
var AGENT_ACTIVITY_TIMEOUT_MS = 9e5;
|
|
100555
|
+
var AGENT_FIRST_EVENT_TIMEOUT_MS = 12e4;
|
|
100552
100556
|
var DEFAULT_ACTIVITY_CHECK_INTERVAL_MS = 5e3;
|
|
100553
100557
|
var DEBUG_TS_PREFIX = /^(?:\[\d{4}-\d{2}-\d{2}T[^\]]+\]\s+)?/.source;
|
|
100554
100558
|
var ACTIVITY_NOISE_PATTERNS = [
|
|
@@ -100592,7 +100596,7 @@ function startProcessOutputMonitor(ctx) {
|
|
|
100592
100596
|
process.stdout.write = wrapWrite(originalStdoutWrite, markActivity);
|
|
100593
100597
|
process.stderr.write = wrapWrite(originalStderrWrite, markActivity);
|
|
100594
100598
|
const debugBypass = (msg) => {
|
|
100595
|
-
if (!
|
|
100599
|
+
if (!isDebugEnabled()) return;
|
|
100596
100600
|
originalStdoutWrite(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] ${msg}
|
|
100597
100601
|
`);
|
|
100598
100602
|
};
|
|
@@ -100801,7 +100805,6 @@ function prefixPlain(name) {
|
|
|
100801
100805
|
}
|
|
100802
100806
|
var isRunnerDebugEnabled = () => core.isDebug();
|
|
100803
100807
|
var isLocalDebugEnabled = () => process.env.LOG_LEVEL === "debug" || process.env.ACTIONS_STEP_DEBUG === "true";
|
|
100804
|
-
var isDebugEnabled = () => isLocalDebugEnabled() || isRunnerDebugEnabled();
|
|
100805
100808
|
function ts() {
|
|
100806
100809
|
return isDebugEnabled() ? `[${(/* @__PURE__ */ new Date()).toISOString()}] ` : "";
|
|
100807
100810
|
}
|
|
@@ -101242,7 +101245,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
101242
101245
|
// package.json
|
|
101243
101246
|
var package_default = {
|
|
101244
101247
|
name: "pullfrog",
|
|
101245
|
-
version: "0.1.
|
|
101248
|
+
version: "0.1.51",
|
|
101246
101249
|
type: "module",
|
|
101247
101250
|
bin: {
|
|
101248
101251
|
pullfrog: "dist/cli.mjs",
|
|
@@ -109155,7 +109158,7 @@ async function installOpencodeCli(params) {
|
|
|
109155
109158
|
installDependencies: true
|
|
109156
109159
|
});
|
|
109157
109160
|
}
|
|
109158
|
-
var AUTO_SELECT_WARNING = "select a model explicitly in the Pullfrog console (https://pullfrog.com/console) to avoid this.";
|
|
109161
|
+
var AUTO_SELECT_WARNING = "select a model explicitly in the Pullfrog console (https://pullfrog.com/console) to avoid this \u2014 if the picker is locked, this run had no Pullfrog Router funding: add a card or top up your credit.";
|
|
109159
109162
|
function autoSelectModel() {
|
|
109160
109163
|
const authorized2 = getAuthorizedModels();
|
|
109161
109164
|
if (authorized2.size > 0) {
|
|
@@ -109230,9 +109233,11 @@ function parseModel2(value2) {
|
|
|
109230
109233
|
return { providerID: value2.slice(0, slash), modelID: value2.slice(slash + 1) };
|
|
109231
109234
|
}
|
|
109232
109235
|
function bootOpencodeServer(params) {
|
|
109236
|
+
const logLevel = isDebugEnabled() ? "INFO" : "ERROR";
|
|
109237
|
+
if (logLevel !== "ERROR") log.info(`\xBB opencode log level: ${logLevel} (debug run)`);
|
|
109233
109238
|
const proc = nodeSpawn2(
|
|
109234
109239
|
params.cliPath,
|
|
109235
|
-
["serve", "--port", "0", "--hostname", "127.0.0.1", "--print-logs", "--log-level",
|
|
109240
|
+
["serve", "--port", "0", "--hostname", "127.0.0.1", "--print-logs", "--log-level", logLevel],
|
|
109236
109241
|
{
|
|
109237
109242
|
cwd: params.cwd,
|
|
109238
109243
|
env: params.env,
|
|
@@ -109367,9 +109372,18 @@ async function consumeEvents(ctx, signal) {
|
|
|
109367
109372
|
}
|
|
109368
109373
|
}
|
|
109369
109374
|
}
|
|
109375
|
+
function isModelOutput(ctx, part) {
|
|
109376
|
+
if (part.type !== "text") return true;
|
|
109377
|
+
if (ctx.promptMessageID === void 0) {
|
|
109378
|
+
ctx.promptMessageID = part.messageID;
|
|
109379
|
+
return false;
|
|
109380
|
+
}
|
|
109381
|
+
return part.messageID !== ctx.promptMessageID;
|
|
109382
|
+
}
|
|
109370
109383
|
async function dispatchEvent(ctx, event) {
|
|
109371
109384
|
if (event.type === "message.part.updated") {
|
|
109372
109385
|
ctx.lastEventAt = performance6.now();
|
|
109386
|
+
if (isModelOutput(ctx, event.properties.part)) ctx.sawModelOutput = true;
|
|
109373
109387
|
await onPartUpdated(ctx, event.properties.part);
|
|
109374
109388
|
return;
|
|
109375
109389
|
}
|
|
@@ -109513,6 +109527,8 @@ async function runPromptTurn(ctx, params) {
|
|
|
109513
109527
|
ctx.currentTurn = newTurn();
|
|
109514
109528
|
const turn = ctx.currentTurn;
|
|
109515
109529
|
const part = { type: "text", text: params.text };
|
|
109530
|
+
ctx.promptMessageID = void 0;
|
|
109531
|
+
ctx.sawModelOutput = false;
|
|
109516
109532
|
let assistant;
|
|
109517
109533
|
let returnedParts;
|
|
109518
109534
|
let networkError = null;
|
|
@@ -109686,11 +109702,14 @@ function startInnerActivityWatchdog(params) {
|
|
|
109686
109702
|
const id = setInterval(() => {
|
|
109687
109703
|
if (fired) return;
|
|
109688
109704
|
const idleMs = performance6.now() - params.ctx.lastEventAt;
|
|
109689
|
-
|
|
109705
|
+
const budgetMs = params.ctx.sawModelOutput ? params.timeoutMs : AGENT_FIRST_EVENT_TIMEOUT_MS;
|
|
109706
|
+
if (idleMs <= budgetMs) return;
|
|
109690
109707
|
fired = true;
|
|
109691
109708
|
const idleSec = Math.round(idleMs / 1e3);
|
|
109709
|
+
params.ctx.diagnostic.idleSec = idleSec;
|
|
109710
|
+
params.ctx.diagnostic.sawModelOutput = params.ctx.sawModelOutput;
|
|
109692
109711
|
log.info(
|
|
109693
|
-
`\xBB no opencode events for ${idleSec}s \u2014 aborting in-flight prompt and notifying harness`
|
|
109712
|
+
params.ctx.sawModelOutput ? `\xBB no opencode events for ${idleSec}s \u2014 aborting in-flight prompt and notifying harness` : `\xBB no opencode events for ${idleSec}s \u2014 the provider never returned a first token; aborting in-flight prompt and notifying harness`
|
|
109694
109713
|
);
|
|
109695
109714
|
params.abortController.abort();
|
|
109696
109715
|
try {
|
|
@@ -109815,6 +109834,8 @@ var opencode = agent({
|
|
|
109815
109834
|
currentTurn: null,
|
|
109816
109835
|
eventCount: 0,
|
|
109817
109836
|
lastEventAt: performance6.now(),
|
|
109837
|
+
sawModelOutput: false,
|
|
109838
|
+
promptMessageID: void 0,
|
|
109818
109839
|
taskDispatchByCallID: /* @__PURE__ */ new Map(),
|
|
109819
109840
|
loggedToolCallIDs: /* @__PURE__ */ new Set(),
|
|
109820
109841
|
recentStderr: server.recentStderr,
|
|
@@ -109822,6 +109843,8 @@ var opencode = agent({
|
|
|
109822
109843
|
label: "Pullfrog",
|
|
109823
109844
|
recentStderr: server.recentStderr,
|
|
109824
109845
|
lastProviderError: void 0,
|
|
109846
|
+
idleSec: void 0,
|
|
109847
|
+
sawModelOutput: false,
|
|
109825
109848
|
eventCount: 0
|
|
109826
109849
|
}
|
|
109827
109850
|
};
|
|
@@ -158055,6 +158078,12 @@ function fixDoubleEscapedString(str) {
|
|
|
158055
158078
|
return str;
|
|
158056
158079
|
}
|
|
158057
158080
|
|
|
158081
|
+
// utils/isPullfrog.ts
|
|
158082
|
+
function isPullfrog(actor) {
|
|
158083
|
+
actor = actor?.toLowerCase().replace("[bot]", "");
|
|
158084
|
+
return !!actor && (actor === "pullfrog" || actor === "pullfrogdev");
|
|
158085
|
+
}
|
|
158086
|
+
|
|
158058
158087
|
// utils/isTransientNetworkError.ts
|
|
158059
158088
|
function isTransientNetworkError(error49, extraPatterns = []) {
|
|
158060
158089
|
if (!(error49 instanceof Error)) return false;
|
|
@@ -158161,216 +158190,6 @@ function aggregateUsage(entries) {
|
|
|
158161
158190
|
return out;
|
|
158162
158191
|
}
|
|
158163
158192
|
|
|
158164
|
-
// utils/payload.ts
|
|
158165
|
-
var core4 = __toESM(require_core(), 1);
|
|
158166
|
-
import { readFileSync as readFileSync3 } from "node:fs";
|
|
158167
|
-
import { isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
|
|
158168
|
-
|
|
158169
|
-
// utils/versioning.ts
|
|
158170
|
-
var import_semver2 = __toESM(require_semver2(), 1);
|
|
158171
|
-
var COMPATIBILITY_POLICY = "non-breaking";
|
|
158172
|
-
function validateCompatibility(payloadVersion, actionVersion) {
|
|
158173
|
-
const payloadSemVer = import_semver2.default.parse(payloadVersion);
|
|
158174
|
-
if (!payloadSemVer)
|
|
158175
|
-
throw new Error(`Payload version ${payloadVersion} is not a valid semantic version.`);
|
|
158176
|
-
const major = payloadSemVer.major;
|
|
158177
|
-
const minor = payloadSemVer.minor;
|
|
158178
|
-
const patch = payloadSemVer.patch;
|
|
158179
|
-
const compatibilityRange = COMPATIBILITY_POLICY === "same-features" ? `^${major}.${minor}.${major === 0 ? patch : 0}` : `^${major}.${major === 0 ? minor : 0}.${major === 0 ? "x" : 0}`;
|
|
158180
|
-
if (!import_semver2.default.satisfies(actionVersion, compatibilityRange)) {
|
|
158181
|
-
throw new Error(
|
|
158182
|
-
`Payload version ${payloadVersion} is incompatible with action version ${actionVersion}. Please update your workflow to use at least ${import_semver2.default.minVersion(compatibilityRange)} version of the action.`
|
|
158183
|
-
);
|
|
158184
|
-
}
|
|
158185
|
-
}
|
|
158186
|
-
|
|
158187
|
-
// utils/payload.ts
|
|
158188
|
-
var ShellPermissionInput = type.enumerated("disabled", "restricted", "enabled");
|
|
158189
|
-
var PushPermissionInput = type.enumerated("disabled", "restricted", "enabled");
|
|
158190
|
-
var StatusChecksInput = type.enumerated("disabled", "enabled");
|
|
158191
|
-
var ProgressCommentsInput = type.enumerated("disabled", "enabled");
|
|
158192
|
-
var JsonPayload = type({
|
|
158193
|
-
"~pullfrog": "true",
|
|
158194
|
-
version: "string",
|
|
158195
|
-
"model?": "string | undefined",
|
|
158196
|
-
"modelExplicit?": "boolean | undefined",
|
|
158197
|
-
"effort?": "number | string | undefined",
|
|
158198
|
-
prompt: "string",
|
|
158199
|
-
"triggerer?": "string | undefined",
|
|
158200
|
-
"baseInstructions?": "string | undefined",
|
|
158201
|
-
"eventInstructions?": "string",
|
|
158202
|
-
"previousRunsNote?": "string",
|
|
158203
|
-
"event?": "object",
|
|
158204
|
-
"xrepo?": type({
|
|
158205
|
-
mode: "'all' | 'explicit'",
|
|
158206
|
-
read: "string[]",
|
|
158207
|
-
write: "string[]",
|
|
158208
|
-
// optional so a payload from an older server build (pre-`unavailable`)
|
|
158209
|
-
// still parses against a newer action across a rolling deploy.
|
|
158210
|
-
"unavailable?": "string[]"
|
|
158211
|
-
}).or("undefined"),
|
|
158212
|
-
"timeout?": "string | undefined",
|
|
158213
|
-
"progressComment?": type({
|
|
158214
|
-
id: "string",
|
|
158215
|
-
type: "'issue' | 'review'"
|
|
158216
|
-
}).or("undefined"),
|
|
158217
|
-
// optional so a payload from an older server build (pre-`checkRun`) still parses
|
|
158218
|
-
// against a newer action across a rolling deploy.
|
|
158219
|
-
"checkRun?": type({ id: "string" }).or("undefined"),
|
|
158220
|
-
"generateSummary?": "boolean | undefined"
|
|
158221
|
-
});
|
|
158222
|
-
var COLLABORATOR_PERMISSIONS = ["admin", "maintain", "write"];
|
|
158223
|
-
function isCollaborator(event) {
|
|
158224
|
-
const perm = event.authorPermission;
|
|
158225
|
-
return perm !== void 0 && COLLABORATOR_PERMISSIONS.includes(perm);
|
|
158226
|
-
}
|
|
158227
|
-
var Inputs = type({
|
|
158228
|
-
"prompt?": type.string.or("undefined"),
|
|
158229
|
-
"prompt_file?": type.string.or("undefined"),
|
|
158230
|
-
"model?": type.string.or("undefined"),
|
|
158231
|
-
"effort?": type.string.or("undefined"),
|
|
158232
|
-
"timeout?": type.string.or("undefined"),
|
|
158233
|
-
"push?": PushPermissionInput.or("undefined"),
|
|
158234
|
-
"shell?": ShellPermissionInput.or("undefined"),
|
|
158235
|
-
"status_checks?": StatusChecksInput.or("undefined"),
|
|
158236
|
-
"progress_comments?": ProgressCommentsInput.or("undefined"),
|
|
158237
|
-
"cwd?": type.string.or("undefined"),
|
|
158238
|
-
"output_schema?": type.string.or("undefined")
|
|
158239
|
-
});
|
|
158240
|
-
function isPayloadEvent(value2) {
|
|
158241
|
-
return typeof value2 === "object" && value2 !== null && "trigger" in value2;
|
|
158242
|
-
}
|
|
158243
|
-
function resolveCwd(cwd) {
|
|
158244
|
-
const workspace = process.env.GITHUB_WORKSPACE;
|
|
158245
|
-
if (!cwd) return workspace;
|
|
158246
|
-
if (isAbsolute2(cwd)) return cwd;
|
|
158247
|
-
return workspace ? resolve2(workspace, cwd) : cwd;
|
|
158248
|
-
}
|
|
158249
|
-
function resolvePromptInput() {
|
|
158250
|
-
const promptInput = core4.getInput("prompt");
|
|
158251
|
-
const promptFile = core4.getInput("prompt_file");
|
|
158252
|
-
if (promptInput && promptFile) {
|
|
158253
|
-
throw new Error("set exactly one of 'prompt' or 'prompt_file' inputs, not both.");
|
|
158254
|
-
}
|
|
158255
|
-
if (promptFile) {
|
|
158256
|
-
return resolvePromptFile(promptFile);
|
|
158257
|
-
}
|
|
158258
|
-
if (!promptInput) {
|
|
158259
|
-
throw new Error("one of 'prompt' or 'prompt_file' inputs is required.");
|
|
158260
|
-
}
|
|
158261
|
-
let parsed2;
|
|
158262
|
-
try {
|
|
158263
|
-
parsed2 = JSON.parse(promptInput);
|
|
158264
|
-
} catch {
|
|
158265
|
-
return promptInput;
|
|
158266
|
-
}
|
|
158267
|
-
if (!parsed2 || typeof parsed2 !== "object" || !("~pullfrog" in parsed2)) {
|
|
158268
|
-
return promptInput;
|
|
158269
|
-
}
|
|
158270
|
-
const jsonPayload = JsonPayload.assert(parsed2);
|
|
158271
|
-
validateCompatibility(jsonPayload.version, package_default.version);
|
|
158272
|
-
return jsonPayload;
|
|
158273
|
-
}
|
|
158274
|
-
function resolvePromptFile(input) {
|
|
158275
|
-
const workspace = process.env.GITHUB_WORKSPACE;
|
|
158276
|
-
const path4 = isAbsolute2(input) ? input : workspace ? resolve2(workspace, input) : resolve2(input);
|
|
158277
|
-
const content = readFileSync3(path4, "utf-8");
|
|
158278
|
-
if (!content.trim()) {
|
|
158279
|
-
throw new Error(`prompt_file ${JSON.stringify(input)} is empty.`);
|
|
158280
|
-
}
|
|
158281
|
-
return content;
|
|
158282
|
-
}
|
|
158283
|
-
function resolveNonPromptInputs() {
|
|
158284
|
-
return Inputs.omit("prompt", "prompt_file").assert({
|
|
158285
|
-
model: core4.getInput("model") || void 0,
|
|
158286
|
-
effort: core4.getInput("effort") || void 0,
|
|
158287
|
-
timeout: core4.getInput("timeout") || void 0,
|
|
158288
|
-
cwd: core4.getInput("cwd") || void 0,
|
|
158289
|
-
push: core4.getInput("push") || void 0,
|
|
158290
|
-
shell: core4.getInput("shell") || void 0,
|
|
158291
|
-
status_checks: core4.getInput("status_checks") || void 0,
|
|
158292
|
-
progress_comments: core4.getInput("progress_comments") || void 0
|
|
158293
|
-
});
|
|
158294
|
-
}
|
|
158295
|
-
var isPullfrog = (actor) => {
|
|
158296
|
-
actor = actor?.replace("[bot]", "");
|
|
158297
|
-
return !!actor && (actor === "pullfrog" || actor === "pullfrogdev");
|
|
158298
|
-
};
|
|
158299
|
-
function resolvePayload(resolvedPromptInput, repoSettings) {
|
|
158300
|
-
const [prompt, jsonPayload] = typeof resolvedPromptInput !== "string" ? [resolvedPromptInput.prompt, resolvedPromptInput] : [resolvedPromptInput, void 0];
|
|
158301
|
-
const inputs = resolveNonPromptInputs();
|
|
158302
|
-
const rawEvent = jsonPayload?.event;
|
|
158303
|
-
const event = isPayloadEvent(rawEvent) ? rawEvent : { trigger: "unknown" };
|
|
158304
|
-
const model = jsonPayload?.model ?? inputs.model ?? repoSettings.model ?? void 0;
|
|
158305
|
-
const rawEffort = jsonPayload?.effort ?? inputs.effort ?? repoSettings.effort ?? void 0;
|
|
158306
|
-
const effort = rawEffort === void 0 ? void 0 : parseEffortPosition(String(rawEffort));
|
|
158307
|
-
const isNonCollaborator = !isCollaborator(event);
|
|
158308
|
-
const repoShell = repoSettings.shell ?? "restricted";
|
|
158309
|
-
const inputShell = inputs.shell;
|
|
158310
|
-
let resolvedShell = repoShell;
|
|
158311
|
-
if (inputShell === "disabled") {
|
|
158312
|
-
resolvedShell = "disabled";
|
|
158313
|
-
} else if (inputShell === "restricted" && resolvedShell === "enabled") {
|
|
158314
|
-
resolvedShell = "restricted";
|
|
158315
|
-
}
|
|
158316
|
-
if (isNonCollaborator && resolvedShell === "enabled") {
|
|
158317
|
-
resolvedShell = "restricted";
|
|
158318
|
-
}
|
|
158319
|
-
return {
|
|
158320
|
-
"~pullfrog": true,
|
|
158321
|
-
version: jsonPayload?.version ?? package_default.version,
|
|
158322
|
-
model,
|
|
158323
|
-
// explicit only when the model came from a per-run override flag (carried on
|
|
158324
|
-
// the JSON payload). a GHA `model` input or the repo default is not explicit.
|
|
158325
|
-
modelExplicit: jsonPayload?.modelExplicit ?? false,
|
|
158326
|
-
effort,
|
|
158327
|
-
prompt,
|
|
158328
|
-
triggerer: jsonPayload?.triggerer ?? // it's not a common use case but GITHUB_ACTOR can be a user when the workflow is manually triggered by a user through GitHub Actions UI
|
|
158329
|
-
(!isPullfrog(process.env.GITHUB_ACTOR) ? process.env.GITHUB_ACTOR : void 0),
|
|
158330
|
-
baseInstructions: jsonPayload?.baseInstructions,
|
|
158331
|
-
eventInstructions: jsonPayload?.eventInstructions,
|
|
158332
|
-
previousRunsNote: jsonPayload?.previousRunsNote,
|
|
158333
|
-
event,
|
|
158334
|
-
xrepo: jsonPayload?.xrepo,
|
|
158335
|
-
timeout: inputs.timeout ?? jsonPayload?.timeout,
|
|
158336
|
-
cwd: resolveCwd(inputs.cwd),
|
|
158337
|
-
progressComment: jsonPayload?.progressComment,
|
|
158338
|
-
checkRun: jsonPayload?.checkRun,
|
|
158339
|
-
generateSummary: jsonPayload?.generateSummary,
|
|
158340
|
-
// permissions: inputs > repoSettings > fallbacks
|
|
158341
|
-
push: inputs.push ?? repoSettings.push ?? "restricted",
|
|
158342
|
-
shell: resolvedShell,
|
|
158343
|
-
// the `pullfrog` run-lifecycle check. ON by default — the whole point is that a PR
|
|
158344
|
-
// shows whether Pullfrog is running without anyone having to opt in. the workflow
|
|
158345
|
-
// input is the source of truth when set (mirrors `push`); otherwise the repo
|
|
158346
|
-
// setting decides.
|
|
158347
|
-
runStatusCheck: inputs.status_checks === void 0 ? repoSettings.statusChecks : inputs.status_checks === "enabled",
|
|
158348
|
-
// the `pullfrog-approval` verdict check stays opt-in and workflow-only. it exists to
|
|
158349
|
-
// be *required* by branch protection, so it must never turn itself on.
|
|
158350
|
-
approvalCheck: inputs.status_checks === "enabled",
|
|
158351
|
-
// temporary progress chrome. the workflow input is the source of truth when
|
|
158352
|
-
// set (mirrors `push`); otherwise the repo setting decides. defaults to true.
|
|
158353
|
-
progressComments: inputs.progress_comments === void 0 ? repoSettings.progressComments : inputs.progress_comments === "enabled",
|
|
158354
|
-
// set by proxy logic in main.ts when routing through OpenRouter
|
|
158355
|
-
proxyModel: void 0
|
|
158356
|
-
};
|
|
158357
|
-
}
|
|
158358
|
-
function resolveOutputSchema() {
|
|
158359
|
-
const raw2 = core4.getInput("output_schema");
|
|
158360
|
-
if (!raw2) return void 0;
|
|
158361
|
-
let parsed2;
|
|
158362
|
-
try {
|
|
158363
|
-
parsed2 = JSON.parse(raw2);
|
|
158364
|
-
} catch {
|
|
158365
|
-
throw new Error(`invalid output_schema: not valid JSON`);
|
|
158366
|
-
}
|
|
158367
|
-
if (!parsed2 || typeof parsed2 !== "object" || Array.isArray(parsed2)) {
|
|
158368
|
-
throw new Error(`invalid output_schema: must be a JSON object`);
|
|
158369
|
-
}
|
|
158370
|
-
log.info("\xBB structured output schema provided \u2014 output will be required");
|
|
158371
|
-
return parsed2;
|
|
158372
|
-
}
|
|
158373
|
-
|
|
158374
158193
|
// mcp/comment.ts
|
|
158375
158194
|
function isNotFoundError(error49) {
|
|
158376
158195
|
return error49 instanceof Error && error49.message.includes("Not Found");
|
|
@@ -160681,7 +160500,7 @@ function isMetadataYarnClassic(metadataPath) {
|
|
|
160681
160500
|
}
|
|
160682
160501
|
|
|
160683
160502
|
// utils/packageManager.ts
|
|
160684
|
-
var
|
|
160503
|
+
var import_semver2 = __toESM(require_semver2(), 1);
|
|
160685
160504
|
import { existsSync as existsSync5 } from "node:fs";
|
|
160686
160505
|
import { mkdir, readFile as readFile2 } from "node:fs/promises";
|
|
160687
160506
|
import { delimiter, join as join16 } from "node:path";
|
|
@@ -160703,7 +160522,7 @@ function parsePackageManagerField(value2) {
|
|
|
160703
160522
|
return {
|
|
160704
160523
|
name,
|
|
160705
160524
|
version: version3,
|
|
160706
|
-
concrete:
|
|
160525
|
+
concrete: import_semver2.default.valid(version3) !== null,
|
|
160707
160526
|
source: "packageManager"
|
|
160708
160527
|
};
|
|
160709
160528
|
}
|
|
@@ -160717,7 +160536,7 @@ function parseDevEnginesField(field) {
|
|
|
160717
160536
|
return {
|
|
160718
160537
|
name: field.name,
|
|
160719
160538
|
version: version3,
|
|
160720
|
-
concrete:
|
|
160539
|
+
concrete: import_semver2.default.valid(version3) !== null,
|
|
160721
160540
|
source: "devEngines"
|
|
160722
160541
|
};
|
|
160723
160542
|
}
|
|
@@ -160751,7 +160570,7 @@ async function resolvePackageManagerSpec(cwd) {
|
|
|
160751
160570
|
}
|
|
160752
160571
|
return devSpec;
|
|
160753
160572
|
}
|
|
160754
|
-
if (pmSpec.concrete &&
|
|
160573
|
+
if (pmSpec.concrete && import_semver2.default.satisfies(pmSpec.version, devSpec.version)) {
|
|
160755
160574
|
return pmSpec;
|
|
160756
160575
|
}
|
|
160757
160576
|
if (pmSpec.concrete) {
|
|
@@ -160963,10 +160782,10 @@ ${errorMessage}`]
|
|
|
160963
160782
|
};
|
|
160964
160783
|
|
|
160965
160784
|
// prep/installPythonDependencies.ts
|
|
160966
|
-
import { existsSync as existsSync7, readFileSync as
|
|
160785
|
+
import { existsSync as existsSync7, readFileSync as readFileSync3 } from "node:fs";
|
|
160967
160786
|
import { join as join18 } from "node:path";
|
|
160968
160787
|
function declaresBuildSystem(path4) {
|
|
160969
|
-
return /^\s*\[\s*build-system\s*\]/m.test(
|
|
160788
|
+
return /^\s*\[\s*build-system\s*\]/m.test(readFileSync3(path4, "utf8"));
|
|
160970
160789
|
}
|
|
160971
160790
|
function configApplies(config3, cwd) {
|
|
160972
160791
|
const path4 = join18(cwd, config3.file);
|
|
@@ -163101,6 +162920,36 @@ function KillBackgroundTool(ctx) {
|
|
|
163101
162920
|
});
|
|
163102
162921
|
}
|
|
163103
162922
|
|
|
162923
|
+
// mcp/similarIssues.ts
|
|
162924
|
+
var SimilarIssues = type({
|
|
162925
|
+
issue_number: type.number.describe("The issue number to find older duplicate candidates for")
|
|
162926
|
+
});
|
|
162927
|
+
function SimilarIssuesTool(ctx) {
|
|
162928
|
+
return tool({
|
|
162929
|
+
name: "find_similar_issues",
|
|
162930
|
+
description: "Find high-recall older duplicate candidates for an issue. Similarity is only retrieval: inspect promising candidates with get_issue before deciding whether they are duplicates.",
|
|
162931
|
+
mutates: true,
|
|
162932
|
+
parameters: SimilarIssues,
|
|
162933
|
+
execute: execute(async (input) => {
|
|
162934
|
+
if (ctx.payload.event.is_pr || ctx.payload.event.issue_number !== input.issue_number) {
|
|
162935
|
+
throw new Error("find_similar_issues is limited to the issue that triggered this run");
|
|
162936
|
+
}
|
|
162937
|
+
const response = await apiFetch({
|
|
162938
|
+
path: `/api/repo/${ctx.repo.owner}/${ctx.repo.name}/issues/${input.issue_number}/similar`,
|
|
162939
|
+
headers: {
|
|
162940
|
+
authorization: `Bearer ${ctx.apiToken}`
|
|
162941
|
+
},
|
|
162942
|
+
signal: AbortSignal.timeout(13 * 6e4)
|
|
162943
|
+
});
|
|
162944
|
+
if (!response.ok) {
|
|
162945
|
+
const message = await response.text();
|
|
162946
|
+
throw new Error(`similar issue lookup returned ${response.status}: ${message}`);
|
|
162947
|
+
}
|
|
162948
|
+
return { result: await response.json() };
|
|
162949
|
+
})
|
|
162950
|
+
});
|
|
162951
|
+
}
|
|
162952
|
+
|
|
163104
162953
|
// mcp/upload.ts
|
|
163105
162954
|
import * as fs4 from "node:fs";
|
|
163106
162955
|
import * as path3 from "node:path";
|
|
@@ -163339,6 +163188,9 @@ function buildCommonTools(ctx, outputSchema) {
|
|
|
163339
163188
|
if (ctx.xrepo) {
|
|
163340
163189
|
tools.push(ListReposTool(ctx), CheckoutRepoTool(ctx));
|
|
163341
163190
|
}
|
|
163191
|
+
if (hasSimilarIssues({ repoIntelligence: ctx.repoIntelligence, event: ctx.payload.event })) {
|
|
163192
|
+
tools.push(SimilarIssuesTool(ctx));
|
|
163193
|
+
}
|
|
163342
163194
|
const isStandalone = ctx.payload.event.trigger === "unknown";
|
|
163343
163195
|
if (isStandalone || outputSchema) {
|
|
163344
163196
|
tools.push(SetOutputTool(ctx, outputSchema));
|
|
@@ -164282,6 +164134,11 @@ Rules:
|
|
|
164282
164134
|
### GitHub
|
|
164283
164135
|
|
|
164284
164136
|
Use MCP tools from ${pullfrogMcpName} for all GitHub operations. Never use the \`gh\` CLI \u2014 it is not authenticated and will fail. The MCP tools handle authentication and enforce permissions.
|
|
164137
|
+
${hasSimilarIssues({ repoIntelligence: ctx.repoIntelligence, event: ctx.payload.event }) ? `
|
|
164138
|
+
#### Duplicate detection (enabled for this repository)
|
|
164139
|
+
|
|
164140
|
+
Call \`${t("find_similar_issues")}\` for #${ctx.payload.event.issue_number} before planning. If it duplicates an existing issue, link that instead of producing a plan; never close or label on similarity alone.
|
|
164141
|
+
` : ""}
|
|
164285
164142
|
|
|
164286
164143
|
${getShellInstructions(ctx.payload.shell, t)}
|
|
164287
164144
|
|
|
@@ -164608,7 +164465,7 @@ function buildModelAccessError(input) {
|
|
|
164608
164465
|
}
|
|
164609
164466
|
|
|
164610
164467
|
// utils/normalizeEnv.ts
|
|
164611
|
-
var
|
|
164468
|
+
var core4 = __toESM(require_core(), 1);
|
|
164612
164469
|
function sanitizeSecret(key, value2) {
|
|
164613
164470
|
const trimmed = value2.trim();
|
|
164614
164471
|
if (trimmed.length === 0) {
|
|
@@ -164622,7 +164479,7 @@ function sanitizeSecret(key, value2) {
|
|
|
164622
164479
|
`\xBB stripped whitespace from ${key} (whitespace in secret values breaks GitHub Actions log masking)`
|
|
164623
164480
|
);
|
|
164624
164481
|
}
|
|
164625
|
-
|
|
164482
|
+
core4.setSecret(trimmed);
|
|
164626
164483
|
return trimmed;
|
|
164627
164484
|
}
|
|
164628
164485
|
function normalizeEnv() {
|
|
@@ -164666,7 +164523,7 @@ function normalizeEnv() {
|
|
|
164666
164523
|
}
|
|
164667
164524
|
|
|
164668
164525
|
// utils/overrides.ts
|
|
164669
|
-
var
|
|
164526
|
+
var core5 = __toESM(require_core(), 1);
|
|
164670
164527
|
var DENIED_OVERRIDE_NAMES = /* @__PURE__ */ new Set([
|
|
164671
164528
|
"GITHUB_TOKEN",
|
|
164672
164529
|
"GH_TOKEN",
|
|
@@ -164712,7 +164569,7 @@ function applyOverrides(params) {
|
|
|
164712
164569
|
denied.push(key);
|
|
164713
164570
|
continue;
|
|
164714
164571
|
}
|
|
164715
|
-
if (value2.length > 0)
|
|
164572
|
+
if (value2.length > 0) core5.setSecret(value2);
|
|
164716
164573
|
params.env[key] = value2;
|
|
164717
164574
|
applied.push(key);
|
|
164718
164575
|
}
|
|
@@ -164720,6 +164577,212 @@ function applyOverrides(params) {
|
|
|
164720
164577
|
return { applied, denied };
|
|
164721
164578
|
}
|
|
164722
164579
|
|
|
164580
|
+
// utils/payload.ts
|
|
164581
|
+
var core6 = __toESM(require_core(), 1);
|
|
164582
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
164583
|
+
import { isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
|
|
164584
|
+
|
|
164585
|
+
// utils/versioning.ts
|
|
164586
|
+
var import_semver3 = __toESM(require_semver2(), 1);
|
|
164587
|
+
var COMPATIBILITY_POLICY = "non-breaking";
|
|
164588
|
+
function validateCompatibility(payloadVersion, actionVersion) {
|
|
164589
|
+
const payloadSemVer = import_semver3.default.parse(payloadVersion);
|
|
164590
|
+
if (!payloadSemVer)
|
|
164591
|
+
throw new Error(`Payload version ${payloadVersion} is not a valid semantic version.`);
|
|
164592
|
+
const major = payloadSemVer.major;
|
|
164593
|
+
const minor = payloadSemVer.minor;
|
|
164594
|
+
const patch = payloadSemVer.patch;
|
|
164595
|
+
const compatibilityRange = COMPATIBILITY_POLICY === "same-features" ? `^${major}.${minor}.${major === 0 ? patch : 0}` : `^${major}.${major === 0 ? minor : 0}.${major === 0 ? "x" : 0}`;
|
|
164596
|
+
if (!import_semver3.default.satisfies(actionVersion, compatibilityRange)) {
|
|
164597
|
+
throw new Error(
|
|
164598
|
+
`Payload version ${payloadVersion} is incompatible with action version ${actionVersion}. Please update your workflow to use at least ${import_semver3.default.minVersion(compatibilityRange)} version of the action.`
|
|
164599
|
+
);
|
|
164600
|
+
}
|
|
164601
|
+
}
|
|
164602
|
+
|
|
164603
|
+
// utils/payload.ts
|
|
164604
|
+
var ShellPermissionInput = type.enumerated("disabled", "restricted", "enabled");
|
|
164605
|
+
var PushPermissionInput = type.enumerated("disabled", "restricted", "enabled");
|
|
164606
|
+
var StatusChecksInput = type.enumerated("disabled", "enabled");
|
|
164607
|
+
var ProgressCommentsInput = type.enumerated("disabled", "enabled");
|
|
164608
|
+
var JsonPayload = type({
|
|
164609
|
+
"~pullfrog": "true",
|
|
164610
|
+
version: "string",
|
|
164611
|
+
"model?": "string | undefined",
|
|
164612
|
+
"modelExplicit?": "boolean | undefined",
|
|
164613
|
+
"effort?": "number | string | undefined",
|
|
164614
|
+
prompt: "string",
|
|
164615
|
+
"triggerer?": "string | undefined",
|
|
164616
|
+
"baseInstructions?": "string | undefined",
|
|
164617
|
+
"eventInstructions?": "string",
|
|
164618
|
+
"previousRunsNote?": "string",
|
|
164619
|
+
"event?": "object",
|
|
164620
|
+
"xrepo?": type({
|
|
164621
|
+
mode: "'all' | 'explicit'",
|
|
164622
|
+
read: "string[]",
|
|
164623
|
+
write: "string[]",
|
|
164624
|
+
// optional so a payload from an older server build (pre-`unavailable`)
|
|
164625
|
+
// still parses against a newer action across a rolling deploy.
|
|
164626
|
+
"unavailable?": "string[]"
|
|
164627
|
+
}).or("undefined"),
|
|
164628
|
+
"timeout?": "string | undefined",
|
|
164629
|
+
"progressComment?": type({
|
|
164630
|
+
id: "string",
|
|
164631
|
+
type: "'issue' | 'review'"
|
|
164632
|
+
}).or("undefined"),
|
|
164633
|
+
// optional so a payload from an older server build (pre-`checkRun`) still parses
|
|
164634
|
+
// against a newer action across a rolling deploy.
|
|
164635
|
+
"checkRun?": type({ id: "string" }).or("undefined"),
|
|
164636
|
+
"generateSummary?": "boolean | undefined"
|
|
164637
|
+
});
|
|
164638
|
+
var COLLABORATOR_PERMISSIONS = ["admin", "maintain", "write"];
|
|
164639
|
+
function isCollaborator(event) {
|
|
164640
|
+
const perm = event.authorPermission;
|
|
164641
|
+
return perm !== void 0 && COLLABORATOR_PERMISSIONS.includes(perm);
|
|
164642
|
+
}
|
|
164643
|
+
var Inputs = type({
|
|
164644
|
+
"prompt?": type.string.or("undefined"),
|
|
164645
|
+
"prompt_file?": type.string.or("undefined"),
|
|
164646
|
+
"model?": type.string.or("undefined"),
|
|
164647
|
+
"effort?": type.string.or("undefined"),
|
|
164648
|
+
"timeout?": type.string.or("undefined"),
|
|
164649
|
+
"push?": PushPermissionInput.or("undefined"),
|
|
164650
|
+
"shell?": ShellPermissionInput.or("undefined"),
|
|
164651
|
+
"status_checks?": StatusChecksInput.or("undefined"),
|
|
164652
|
+
"progress_comments?": ProgressCommentsInput.or("undefined"),
|
|
164653
|
+
"cwd?": type.string.or("undefined"),
|
|
164654
|
+
"output_schema?": type.string.or("undefined")
|
|
164655
|
+
});
|
|
164656
|
+
function isPayloadEvent(value2) {
|
|
164657
|
+
return typeof value2 === "object" && value2 !== null && "trigger" in value2;
|
|
164658
|
+
}
|
|
164659
|
+
function resolveCwd(cwd) {
|
|
164660
|
+
const workspace = process.env.GITHUB_WORKSPACE;
|
|
164661
|
+
if (!cwd) return workspace;
|
|
164662
|
+
if (isAbsolute2(cwd)) return cwd;
|
|
164663
|
+
return workspace ? resolve2(workspace, cwd) : cwd;
|
|
164664
|
+
}
|
|
164665
|
+
function resolvePromptInput() {
|
|
164666
|
+
const promptInput = core6.getInput("prompt");
|
|
164667
|
+
const promptFile = core6.getInput("prompt_file");
|
|
164668
|
+
if (promptInput && promptFile) {
|
|
164669
|
+
throw new Error("set exactly one of 'prompt' or 'prompt_file' inputs, not both.");
|
|
164670
|
+
}
|
|
164671
|
+
if (promptFile) {
|
|
164672
|
+
return resolvePromptFile(promptFile);
|
|
164673
|
+
}
|
|
164674
|
+
if (!promptInput) {
|
|
164675
|
+
throw new Error("one of 'prompt' or 'prompt_file' inputs is required.");
|
|
164676
|
+
}
|
|
164677
|
+
let parsed2;
|
|
164678
|
+
try {
|
|
164679
|
+
parsed2 = JSON.parse(promptInput);
|
|
164680
|
+
} catch {
|
|
164681
|
+
return promptInput;
|
|
164682
|
+
}
|
|
164683
|
+
if (!parsed2 || typeof parsed2 !== "object" || !("~pullfrog" in parsed2)) {
|
|
164684
|
+
return promptInput;
|
|
164685
|
+
}
|
|
164686
|
+
const jsonPayload = JsonPayload.assert(parsed2);
|
|
164687
|
+
validateCompatibility(jsonPayload.version, package_default.version);
|
|
164688
|
+
return jsonPayload;
|
|
164689
|
+
}
|
|
164690
|
+
function resolvePromptFile(input) {
|
|
164691
|
+
const workspace = process.env.GITHUB_WORKSPACE;
|
|
164692
|
+
const path4 = isAbsolute2(input) ? input : workspace ? resolve2(workspace, input) : resolve2(input);
|
|
164693
|
+
const content = readFileSync5(path4, "utf-8");
|
|
164694
|
+
if (!content.trim()) {
|
|
164695
|
+
throw new Error(`prompt_file ${JSON.stringify(input)} is empty.`);
|
|
164696
|
+
}
|
|
164697
|
+
return content;
|
|
164698
|
+
}
|
|
164699
|
+
function resolveNonPromptInputs() {
|
|
164700
|
+
return Inputs.omit("prompt", "prompt_file").assert({
|
|
164701
|
+
model: core6.getInput("model") || void 0,
|
|
164702
|
+
effort: core6.getInput("effort") || void 0,
|
|
164703
|
+
timeout: core6.getInput("timeout") || void 0,
|
|
164704
|
+
cwd: core6.getInput("cwd") || void 0,
|
|
164705
|
+
push: core6.getInput("push") || void 0,
|
|
164706
|
+
shell: core6.getInput("shell") || void 0,
|
|
164707
|
+
status_checks: core6.getInput("status_checks") || void 0,
|
|
164708
|
+
progress_comments: core6.getInput("progress_comments") || void 0
|
|
164709
|
+
});
|
|
164710
|
+
}
|
|
164711
|
+
function resolvePayload(resolvedPromptInput, repoSettings) {
|
|
164712
|
+
const [prompt, jsonPayload] = typeof resolvedPromptInput !== "string" ? [resolvedPromptInput.prompt, resolvedPromptInput] : [resolvedPromptInput, void 0];
|
|
164713
|
+
const inputs = resolveNonPromptInputs();
|
|
164714
|
+
const rawEvent = jsonPayload?.event;
|
|
164715
|
+
const event = isPayloadEvent(rawEvent) ? rawEvent : { trigger: "unknown" };
|
|
164716
|
+
const model = jsonPayload?.model ?? inputs.model ?? repoSettings.model ?? void 0;
|
|
164717
|
+
const rawEffort = jsonPayload?.effort ?? inputs.effort ?? repoSettings.effort ?? void 0;
|
|
164718
|
+
const effort = rawEffort === void 0 ? void 0 : parseEffortPosition(String(rawEffort));
|
|
164719
|
+
const isNonCollaborator = !isCollaborator(event);
|
|
164720
|
+
const repoShell = repoSettings.shell ?? "restricted";
|
|
164721
|
+
const inputShell = inputs.shell;
|
|
164722
|
+
let resolvedShell = repoShell;
|
|
164723
|
+
if (inputShell === "disabled") {
|
|
164724
|
+
resolvedShell = "disabled";
|
|
164725
|
+
} else if (inputShell === "restricted" && resolvedShell === "enabled") {
|
|
164726
|
+
resolvedShell = "restricted";
|
|
164727
|
+
}
|
|
164728
|
+
if (isNonCollaborator && resolvedShell === "enabled") {
|
|
164729
|
+
resolvedShell = "restricted";
|
|
164730
|
+
}
|
|
164731
|
+
return {
|
|
164732
|
+
"~pullfrog": true,
|
|
164733
|
+
version: jsonPayload?.version ?? package_default.version,
|
|
164734
|
+
model,
|
|
164735
|
+
// explicit only when the model came from a per-run override flag (carried on
|
|
164736
|
+
// the JSON payload). a GHA `model` input or the repo default is not explicit.
|
|
164737
|
+
modelExplicit: jsonPayload?.modelExplicit ?? false,
|
|
164738
|
+
effort,
|
|
164739
|
+
prompt,
|
|
164740
|
+
triggerer: jsonPayload?.triggerer ?? // it's not a common use case but GITHUB_ACTOR can be a user when the workflow is manually triggered by a user through GitHub Actions UI
|
|
164741
|
+
(!isPullfrog(process.env.GITHUB_ACTOR) ? process.env.GITHUB_ACTOR : void 0),
|
|
164742
|
+
baseInstructions: jsonPayload?.baseInstructions,
|
|
164743
|
+
eventInstructions: jsonPayload?.eventInstructions,
|
|
164744
|
+
previousRunsNote: jsonPayload?.previousRunsNote,
|
|
164745
|
+
event,
|
|
164746
|
+
xrepo: jsonPayload?.xrepo,
|
|
164747
|
+
timeout: inputs.timeout ?? jsonPayload?.timeout,
|
|
164748
|
+
cwd: resolveCwd(inputs.cwd),
|
|
164749
|
+
progressComment: jsonPayload?.progressComment,
|
|
164750
|
+
checkRun: jsonPayload?.checkRun,
|
|
164751
|
+
generateSummary: jsonPayload?.generateSummary,
|
|
164752
|
+
// permissions: inputs > repoSettings > fallbacks
|
|
164753
|
+
push: inputs.push ?? repoSettings.push ?? "restricted",
|
|
164754
|
+
shell: resolvedShell,
|
|
164755
|
+
// the `pullfrog` run-lifecycle check. ON by default — the whole point is that a PR
|
|
164756
|
+
// shows whether Pullfrog is running without anyone having to opt in. the workflow
|
|
164757
|
+
// input is the source of truth when set (mirrors `push`); otherwise the repo
|
|
164758
|
+
// setting decides.
|
|
164759
|
+
runStatusCheck: inputs.status_checks === void 0 ? repoSettings.statusChecks : inputs.status_checks === "enabled",
|
|
164760
|
+
// the `pullfrog-approval` verdict check stays opt-in and workflow-only. it exists to
|
|
164761
|
+
// be *required* by branch protection, so it must never turn itself on.
|
|
164762
|
+
approvalCheck: inputs.status_checks === "enabled",
|
|
164763
|
+
// temporary progress chrome. the workflow input is the source of truth when
|
|
164764
|
+
// set (mirrors `push`); otherwise the repo setting decides. defaults to true.
|
|
164765
|
+
progressComments: inputs.progress_comments === void 0 ? repoSettings.progressComments : inputs.progress_comments === "enabled",
|
|
164766
|
+
// set by proxy logic in main.ts when routing through OpenRouter
|
|
164767
|
+
proxyModel: void 0
|
|
164768
|
+
};
|
|
164769
|
+
}
|
|
164770
|
+
function resolveOutputSchema() {
|
|
164771
|
+
const raw2 = core6.getInput("output_schema");
|
|
164772
|
+
if (!raw2) return void 0;
|
|
164773
|
+
let parsed2;
|
|
164774
|
+
try {
|
|
164775
|
+
parsed2 = JSON.parse(raw2);
|
|
164776
|
+
} catch {
|
|
164777
|
+
throw new Error(`invalid output_schema: not valid JSON`);
|
|
164778
|
+
}
|
|
164779
|
+
if (!parsed2 || typeof parsed2 !== "object" || Array.isArray(parsed2)) {
|
|
164780
|
+
throw new Error(`invalid output_schema: must be a JSON object`);
|
|
164781
|
+
}
|
|
164782
|
+
log.info("\xBB structured output schema provided \u2014 output will be required");
|
|
164783
|
+
return parsed2;
|
|
164784
|
+
}
|
|
164785
|
+
|
|
164723
164786
|
// utils/proxy.ts
|
|
164724
164787
|
var core8 = __toESM(require_core(), 1);
|
|
164725
164788
|
|
|
@@ -165267,6 +165330,7 @@ var defaultSettings = {
|
|
|
165267
165330
|
prApproveEnabled: false,
|
|
165268
165331
|
autoMergeEnabled: false,
|
|
165269
165332
|
signedCommits: false,
|
|
165333
|
+
repoIntelligence: false,
|
|
165270
165334
|
progressComments: true,
|
|
165271
165335
|
statusChecks: true,
|
|
165272
165336
|
modeInstructions: {},
|
|
@@ -165406,7 +165470,8 @@ function formatAgentHangBody(input) {
|
|
|
165406
165470
|
const headline = `**${input.diagnostic.label} ${verb}**${cause}`;
|
|
165407
165471
|
const explanation = formatExplanation({
|
|
165408
165472
|
isHang: input.isHang,
|
|
165409
|
-
errorMessage: input.errorMessage
|
|
165473
|
+
errorMessage: input.errorMessage,
|
|
165474
|
+
idleSec: input.diagnostic.idleSec
|
|
165410
165475
|
});
|
|
165411
165476
|
const parts = [headline, "", `${explanation} ${formatEventsPart(input.diagnostic)}`];
|
|
165412
165477
|
const tail = renderStderrTail(input.diagnostic.recentStderr);
|
|
@@ -165427,7 +165492,7 @@ function formatAgentHangBody(input) {
|
|
|
165427
165492
|
}
|
|
165428
165493
|
function formatExplanation(input) {
|
|
165429
165494
|
if (!input.isHang) return `The agent exited unexpectedly: ${input.errorMessage}`;
|
|
165430
|
-
const idleSec = parseIdleSec(input.errorMessage);
|
|
165495
|
+
const idleSec = input.idleSec ?? parseIdleSec(input.errorMessage);
|
|
165431
165496
|
if (idleSec === void 0) {
|
|
165432
165497
|
return "The agent stopped emitting events and was killed by the activity-timeout watchdog.";
|
|
165433
165498
|
}
|
|
@@ -165438,11 +165503,13 @@ function parseIdleSec(message) {
|
|
|
165438
165503
|
return match3 ? Number(match3[1]) : void 0;
|
|
165439
165504
|
}
|
|
165440
165505
|
function formatEventsPart(diagnostic) {
|
|
165441
|
-
if (diagnostic.
|
|
165506
|
+
if (diagnostic.lastProviderError) {
|
|
165442
165507
|
return `${diagnostic.eventCount} events were processed before the failure.`;
|
|
165443
165508
|
}
|
|
165444
|
-
if (diagnostic.
|
|
165445
|
-
|
|
165509
|
+
if (!diagnostic.sawModelOutput) {
|
|
165510
|
+
return "The model produced no output at all before the stall \u2014 the request was sent but nothing came back. This is usually transient; re-running often succeeds.";
|
|
165511
|
+
}
|
|
165512
|
+
return `${diagnostic.eventCount} events were processed before the failure.`;
|
|
165446
165513
|
}
|
|
165447
165514
|
function renderStderrTail(lines) {
|
|
165448
165515
|
if (lines.length === 0) return "";
|
|
@@ -165798,8 +165865,8 @@ function getCurrentWorkflowFilename() {
|
|
|
165798
165865
|
}
|
|
165799
165866
|
|
|
165800
165867
|
// utils/runStatusCheck.ts
|
|
165801
|
-
var RUN_STATUS_CHECK_NAME = "
|
|
165802
|
-
var APPROVAL_CHECK_NAME = "
|
|
165868
|
+
var RUN_STATUS_CHECK_NAME = "pullfrog";
|
|
165869
|
+
var APPROVAL_CHECK_NAME = "pullfrog-approval";
|
|
165803
165870
|
function parseCheckRunId(raw2) {
|
|
165804
165871
|
if (!raw2?.id) return void 0;
|
|
165805
165872
|
const id = parseInt(raw2.id, 10);
|
|
@@ -166324,7 +166391,7 @@ async function main() {
|
|
|
166324
166391
|
_promise2 && await _promise2;
|
|
166325
166392
|
}
|
|
166326
166393
|
}
|
|
166327
|
-
createTempDirectory();
|
|
166394
|
+
const tmpdir3 = createTempDirectory();
|
|
166328
166395
|
const opencodeCliPath = await agents.opencode.install();
|
|
166329
166396
|
captureBaselineModels(opencodeCliPath);
|
|
166330
166397
|
if (runContext.dbSecrets) {
|
|
@@ -166378,7 +166445,6 @@ async function main() {
|
|
|
166378
166445
|
if (payload.cwd && process.cwd() !== payload.cwd) {
|
|
166379
166446
|
process.chdir(payload.cwd);
|
|
166380
166447
|
}
|
|
166381
|
-
const tmpdir3 = createTempDirectory();
|
|
166382
166448
|
const originalBody = payload.event.body;
|
|
166383
166449
|
const resolvedBody = await resolveBody({
|
|
166384
166450
|
event: payload.event,
|
|
@@ -166487,6 +166553,7 @@ async function main() {
|
|
|
166487
166553
|
prApproveEnabled: runContext.repoSettings.prApproveEnabled,
|
|
166488
166554
|
autoMergeEnabled: runContext.repoSettings.autoMergeEnabled,
|
|
166489
166555
|
signedCommits: runContext.repoSettings.signedCommits,
|
|
166556
|
+
repoIntelligence: runContext.repoSettings.repoIntelligence,
|
|
166490
166557
|
modeInstructions: runContext.repoSettings.modeInstructions,
|
|
166491
166558
|
toolState,
|
|
166492
166559
|
runId: runInfo.runId,
|
|
@@ -166561,6 +166628,7 @@ async function main() {
|
|
|
166561
166628
|
agentId,
|
|
166562
166629
|
outputSchema,
|
|
166563
166630
|
signedCommits: runContext.repoSettings.signedCommits,
|
|
166631
|
+
repoIntelligence: runContext.repoSettings.repoIntelligence,
|
|
166564
166632
|
learningsFilePath: toolState.learningsFilePath ?? null,
|
|
166565
166633
|
learningsHeadings: runContext.repoSettings.learningsHeadings,
|
|
166566
166634
|
setupHookFailure: describeSetupFailure(setupHook.failure),
|