pullfrog 0.1.61 → 0.1.62
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 +52 -21
- package/dist/index.js +51 -20
- package/dist/utils/providerErrors.d.ts +6 -0
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -107293,6 +107293,9 @@ function isProviderNoRoutableEndpoints(text) {
|
|
|
107293
107293
|
function isOpenRouterKeyLimitExceeded(text) {
|
|
107294
107294
|
return /Key limit exceeded \(total limit\)/i.test(text) || /openrouter\.ai\/[^\s"')]*\/keys\//i.test(text);
|
|
107295
107295
|
}
|
|
107296
|
+
function isProviderMissingCredential(text) {
|
|
107297
|
+
return /API key is missing\. Pass it using the/i.test(text) || /Missing Authentication header/i.test(text);
|
|
107298
|
+
}
|
|
107296
107299
|
function isTransientUpstreamError(text) {
|
|
107297
107300
|
return /API Error:\s*5\d\d/i.test(text) || /\bOverloaded\b/.test(text) || /"error_type"\s*:\s*"(?:provider_unavailable|timeout)"/i.test(text) || /Streaming response failed:\s*\[5\d\d\]/i.test(text);
|
|
107298
107301
|
}
|
|
@@ -107355,7 +107358,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
107355
107358
|
// package.json
|
|
107356
107359
|
var package_default = {
|
|
107357
107360
|
name: "pullfrog",
|
|
107358
|
-
version: "0.1.
|
|
107361
|
+
version: "0.1.62",
|
|
107359
107362
|
type: "module",
|
|
107360
107363
|
bin: {
|
|
107361
107364
|
pullfrog: "dist/cli.mjs",
|
|
@@ -108446,7 +108449,6 @@ function getUnsubmittedReview(toolState, expectsReviewOutput2 = toolState.hadPro
|
|
|
108446
108449
|
}
|
|
108447
108450
|
function expectsReviewOutput(ctx) {
|
|
108448
108451
|
if (ctx.toolState.hadProgressComment) return true;
|
|
108449
|
-
if (ctx.payload.progressComments) return false;
|
|
108450
108452
|
return ctx.payload.event.silent !== true && ctx.payload.event.issue_number !== void 0;
|
|
108451
108453
|
}
|
|
108452
108454
|
function buildStopHookPrompt(failure2) {
|
|
@@ -108661,6 +108663,7 @@ async function runPostRunRetryLoop(params) {
|
|
|
108661
108663
|
result = preResume;
|
|
108662
108664
|
break;
|
|
108663
108665
|
}
|
|
108666
|
+
if (onlySummaryStale) result = { ...result, output: preResume.output || result.output };
|
|
108664
108667
|
gateResumeCount++;
|
|
108665
108668
|
}
|
|
108666
108669
|
if (gateResumeCount > 0 && result.success && hasPostRunIssues(finalIssues)) {
|
|
@@ -116005,24 +116008,23 @@ async function installOpencodeCli(params) {
|
|
|
116005
116008
|
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.";
|
|
116006
116009
|
function autoSelectModel() {
|
|
116007
116010
|
const authorized2 = getAuthorizedModels();
|
|
116008
|
-
|
|
116009
|
-
|
|
116010
|
-
|
|
116011
|
-
|
|
116012
|
-
|
|
116013
|
-
|
|
116014
|
-
|
|
116015
|
-
|
|
116016
|
-
log2.info(
|
|
116017
|
-
`\xBB model: ${match3.resolve} (auto-selected${match3.preferred ? " \u2014 preferred" : ""} curated match)`
|
|
116018
|
-
);
|
|
116019
|
-
log2.warning(`\xBB model auto-selected. ${AUTO_SELECT_WARNING}`);
|
|
116020
|
-
return match3.resolve;
|
|
116021
|
-
}
|
|
116011
|
+
const selectable = modelAliases.filter((a2) => !a2.hidden && !a2.fallback && !a2.routing);
|
|
116012
|
+
const servable = selectable.filter((a2) => {
|
|
116013
|
+
const envVars = getModelEnvVars(a2.resolve);
|
|
116014
|
+
return envVars.length === 0 || envVars.some((name) => process.env[name]);
|
|
116015
|
+
});
|
|
116016
|
+
const pick4 = (list) => list.find((a2) => a2.preferred) ?? list[0];
|
|
116017
|
+
const match3 = pick4(servable.filter((a2) => authorized2.has(a2.resolve))) ?? pick4(servable);
|
|
116018
|
+
if (match3) {
|
|
116022
116019
|
log2.info(
|
|
116023
|
-
`\xBB
|
|
116020
|
+
`\xBB model: ${match3.resolve} (auto-selected${match3.preferred ? " \u2014 preferred" : ""} curated match)`
|
|
116024
116021
|
);
|
|
116022
|
+
log2.warning(`\xBB model auto-selected. ${AUTO_SELECT_WARNING}`);
|
|
116023
|
+
return match3.resolve;
|
|
116025
116024
|
}
|
|
116025
|
+
log2.info(
|
|
116026
|
+
`\xBB opencode has ${authorized2.size} models but none match curated aliases and none hold a credential \u2014 letting OpenCode auto-select: ${[...authorized2].join(", ")}`
|
|
116027
|
+
);
|
|
116026
116028
|
log2.warning(`\xBB no model resolved. letting OpenCode auto-select. ${AUTO_SELECT_WARNING}`);
|
|
116027
116029
|
return void 0;
|
|
116028
116030
|
}
|
|
@@ -188634,8 +188636,8 @@ function validatePushDestination(repoState, branch, cwd) {
|
|
|
188634
188636
|
throw new Error(
|
|
188635
188637
|
`Push blocked: destination does not match expected repository.
|
|
188636
188638
|
Expected: ${pushUrl}
|
|
188637
|
-
Actual: ${dest.url}
|
|
188638
|
-
Git configuration may have been tampered with.`
|
|
188639
|
+
Actual: remote '${dest.remoteName}' -> ${dest.url}
|
|
188640
|
+
Git configuration may have been tampered with, or a url.*.insteadOf rewrite is in effect.`
|
|
188639
188641
|
);
|
|
188640
188642
|
}
|
|
188641
188643
|
return dest;
|
|
@@ -190757,6 +190759,9 @@ async function configureRepoGit(params) {
|
|
|
190757
190759
|
removeIncludeIfEntries(repoDir);
|
|
190758
190760
|
const originUrl = `https://github.com/${params.owner}/${params.name}.git`;
|
|
190759
190761
|
$("git", ["remote", "set-url", "origin", originUrl], { cwd: repoDir });
|
|
190762
|
+
$("git", ["config", "--local", "--replace-all", "remote.origin.pushurl", originUrl], {
|
|
190763
|
+
cwd: repoDir
|
|
190764
|
+
});
|
|
190760
190765
|
repoState.pushUrl = originUrl;
|
|
190761
190766
|
$("git", ["config", "--local", "credential.helper", ""], { cwd: repoDir });
|
|
190762
190767
|
repoState.initialHead = captureInitialHead(repoDir);
|
|
@@ -191095,6 +191100,9 @@ async function checkoutPrBranch(pr, params) {
|
|
|
191095
191100
|
$("git", ["remote", "set-url", remoteName, forkUrl], { log: false });
|
|
191096
191101
|
log2.debug(`\xBB updated remote '${remoteName}' for fork ${pr.headRepoFullName}`);
|
|
191097
191102
|
}
|
|
191103
|
+
$("git", ["config", "--local", "--replace-all", `remote.${remoteName}.pushurl`, forkUrl], {
|
|
191104
|
+
log: false
|
|
191105
|
+
});
|
|
191098
191106
|
$("git", ["config", `branch.${localBranch}.pushRemote`, remoteName], { log: false });
|
|
191099
191107
|
$("git", ["config", `branch.${localBranch}.merge`, `refs/heads/${pr.headRef}`], { log: false });
|
|
191100
191108
|
log2.debug(`\xBB configured branch '${localBranch}' to push to '${remoteName}/${pr.headRef}'`);
|
|
@@ -196916,7 +196924,7 @@ async function handleAgentResult(ctx) {
|
|
|
196916
196924
|
const mode = toolState.selectedMode;
|
|
196917
196925
|
const isReviewMode = mode === "Review" || mode === "IncrementalReview";
|
|
196918
196926
|
const payload = ctx.toolContext.payload;
|
|
196919
|
-
const hasCommentTarget = toolState.hadProgressComment ||
|
|
196927
|
+
const hasCommentTarget = toolState.hadProgressComment || payload.event.issue_number !== void 0;
|
|
196920
196928
|
if (!isReviewMode && !toolState.wasUpdated && hasCommentTarget && !ctx.silent) {
|
|
196921
196929
|
const tracker = toolState.todoTracker;
|
|
196922
196930
|
if (tracker) {
|
|
@@ -197350,6 +197358,19 @@ ${input.errorMessage}
|
|
|
197350
197358
|
\`\`\``
|
|
197351
197359
|
].join("\n");
|
|
197352
197360
|
}
|
|
197361
|
+
function formatProviderMissingCredential(input) {
|
|
197362
|
+
return [
|
|
197363
|
+
"**No credential reached the model provider.**",
|
|
197364
|
+
"",
|
|
197365
|
+
"The run started without a key for the provider it ended up using, so the request was refused before any model work happened. Nothing was billed, and no key of yours was rejected \u2014 add a provider key, or pick a model you already have one for.",
|
|
197366
|
+
"",
|
|
197367
|
+
`[Configure model \u2192](${getApiUrl()}/console/${input.owner}/${input.name})`,
|
|
197368
|
+
"",
|
|
197369
|
+
`\`\`\`
|
|
197370
|
+
${input.errorMessage}
|
|
197371
|
+
\`\`\``
|
|
197372
|
+
].join("\n");
|
|
197373
|
+
}
|
|
197353
197374
|
function formatProviderModelNotFoundSummary(input) {
|
|
197354
197375
|
return `The configured model is no longer available in OpenCode's catalog. Pick a different model in the Pullfrog console for \`${input.owner}/${input.name}\`, or contact support if this persists.
|
|
197355
197376
|
|
|
@@ -197395,6 +197416,16 @@ ${body}`, comment: body };
|
|
|
197395
197416
|
});
|
|
197396
197417
|
return { summary: `### \u274C Pullfrog failed
|
|
197397
197418
|
|
|
197419
|
+
${body}`, comment: body };
|
|
197420
|
+
}
|
|
197421
|
+
if (isProviderMissingCredential(input.errorMessage)) {
|
|
197422
|
+
const body = formatProviderMissingCredential({
|
|
197423
|
+
owner: input.repo.owner,
|
|
197424
|
+
name: input.repo.name,
|
|
197425
|
+
errorMessage: input.errorMessage
|
|
197426
|
+
});
|
|
197427
|
+
return { summary: `### \u274C Pullfrog failed
|
|
197428
|
+
|
|
197398
197429
|
${body}`, comment: body };
|
|
197399
197430
|
}
|
|
197400
197431
|
const apiKeySource = hangBody ?? input.errorMessage;
|
|
@@ -199234,7 +199265,7 @@ async function runCli4(input) {
|
|
|
199234
199265
|
}
|
|
199235
199266
|
|
|
199236
199267
|
// cli.ts
|
|
199237
|
-
var VERSION10 = "0.1.
|
|
199268
|
+
var VERSION10 = "0.1.62";
|
|
199238
199269
|
var bin = basename2(process.argv[1] || "");
|
|
199239
199270
|
var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
|
|
199240
199271
|
var rawArgs = process.argv.slice(2);
|
package/dist/index.js
CHANGED
|
@@ -105126,6 +105126,9 @@ function isProviderNoRoutableEndpoints(text) {
|
|
|
105126
105126
|
function isOpenRouterKeyLimitExceeded(text) {
|
|
105127
105127
|
return /Key limit exceeded \(total limit\)/i.test(text) || /openrouter\.ai\/[^\s"')]*\/keys\//i.test(text);
|
|
105128
105128
|
}
|
|
105129
|
+
function isProviderMissingCredential(text) {
|
|
105130
|
+
return /API key is missing\. Pass it using the/i.test(text) || /Missing Authentication header/i.test(text);
|
|
105131
|
+
}
|
|
105129
105132
|
function isTransientUpstreamError(text) {
|
|
105130
105133
|
return /API Error:\s*5\d\d/i.test(text) || /\bOverloaded\b/.test(text) || /"error_type"\s*:\s*"(?:provider_unavailable|timeout)"/i.test(text) || /Streaming response failed:\s*\[5\d\d\]/i.test(text);
|
|
105131
105134
|
}
|
|
@@ -105188,7 +105191,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
105188
105191
|
// package.json
|
|
105189
105192
|
var package_default = {
|
|
105190
105193
|
name: "pullfrog",
|
|
105191
|
-
version: "0.1.
|
|
105194
|
+
version: "0.1.62",
|
|
105192
105195
|
type: "module",
|
|
105193
105196
|
bin: {
|
|
105194
105197
|
pullfrog: "dist/cli.mjs",
|
|
@@ -106279,7 +106282,6 @@ function getUnsubmittedReview(toolState, expectsReviewOutput2 = toolState.hadPro
|
|
|
106279
106282
|
}
|
|
106280
106283
|
function expectsReviewOutput(ctx) {
|
|
106281
106284
|
if (ctx.toolState.hadProgressComment) return true;
|
|
106282
|
-
if (ctx.payload.progressComments) return false;
|
|
106283
106285
|
return ctx.payload.event.silent !== true && ctx.payload.event.issue_number !== void 0;
|
|
106284
106286
|
}
|
|
106285
106287
|
function buildStopHookPrompt(failure2) {
|
|
@@ -106494,6 +106496,7 @@ async function runPostRunRetryLoop(params) {
|
|
|
106494
106496
|
result = preResume;
|
|
106495
106497
|
break;
|
|
106496
106498
|
}
|
|
106499
|
+
if (onlySummaryStale) result = { ...result, output: preResume.output || result.output };
|
|
106497
106500
|
gateResumeCount++;
|
|
106498
106501
|
}
|
|
106499
106502
|
if (gateResumeCount > 0 && result.success && hasPostRunIssues(finalIssues)) {
|
|
@@ -113885,24 +113888,23 @@ async function installOpencodeCli(params) {
|
|
|
113885
113888
|
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.";
|
|
113886
113889
|
function autoSelectModel() {
|
|
113887
113890
|
const authorized2 = getAuthorizedModels();
|
|
113888
|
-
|
|
113889
|
-
|
|
113890
|
-
|
|
113891
|
-
|
|
113892
|
-
|
|
113893
|
-
|
|
113894
|
-
|
|
113895
|
-
|
|
113896
|
-
log.info(
|
|
113897
|
-
`\xBB model: ${match3.resolve} (auto-selected${match3.preferred ? " \u2014 preferred" : ""} curated match)`
|
|
113898
|
-
);
|
|
113899
|
-
log.warning(`\xBB model auto-selected. ${AUTO_SELECT_WARNING}`);
|
|
113900
|
-
return match3.resolve;
|
|
113901
|
-
}
|
|
113891
|
+
const selectable = modelAliases.filter((a) => !a.hidden && !a.fallback && !a.routing);
|
|
113892
|
+
const servable = selectable.filter((a) => {
|
|
113893
|
+
const envVars = getModelEnvVars(a.resolve);
|
|
113894
|
+
return envVars.length === 0 || envVars.some((name) => process.env[name]);
|
|
113895
|
+
});
|
|
113896
|
+
const pick4 = (list) => list.find((a) => a.preferred) ?? list[0];
|
|
113897
|
+
const match3 = pick4(servable.filter((a) => authorized2.has(a.resolve))) ?? pick4(servable);
|
|
113898
|
+
if (match3) {
|
|
113902
113899
|
log.info(
|
|
113903
|
-
`\xBB
|
|
113900
|
+
`\xBB model: ${match3.resolve} (auto-selected${match3.preferred ? " \u2014 preferred" : ""} curated match)`
|
|
113904
113901
|
);
|
|
113902
|
+
log.warning(`\xBB model auto-selected. ${AUTO_SELECT_WARNING}`);
|
|
113903
|
+
return match3.resolve;
|
|
113905
113904
|
}
|
|
113905
|
+
log.info(
|
|
113906
|
+
`\xBB opencode has ${authorized2.size} models but none match curated aliases and none hold a credential \u2014 letting OpenCode auto-select: ${[...authorized2].join(", ")}`
|
|
113907
|
+
);
|
|
113906
113908
|
log.warning(`\xBB no model resolved. letting OpenCode auto-select. ${AUTO_SELECT_WARNING}`);
|
|
113907
113909
|
return void 0;
|
|
113908
113910
|
}
|
|
@@ -186514,8 +186516,8 @@ function validatePushDestination(repoState, branch, cwd) {
|
|
|
186514
186516
|
throw new Error(
|
|
186515
186517
|
`Push blocked: destination does not match expected repository.
|
|
186516
186518
|
Expected: ${pushUrl}
|
|
186517
|
-
Actual: ${dest.url}
|
|
186518
|
-
Git configuration may have been tampered with.`
|
|
186519
|
+
Actual: remote '${dest.remoteName}' -> ${dest.url}
|
|
186520
|
+
Git configuration may have been tampered with, or a url.*.insteadOf rewrite is in effect.`
|
|
186519
186521
|
);
|
|
186520
186522
|
}
|
|
186521
186523
|
return dest;
|
|
@@ -188637,6 +188639,9 @@ async function configureRepoGit(params) {
|
|
|
188637
188639
|
removeIncludeIfEntries(repoDir);
|
|
188638
188640
|
const originUrl = `https://github.com/${params.owner}/${params.name}.git`;
|
|
188639
188641
|
$("git", ["remote", "set-url", "origin", originUrl], { cwd: repoDir });
|
|
188642
|
+
$("git", ["config", "--local", "--replace-all", "remote.origin.pushurl", originUrl], {
|
|
188643
|
+
cwd: repoDir
|
|
188644
|
+
});
|
|
188640
188645
|
repoState.pushUrl = originUrl;
|
|
188641
188646
|
$("git", ["config", "--local", "credential.helper", ""], { cwd: repoDir });
|
|
188642
188647
|
repoState.initialHead = captureInitialHead(repoDir);
|
|
@@ -188975,6 +188980,9 @@ async function checkoutPrBranch(pr, params) {
|
|
|
188975
188980
|
$("git", ["remote", "set-url", remoteName, forkUrl], { log: false });
|
|
188976
188981
|
log.debug(`\xBB updated remote '${remoteName}' for fork ${pr.headRepoFullName}`);
|
|
188977
188982
|
}
|
|
188983
|
+
$("git", ["config", "--local", "--replace-all", `remote.${remoteName}.pushurl`, forkUrl], {
|
|
188984
|
+
log: false
|
|
188985
|
+
});
|
|
188978
188986
|
$("git", ["config", `branch.${localBranch}.pushRemote`, remoteName], { log: false });
|
|
188979
188987
|
$("git", ["config", `branch.${localBranch}.merge`, `refs/heads/${pr.headRef}`], { log: false });
|
|
188980
188988
|
log.debug(`\xBB configured branch '${localBranch}' to push to '${remoteName}/${pr.headRef}'`);
|
|
@@ -194796,7 +194804,7 @@ async function handleAgentResult(ctx) {
|
|
|
194796
194804
|
const mode = toolState.selectedMode;
|
|
194797
194805
|
const isReviewMode = mode === "Review" || mode === "IncrementalReview";
|
|
194798
194806
|
const payload = ctx.toolContext.payload;
|
|
194799
|
-
const hasCommentTarget = toolState.hadProgressComment ||
|
|
194807
|
+
const hasCommentTarget = toolState.hadProgressComment || payload.event.issue_number !== void 0;
|
|
194800
194808
|
if (!isReviewMode && !toolState.wasUpdated && hasCommentTarget && !ctx.silent) {
|
|
194801
194809
|
const tracker = toolState.todoTracker;
|
|
194802
194810
|
if (tracker) {
|
|
@@ -195230,6 +195238,19 @@ ${input.errorMessage}
|
|
|
195230
195238
|
\`\`\``
|
|
195231
195239
|
].join("\n");
|
|
195232
195240
|
}
|
|
195241
|
+
function formatProviderMissingCredential(input) {
|
|
195242
|
+
return [
|
|
195243
|
+
"**No credential reached the model provider.**",
|
|
195244
|
+
"",
|
|
195245
|
+
"The run started without a key for the provider it ended up using, so the request was refused before any model work happened. Nothing was billed, and no key of yours was rejected \u2014 add a provider key, or pick a model you already have one for.",
|
|
195246
|
+
"",
|
|
195247
|
+
`[Configure model \u2192](${getApiUrl()}/console/${input.owner}/${input.name})`,
|
|
195248
|
+
"",
|
|
195249
|
+
`\`\`\`
|
|
195250
|
+
${input.errorMessage}
|
|
195251
|
+
\`\`\``
|
|
195252
|
+
].join("\n");
|
|
195253
|
+
}
|
|
195233
195254
|
function formatProviderModelNotFoundSummary(input) {
|
|
195234
195255
|
return `The configured model is no longer available in OpenCode's catalog. Pick a different model in the Pullfrog console for \`${input.owner}/${input.name}\`, or contact support if this persists.
|
|
195235
195256
|
|
|
@@ -195275,6 +195296,16 @@ ${body}`, comment: body };
|
|
|
195275
195296
|
});
|
|
195276
195297
|
return { summary: `### \u274C Pullfrog failed
|
|
195277
195298
|
|
|
195299
|
+
${body}`, comment: body };
|
|
195300
|
+
}
|
|
195301
|
+
if (isProviderMissingCredential(input.errorMessage)) {
|
|
195302
|
+
const body = formatProviderMissingCredential({
|
|
195303
|
+
owner: input.repo.owner,
|
|
195304
|
+
name: input.repo.name,
|
|
195305
|
+
errorMessage: input.errorMessage
|
|
195306
|
+
});
|
|
195307
|
+
return { summary: `### \u274C Pullfrog failed
|
|
195308
|
+
|
|
195278
195309
|
${body}`, comment: body };
|
|
195279
195310
|
}
|
|
195280
195311
|
const apiKeySource = hangBody ?? input.errorMessage;
|
|
@@ -50,6 +50,12 @@ export declare function isProviderNoRoutableEndpoints(text: string): boolean;
|
|
|
50
50
|
* …/settings/credits`) carries no `/keys/` path and correctly stays out.
|
|
51
51
|
*/
|
|
52
52
|
export declare function isOpenRouterKeyLimitExceeded(text: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* the provider was reached with NO credential at all — the AI SDK's shared `loadApiKey`
|
|
55
|
+
* refusal, so it is provider-agnostic. NOT `isApiKeyAuthError`, which is a key we hold
|
|
56
|
+
* being rejected: "rotate your key" names a credential that does not exist here.
|
|
57
|
+
*/
|
|
58
|
+
export declare function isProviderMissingCredential(text: string): boolean;
|
|
53
59
|
/**
|
|
54
60
|
* The upstream is having a moment: Anthropic's `API Error: 529 Overloaded`,
|
|
55
61
|
* OpenRouter's `provider_unavailable` / `timeout`, OpenCode Zen's `Streaming
|