pullfrog 0.1.62 → 0.1.63
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/dist/cli.mjs +51 -13
- package/dist/index.js +50 -12
- package/dist/utils/runErrorRenderer.d.ts +7 -7
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -107358,7 +107358,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
107358
107358
|
// package.json
|
|
107359
107359
|
var package_default = {
|
|
107360
107360
|
name: "pullfrog",
|
|
107361
|
-
version: "0.1.
|
|
107361
|
+
version: "0.1.63",
|
|
107362
107362
|
type: "module",
|
|
107363
107363
|
bin: {
|
|
107364
107364
|
pullfrog: "dist/cli.mjs",
|
|
@@ -116237,7 +116237,7 @@ function isModelOutput(ctx, part) {
|
|
|
116237
116237
|
async function dispatchEvent(ctx, event) {
|
|
116238
116238
|
if (event.type === "message.part.updated") {
|
|
116239
116239
|
ctx.lastEventAt = performance7.now();
|
|
116240
|
-
if (isModelOutput(ctx, event.properties.part)) ctx.sawModelOutput = true;
|
|
116240
|
+
if (isModelOutput(ctx, event.properties.part)) ctx.diagnostic.sawModelOutput = true;
|
|
116241
116241
|
await onPartUpdated(ctx, event.properties.part);
|
|
116242
116242
|
return;
|
|
116243
116243
|
}
|
|
@@ -116383,7 +116383,8 @@ async function runPromptTurn(ctx, params) {
|
|
|
116383
116383
|
const turn = ctx.currentTurn;
|
|
116384
116384
|
const part = { type: "text", text: params.text };
|
|
116385
116385
|
ctx.promptMessageID = void 0;
|
|
116386
|
-
ctx.sawModelOutput = false;
|
|
116386
|
+
ctx.diagnostic.sawModelOutput = false;
|
|
116387
|
+
ctx.diagnostic.idleSec = void 0;
|
|
116387
116388
|
let assistant;
|
|
116388
116389
|
let returnedParts;
|
|
116389
116390
|
let networkError = null;
|
|
@@ -116443,7 +116444,7 @@ async function runPromptTurn(ctx, params) {
|
|
|
116443
116444
|
usage
|
|
116444
116445
|
};
|
|
116445
116446
|
}
|
|
116446
|
-
if (!ctx.sawModelOutput && finalText.trim().length === 0 && !usage) {
|
|
116447
|
+
if (!ctx.diagnostic.sawModelOutput && finalText.trim().length === 0 && !usage) {
|
|
116447
116448
|
return {
|
|
116448
116449
|
success: false,
|
|
116449
116450
|
output: finalText,
|
|
@@ -116568,19 +116569,18 @@ function startInnerActivityWatchdog(params) {
|
|
|
116568
116569
|
const id = setInterval(() => {
|
|
116569
116570
|
if (fired) return;
|
|
116570
116571
|
const idleMs = performance7.now() - params.ctx.lastEventAt;
|
|
116571
|
-
const compiledMs = params.ctx.sawModelOutput ? params.timeoutMs : AGENT_FIRST_EVENT_TIMEOUT_MS;
|
|
116572
|
+
const compiledMs = params.ctx.diagnostic.sawModelOutput ? params.timeoutMs : AGENT_FIRST_EVENT_TIMEOUT_MS;
|
|
116572
116573
|
const budgetMs = everFired ? compiledMs : watchdogBudgetMs(
|
|
116573
116574
|
compiledMs,
|
|
116574
|
-
params.ctx.sawModelOutput ? "PULLFROG_E2E_ACTIVITY_TIMEOUT_MS" : "PULLFROG_E2E_FIRST_EVENT_TIMEOUT_MS"
|
|
116575
|
+
params.ctx.diagnostic.sawModelOutput ? "PULLFROG_E2E_ACTIVITY_TIMEOUT_MS" : "PULLFROG_E2E_FIRST_EVENT_TIMEOUT_MS"
|
|
116575
116576
|
);
|
|
116576
116577
|
if (idleMs <= budgetMs) return;
|
|
116577
116578
|
fired = true;
|
|
116578
116579
|
everFired = true;
|
|
116579
116580
|
const idleSec = Math.round(idleMs / 1e3);
|
|
116580
116581
|
params.ctx.diagnostic.idleSec = idleSec;
|
|
116581
|
-
params.ctx.diagnostic.sawModelOutput = params.ctx.sawModelOutput;
|
|
116582
116582
|
log2.info(
|
|
116583
|
-
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`
|
|
116583
|
+
params.ctx.diagnostic.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`
|
|
116584
116584
|
);
|
|
116585
116585
|
params.abortTurn();
|
|
116586
116586
|
try {
|
|
@@ -116724,7 +116724,6 @@ var opencode = agent({
|
|
|
116724
116724
|
currentTurn: null,
|
|
116725
116725
|
eventCount: 0,
|
|
116726
116726
|
lastEventAt: performance7.now(),
|
|
116727
|
-
sawModelOutput: false,
|
|
116728
116727
|
promptMessageID: void 0,
|
|
116729
116728
|
taskDispatchByCallID: /* @__PURE__ */ new Map(),
|
|
116730
116729
|
loggedToolCallIDs: /* @__PURE__ */ new Set(),
|
|
@@ -116788,7 +116787,9 @@ var opencode = agent({
|
|
|
116788
116787
|
);
|
|
116789
116788
|
};
|
|
116790
116789
|
const standDownIfRecovered = (turn) => {
|
|
116791
|
-
if (watchdog.firedThisTurn()
|
|
116790
|
+
if (!watchdog.firedThisTurn() || !turn.success) return turn;
|
|
116791
|
+
runnerCtx.diagnostic.idleSec = void 0;
|
|
116792
|
+
ctx.onTurnRecovered?.();
|
|
116792
116793
|
return turn;
|
|
116793
116794
|
};
|
|
116794
116795
|
const result = await attempt(text);
|
|
@@ -196276,6 +196277,43 @@ function resolveCwd(cwd) {
|
|
|
196276
196277
|
if (isAbsolute2(cwd)) return cwd;
|
|
196277
196278
|
return workspace ? resolve2(workspace, cwd) : cwd;
|
|
196278
196279
|
}
|
|
196280
|
+
var DISPATCH_PAYLOAD_KEY = '"~pullfrog"';
|
|
196281
|
+
function sliceBalancedObject(text, open) {
|
|
196282
|
+
let depth = 0;
|
|
196283
|
+
let inString = false;
|
|
196284
|
+
for (let i2 = open; i2 < text.length; i2++) {
|
|
196285
|
+
const char = text[i2];
|
|
196286
|
+
if (inString) {
|
|
196287
|
+
if (char === "\\") i2++;
|
|
196288
|
+
else if (char === '"') inString = false;
|
|
196289
|
+
continue;
|
|
196290
|
+
}
|
|
196291
|
+
if (char === '"') inString = true;
|
|
196292
|
+
else if (char === "{") depth++;
|
|
196293
|
+
else if (char === "}" && --depth === 0) return text.slice(open, i2 + 1);
|
|
196294
|
+
}
|
|
196295
|
+
return void 0;
|
|
196296
|
+
}
|
|
196297
|
+
function findEmbeddedDispatchPayload(text) {
|
|
196298
|
+
const limit = text.lastIndexOf(DISPATCH_PAYLOAD_KEY);
|
|
196299
|
+
if (limit === -1) return void 0;
|
|
196300
|
+
for (let open = text.indexOf("{"); open !== -1 && open < limit; open = text.indexOf("{", open + 1)) {
|
|
196301
|
+
const candidate = sliceBalancedObject(text, open);
|
|
196302
|
+
if (!candidate) continue;
|
|
196303
|
+
try {
|
|
196304
|
+
const parsed2 = JSON.parse(candidate);
|
|
196305
|
+
if (JsonPayload.allows(parsed2)) return parsed2;
|
|
196306
|
+
} catch {
|
|
196307
|
+
}
|
|
196308
|
+
}
|
|
196309
|
+
return void 0;
|
|
196310
|
+
}
|
|
196311
|
+
function assertDispatchPayloadIntact(promptInput) {
|
|
196312
|
+
if (!findEmbeddedDispatchPayload(promptInput)) return;
|
|
196313
|
+
throw new Error(
|
|
196314
|
+
"this workflow wraps `${{ inputs.prompt }}` in other text, so Pullfrog's dispatch payload can't be read and the run would lose its pull request context, its progress comment, and its standing instructions. in `.github/workflows/pullfrog.yml`, set `prompt:` to exactly `${{ inputs.prompt }}`, and move your own preamble into Standing instructions in the Pullfrog console."
|
|
196315
|
+
);
|
|
196316
|
+
}
|
|
196279
196317
|
function resolvePromptInput() {
|
|
196280
196318
|
const promptInput = core7.getInput("prompt");
|
|
196281
196319
|
const promptFile = core7.getInput("prompt_file");
|
|
@@ -196292,9 +196330,9 @@ function resolvePromptInput() {
|
|
|
196292
196330
|
try {
|
|
196293
196331
|
parsed2 = JSON.parse(promptInput);
|
|
196294
196332
|
} catch {
|
|
196295
|
-
return promptInput;
|
|
196296
196333
|
}
|
|
196297
196334
|
if (!parsed2 || typeof parsed2 !== "object" || !("~pullfrog" in parsed2)) {
|
|
196335
|
+
assertDispatchPayloadIntact(promptInput);
|
|
196298
196336
|
return promptInput;
|
|
196299
196337
|
}
|
|
196300
196338
|
const jsonPayload = JsonPayload.assert(parsed2);
|
|
@@ -197472,7 +197510,7 @@ ${body}`, comment: body };
|
|
|
197472
197510
|
${body}`, comment: body };
|
|
197473
197511
|
}
|
|
197474
197512
|
if (hangBody) {
|
|
197475
|
-
const explained = input.agentDiagnostic?.lastProviderError !== void 0;
|
|
197513
|
+
const explained = input.agentDiagnostic?.lastProviderError !== void 0 || input.agentDiagnostic?.sawModelOutput === false;
|
|
197476
197514
|
return {
|
|
197477
197515
|
summary: `### \u274C Pullfrog failed
|
|
197478
197516
|
|
|
@@ -199265,7 +199303,7 @@ async function runCli4(input) {
|
|
|
199265
199303
|
}
|
|
199266
199304
|
|
|
199267
199305
|
// cli.ts
|
|
199268
|
-
var VERSION10 = "0.1.
|
|
199306
|
+
var VERSION10 = "0.1.63";
|
|
199269
199307
|
var bin = basename2(process.argv[1] || "");
|
|
199270
199308
|
var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
|
|
199271
199309
|
var rawArgs = process.argv.slice(2);
|
package/dist/index.js
CHANGED
|
@@ -105191,7 +105191,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
105191
105191
|
// package.json
|
|
105192
105192
|
var package_default = {
|
|
105193
105193
|
name: "pullfrog",
|
|
105194
|
-
version: "0.1.
|
|
105194
|
+
version: "0.1.63",
|
|
105195
105195
|
type: "module",
|
|
105196
105196
|
bin: {
|
|
105197
105197
|
pullfrog: "dist/cli.mjs",
|
|
@@ -114117,7 +114117,7 @@ function isModelOutput(ctx, part) {
|
|
|
114117
114117
|
async function dispatchEvent(ctx, event) {
|
|
114118
114118
|
if (event.type === "message.part.updated") {
|
|
114119
114119
|
ctx.lastEventAt = performance7.now();
|
|
114120
|
-
if (isModelOutput(ctx, event.properties.part)) ctx.sawModelOutput = true;
|
|
114120
|
+
if (isModelOutput(ctx, event.properties.part)) ctx.diagnostic.sawModelOutput = true;
|
|
114121
114121
|
await onPartUpdated(ctx, event.properties.part);
|
|
114122
114122
|
return;
|
|
114123
114123
|
}
|
|
@@ -114263,7 +114263,8 @@ async function runPromptTurn(ctx, params) {
|
|
|
114263
114263
|
const turn = ctx.currentTurn;
|
|
114264
114264
|
const part = { type: "text", text: params.text };
|
|
114265
114265
|
ctx.promptMessageID = void 0;
|
|
114266
|
-
ctx.sawModelOutput = false;
|
|
114266
|
+
ctx.diagnostic.sawModelOutput = false;
|
|
114267
|
+
ctx.diagnostic.idleSec = void 0;
|
|
114267
114268
|
let assistant;
|
|
114268
114269
|
let returnedParts;
|
|
114269
114270
|
let networkError = null;
|
|
@@ -114323,7 +114324,7 @@ async function runPromptTurn(ctx, params) {
|
|
|
114323
114324
|
usage
|
|
114324
114325
|
};
|
|
114325
114326
|
}
|
|
114326
|
-
if (!ctx.sawModelOutput && finalText.trim().length === 0 && !usage) {
|
|
114327
|
+
if (!ctx.diagnostic.sawModelOutput && finalText.trim().length === 0 && !usage) {
|
|
114327
114328
|
return {
|
|
114328
114329
|
success: false,
|
|
114329
114330
|
output: finalText,
|
|
@@ -114448,19 +114449,18 @@ function startInnerActivityWatchdog(params) {
|
|
|
114448
114449
|
const id = setInterval(() => {
|
|
114449
114450
|
if (fired) return;
|
|
114450
114451
|
const idleMs = performance7.now() - params.ctx.lastEventAt;
|
|
114451
|
-
const compiledMs = params.ctx.sawModelOutput ? params.timeoutMs : AGENT_FIRST_EVENT_TIMEOUT_MS;
|
|
114452
|
+
const compiledMs = params.ctx.diagnostic.sawModelOutput ? params.timeoutMs : AGENT_FIRST_EVENT_TIMEOUT_MS;
|
|
114452
114453
|
const budgetMs = everFired ? compiledMs : watchdogBudgetMs(
|
|
114453
114454
|
compiledMs,
|
|
114454
|
-
params.ctx.sawModelOutput ? "PULLFROG_E2E_ACTIVITY_TIMEOUT_MS" : "PULLFROG_E2E_FIRST_EVENT_TIMEOUT_MS"
|
|
114455
|
+
params.ctx.diagnostic.sawModelOutput ? "PULLFROG_E2E_ACTIVITY_TIMEOUT_MS" : "PULLFROG_E2E_FIRST_EVENT_TIMEOUT_MS"
|
|
114455
114456
|
);
|
|
114456
114457
|
if (idleMs <= budgetMs) return;
|
|
114457
114458
|
fired = true;
|
|
114458
114459
|
everFired = true;
|
|
114459
114460
|
const idleSec = Math.round(idleMs / 1e3);
|
|
114460
114461
|
params.ctx.diagnostic.idleSec = idleSec;
|
|
114461
|
-
params.ctx.diagnostic.sawModelOutput = params.ctx.sawModelOutput;
|
|
114462
114462
|
log.info(
|
|
114463
|
-
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`
|
|
114463
|
+
params.ctx.diagnostic.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`
|
|
114464
114464
|
);
|
|
114465
114465
|
params.abortTurn();
|
|
114466
114466
|
try {
|
|
@@ -114604,7 +114604,6 @@ var opencode = agent({
|
|
|
114604
114604
|
currentTurn: null,
|
|
114605
114605
|
eventCount: 0,
|
|
114606
114606
|
lastEventAt: performance7.now(),
|
|
114607
|
-
sawModelOutput: false,
|
|
114608
114607
|
promptMessageID: void 0,
|
|
114609
114608
|
taskDispatchByCallID: /* @__PURE__ */ new Map(),
|
|
114610
114609
|
loggedToolCallIDs: /* @__PURE__ */ new Set(),
|
|
@@ -114668,7 +114667,9 @@ var opencode = agent({
|
|
|
114668
114667
|
);
|
|
114669
114668
|
};
|
|
114670
114669
|
const standDownIfRecovered = (turn) => {
|
|
114671
|
-
if (watchdog.firedThisTurn()
|
|
114670
|
+
if (!watchdog.firedThisTurn() || !turn.success) return turn;
|
|
114671
|
+
runnerCtx.diagnostic.idleSec = void 0;
|
|
114672
|
+
ctx.onTurnRecovered?.();
|
|
114672
114673
|
return turn;
|
|
114673
114674
|
};
|
|
114674
114675
|
const result = await attempt(text);
|
|
@@ -194156,6 +194157,43 @@ function resolveCwd(cwd) {
|
|
|
194156
194157
|
if (isAbsolute2(cwd)) return cwd;
|
|
194157
194158
|
return workspace ? resolve2(workspace, cwd) : cwd;
|
|
194158
194159
|
}
|
|
194160
|
+
var DISPATCH_PAYLOAD_KEY = '"~pullfrog"';
|
|
194161
|
+
function sliceBalancedObject(text, open) {
|
|
194162
|
+
let depth = 0;
|
|
194163
|
+
let inString = false;
|
|
194164
|
+
for (let i = open; i < text.length; i++) {
|
|
194165
|
+
const char = text[i];
|
|
194166
|
+
if (inString) {
|
|
194167
|
+
if (char === "\\") i++;
|
|
194168
|
+
else if (char === '"') inString = false;
|
|
194169
|
+
continue;
|
|
194170
|
+
}
|
|
194171
|
+
if (char === '"') inString = true;
|
|
194172
|
+
else if (char === "{") depth++;
|
|
194173
|
+
else if (char === "}" && --depth === 0) return text.slice(open, i + 1);
|
|
194174
|
+
}
|
|
194175
|
+
return void 0;
|
|
194176
|
+
}
|
|
194177
|
+
function findEmbeddedDispatchPayload(text) {
|
|
194178
|
+
const limit = text.lastIndexOf(DISPATCH_PAYLOAD_KEY);
|
|
194179
|
+
if (limit === -1) return void 0;
|
|
194180
|
+
for (let open = text.indexOf("{"); open !== -1 && open < limit; open = text.indexOf("{", open + 1)) {
|
|
194181
|
+
const candidate = sliceBalancedObject(text, open);
|
|
194182
|
+
if (!candidate) continue;
|
|
194183
|
+
try {
|
|
194184
|
+
const parsed2 = JSON.parse(candidate);
|
|
194185
|
+
if (JsonPayload.allows(parsed2)) return parsed2;
|
|
194186
|
+
} catch {
|
|
194187
|
+
}
|
|
194188
|
+
}
|
|
194189
|
+
return void 0;
|
|
194190
|
+
}
|
|
194191
|
+
function assertDispatchPayloadIntact(promptInput) {
|
|
194192
|
+
if (!findEmbeddedDispatchPayload(promptInput)) return;
|
|
194193
|
+
throw new Error(
|
|
194194
|
+
"this workflow wraps `${{ inputs.prompt }}` in other text, so Pullfrog's dispatch payload can't be read and the run would lose its pull request context, its progress comment, and its standing instructions. in `.github/workflows/pullfrog.yml`, set `prompt:` to exactly `${{ inputs.prompt }}`, and move your own preamble into Standing instructions in the Pullfrog console."
|
|
194195
|
+
);
|
|
194196
|
+
}
|
|
194159
194197
|
function resolvePromptInput() {
|
|
194160
194198
|
const promptInput = core7.getInput("prompt");
|
|
194161
194199
|
const promptFile = core7.getInput("prompt_file");
|
|
@@ -194172,9 +194210,9 @@ function resolvePromptInput() {
|
|
|
194172
194210
|
try {
|
|
194173
194211
|
parsed2 = JSON.parse(promptInput);
|
|
194174
194212
|
} catch {
|
|
194175
|
-
return promptInput;
|
|
194176
194213
|
}
|
|
194177
194214
|
if (!parsed2 || typeof parsed2 !== "object" || !("~pullfrog" in parsed2)) {
|
|
194215
|
+
assertDispatchPayloadIntact(promptInput);
|
|
194178
194216
|
return promptInput;
|
|
194179
194217
|
}
|
|
194180
194218
|
const jsonPayload = JsonPayload.assert(parsed2);
|
|
@@ -195352,7 +195390,7 @@ ${body}`, comment: body };
|
|
|
195352
195390
|
${body}`, comment: body };
|
|
195353
195391
|
}
|
|
195354
195392
|
if (hangBody) {
|
|
195355
|
-
const explained = input.agentDiagnostic?.lastProviderError !== void 0;
|
|
195393
|
+
const explained = input.agentDiagnostic?.lastProviderError !== void 0 || input.agentDiagnostic?.sawModelOutput === false;
|
|
195356
195394
|
return {
|
|
195357
195395
|
summary: `### \u274C Pullfrog failed
|
|
195358
195396
|
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
* `"activity timeout"` or `"agent still pending"` AND none of the
|
|
46
46
|
* above matched. The harness keeps structured diagnostic state on
|
|
47
47
|
* `toolState.agentDiagnostic`; `formatAgentHangBody` renders that into
|
|
48
|
-
* the job summary. The PR comment
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
48
|
+
* the job summary. The PR comment keeps that same body whenever the hang
|
|
49
|
+
* is EXPLAINED — a classified provider error (#778, #1183) or a provider
|
|
50
|
+
* that never returned a first token — and otherwise collapses to a
|
|
51
|
+
* one-line `**Run failed.** [View the logs →]`, because watchdog jargon,
|
|
52
|
+
* event counts and a benign stderr tail are operator-grade detail that
|
|
53
|
+
* only alarm the average user.
|
|
54
54
|
*
|
|
55
55
|
* 6. Default — the job summary gets a plain-English lead sentence plus the
|
|
56
56
|
* raw error in a fenced code block under the `### ❌ Pullfrog failed`
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
*
|
|
60
60
|
* Net: the actionable classifications (billing, API-key, model-not-found,
|
|
61
61
|
* no-provider-available, context-overflow, transient-upstream) render identical
|
|
62
|
-
* bodies on both surfaces; the non-actionable ones (hang,
|
|
62
|
+
* bodies on both surfaces; the non-actionable ones (unexplained hang,
|
|
63
63
|
* generic) keep the forensics in the Actions job summary and show a calm
|
|
64
64
|
* one-liner in the PR comment, whose footer already carries Pullfrog
|
|
65
65
|
* branding + rerun links.
|