pullfrog 0.1.89 → 0.1.90
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 +9 -4
- package/dist/index.js +7 -2
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal.js +142 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -107103,7 +107103,7 @@ var import_picocolors = __toESM(require_picocolors(), 1);
|
|
|
107103
107103
|
// package.json
|
|
107104
107104
|
var package_default = {
|
|
107105
107105
|
name: "pullfrog",
|
|
107106
|
-
version: "0.1.
|
|
107106
|
+
version: "0.1.90",
|
|
107107
107107
|
cliContractVersion: "1",
|
|
107108
107108
|
type: "module",
|
|
107109
107109
|
bin: {
|
|
@@ -196672,8 +196672,9 @@ function ResolveReviewThreadTool(ctx) {
|
|
|
196672
196672
|
}
|
|
196673
196673
|
|
|
196674
196674
|
// mcp/searchIssues.ts
|
|
196675
|
+
var TERM = /^[\p{L}\p{N}_./-]+$/u;
|
|
196675
196676
|
var SearchIssues = type({
|
|
196676
|
-
terms: type.string.
|
|
196677
|
+
terms: type.string.atMostLength(40).array().atLeastLength(1).atMostLength(5).describe("1-5 keywords from the issue; no GitHub qualifiers or query operators")
|
|
196677
196678
|
});
|
|
196678
196679
|
function SearchIssuesTool(ctx) {
|
|
196679
196680
|
return tool({
|
|
@@ -196681,6 +196682,10 @@ function SearchIssuesTool(ctx) {
|
|
|
196681
196682
|
description: "Find open or closed issues in this repository by keyword. Inspect promising matches with get_issue before deciding whether they are duplicates or related. Results are bounded, not an exhaustive duplicate check.",
|
|
196682
196683
|
parameters: SearchIssues,
|
|
196683
196684
|
execute: execute(async (params) => {
|
|
196685
|
+
const invalid = params.terms.find((term) => !TERM.test(term));
|
|
196686
|
+
if (invalid) {
|
|
196687
|
+
throw new Error(`search term "${invalid}" may contain only letters, digits and _ . / -`);
|
|
196688
|
+
}
|
|
196684
196689
|
const repoPath = `/repos/${ctx.repo.owner}/${ctx.repo.name}`.toLowerCase();
|
|
196685
196690
|
const terms = params.terms.map((term) => `"${term}"`).join(" ");
|
|
196686
196691
|
const response = await ctx.octokit.rest.search.issuesAndPullRequests({
|
|
@@ -202225,7 +202230,7 @@ function resolveTarget2(repo) {
|
|
|
202225
202230
|
return { owner: match3[1], repo: match3[2] };
|
|
202226
202231
|
}
|
|
202227
202232
|
function cliVersion() {
|
|
202228
|
-
const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.
|
|
202233
|
+
const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.90");
|
|
202229
202234
|
if (!parts) return "0.0.0";
|
|
202230
202235
|
return `${Number(parts[1])}.${Number(parts[2])}.${Number(parts[3])}`;
|
|
202231
202236
|
}
|
|
@@ -202392,7 +202397,7 @@ async function runCli8(input) {
|
|
|
202392
202397
|
}
|
|
202393
202398
|
|
|
202394
202399
|
// cli.ts
|
|
202395
|
-
var VERSION10 = "0.1.
|
|
202400
|
+
var VERSION10 = "0.1.90";
|
|
202396
202401
|
var bin = basename2(process.argv[1] || "");
|
|
202397
202402
|
var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
|
|
202398
202403
|
var rawArgs = process.argv.slice(2);
|
package/dist/index.js
CHANGED
|
@@ -105729,7 +105729,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
105729
105729
|
// package.json
|
|
105730
105730
|
var package_default = {
|
|
105731
105731
|
name: "pullfrog",
|
|
105732
|
-
version: "0.1.
|
|
105732
|
+
version: "0.1.90",
|
|
105733
105733
|
cliContractVersion: "1",
|
|
105734
105734
|
type: "module",
|
|
105735
105735
|
bin: {
|
|
@@ -193165,8 +193165,9 @@ function ResolveReviewThreadTool(ctx) {
|
|
|
193165
193165
|
}
|
|
193166
193166
|
|
|
193167
193167
|
// mcp/searchIssues.ts
|
|
193168
|
+
var TERM = /^[\p{L}\p{N}_./-]+$/u;
|
|
193168
193169
|
var SearchIssues = type({
|
|
193169
|
-
terms: type.string.
|
|
193170
|
+
terms: type.string.atMostLength(40).array().atLeastLength(1).atMostLength(5).describe("1-5 keywords from the issue; no GitHub qualifiers or query operators")
|
|
193170
193171
|
});
|
|
193171
193172
|
function SearchIssuesTool(ctx) {
|
|
193172
193173
|
return tool({
|
|
@@ -193174,6 +193175,10 @@ function SearchIssuesTool(ctx) {
|
|
|
193174
193175
|
description: "Find open or closed issues in this repository by keyword. Inspect promising matches with get_issue before deciding whether they are duplicates or related. Results are bounded, not an exhaustive duplicate check.",
|
|
193175
193176
|
parameters: SearchIssues,
|
|
193176
193177
|
execute: execute(async (params) => {
|
|
193178
|
+
const invalid = params.terms.find((term) => !TERM.test(term));
|
|
193179
|
+
if (invalid) {
|
|
193180
|
+
throw new Error(`search term "${invalid}" may contain only letters, digits and _ . / -`);
|
|
193181
|
+
}
|
|
193177
193182
|
const repoPath = `/repos/${ctx.repo.owner}/${ctx.repo.name}`.toLowerCase();
|
|
193178
193183
|
const terms = params.terms.map((term) => `"${term}"`).join(" ");
|
|
193179
193184
|
const response = await ctx.octokit.rest.search.issuesAndPullRequests({
|
package/dist/internal/index.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export { countOutstandingPullfrogThreads } from "../utils/outstandingThreads.ts"
|
|
|
24
24
|
export type { CreateProgressCommentTarget, ProgressComment, ProgressCommentType, } from "../utils/progressComment.ts";
|
|
25
25
|
export { createLeapingProgressComment, deleteProgressCommentApi, getProgressComment, updateProgressComment, } from "../utils/progressComment.ts";
|
|
26
26
|
export { PROVIDER_DASHBOARDS, type ProviderDashboard } from "../utils/providerDashboards.ts";
|
|
27
|
+
export { detectProviderError } from "../utils/providerErrors.ts";
|
|
27
28
|
export type { RunStatusCheckConclusion, RunStatusCheckOctokit, } from "../utils/runStatusCheck.ts";
|
|
28
29
|
export { APPROVAL_CHECK_NAME, createRunStatusCheck, finalizeRunStatusCheck, RUN_STATUS_CHECK_NAME, runStatusCheckNeedsFinalizing, } from "../utils/runStatusCheck.ts";
|
|
29
30
|
export * from "../utils/subscriptionCredentials.ts";
|
package/dist/internal.js
CHANGED
|
@@ -8,7 +8,7 @@ var __export = (target, all) => {
|
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "pullfrog",
|
|
11
|
-
version: "0.1.
|
|
11
|
+
version: "0.1.90",
|
|
12
12
|
cliContractVersion: "1",
|
|
13
13
|
type: "module",
|
|
14
14
|
bin: {
|
|
@@ -16821,6 +16821,146 @@ var PROVIDER_DASHBOARDS = {
|
|
|
16821
16821
|
}
|
|
16822
16822
|
};
|
|
16823
16823
|
|
|
16824
|
+
// utils/providerErrors.ts
|
|
16825
|
+
var PROVIDER_BILLING_EXHAUSTED_LABEL = "provider billing exhausted";
|
|
16826
|
+
var PROVIDER_NO_ENDPOINTS_LABEL = "provider no routable endpoints";
|
|
16827
|
+
var PROVIDER_USAGE_LIMIT_LABEL = "provider usage limit reached";
|
|
16828
|
+
var statusKey = `\\b(?:status[_ ]?code|http[_ ]?status|status)["']?\\s*[:=]\\s*["']?`;
|
|
16829
|
+
var ANTHROPIC_SPEND_CAP_PATTERN = /reached your specified API usage limits\.?(?:\s*You will regain access on ([^"\n]+?)\.)?/i;
|
|
16830
|
+
var PROVIDER_ERROR_PATTERNS = [
|
|
16831
|
+
// billing-payload patterns come BEFORE bare status-code patterns. providers
|
|
16832
|
+
// commonly return 401 / 429 for billing/quota exhaustion (OpenCode Zen
|
|
16833
|
+
// `CreditsError` / `FreeUsageLimitError`, Gemini `RESOURCE_EXHAUSTED` +
|
|
16834
|
+
// "spending cap", Anthropic "Insufficient balance" / "credit balance is
|
|
16835
|
+
// too low"). these are non-retryable and require user-billing action —
|
|
16836
|
+
// distinct from a transient auth error or rate-limit. status-code patterns
|
|
16837
|
+
// would otherwise win and surface "auth error (401)" / "rate limited (429)"
|
|
16838
|
+
// with no billing hint. see #778, #835.
|
|
16839
|
+
{ regex: /\bCreditsError\b/, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
16840
|
+
{ regex: /\bFreeUsageLimitError\b/, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
16841
|
+
// `balance` is DeepSeek's noun, `credits` is OpenRouter's for the SAME
|
|
16842
|
+
// terminal state — #1164's run 7 (`Insufficient credits. Add more using
|
|
16843
|
+
// …/settings/credits`) matched neither this nor `requires more credits`, so
|
|
16844
|
+
// the one run in that episode that was a genuinely empty wallet rendered with
|
|
16845
|
+
// no CTA at all while runs 1-6 rendered correctly.
|
|
16846
|
+
{ regex: /Insufficient (?:balance|credits)/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
16847
|
+
{ regex: /credit balance is too low/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
16848
|
+
// "spending cap" (Gemini) and "spending limit" (xAI, #1076) are the same
|
|
16849
|
+
// condition in two house styles — a configured ceiling was reached.
|
|
16850
|
+
{ regex: /spending (?:cap|limit)/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
16851
|
+
// xAI exhausts credits and the monthly ceiling in one 403 whose status code
|
|
16852
|
+
// sits nowhere near a `status:` key, so no status pattern below fires (#1076).
|
|
16853
|
+
{ regex: /used all available credits/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
16854
|
+
// Gemini's daily / free-tier cap. it tells the user to "check your plan and
|
|
16855
|
+
// billing details" in its own words but matches none of the wallet wordings
|
|
16856
|
+
// above, so it fell to the catch-all `quota` label — which is not the label
|
|
16857
|
+
// the actionable copy is keyed on, so the run rendered a blank comment for a
|
|
16858
|
+
// condition the provider had spelled out (#1114).
|
|
16859
|
+
{
|
|
16860
|
+
regex: /exceeded your current quota, please check your plan and billing/i,
|
|
16861
|
+
label: PROVIDER_BILLING_EXHAUSTED_LABEL
|
|
16862
|
+
},
|
|
16863
|
+
{ regex: /generate_content_free_tier_requests/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
16864
|
+
// Anthropic's Console spend cap. its noun is "API usage limits", which none of
|
|
16865
|
+
// the wallet-shaped patterns above reach, and its 400 sits nowhere near a
|
|
16866
|
+
// `status:` key either — so the whole message was dropped on the floor (#1208).
|
|
16867
|
+
{ regex: ANTHROPIC_SPEND_CAP_PATTERN, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
16868
|
+
// OpenCode Zen / Codex-subscription cap: `AI_APICallError: The usage limit has
|
|
16869
|
+
// been reached`. Its noun is "usage limit" with no "rate", no status code and
|
|
16870
|
+
// no wallet wording, so every pattern here missed it and `lastProviderError`
|
|
16871
|
+
// stayed unset — which suppresses nothing, so the run was reported as "The
|
|
16872
|
+
// model produced no output at all … usually transient; re-running often
|
|
16873
|
+
// succeeds" while the same log held nine of these. Measured on a live account
|
|
16874
|
+
// whose ChatGPT subscription was capped.
|
|
16875
|
+
{ regex: /\bthe usage limit has been reached\b/i, label: PROVIDER_USAGE_LIMIT_LABEL },
|
|
16876
|
+
// the OpenRouter shapes `isRouterKeylimitExhaustedError` matches. on a Router
|
|
16877
|
+
// run those mean the PULLFROG wallet is empty and `renderRunError` returns a
|
|
16878
|
+
// `BillingError` before ever reaching this list; on a BYOK run the very same
|
|
16879
|
+
// wire text means the user's OWN OpenRouter wallet is empty, and this entry is
|
|
16880
|
+
// what gives them the right dashboard instead of ours. see #1135.
|
|
16881
|
+
{
|
|
16882
|
+
regex: /requires more credits|Key limit exceeded \(total limit\)/i,
|
|
16883
|
+
label: PROVIDER_BILLING_EXHAUSTED_LABEL
|
|
16884
|
+
},
|
|
16885
|
+
// OpenRouter has no endpoint it is allowed to route to: the customer's
|
|
16886
|
+
// data-policy / guardrail settings exclude every provider serving the model.
|
|
16887
|
+
// dies ~2s into the session with nothing billed, so it is neither a billing
|
|
16888
|
+
// nor an auth condition — and both of those patterns would otherwise be
|
|
16889
|
+
// reached first for a message that mentions neither. see #1164.
|
|
16890
|
+
{
|
|
16891
|
+
regex: /No endpoints available matching your (?:guardrail restrictions|data policy)/i,
|
|
16892
|
+
label: PROVIDER_NO_ENDPOINTS_LABEL
|
|
16893
|
+
},
|
|
16894
|
+
// auth patterns must come BEFORE rate-limit patterns. OpenRouter 401 error
|
|
16895
|
+
// payloads carry `x-ratelimit-*` response headers in the dump, and the
|
|
16896
|
+
// free-form rate-limit regex below would otherwise win on word-boundary
|
|
16897
|
+
// matches inside header names. canonical 401 messages: OpenRouter returns
|
|
16898
|
+
// `{"error":{"message":"User not found","code":401}}` for disabled or
|
|
16899
|
+
// invalid keys (https://openai.luzhipeng.com/docs/api/reference/errors-and-debugging).
|
|
16900
|
+
{ regex: new RegExp(`${statusKey}401\\b`, "i"), label: "auth error (401)" },
|
|
16901
|
+
{ regex: new RegExp(`${statusKey}403\\b`, "i"), label: "auth error (403)" },
|
|
16902
|
+
{ regex: /\bUser not found\b/i, label: "auth error (invalid/disabled key)" },
|
|
16903
|
+
{ regex: /\bInvalid authentication\b/i, label: "auth error (invalid credentials)" },
|
|
16904
|
+
{ regex: /\bNo auth credentials found\b/i, label: "auth error (missing credentials)" },
|
|
16905
|
+
{ regex: new RegExp(`${statusKey}429\\b`, "i"), label: "rate limited (429)" },
|
|
16906
|
+
{ regex: new RegExp(`${statusKey}500\\b`, "i"), label: "provider 500 error" },
|
|
16907
|
+
{ regex: new RegExp(`${statusKey}503\\b`, "i"), label: "provider unavailable (503)" },
|
|
16908
|
+
// matches `rate limit`, `rate limited`, `rate limits exceeded`,
|
|
16909
|
+
// `rate_limit_error`, `rate_limit_exceeded`. the leading `\b` + `[_ ]`
|
|
16910
|
+
// separator rejects `x-ratelimit-*` / `anthropic-ratelimit-*` response
|
|
16911
|
+
// headers (no separator between "rate" and "limit") which routinely
|
|
16912
|
+
// appear in dumped 401 / 4xx error JSON.
|
|
16913
|
+
{ regex: /\brate[_ ]limit/i, label: "rate limited" },
|
|
16914
|
+
{ regex: /\bRESOURCE_EXHAUSTED\b/, label: "quota exhausted" },
|
|
16915
|
+
// Google gRPC `INTERNAL` status. word-boundary anchors reject
|
|
16916
|
+
// `INTERNAL_SERVER_ERROR` (HTTP 500 message that may appear in unrelated
|
|
16917
|
+
// log lines) and identifiers like `INTERNALS`.
|
|
16918
|
+
{ regex: /\bINTERNAL\b/, label: "provider internal error" },
|
|
16919
|
+
{ regex: /\bUNAVAILABLE\b/, label: "provider unavailable" },
|
|
16920
|
+
// matches `quota`, `insufficient_quota`, `quota_exceeded`, `quotaExceeded`.
|
|
16921
|
+
// word-character lookarounds would reject `_quota` / `quotaX`; `quota` is
|
|
16922
|
+
// specific enough that a plain substring match is safe.
|
|
16923
|
+
{ regex: /quota/i, label: "quota error" },
|
|
16924
|
+
// explicit zero-quota response, e.g. `{"limit": 0}`. the `\b` anchor
|
|
16925
|
+
// around `limit` rejects keys like `time_limit` or `field_limit`.
|
|
16926
|
+
{ regex: /["']?\blimit\b["']?\s*:\s*0\b/, label: "zero quota" }
|
|
16927
|
+
];
|
|
16928
|
+
var EXCERPT_MAX_BYTES = 600;
|
|
16929
|
+
var LINES_BEFORE = 1;
|
|
16930
|
+
var LINES_AFTER = 2;
|
|
16931
|
+
function findProviderErrorMatch(text) {
|
|
16932
|
+
for (const entry of PROVIDER_ERROR_PATTERNS) {
|
|
16933
|
+
const m = entry.regex.exec(text);
|
|
16934
|
+
if (!m) continue;
|
|
16935
|
+
return { label: entry.label, excerpt: extractExcerpt(text, m.index) };
|
|
16936
|
+
}
|
|
16937
|
+
return null;
|
|
16938
|
+
}
|
|
16939
|
+
function detectProviderError(text) {
|
|
16940
|
+
return findProviderErrorMatch(text)?.label ?? null;
|
|
16941
|
+
}
|
|
16942
|
+
function extractExcerpt(text, matchIndex) {
|
|
16943
|
+
const lineStart = text.lastIndexOf("\n", matchIndex - 1) + 1;
|
|
16944
|
+
const lineEndRaw = text.indexOf("\n", matchIndex);
|
|
16945
|
+
const lineEnd = lineEndRaw === -1 ? text.length : lineEndRaw;
|
|
16946
|
+
let start = lineStart;
|
|
16947
|
+
for (let i = 0; i < LINES_BEFORE && start > 0; i++) {
|
|
16948
|
+
const prev = text.lastIndexOf("\n", start - 2);
|
|
16949
|
+
start = prev < 0 ? 0 : prev + 1;
|
|
16950
|
+
}
|
|
16951
|
+
let end = lineEnd;
|
|
16952
|
+
for (let i = 0; i < LINES_AFTER && end < text.length; i++) {
|
|
16953
|
+
const next = text.indexOf("\n", end + 1);
|
|
16954
|
+
end = next < 0 ? text.length : next;
|
|
16955
|
+
}
|
|
16956
|
+
let excerpt = text.slice(start, end);
|
|
16957
|
+
if (excerpt.length > EXCERPT_MAX_BYTES) {
|
|
16958
|
+
excerpt = text.slice(lineStart, lineEnd);
|
|
16959
|
+
if (excerpt.length > EXCERPT_MAX_BYTES) excerpt = excerpt.slice(0, EXCERPT_MAX_BYTES);
|
|
16960
|
+
}
|
|
16961
|
+
return excerpt.trim();
|
|
16962
|
+
}
|
|
16963
|
+
|
|
16824
16964
|
// utils/runStatusCheck.ts
|
|
16825
16965
|
var RUN_STATUS_CHECK_NAME = "pullfrog";
|
|
16826
16966
|
var GITHUB_ACTIONS_APP_SLUG = "github-actions";
|
|
@@ -17214,6 +17354,7 @@ export {
|
|
|
17214
17354
|
decodeJwtExpMs,
|
|
17215
17355
|
defaultAutoTier,
|
|
17216
17356
|
deleteProgressCommentApi,
|
|
17357
|
+
detectProviderError,
|
|
17217
17358
|
finalizeRunStatusCheck,
|
|
17218
17359
|
getAutoSelectHintModel,
|
|
17219
17360
|
getModelEffortLevels,
|