pullfrog 0.1.95 → 0.1.97
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 -0
- package/dist/agents/opencodePlugin.d.ts +4 -2
- package/dist/cli.mjs +1415 -1279
- package/dist/external.d.ts +1 -1
- package/dist/index.js +1358 -1231
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal.js +107 -42
- package/dist/mcp/checkout.d.ts +2 -0
- package/dist/mcp/comment.d.ts +3 -0
- package/dist/models.d.ts +5 -5
- package/dist/toolState.d.ts +6 -4
- package/dist/utils/apiKeys.d.ts +26 -0
- package/dist/utils/changeImpact.d.ts +1 -0
- package/dist/utils/codexHome.d.ts +4 -6
- package/dist/utils/gitAuth.d.ts +1 -0
- package/dist/utils/github.d.ts +1 -1
- package/dist/utils/oauthWriteback.d.ts +5 -0
- package/dist/utils/openCodeModels.d.ts +19 -2
- package/dist/utils/patchWorkflowRunFields.d.ts +8 -1
- package/dist/utils/providerErrors.d.ts +4 -1
- package/dist/utils/runContext.d.ts +8 -0
- package/dist/utils/runContextData.d.ts +2 -0
- package/dist/utils/runErrorRenderer.d.ts +25 -9
- package/dist/utils/runStatusCheck.d.ts +11 -0
- package/dist/utils/statusChecks.d.ts +2 -1
- package/dist/utils/subprocess.d.ts +2 -0
- package/package.json +2 -2
package/dist/internal/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { CLI_CONTRACT_HEADER, CLI_CONTRACT_VERSION, CLI_UPGRADE_MESSAGE } from "
|
|
|
6
6
|
export type { ConfigField, ConfigScope, ConfigValue } from "../configuration.ts";
|
|
7
7
|
export { configEntrySchema, configFields, configResponseSchema, configValueSchema, } from "../configuration.ts";
|
|
8
8
|
export type { AuthorPermission, AutoTier, EffortPosition, ModelAlias, ModelProvider, Payload, PayloadEvent, PayloadRouting, ProviderConfig, PushPermission, RouterSource, RouterTier, ShellPermission, ToolPermission, WriteablePayload, XrepoConfig, } from "../external.ts";
|
|
9
|
-
export { AUTO_EFFICIENT, AUTO_INTELLIGENT, AUTO_ROUTER, autoLadder, autoRoutedSlug, DEFAULT_EFFORT_POSITION, DEFAULT_PROXY_MODEL, defaultAutoTier, EFFORT_ALIASES, getAutoSelectHintModel, getModelEffortLevels, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, isAutoRouted, isAutoSlug, isAutoTier, isCardGatedModel, isEffortPosition, isOssAllowedModel, isRouterTier, ladderRungs, modelAliases, modelHasStoredAuth, modelIdLabel, OSS_MODEL_ALLOWLIST, OSS_RECOMMENDED_MODEL, offeredRungs, ossFundedModelNames, PROVIDER_GATEWAY_URL_ENV, parseEffortPosition, parseModel,
|
|
9
|
+
export { AUTO_EFFICIENT, AUTO_INTELLIGENT, AUTO_ROUTER, autoLadder, autoRoutedSlug, DEFAULT_EFFORT_POSITION, DEFAULT_PROXY_MODEL, defaultAutoTier, EFFORT_ALIASES, getAutoSelectHintModel, getModelEffortLevels, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, isAutoRouted, isAutoSlug, isAutoTier, isCardGatedModel, isEffortPosition, isOssAllowedModel, isRouterTier, ladderRungs, modelAliases, modelHasStoredAuth, modelIdLabel, OSS_MODEL_ALLOWLIST, OSS_RECOMMENDED_MODEL, offeredRungs, ossFundedModelNames, PROVIDER_GATEWAY_URL_ENV, parseEffortPosition, parseModel, providers, pullfrogMcpName, ROUTED_PROVIDERS, ROUTER_LADDER, ROUTER_TIERS, resolveAutoTier, resolveCliModel, resolveDisplayAlias, resolveModelRung, resolveModelSlug, resolveOpenRouterModel, resolvePickModel, resolveRoutedModel, resolveRung, routerProxyOptOut, rungLabel, rungPosition, SUBSIDY_RUNG, } from "../external.ts";
|
|
10
10
|
export type { Mode } from "../modes.ts";
|
|
11
11
|
export { modes } from "../modes.ts";
|
|
12
12
|
export { type CommercialRefusal, commercialPaywallBody } from "../utils/billingErrors.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.97",
|
|
12
12
|
cliContractVersion: "1",
|
|
13
13
|
type: "module",
|
|
14
14
|
bin: {
|
|
@@ -74,7 +74,7 @@ var package_default = {
|
|
|
74
74
|
undici: "^7.22.0",
|
|
75
75
|
vitest: "^4.0.17",
|
|
76
76
|
yaml: "^2.8.2",
|
|
77
|
-
yes: "0.
|
|
77
|
+
yes: "0.2.3",
|
|
78
78
|
zod: "4.3.6"
|
|
79
79
|
},
|
|
80
80
|
repository: {
|
|
@@ -14932,6 +14932,15 @@ var providers = {
|
|
|
14932
14932
|
openRouterEffort: [],
|
|
14933
14933
|
openRouterResolve: "openrouter/qwen/qwen3.8-flash"
|
|
14934
14934
|
},
|
|
14935
|
+
// Zen lists Mistral Large 4 at half its list price for launch, level with
|
|
14936
|
+
// the routers. hidden until a published `pullfrog` resolves it, as there.
|
|
14937
|
+
"mistral-large": {
|
|
14938
|
+
displayName: "Mistral Large",
|
|
14939
|
+
resolve: "opencode/mistral-large-4",
|
|
14940
|
+
effort: ["none", "high"],
|
|
14941
|
+
openRouterResolve: "openrouter/mistralai/mistral-large-4-0",
|
|
14942
|
+
hidden: true
|
|
14943
|
+
},
|
|
14935
14944
|
"gpt-5-nano": {
|
|
14936
14945
|
displayName: "GPT Nano",
|
|
14937
14946
|
resolve: "opencode/gpt-5.4-nano",
|
|
@@ -14980,12 +14989,12 @@ var providers = {
|
|
|
14980
14989
|
fallback: "opencode/big-pickle"
|
|
14981
14990
|
},
|
|
14982
14991
|
// Zen's FREE stealth preview (listed 2026-09-23), the third after
|
|
14983
|
-
// big-pickle and union-alpha.
|
|
14984
|
-
//
|
|
14985
|
-
//
|
|
14992
|
+
// big-pickle and union-alpha. Zen's docs: zero retention, no training.
|
|
14993
|
+
// unlike the first two it publishes an effort ladder, so the gate
|
|
14994
|
+
// mirrors one here.
|
|
14986
14995
|
"space-bunny": {
|
|
14987
14996
|
displayName: "Space Bunny",
|
|
14988
|
-
description: "Stealth preview
|
|
14997
|
+
description: "Stealth preview, free for a limited time",
|
|
14989
14998
|
resolve: "opencode/space-bunny-free",
|
|
14990
14999
|
effort: ["low", "medium", "high", "xhigh", "max"],
|
|
14991
15000
|
// free to run, still gated on the provider's own OPENCODE_API_KEY —
|
|
@@ -15003,17 +15012,30 @@ var providers = {
|
|
|
15003
15012
|
// see the big-pickle note above (#1077).
|
|
15004
15013
|
isFree: true
|
|
15005
15014
|
},
|
|
15006
|
-
// Zen's FREE stealth preview (listed 2026-10-01), the fifth promo. Zen
|
|
15007
|
-
//
|
|
15015
|
+
// Zen's FREE stealth preview (listed 2026-10-01), the fifth promo. Zen's
|
|
15016
|
+
// docs: data may be used to improve the model during the free period.
|
|
15008
15017
|
"fledge-alpha": {
|
|
15009
15018
|
displayName: "Fledge Alpha",
|
|
15010
|
-
description: "Stealth preview
|
|
15019
|
+
description: "Stealth preview; data may be used to improve it",
|
|
15011
15020
|
resolve: "opencode/fledge-alpha-free",
|
|
15012
15021
|
effort: ["low", "high", "max"],
|
|
15013
15022
|
// free to run, still gated on the provider's own OPENCODE_API_KEY —
|
|
15014
15023
|
// see the big-pickle note above (#1077).
|
|
15015
15024
|
isFree: true
|
|
15016
15025
|
},
|
|
15026
|
+
// Zen's FREE preview (listed 2026-10-06), the sixth promo, on Fledge
|
|
15027
|
+
// Alpha's terms. hidden until a published `pullfrog` resolves it.
|
|
15028
|
+
exo: {
|
|
15029
|
+
displayName: "Exo",
|
|
15030
|
+
description: "Preview; data may be used to improve it",
|
|
15031
|
+
resolve: "opencode/exo-free",
|
|
15032
|
+
// Zen publishes a single rung.
|
|
15033
|
+
effort: ["high"],
|
|
15034
|
+
// free to run, still gated on the provider's own OPENCODE_API_KEY —
|
|
15035
|
+
// see the big-pickle note above (#1077).
|
|
15036
|
+
isFree: true,
|
|
15037
|
+
hidden: true
|
|
15038
|
+
},
|
|
15017
15039
|
// Zen's live free MiMo, and the second free row in a menu that big-pickle
|
|
15018
15040
|
// was alone in since `mimo-v2-pro-free` lost its model.
|
|
15019
15041
|
mimo: {
|
|
@@ -15076,7 +15098,11 @@ var providers = {
|
|
|
15076
15098
|
"glm-flash": {
|
|
15077
15099
|
displayName: "GLM Flash",
|
|
15078
15100
|
resolve: "opencode-go/glm-5.3-flash",
|
|
15079
|
-
|
|
15101
|
+
// the Go endpoint intermittently rejects reasoning_effort ("native reasoning
|
|
15102
|
+
// control reasoning_effort is not allowed") mid-run, despite models.dev
|
|
15103
|
+
// advertising a ladder — so this route sends none.
|
|
15104
|
+
effort: [],
|
|
15105
|
+
openRouterEffort: ["low", "high", "max"],
|
|
15080
15106
|
openRouterResolve: "openrouter/z-ai/glm-5.3-flash"
|
|
15081
15107
|
},
|
|
15082
15108
|
// legacy alias — the slug pinned a version instead of a brand tier and
|
|
@@ -15465,6 +15491,17 @@ var providers = {
|
|
|
15465
15491
|
resolve: "openrouter/meta/muse-spark-1.3-contributor",
|
|
15466
15492
|
effort: ["minimal", "low", "medium", "high", "xhigh", "max"],
|
|
15467
15493
|
openRouterResolve: "openrouter/meta/muse-spark-1.3-contributor"
|
|
15494
|
+
},
|
|
15495
|
+
// Mistral's flagship (public preview, 2026-10-06), on the routers only:
|
|
15496
|
+
// the catalog carries no direct Mistral provider. out of the pickers
|
|
15497
|
+
// until a published `pullfrog` resolves the slug; see "A new alias
|
|
15498
|
+
// reaches the picker at merge".
|
|
15499
|
+
"mistral-large": {
|
|
15500
|
+
displayName: "Mistral Large",
|
|
15501
|
+
resolve: "openrouter/mistralai/mistral-large-4-0",
|
|
15502
|
+
effort: ["none", "high"],
|
|
15503
|
+
openRouterResolve: "openrouter/mistralai/mistral-large-4-0",
|
|
15504
|
+
hidden: true
|
|
15468
15505
|
}
|
|
15469
15506
|
}
|
|
15470
15507
|
}),
|
|
@@ -15532,7 +15569,7 @@ var providers = {
|
|
|
15532
15569
|
"deepseek-pro": {
|
|
15533
15570
|
displayName: "DeepSeek Pro",
|
|
15534
15571
|
resolve: "vercel/deepseek/deepseek-v4-pro-0813",
|
|
15535
|
-
effort: ["none", "high", "max"]
|
|
15572
|
+
effort: ["none", "low", "high", "max"]
|
|
15536
15573
|
},
|
|
15537
15574
|
// the gateway's bare `deepseek-v4-flash` is the April preview — the same
|
|
15538
15575
|
// fork trap as OpenRouter, with `deepseek-v4-flash-0731` beside it — so
|
|
@@ -15540,7 +15577,7 @@ var providers = {
|
|
|
15540
15577
|
"deepseek-flash": {
|
|
15541
15578
|
displayName: "DeepSeek Flash",
|
|
15542
15579
|
resolve: "vercel/deepseek/deepseek-v4.1-flash",
|
|
15543
|
-
effort: ["none", "high", "max"]
|
|
15580
|
+
effort: ["none", "low", "high", "max"]
|
|
15544
15581
|
},
|
|
15545
15582
|
glm: {
|
|
15546
15583
|
displayName: "GLM",
|
|
@@ -15556,6 +15593,13 @@ var providers = {
|
|
|
15556
15593
|
displayName: "Muse Spark",
|
|
15557
15594
|
resolve: "vercel/meta/muse-spark-1.3",
|
|
15558
15595
|
effort: ["minimal", "low", "medium", "high", "xhigh"]
|
|
15596
|
+
},
|
|
15597
|
+
// hidden until a published `pullfrog` resolves it, as on OpenRouter.
|
|
15598
|
+
"mistral-large": {
|
|
15599
|
+
displayName: "Mistral Large",
|
|
15600
|
+
resolve: "vercel/mistral/mistral-large-4",
|
|
15601
|
+
effort: ["none", "low", "medium", "high"],
|
|
15602
|
+
hidden: true
|
|
15559
15603
|
}
|
|
15560
15604
|
}
|
|
15561
15605
|
})
|
|
@@ -15611,8 +15655,8 @@ function routerProxyOptOut(ctx) {
|
|
|
15611
15655
|
if (ctx.slug === null) return false;
|
|
15612
15656
|
return resolveDisplayAlias(ctx.slug)?.isFree === true || modelHasStoredAuth({ model: ctx.slug, secretNames: ctx.secretNames });
|
|
15613
15657
|
}
|
|
15614
|
-
function
|
|
15615
|
-
return params.proxied && !routerProxyOptOut(params);
|
|
15658
|
+
function resolvePickModel(params) {
|
|
15659
|
+
return params.proxied && !routerProxyOptOut(params) ? resolveOpenRouterModel(params.slug) : resolveCliModel(params.slug);
|
|
15616
15660
|
}
|
|
15617
15661
|
var modelAliases = Object.entries(providers).flatMap(
|
|
15618
15662
|
([providerKey, config2]) => Object.entries(config2.models).map(([modelId, def]) => ({
|
|
@@ -15795,13 +15839,13 @@ for (const [name, ladder] of Object.entries({ ...PROVIDER_LADDERS, router: ROUTE
|
|
|
15795
15839
|
if (terminal.size < 2) throw new Error(`${name} ladder runs every tier on ${[...terminal][0]}`);
|
|
15796
15840
|
}
|
|
15797
15841
|
var OSS_MODEL_ALLOWLIST = [
|
|
15798
|
-
"deepseek/deepseek-flash",
|
|
15799
|
-
"openai/gpt-luna",
|
|
15800
|
-
"openrouter/minimax-m2.5",
|
|
15801
15842
|
// opt-in: 0.86x the old default on the measured mix, and Meta trains on the
|
|
15802
15843
|
// traffic — fine for public code on headless runs, the human decided
|
|
15803
15844
|
// 2026-09-11. unmeasured on a real run; not the default until it is.
|
|
15804
|
-
"meta/muse-spark-contributor"
|
|
15845
|
+
"meta/muse-spark-contributor",
|
|
15846
|
+
"deepseek/deepseek-flash",
|
|
15847
|
+
"openai/gpt-luna",
|
|
15848
|
+
"openrouter/minimax-m2.5"
|
|
15805
15849
|
];
|
|
15806
15850
|
var OSS_RECOMMENDED_MODEL = AUTO_TIER_TARGET[AUTO_EFFICIENT];
|
|
15807
15851
|
function ossFundedModelNames() {
|
|
@@ -15848,17 +15892,16 @@ var REVIEWER_AGENT_NAME = "reviewfrog";
|
|
|
15848
15892
|
// modes.ts
|
|
15849
15893
|
var PR_SUMMARY_FORMAT = `### Default format
|
|
15850
15894
|
|
|
15851
|
-
The body has at most
|
|
15895
|
+
The body has at most two parts, in this order:
|
|
15852
15896
|
|
|
15853
15897
|
1. **Reviewed changes preamble** \u2014 a bolded \`**Reviewed changes**\` lead-in with one sentence on what was reviewed in this run (for \`IncrementalReview\`: what changed since the prior pullfrog review), then a bullet list of the substantive changes \u2014 short bolded title, one sentence each. A reviewer should understand the full reviewed scope from this list alone. Close the preamble with the metadata comment below.
|
|
15854
15898
|
2. **Cross-cutting issue sections** (zero or more) \u2014 one \`### {emoji} {what's wrong, not what to do}\` heading per concern.
|
|
15855
|
-
3. **\`### \u2139\uFE0F Nitpicks\`** at the very bottom, if any \u2014 a flat bullet list, no technical-details block. Only for what has no runtime effect: a stale or wrong comment or doc, a misleading name, a typo, dead code, a missing test. Never formatting or whitespace.
|
|
15856
15899
|
|
|
15857
15900
|
**Inline vs. body.** Concerns that anchor to a specific line go inline (the \`comments\` parameter), even when their implications are broad. Body \`### \` sections are reserved for concerns that have **no line to anchor to** \u2014 *absence* (something the diff should have done but didn't), *sequencing* (rollout / deletion / migration order), *design decisions only the human can make*, or *scope questions the diff raises but doesn't address*. With no non-anchorable concerns, the body is just the preamble + metadata.
|
|
15858
15901
|
|
|
15859
15902
|
**Severity emoji** on every \`### \` heading, and nowhere else: \u{1F6A8} critical (blocks merge \u2014 data loss, security, broken core flow) \xB7 \u26A0\uFE0F important (must address before merging) \xB7 \u2139\uFE0F informational (mergeable as-is).
|
|
15860
15903
|
|
|
15861
|
-
**Behavior decides placement, not fix size.** A finding that changes what the code does \u2014 a wrong value or message, a crash, a race, a leak, a missed cleanup, a slow path \u2014 gets its own inline comment (or a \`### \` section if no line anchors it) at its real severity, however small the fix.
|
|
15904
|
+
**Behavior decides placement, not fix size.** A finding that changes what the code does \u2014 a wrong value or message, a crash, a race, a leak, a missed cleanup, a slow path \u2014 gets its own inline comment (or a \`### \` section if no line anchors it) at its real severity, however small the fix.
|
|
15862
15905
|
|
|
15863
15906
|
**Blank line between every block-level element.** GitHub's markdown parser requires one before and after HTML tags (\`<details>\`, \`<summary>\`, \`<sub>\`, \`<br/>\`) \u2014 without it GitHub treats what follows as a continuation of the HTML block and renders your markdown as literal text. This is a parser quirk, not a style preference, and it permanently breaks the posted review.
|
|
15864
15907
|
|
|
@@ -16007,8 +16050,6 @@ For simple, well-defined tasks, skip the plan phase and go straight to build.`
|
|
|
16007
16050
|
|
|
16008
16051
|
3. **triage**: orient yourself on the PR \u2014 identify *what kind of thing this is* (domain it touches, seams it crosses, external contracts it depends on, user-facing surfaces it changes). pull as much context as you need to render a confident, well-grounded review: read related files, grep for callers of changed symbols, check tests that exercise the touched paths, fetch related GitHub state. **you are the synthesizer** \u2014 never delegate understanding to subagents.
|
|
16009
16052
|
|
|
16010
|
-
when the diff adds or changes a test, check that it can actually fail: a test that would still pass with the bug present is theatre, not coverage. the usual tell is a loose assertion standing where an exact one belongs \u2014 \`>=\` or a truthiness check over an expected value, or a snapshot that absorbs whatever it is handed. read the assertion against the behavior it claims to pin, not against whether it currently passes.
|
|
16011
|
-
|
|
16012
16053
|
skip the deeper pass and submit a \`No new issues found.\` review per step 7 only when the diff has **no behavioral surface at all** \u2014 doc typos, whitespace/formatting, lockfile or generated-code regeneration, a mechanical rename whose only effect is import-path updates. line count is not the signal: a one-line change to auth, money, SQL, a comparison operator, a redirect, or a config default is not trivial.
|
|
16013
16054
|
|
|
16014
16055
|
4. **specialist decision**: after reading the complete diff, name the questions you still cannot answer confidently yourself, and dispatch one \`${REVIEWER_AGENT_NAME}\` specialist per question. a question qualifies only when a specialist could return evidence that **changes your disposition** on the PR \u2014 generic requests for another look, extra confidence, or polish do not. most reviews need zero or one; some need several.
|
|
@@ -16032,8 +16073,6 @@ For simple, well-defined tasks, skip the plan phase and go straight to build.`
|
|
|
16032
16073
|
|
|
16033
16074
|
6. **aggregate & draft**: when specialist results land, merge findings; de-dup overlaps (two specialists catching the same issue = higher-confidence signal); trace each finding yourself before accepting it. drop praise, style preferences, speculative/unverified claims, findings about pre-existing code unrelated to the PR (heuristic: if the finding's root cause lives in lines this PR added or modified, it's in scope; otherwise drop unless the PR plausibly introduced or amplified the regression), and anything not actionable. also drop **bloat-shaped findings** \u2014 proposed fixes that would add defensive checks for cases that can't happen, abstractions used once, comments restating obvious code, tests asserting tautologies, or "just-in-case" guards. subagents are fallible and bias toward recommending changes; the bar for an actionable inline comment is sound + correct + elegant. recommending a change that improves only one of the three (or worse, degrades elegance to nominally improve correctness) makes the codebase worse, not better.
|
|
16034
16075
|
|
|
16035
|
-
**Hunt for non-anchored concerns before drafting.** After collecting your anchored findings, deliberately scan for concerns that have no specific line to point at \u2014 typically: deletion / cleanup plans for code the diff replaces or shadows; rollout sequencing (what happens to in-flight state during deploy / revert?); scope questions that only the human can answer (e.g. is the legacy path going away or is this a long-term dual track?); architectural risks the diff opens up that aren't a single-line bug.
|
|
16036
|
-
|
|
16037
16076
|
for surviving findings, draft inline comments with NEW line numbers from the diff \u2014 attach a \`<details>Technical details</details>\` block to any inline comment whose fix is non-trivial or has cross-file implications (see Inline technical details in the format below). every comment must be actionable, 2-3 sentences max in the visible part, one per root cause \u2014 name its other sites in that comment rather than repeating it. use GitHub permalink format for code references. for impact-analysis findings (stale references after rename/remove), report them in the review body ordered by severity (runtime breakage > incorrect docs > stale comments) rather than as inline comments unless they're anchored to a specific line.
|
|
16038
16077
|
|
|
16039
16078
|
7. **submit**: ALWAYS submit exactly one review via \`${t("create_pull_request_review")}\`. Do NOT call \`report_progress\` \u2014 the review is the final record and the progress comment will be cleaned up automatically.
|
|
@@ -16055,7 +16094,7 @@ For simple, well-defined tasks, skip the plan phase and go straight to build.`
|
|
|
16055
16094
|
\`approved: false\`. Body opens with \`> [!CAUTION]\\n> This PR introduces ...\`, followed by the PR summary. Include all inline comments via \`comments\`.
|
|
16056
16095
|
- **must-address non-critical findings** (real consequences if shipped \u2014 incorrect behavior in non-critical paths, missing validation on user input, regressions the author should fix before merge):
|
|
16057
16096
|
\`approved: false\`. Body opens with \`> [!IMPORTANT]\\n> ...\`, followed by the PR summary. Reserve this tier for findings with concrete fallout \u2014 do NOT use \`[!IMPORTANT]\` for nits, style preferences, or "consider also" suggestions. Include all inline comments via \`comments\`.
|
|
16058
|
-
- **minor suggestions only** (low-stakes findings
|
|
16097
|
+
- **minor suggestions only** (low-stakes findings):
|
|
16059
16098
|
\`approved: false\`. Body opens with \`> \u2139\uFE0F No critical issues \u2014 minor suggestions inline.\\n\\n\` followed by the PR summary. Include all inline comments via \`comments\`. Vary the wording after the emoji to fit the review (e.g. "Minor suggestions only.", "Two rough edges worth a look."), but always keep the \u2139\uFE0F prefix and keep it short.
|
|
16060
16099
|
- **informational observations** (mergeable as-is, nothing actionable \u2014 e.g. prior feedback addressed cleanly, calling out something noteworthy without recommending a change):
|
|
16061
16100
|
\`approved: true\`. Body opens with \`> \u2705 No new issues found.\\n\\n\` followed by the PR summary. Do NOT include inline \`comments\` \u2014 the \u2705 signals "no action needed", which contradicts an actionable anchor; if a point is concrete enough to anchor to a line, downgrade the whole review to "minor suggestions only" (\`approved: false\`) instead.
|
|
@@ -16098,8 +16137,6 @@ ${PR_SUMMARY_FORMAT}`
|
|
|
16098
16137
|
|
|
16099
16138
|
5. **triage**: orient on the *incremental* changes \u2014 domain, seams, external contracts, user-facing surfaces. pull as much context as you need to render a confident review: read related files, grep for callers of changed symbols, check tests that exercise the touched paths. **you are the synthesizer.**
|
|
16100
16139
|
|
|
16101
|
-
a test added or changed in this delta must be able to fail \u2014 one that would still pass with the bug present is theatre, not coverage. the tell is a loose assertion where an exact one belongs (\`>=\` or a truthiness check over an expected value, a snapshot that absorbs whatever it is handed).
|
|
16102
|
-
|
|
16103
16140
|
skip the deeper pass and jump to step 10's non-substantive path (do NOT submit a review) only when the incremental changes have **no behavioral surface at all** \u2014 formatting, comment tweaks, import reordering, lockfile regen, a mechanical rename of import paths. line count is not the signal: a one-line change to auth, money, SQL, a comparison operator, a redirect, or a config default is not trivial.
|
|
16104
16141
|
|
|
16105
16142
|
6. **specialist decision**: after covering the incremental and full diffs, name the questions about the new changes that you still cannot answer confidently yourself, and dispatch one \`${REVIEWER_AGENT_NAME}\` specialist per question. a question qualifies only when a specialist could return evidence that **changes your disposition** on the PR \u2014 generic requests for another look, extra confidence, or polish do not. most incremental reviews need zero or one, especially thread-reply re-reviews; some need several.
|
|
@@ -16123,11 +16160,9 @@ ${PR_SUMMARY_FORMAT}`
|
|
|
16123
16160
|
|
|
16124
16161
|
8. **aggregate, draft, self-critique**: merge findings (yours + output from every specialist you dispatched); de-dup overlaps; trace each finding yourself. drop praise, style preferences, speculative/unverified claims, findings about pre-existing code unrelated to the new commits, anything not actionable, and anything that re-states prior review feedback (heuristic: if the finding's root cause lives in lines the *new commits* added or modified, it's in scope; otherwise drop). also drop **bloat-shaped findings** \u2014 proposed fixes that would add defensive checks for cases that can't happen, abstractions used once, comments restating obvious code, tests asserting tautologies, or "just-in-case" guards. subagents are fallible and bias toward recommending changes; the bar for an actionable inline comment is sound + correct + elegant. recommending a change that improves only one of the three (or degrades elegance to nominally improve correctness) makes the codebase worse, not better. To compute "lines the new commits added or modified": if \`incrementalDiffPath\` from step 2 is present, use it directly. Otherwise, take the prior Pullfrog review's \`commit_id\` (returned alongside each entry from \`${t("list_pull_request_reviews")}\` in step 4) and run \`git diff <prior-review-sha>..HEAD\` to isolate the lines added since that review.
|
|
16125
16162
|
|
|
16126
|
-
**Hunt for non-anchored concerns before drafting.** After collecting your anchored findings, deliberately scan for concerns that have no specific line to point at \u2014 typically: deletion / cleanup plans for code the new commits replace or shadow; rollout sequencing (what happens to in-flight state during deploy / revert?); scope questions that only the human can answer (e.g. is the legacy path going away or is this a long-term dual track?); architectural risks the new commits open up that aren't a single-line bug.
|
|
16127
|
-
|
|
16128
16163
|
draft inline comments with NEW line numbers from the full PR diff \u2014 attach a \`<details>Technical details</details>\` block to any inline comment whose fix is non-trivial or has cross-file implications (see Inline technical details in the format below). every comment must be actionable, 2-3 sentences max in the visible part, one per root cause \u2014 name its other sites in that comment rather than repeating it.
|
|
16129
16164
|
|
|
16130
|
-
9. **build the review body**: use the same default format as Review mode (preamble + optional cross-cutting \`### \` sections
|
|
16165
|
+
9. **build the review body**: use the same default format as Review mode (preamble + optional cross-cutting \`### \` sections) \u2014 scoped to the **incremental delta**, not the full PR. The "Reviewed changes" bullets describe what changed since the prior pullfrog review (each bullet starts with a past-tense verb, e.g. \`- Extracted shared CLI runtime into a single module\`). Do NOT include a separate "Prior review feedback" checklist \u2014 that's tracked in the rolling PR summary snapshot for the next agent run, and surfacing it in the user-facing body is noise (changes that addressed prior feedback are already covered by the Reviewed-changes bullets). In some cases you may receive a complete diff for the whole PR instead of an incremental one; when this happens, determine what changed since Pullfrog's most recent review yourself before drafting bullets.
|
|
16131
16166
|
|
|
16132
16167
|
10. Submit \u2014 every run must end with EXACTLY ONE of \`${t("create_pull_request_review")}\` (substantive review) or \`${t("report_progress")}\` (no-review acknowledgement). do NOT call \`create_issue_comment\` for review output.
|
|
16133
16168
|
|
|
@@ -16135,10 +16170,10 @@ ${PR_SUMMARY_FORMAT}`
|
|
|
16135
16170
|
|
|
16136
16171
|
Follow these rules:
|
|
16137
16172
|
- note: the first create_pull_request_review submission may error with a one-time diff-coverage nudge listing unread TOC regions. retry the same call to proceed \u2014 optionally after reading the listed ranges. the pre-flight will not block again this session.
|
|
16138
|
-
- IF NO NEW ISSUES, NON-SUBSTANTIVE CHANGES ONLY (trivial formatting, import reordering, comment tweaks): do NOT submit a review. Instead call \`${t("report_progress")}\` with a 1-2 sentence note explaining no review was warranted (e.g. "No new issues. Changes since last review are formatting-only."). this leaves a visible signal that the run completed.
|
|
16173
|
+
- IF NO NEW ISSUES, NON-SUBSTANTIVE CHANGES ONLY (trivial formatting, import reordering, comment tweaks): do NOT submit a review. Instead call \`${t("report_progress")}\` with \`no_review_needed: true\` and a 1-2 sentence note explaining no review was warranted (e.g. "No new issues. Changes since last review are formatting-only."). this leaves a visible signal that the run completed.
|
|
16139
16174
|
- ELSE IF NEW CRITICAL ISSUES (blocks merge \u2014 bugs, security, data loss, broken core flows): call \`${t("create_pull_request_review")}\` with \`approved: false\`, all comments, and the review body. body opens with \`> [!CAUTION]\\n> This PR introduces ...\`, followed by the PR summary using the default format below.
|
|
16140
16175
|
- ELSE IF NEW MUST-ADDRESS NON-CRITICAL FINDINGS (real consequences if shipped \u2014 incorrect behavior, missing validation, regressions the author should fix before merge): call \`${t("create_pull_request_review")}\` with \`approved: false\`, all comments, and the review body. body opens with \`> [!IMPORTANT]\\n> ...\`, followed by the PR summary using the default format below. Do NOT use this tier for nits, style preferences, or "consider also" suggestions.
|
|
16141
|
-
- ELSE IF NEW MINOR SUGGESTIONS ONLY (low-stakes findings
|
|
16176
|
+
- ELSE IF NEW MINOR SUGGESTIONS ONLY (low-stakes findings): call \`${t("create_pull_request_review")}\` with \`approved: false\`, all comments, and the review body. body opens with \`> \u2139\uFE0F No critical issues \u2014 minor suggestions inline.\\n\\n\` (vary the wording after \u2139\uFE0F to fit the review), followed by the PR summary using the default format below.
|
|
16142
16177
|
- ELSE IF INFORMATIONAL OBSERVATIONS (mergeable as-is, but worth surfacing \u2014 e.g. prior feedback addressed cleanly, or a noteworthy positive observation): call \`${t("create_pull_request_review")}\` with \`approved: true\`, NO inline comments, and the review body. body opens with \`> \u2705 No new issues found.\\n\\n\` (or similar friendly green opener), followed by the PR summary using the default format below. If a point is concrete enough to anchor to a line, downgrade the whole review to "minor suggestions only" (\`approved: false\`) instead \u2014 the \u2705 signals "no action needed", which contradicts an actionable anchor.
|
|
16143
16178
|
- ELSE IF NO NEW ISSUES, SUBSTANTIVE CHANGES (new functionality, behavior changes, or fixes to prior review feedback): call \`${t("create_pull_request_review")}\` to create a PR review. If all previous reviews have been properly addressed and no new issues were discovered, set \`approved: true\`. body opens with \`> \u2705 No new issues found.\\n\\n\`, followed by the PR summary using the default format below.
|
|
16144
16179
|
|
|
@@ -16847,7 +16882,13 @@ var PROVIDER_ERROR_PATTERNS = [
|
|
|
16847
16882
|
// …/settings/credits`) matched neither this nor `requires more credits`, so
|
|
16848
16883
|
// the one run in that episode that was a genuinely empty wallet rendered with
|
|
16849
16884
|
// no CTA at all while runs 1-6 rendered correctly.
|
|
16850
|
-
|
|
16885
|
+
// `account funds` is Zen's (#1474).
|
|
16886
|
+
{
|
|
16887
|
+
regex: /Insufficient (?:balance|credits|account funds)/i,
|
|
16888
|
+
label: PROVIDER_BILLING_EXHAUSTED_LABEL
|
|
16889
|
+
},
|
|
16890
|
+
// OpenAI's `You have no credits remaining` (#1474).
|
|
16891
|
+
{ regex: /no credits remaining/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
16851
16892
|
{ regex: /credit balance is too low/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
|
|
16852
16893
|
// "spending cap" (Gemini) and "spending limit" (xAI, #1076) are the same
|
|
16853
16894
|
// condition in two house styles — a configured ceiling was reached.
|
|
@@ -17019,7 +17060,12 @@ function terminalOutput(params) {
|
|
|
17019
17060
|
const review = params.reviewUrl ? `
|
|
17020
17061
|
|
|
17021
17062
|
[View the review Pullfrog posted \u2192](${params.reviewUrl})` : "";
|
|
17022
|
-
if (params.conclusion === "success")
|
|
17063
|
+
if (params.conclusion === "success") {
|
|
17064
|
+
const note = params.note ? `
|
|
17065
|
+
|
|
17066
|
+
${params.note}` : "";
|
|
17067
|
+
return { title: base.title, summary: base.summary + review + note };
|
|
17068
|
+
}
|
|
17023
17069
|
return {
|
|
17024
17070
|
title: base.title,
|
|
17025
17071
|
summary: base.summary + logsLine(params.detailsUrl) + review + disableCheckLine(params.owner, params.repo)
|
|
@@ -17061,7 +17107,8 @@ async function finalizeRunStatusCheck(params) {
|
|
|
17061
17107
|
owner: params.owner,
|
|
17062
17108
|
repo: params.repo,
|
|
17063
17109
|
detailsUrl: params.detailsUrl,
|
|
17064
|
-
reviewUrl: params.reviewUrl
|
|
17110
|
+
reviewUrl: params.reviewUrl,
|
|
17111
|
+
note: params.note
|
|
17065
17112
|
})
|
|
17066
17113
|
};
|
|
17067
17114
|
if (params.detailsUrl) updateParams.details_url = params.detailsUrl;
|
|
@@ -17204,7 +17251,13 @@ var codexUsageSchema = external_exports.object({
|
|
|
17204
17251
|
limit_reached: external_exports.boolean(),
|
|
17205
17252
|
primary_window: codexWindowSchema,
|
|
17206
17253
|
secondary_window: codexWindowSchema
|
|
17207
|
-
}).optional()
|
|
17254
|
+
}).optional(),
|
|
17255
|
+
credits: external_exports.object({
|
|
17256
|
+
has_credits: external_exports.boolean().optional(),
|
|
17257
|
+
unlimited: external_exports.boolean().optional(),
|
|
17258
|
+
overage_limit_reached: external_exports.boolean().optional()
|
|
17259
|
+
}).nullish(),
|
|
17260
|
+
spend_control: external_exports.object({ reached: external_exports.boolean().optional() }).nullish()
|
|
17208
17261
|
});
|
|
17209
17262
|
var unknown2 = { status: "unknown" };
|
|
17210
17263
|
var SubscriptionCredentialError = class extends Error {
|
|
@@ -17272,9 +17325,12 @@ async function probeSubscription(input) {
|
|
|
17272
17325
|
const body = await response.json().catch(() => null);
|
|
17273
17326
|
if (!codex) return unknown2;
|
|
17274
17327
|
const parsed = codexUsageSchema.safeParse(body);
|
|
17275
|
-
|
|
17276
|
-
|
|
17328
|
+
if (!parsed.success || !parsed.data.rate_limit) return unknown2;
|
|
17329
|
+
const limit = parsed.data.rate_limit;
|
|
17277
17330
|
if (limit.allowed && !limit.limit_reached) return { status: "usable" };
|
|
17331
|
+
const credits = parsed.data.credits;
|
|
17332
|
+
if ((credits?.has_credits || credits?.unlimited) && !credits.overage_limit_reached && !parsed.data.spend_control?.reached)
|
|
17333
|
+
return { status: "usable" };
|
|
17278
17334
|
const windows = [limit.primary_window, limit.secondary_window];
|
|
17279
17335
|
const full = windows.filter((window) => (window?.used_percent ?? 0) >= 100);
|
|
17280
17336
|
const resets = (full.length ? full : windows).flatMap(
|
|
@@ -17322,15 +17378,24 @@ async function probeInference(input) {
|
|
|
17322
17378
|
const error48 = external_exports.object({ error: external_exports.object({ code: external_exports.string() }) }).safeParse(await response.json().catch(() => null));
|
|
17323
17379
|
return error48.success && error48.data.error.code === "insufficient_quota" ? { status: "exhausted", detail: "refused with 429: insufficient quota", resetAt: void 0 } : unknown2;
|
|
17324
17380
|
}
|
|
17381
|
+
if (response?.status === 401 || response?.status === 403)
|
|
17382
|
+
return {
|
|
17383
|
+
status: "rejected",
|
|
17384
|
+
detail: `rejected with ${response.status}${await providerReason(response)}`
|
|
17385
|
+
};
|
|
17325
17386
|
await response?.body?.cancel();
|
|
17326
17387
|
if (!response) return unknown2;
|
|
17327
17388
|
if (response.ok) return { status: "usable" };
|
|
17328
|
-
if (response.status === 401 || response.status === 403)
|
|
17329
|
-
return { status: "rejected", detail: `rejected with ${response.status}` };
|
|
17330
17389
|
if (response.status === 402)
|
|
17331
17390
|
return { status: "exhausted", detail: "refused with 402", resetAt: void 0 };
|
|
17332
17391
|
return unknown2;
|
|
17333
17392
|
}
|
|
17393
|
+
async function providerReason(response) {
|
|
17394
|
+
const body = external_exports.object({ error: external_exports.union([external_exports.string(), external_exports.object({ message: external_exports.string() })]) }).safeParse(await response.json().catch(() => null));
|
|
17395
|
+
if (!body.success) return "";
|
|
17396
|
+
const error48 = body.data.error;
|
|
17397
|
+
return `: ${(typeof error48 === "string" ? error48 : error48.message).slice(0, 300)}`;
|
|
17398
|
+
}
|
|
17334
17399
|
|
|
17335
17400
|
// utils/time.ts
|
|
17336
17401
|
var TIMEOUT_DISABLED = "none";
|
|
@@ -17420,7 +17485,6 @@ export {
|
|
|
17420
17485
|
parseModel,
|
|
17421
17486
|
parseTimeString,
|
|
17422
17487
|
parseXaiAuthBody,
|
|
17423
|
-
pickUsesOpenRouter,
|
|
17424
17488
|
probeSubscription,
|
|
17425
17489
|
providers,
|
|
17426
17490
|
pullfrogMcpName,
|
|
@@ -17432,6 +17496,7 @@ export {
|
|
|
17432
17496
|
resolveModelRung,
|
|
17433
17497
|
resolveModelSlug,
|
|
17434
17498
|
resolveOpenRouterModel,
|
|
17499
|
+
resolvePickModel,
|
|
17435
17500
|
resolveRoutedModel,
|
|
17436
17501
|
resolveRung,
|
|
17437
17502
|
routerProxyOptOut,
|
package/dist/mcp/checkout.d.ts
CHANGED
|
@@ -61,6 +61,8 @@ export type PrData = {
|
|
|
61
61
|
};
|
|
62
62
|
type CheckoutPrBranchParams = GitContext & {
|
|
63
63
|
beforeSha?: string | undefined;
|
|
64
|
+
/** aborts the in-flight fetch (SIGTERM, so git removes its own locks) when the tool deadline fires */
|
|
65
|
+
signal: AbortSignal;
|
|
64
66
|
};
|
|
65
67
|
/**
|
|
66
68
|
* Shared helper to checkout a PR branch and configure fork remotes.
|
package/dist/mcp/comment.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export declare function EditCommentTool(ctx: ToolContext): import("fastmcp").Too
|
|
|
33
33
|
export declare const ReportProgress: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
34
34
|
body: string;
|
|
35
35
|
target_plan_comment?: boolean;
|
|
36
|
+
no_review_needed?: boolean;
|
|
36
37
|
}, {}>;
|
|
37
38
|
/**
|
|
38
39
|
* Report progress to a GitHub comment.
|
|
@@ -61,9 +62,11 @@ export declare function reportProgress(ctx: ToolContext, params: {
|
|
|
61
62
|
export declare function ReportProgressTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
|
|
62
63
|
body: string;
|
|
63
64
|
target_plan_comment?: boolean;
|
|
65
|
+
no_review_needed?: boolean;
|
|
64
66
|
}, {
|
|
65
67
|
body: string;
|
|
66
68
|
target_plan_comment?: boolean;
|
|
69
|
+
no_review_needed?: boolean;
|
|
67
70
|
}>> & {
|
|
68
71
|
mutates?: boolean;
|
|
69
72
|
};
|
package/dist/models.d.ts
CHANGED
|
@@ -189,7 +189,7 @@ export declare function modelHasStoredAuth(params: {
|
|
|
189
189
|
* as-configured rather than clamping to the auto tier.
|
|
190
190
|
*
|
|
191
191
|
* one predicate for every reader — the console picker's `customLocked`, the
|
|
192
|
-
* effort ladder's `resolveRunning` and `
|
|
192
|
+
* effort ladder's `resolveRunning` and `resolvePickModel`. they held two
|
|
193
193
|
* copies and the free half was missing from both, which put the whole `opencode/*` free tier (`opencode/big-pickle`
|
|
194
194
|
* is `preferred`, so the most-picked model there is) behind "add a payment
|
|
195
195
|
* method to run it" on a card-less Router repo, against a server that ran it.
|
|
@@ -198,13 +198,13 @@ export declare function routerProxyOptOut(ctx: {
|
|
|
198
198
|
slug: string | null;
|
|
199
199
|
secretNames: string[];
|
|
200
200
|
}): boolean;
|
|
201
|
-
/**
|
|
202
|
-
* mints for every pick `routerProxyOptOut` does not exempt. */
|
|
203
|
-
export declare function
|
|
201
|
+
/** the specifier a pick runs as: its OpenRouter target on a proxied account (Router, the OSS
|
|
202
|
+
* subsidy), which mints for every pick `routerProxyOptOut` does not exempt, else its direct one. */
|
|
203
|
+
export declare function resolvePickModel(params: {
|
|
204
204
|
slug: string;
|
|
205
205
|
proxied: boolean;
|
|
206
206
|
secretNames: string[];
|
|
207
|
-
}):
|
|
207
|
+
}): string | undefined;
|
|
208
208
|
export declare const modelAliases: ModelAlias[];
|
|
209
209
|
/**
|
|
210
210
|
* `repo.model` sentinels for the two managed auto tiers. stored verbatim in
|
package/dist/toolState.d.ts
CHANGED
|
@@ -106,6 +106,7 @@ export interface ToolState {
|
|
|
106
106
|
sha: string | undefined;
|
|
107
107
|
url?: string | undefined;
|
|
108
108
|
};
|
|
109
|
+
noReviewNeededSha?: string | undefined;
|
|
109
110
|
reviewReplies?: Map<number, {
|
|
110
111
|
commentId: number;
|
|
111
112
|
url: string | undefined;
|
|
@@ -147,10 +148,11 @@ export interface ToolState {
|
|
|
147
148
|
todoTracker?: TodoTracker | undefined;
|
|
148
149
|
agentDiagnostic?: AgentDiagnostic | undefined;
|
|
149
150
|
/**
|
|
150
|
-
* a `PATCH /api/workflow-run/:id` came back 404 —
|
|
151
|
-
*
|
|
152
|
-
* setup, strictly before any PATCH). latched so
|
|
153
|
-
* firing: one CI run spent 28 doomed round trips on it.
|
|
151
|
+
* a `PATCH /api/workflow-run/:id` came back 404 — Pullfrog neither claimed a
|
|
152
|
+
* reservation for the run nor recorded it as a custom run, which is permanent for
|
|
153
|
+
* the life of the run (both happen at setup, strictly before any PATCH). latched so
|
|
154
|
+
* the remaining calls stop firing: one CI run spent 28 doomed round trips on it.
|
|
155
|
+
* see #1153.
|
|
154
156
|
*/
|
|
155
157
|
workflowRunUnclaimed?: boolean | undefined;
|
|
156
158
|
}
|
package/dist/utils/apiKeys.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { CredentialCandidate } from "./subscriptionCredentials.ts";
|
|
2
|
+
import type { ProbeVerdict } from "./subscriptionProbe.ts";
|
|
1
3
|
/** shared sentence in the four `resolveSlug` routing-slug throws. */
|
|
2
4
|
export declare const BYOK_SLUG_MARKER = "env var is required when the model is set to";
|
|
3
5
|
/** shared sentence in the four `validate*Setup` throws. */
|
|
@@ -49,6 +51,12 @@ export declare const ROUTER_UNFUNDED_MARKER = "your Pullfrog Router balance is e
|
|
|
49
51
|
* hand that agent the ability to suppress every other error body.
|
|
50
52
|
*/
|
|
51
53
|
export declare const CREDENTIAL_REJECTED_MARKER = "was rejected by its provider";
|
|
54
|
+
/**
|
|
55
|
+
* marker for the credential pool's refusal: every configured credential for the
|
|
56
|
+
* model was rejected or exhausted. verbatim for the same reason as
|
|
57
|
+
* `CREDENTIAL_REJECTED_MARKER` — each bullet quotes the probe's verdict.
|
|
58
|
+
*/
|
|
59
|
+
export declare const CREDENTIAL_POOL_REFUSED_MARKER = "No configured credential can serve this run";
|
|
52
60
|
/**
|
|
53
61
|
* Three ways to arrive at "the runner has no key", each with a different CTA:
|
|
54
62
|
* we couldn't read the key you stored, your Router wallet ran dry and you have
|
|
@@ -184,6 +192,24 @@ export declare function buildRejectedCredentialError(params: {
|
|
|
184
192
|
/** stored in Pullfrog (console / `pullfrog auth`) rather than a GitHub Actions secret. */
|
|
185
193
|
inPullfrogStore: boolean;
|
|
186
194
|
}): string;
|
|
195
|
+
export type RefusedCredential = {
|
|
196
|
+
name: string;
|
|
197
|
+
source: CredentialCandidate["source"] | "workflow";
|
|
198
|
+
verdict: Extract<ProbeVerdict, {
|
|
199
|
+
status: "rejected" | "exhausted";
|
|
200
|
+
}>;
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* The credential pool probed every credential configured for the model and
|
|
204
|
+
* none can serve it. One bullet per credential: the probe's own verdict, quoted,
|
|
205
|
+
* plus the remedy its kind and status call for — never inferred from the prose.
|
|
206
|
+
*/
|
|
207
|
+
export declare function buildCredentialPoolRefusedError(params: {
|
|
208
|
+
model: string;
|
|
209
|
+
refused: RefusedCredential[];
|
|
210
|
+
owner: string;
|
|
211
|
+
name: string;
|
|
212
|
+
}): string;
|
|
187
213
|
/**
|
|
188
214
|
* Friendly Markdown summary for both the missing-key and invalid-key cases.
|
|
189
215
|
* Used in the catch / result-failure paths in `main.ts` to overwrite the raw
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** the data dir a subscription was installed into this run, which opencode's XDG_DATA_HOME must name. */
|
|
2
|
+
export declare function getSubscriptionDataHome(): string | undefined;
|
|
1
3
|
export declare function clearInstalledSubscription(name: "CODEX_AUTH_JSON" | "GROK_AUTH_JSON"): void;
|
|
2
4
|
/** sandbox-hidden home for pullfrog-managed on-disk secrets in CI. bash via
|
|
3
5
|
* MCP shell tmpfs-overlays this path; opencode's internal auth module
|
|
@@ -11,8 +13,6 @@ export interface InstalledCodexAuth {
|
|
|
11
13
|
/** absolute path of the auth.json we wrote — caller passes this to the
|
|
12
14
|
* post-hook via core.saveState for refresh-detection later. */
|
|
13
15
|
authPath: string;
|
|
14
|
-
/** value to set as XDG_DATA_HOME for the OpenCode subprocess. */
|
|
15
|
-
xdgDataHome: string;
|
|
16
16
|
/** refresh_token from the env at materialization time. post-hook
|
|
17
17
|
* compares against the on-disk file after the run to detect whether
|
|
18
18
|
* OpenCode refreshed during the session (only happens on long runs
|
|
@@ -31,15 +31,13 @@ export interface InstalledCodexAuth {
|
|
|
31
31
|
* caller treats null as "no codex auth, fall through to API key flow".
|
|
32
32
|
*
|
|
33
33
|
* The env value is server-side guaranteed fresh by `maybeRotateCodexSecret`
|
|
34
|
-
* in the run-context endpoint. We parse + write it here and
|
|
35
|
-
* `
|
|
34
|
+
* in the run-context endpoint. We parse + write it here and record the dir
|
|
35
|
+
* (`getSubscriptionDataHome`) so every opencode subprocess discovers the
|
|
36
36
|
* auth.json; no refresh, no DB interaction. */
|
|
37
37
|
export declare function installCodexAuth(): InstalledCodexAuth | null;
|
|
38
38
|
export interface InstalledXaiAuth {
|
|
39
39
|
/** absolute path of the auth.json we wrote — the post-hook diffs it. */
|
|
40
40
|
authPath: string;
|
|
41
|
-
/** value to set as XDG_DATA_HOME for the OpenCode subprocess. */
|
|
42
|
-
xdgDataHome: string;
|
|
43
41
|
/** refresh_token at materialization time. opencode's XaiAuthPlugin rotates
|
|
44
42
|
* in-process on a long run, so the post-hook compares against this to decide
|
|
45
43
|
* whether anything needs writing back. */
|
package/dist/utils/gitAuth.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ type GitAuthOptions = {
|
|
|
22
22
|
* when present, an auth-class failure is retried ONCE with a fresh token.
|
|
23
23
|
*/
|
|
24
24
|
refreshGitToken?: ((stale: string) => Promise<string>) | undefined;
|
|
25
|
+
signal?: AbortSignal | undefined;
|
|
25
26
|
};
|
|
26
27
|
/**
|
|
27
28
|
* installation-token 401s on git. GitHub intermittently mints a token its git
|
package/dist/utils/github.d.ts
CHANGED
|
@@ -75,7 +75,7 @@ export declare function fetchIdTokenFromStash(creds: OidcCredentials): Promise<s
|
|
|
75
75
|
* own retry still re-mints. Mid-run refreshes take the stashed-credentials path
|
|
76
76
|
* (`opts.oidc`) and deliberately bypass this.
|
|
77
77
|
*/
|
|
78
|
-
export declare const mintIdToken:
|
|
78
|
+
export declare const mintIdToken: (() => Promise<string>) & yes.CacheMethods<undefined, undefined>;
|
|
79
79
|
/**
|
|
80
80
|
* ensure a GitHub token is available in the environment.
|
|
81
81
|
*
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* post-hook's stdlib-only import graph and bring back #815. Keep the two in
|
|
7
7
|
* sync by hand; `entryPost.stdlibOnly.test.ts` guards the reason they differ. */
|
|
8
8
|
export declare const OAUTH_WRITEBACK_STATE = "oauth_writeback";
|
|
9
|
+
/** GHA state key for the run's subscription data dir (codexHome.ts); `entryPost.ts` spells it literally too. */
|
|
10
|
+
export declare const SUBSCRIPTION_DATA_DIR_STATE = "subscription_data_dir";
|
|
9
11
|
/**
|
|
10
12
|
* Persist any OAuth refresh chain the run rotated, back into Pullfrog's own
|
|
11
13
|
* secret store.
|
|
@@ -22,6 +24,9 @@ export declare const OAUTH_WRITEBACK_STATE = "oauth_writeback";
|
|
|
22
24
|
* to write them back from inside a job — so a token stashed there silently
|
|
23
25
|
* goes stale on the first refresh and the next run fails. See wiki/codex-auth.md.
|
|
24
26
|
*
|
|
27
|
+
* Then removes the run's subscription data dir (codexHome.ts), which holds the
|
|
28
|
+
* auth.json diffed here.
|
|
29
|
+
*
|
|
25
30
|
* Best-effort throughout: a missed write-back costs the user one
|
|
26
31
|
* `pullfrog auth codex` re-run, while a throw here would fail a workflow whose
|
|
27
32
|
* agent already succeeded.
|