pullfrog 0.1.100 → 0.1.102
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 +28860 -22002
- package/dist/external.d.ts +2 -2
- package/dist/index.js +28678 -21828
- package/dist/internal/index.d.ts +3 -2
- package/dist/internal.js +8828 -2812
- package/dist/mcp/reviewComments.d.ts +4 -1
- package/dist/mcp/shell.d.ts +1 -0
- package/dist/models.d.ts +4 -0
- package/dist/toolState.d.ts +3 -4
- package/dist/utils/agentHangReport.d.ts +6 -10
- package/dist/utils/apiKeys.d.ts +47 -7
- package/dist/utils/billingErrors.d.ts +7 -4
- package/dist/utils/buildPullfrogFooter.d.ts +17 -4
- package/dist/utils/errorReport.d.ts +0 -1
- package/dist/utils/failureBody.d.ts +27 -0
- package/dist/utils/github.d.ts +1 -1
- package/dist/utils/leapingComment.d.ts +9 -0
- package/dist/utils/payload.d.ts +5 -0
- package/dist/utils/proxy.d.ts +1 -0
- package/dist/utils/roleMirror.d.ts +3 -2
- package/dist/utils/runContext.d.ts +3 -0
- package/dist/utils/runContextData.d.ts +2 -0
- package/dist/utils/runErrorRenderer.d.ts +44 -69
- package/dist/utils/secretCommands.d.ts +5 -14
- package/package.json +9 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Octokit } from "@octokit/rest";
|
|
2
2
|
import type { ToolContext } from "./server.ts";
|
|
3
|
-
export declare const REVIEW_THREADS_QUERY = "\nquery ($owner: String!, $name: String!, $prNumber: Int!, $cursor: String) {\n repository(owner: $owner, name: $name) {\n pullRequest(number: $prNumber) {\n reviewThreads(first: 100, after: $cursor) {\n pageInfo { hasNextPage endCursor }\n nodes {\n id\n path\n line\n startLine\n diffSide\n isResolved\n isOutdated\n comments(first: 50) {\n nodes {\n fullDatabaseId\n body\n bodyHTML\n createdAt\n diffHunk\n line\n startLine\n originalLine\n originalStartLine\n author { login }\n pullRequestReview {\n databaseId\n author { login }\n }\n reactionGroups {\n content\n reactors(first: 10) {\n nodes {\n ... on Actor { login }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}\n";
|
|
3
|
+
export declare const REVIEW_THREADS_QUERY = "\nquery ($owner: String!, $name: String!, $prNumber: Int!, $cursor: String) {\n repository(owner: $owner, name: $name) {\n pullRequest(number: $prNumber) {\n reviewThreads(first: 100, after: $cursor) {\n pageInfo { hasNextPage endCursor }\n nodes {\n id\n path\n line\n startLine\n diffSide\n isResolved\n isOutdated\n comments(first: 50) {\n nodes {\n fullDatabaseId\n body\n bodyHTML\n createdAt\n diffHunk\n line\n startLine\n originalLine\n originalStartLine\n author { login __typename }\n pullRequestReview {\n databaseId\n author { login }\n }\n reactionGroups {\n content\n reactors(first: 10) {\n nodes {\n ... on Actor { login }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}\n";
|
|
4
4
|
export type ReviewThreadComment = {
|
|
5
5
|
fullDatabaseId: string | null;
|
|
6
6
|
body: string;
|
|
@@ -13,6 +13,7 @@ export type ReviewThreadComment = {
|
|
|
13
13
|
originalStartLine: number | null;
|
|
14
14
|
author: {
|
|
15
15
|
login: string;
|
|
16
|
+
__typename: string;
|
|
16
17
|
} | null;
|
|
17
18
|
pullRequestReview: {
|
|
18
19
|
databaseId: number | null;
|
|
@@ -141,6 +142,8 @@ interface GetReviewDataInput {
|
|
|
141
142
|
* to the dispatching review exactly as before.
|
|
142
143
|
*/
|
|
143
144
|
addressScope?: "all" | "mentions" | undefined;
|
|
145
|
+
/** whether this run can push, which is what makes a comment's author matter */
|
|
146
|
+
canPush: boolean;
|
|
144
147
|
tmpdir: string;
|
|
145
148
|
githubToken: string;
|
|
146
149
|
}
|
package/dist/mcp/shell.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare const ShellParams: import("arktype/internal/variants/object.ts").
|
|
|
9
9
|
export type SandboxMethod = "unshare" | "sudo-unshare" | "userns-unshare" | "none";
|
|
10
10
|
/** get the current sandbox method (for testing/diagnostics) */
|
|
11
11
|
export declare function getSandboxMethod(): SandboxMethod;
|
|
12
|
+
export declare function resolveRepoRoot(): string;
|
|
12
13
|
/** chars of shell output kept inline in the agent reply. anything past this
|
|
13
14
|
* blows the agent's context budget on commands that dump big logs (test
|
|
14
15
|
* runners, build tools, grep on large trees), so the overflow is spilled
|
package/dist/models.d.ts
CHANGED
|
@@ -354,6 +354,10 @@ export declare function resolveModelRung(params: {
|
|
|
354
354
|
useOpenRouter: boolean;
|
|
355
355
|
}): string | undefined;
|
|
356
356
|
export declare const DEFAULT_PROXY_MODEL: string;
|
|
357
|
+
export declare const TRIAL_PROXY_MODEL: string;
|
|
358
|
+
export declare const TRIAL_PROXY_DISPLAY_NAME: string;
|
|
359
|
+
/** lifetime cap, in USD, on the model usage Pullfrog funds for an account's trial runs. */
|
|
360
|
+
export declare const TRIAL_FUNDED_USD_LIMIT = 10;
|
|
357
361
|
/**
|
|
358
362
|
* the models Pullfrog is willing to fund on the OSS program. an accepted OSS
|
|
359
363
|
* repo may pick any of these and run-context honors the pick; anything else
|
package/dist/toolState.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentCredential, AgentUsage } from "./agents/shared.ts";
|
|
2
2
|
import type { PrepResult } from "./prep/types.ts";
|
|
3
3
|
import type { AgentDiagnostic } from "./utils/agentHangReport.ts";
|
|
4
|
+
import type { ModelClamp } from "./utils/buildPullfrogFooter.ts";
|
|
4
5
|
import type { DiffCoverageState } from "./utils/diffCoverage.ts";
|
|
5
6
|
import { type ProgressComment, type ProgressCommentType } from "./utils/progressComment.ts";
|
|
6
7
|
import type { TodoTracker } from "./utils/todoTracking.ts";
|
|
@@ -134,16 +135,14 @@ export interface ToolState {
|
|
|
134
135
|
xrepoLearningsFilePath?: string;
|
|
135
136
|
xrepoLearningsSeed?: string;
|
|
136
137
|
xrepoLearningsPersistAttempted?: boolean;
|
|
138
|
+
learningsLocked?: boolean;
|
|
137
139
|
output?: string | undefined;
|
|
138
140
|
usageEntries: AgentUsage[];
|
|
139
141
|
model?: string | undefined;
|
|
140
142
|
agent?: string | undefined;
|
|
141
143
|
credential?: AgentCredential | undefined;
|
|
142
144
|
unselectedProxyDefault?: boolean | undefined;
|
|
143
|
-
modelClamped?:
|
|
144
|
-
from: string;
|
|
145
|
-
reason: "card" | "noRouterPath" | "oss" | "trial";
|
|
146
|
-
} | undefined;
|
|
145
|
+
modelClamped?: ModelClamp | undefined;
|
|
147
146
|
oss?: boolean | undefined;
|
|
148
147
|
todoTracker?: TodoTracker | undefined;
|
|
149
148
|
agentDiagnostic?: AgentDiagnostic | undefined;
|
|
@@ -33,19 +33,15 @@ export type AgentDiagnostic = {
|
|
|
33
33
|
sawModelOutput: boolean;
|
|
34
34
|
};
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* The body for a run the activity watchdog ended. Rendered into both the PR
|
|
37
|
+
* progress comment and the job summary; `null` when the harness left no
|
|
38
|
+
* diagnostic, so the caller falls back to its bare-error rendering.
|
|
37
39
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* `errorMessage` is the underlying timer / spawn reject string (e.g.
|
|
43
|
-
* `activity timeout: no output for 301s`). The idle seconds are parsed out
|
|
44
|
-
* of it for the hang explanation — total runtime would overstate the stall
|
|
45
|
-
* for runs that streamed for a long time before going quiet.
|
|
40
|
+
* The headline says whose side went quiet, because a silent run is nearly
|
|
41
|
+
* always the provider's and "Pullfrog stalled" read as ours. The agent's last
|
|
42
|
+
* output goes in a collapsed section for whoever wants it.
|
|
46
43
|
*/
|
|
47
44
|
export declare function formatAgentHangBody(input: {
|
|
48
45
|
diagnostic: AgentDiagnostic | undefined;
|
|
49
|
-
isHang: boolean;
|
|
50
46
|
errorMessage: string;
|
|
51
47
|
}): string | null;
|
package/dist/utils/apiKeys.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { type FailureLink } from "./failureBody.ts";
|
|
1
2
|
import type { CredentialCandidate } from "./subscriptionCredentials.ts";
|
|
2
3
|
import type { ProbeVerdict } from "./subscriptionProbe.ts";
|
|
3
4
|
/** shared sentence in the four `resolveSlug` routing-slug throws. */
|
|
4
|
-
export declare const BYOK_SLUG_MARKER = "
|
|
5
|
+
export declare const BYOK_SLUG_MARKER = "must be set when the model is";
|
|
5
6
|
/** shared sentence in the four `validate*Setup` throws. */
|
|
6
|
-
export declare const BYOK_CONFIG_MARKER = "
|
|
7
|
+
export declare const BYOK_CONFIG_MARKER = "is missing required settings:";
|
|
7
8
|
/**
|
|
8
9
|
* A BYOK provider setup is incomplete, at either of the two points that catch it:
|
|
9
10
|
* `resolveSlug` refusing a routing slug whose backing env var is unset, and the
|
|
@@ -28,14 +29,35 @@ export declare function isByokSetupError(text: string): boolean;
|
|
|
28
29
|
* `MODEL_ACCESS_MARKER`) because blaming the user for a transient fetch failure
|
|
29
30
|
* on our side is the wrong CTA — their key is configured and still stored.
|
|
30
31
|
*/
|
|
31
|
-
export declare const SECRETS_UNAVAILABLE_MARKER = "couldn't load your
|
|
32
|
+
export declare const SECRETS_UNAVAILABLE_MARKER = "couldn't load your stored secrets";
|
|
32
33
|
/**
|
|
33
34
|
* marker for the "your Router wallet is empty AND you have no provider key"
|
|
34
35
|
* body. its own marker rather than the missing-key one because
|
|
35
36
|
* `formatApiKeyErrorSummary` rebuilds any body carrying `MISSING_KEY_MARKER`
|
|
36
37
|
* that doesn't start with it, which would silently discard this copy.
|
|
37
38
|
*/
|
|
38
|
-
export declare const ROUTER_UNFUNDED_MARKER = "
|
|
39
|
+
export declare const ROUTER_UNFUNDED_MARKER = "Your Pullfrog Router balance is empty";
|
|
40
|
+
/**
|
|
41
|
+
* marker for the body a trial account gets once its funded credits are spent:
|
|
42
|
+
* at the late fallback, or when the funded key runs out mid-run. Without it the
|
|
43
|
+
* first is told to add an API key and the second that a Router wallet it never
|
|
44
|
+
* had went negative, and neither mentions the trial.
|
|
45
|
+
*/
|
|
46
|
+
export declare const TRIAL_SPENT_MARKER = "reached the limit of your free trial credits";
|
|
47
|
+
export declare function buildTrialSpentError(params: {
|
|
48
|
+
owner: string;
|
|
49
|
+
}): string;
|
|
50
|
+
/** the repo's console page: its model, instructions and scripts. */
|
|
51
|
+
export declare function repoConsoleUrl(repo: {
|
|
52
|
+
owner: string;
|
|
53
|
+
name: string;
|
|
54
|
+
}): string;
|
|
55
|
+
export declare function pickModelLink(repo: {
|
|
56
|
+
owner: string;
|
|
57
|
+
name: string;
|
|
58
|
+
}): FailureLink;
|
|
59
|
+
/** the account console's billing card: provider keys, subscriptions and Router credit. */
|
|
60
|
+
export declare function providerLink(owner: string): FailureLink;
|
|
39
61
|
/**
|
|
40
62
|
* marker for a credential the provider explicitly REJECTED before the agent
|
|
41
63
|
* started. needs a verbatim guard for the same reason as its three siblings,
|
|
@@ -76,6 +98,7 @@ export declare const CREDENTIAL_POOL_REFUSED_MARKER = "No configured credential
|
|
|
76
98
|
*/
|
|
77
99
|
export declare class NoUsableCredentialError extends Error {
|
|
78
100
|
}
|
|
101
|
+
export declare function buildSecretsUnavailableError(): string;
|
|
79
102
|
/**
|
|
80
103
|
* Validate that the resolved model can actually be served by the chosen
|
|
81
104
|
* agent. For routing slugs (Bedrock / Vertex) the auth shape is multi-var
|
|
@@ -160,6 +183,8 @@ export declare function isMalformedKeyError(text: string): boolean;
|
|
|
160
183
|
* Anthropic entitlement denial for Claude Pro/Max subscription auth (#1072):
|
|
161
184
|
* an org admin turned off Claude Code subscription access. no credential the
|
|
162
185
|
* user controls fixes it, so it gets its own copy instead of the re-auth CTA.
|
|
186
|
+
* The probe sees the same denial as a 403, `OAuth authentication is currently
|
|
187
|
+
* not allowed for this organization`, which used to be answered "sign in again".
|
|
163
188
|
*/
|
|
164
189
|
export declare function isClaudeSubscriptionDisabledError(text: string): boolean;
|
|
165
190
|
/**
|
|
@@ -178,6 +203,15 @@ export declare function isClaudeSubscriptionDisabledError(text: string): boolean
|
|
|
178
203
|
*/
|
|
179
204
|
export declare function isKimiPlanTierError(text: string): boolean;
|
|
180
205
|
export declare function isClaudeSessionLimitError(text: string): boolean;
|
|
206
|
+
/** the subscription that serves `model`'s provider, named by the env var that carries it. */
|
|
207
|
+
export declare function subscriptionFor(model: string | undefined): {
|
|
208
|
+
label: string;
|
|
209
|
+
command: string;
|
|
210
|
+
provider: string;
|
|
211
|
+
env: string;
|
|
212
|
+
} | undefined;
|
|
213
|
+
/** a provider id's display name, e.g. `openai` → OpenAI. */
|
|
214
|
+
export declare function providerDisplayName(id: string | null | undefined): string | undefined;
|
|
181
215
|
/**
|
|
182
216
|
* The provider rejected a credential we checked before the agent started, and
|
|
183
217
|
* nothing else on the account can serve this run. Names the credential and the
|
|
@@ -201,8 +235,8 @@ export type RefusedCredential = {
|
|
|
201
235
|
};
|
|
202
236
|
/**
|
|
203
237
|
* The credential pool probed every credential configured for the model and
|
|
204
|
-
* none can serve it. One
|
|
205
|
-
*
|
|
238
|
+
* none can serve it. One sentence per credential, from its kind and status —
|
|
239
|
+
* never inferred from the prose — with the probe's own verdicts collapsed below.
|
|
206
240
|
*/
|
|
207
241
|
export declare function buildCredentialPoolRefusedError(params: {
|
|
208
242
|
model: string;
|
|
@@ -213,10 +247,16 @@ export declare function buildCredentialPoolRefusedError(params: {
|
|
|
213
247
|
/**
|
|
214
248
|
* Friendly Markdown summary for both the missing-key and invalid-key cases.
|
|
215
249
|
* Used in the catch / result-failure paths in `main.ts` to overwrite the raw
|
|
216
|
-
* agent error before it's posted to the PR progress comment.
|
|
250
|
+
* agent error before it's posted to the PR progress comment. `model` names the
|
|
251
|
+
* subscription in play — guessing it from the env once told a GPT run its Claude
|
|
252
|
+
* subscription was rejected — and `output`, the provider's own words, is
|
|
253
|
+
* collapsed under the copy.
|
|
217
254
|
*/
|
|
218
255
|
export declare function formatApiKeyErrorSummary(params: {
|
|
219
256
|
owner: string;
|
|
220
257
|
name: string;
|
|
221
258
|
raw: string;
|
|
259
|
+
model?: string | undefined;
|
|
260
|
+
credential?: string | undefined;
|
|
261
|
+
output?: string | undefined;
|
|
222
262
|
}): string;
|
|
@@ -41,7 +41,9 @@ export declare class BillingError extends Error {
|
|
|
41
41
|
* GH Actions apply whatever retry policy the workflow has configured.
|
|
42
42
|
*/
|
|
43
43
|
export declare class TransientError extends Error {
|
|
44
|
-
|
|
44
|
+
/** the customer-facing follow-up to `message`, which is the headline. */
|
|
45
|
+
detail: string;
|
|
46
|
+
constructor(message: string, detail?: string);
|
|
45
47
|
}
|
|
46
48
|
/**
|
|
47
49
|
* Why the org commercial gate refused a run (billing model v2), resolved by
|
|
@@ -68,7 +70,7 @@ export declare function commercialPaywallBody(params: {
|
|
|
68
70
|
/**
|
|
69
71
|
* commercial-gate copy for action runs, linked to the account billing card.
|
|
70
72
|
*
|
|
71
|
-
* if this fires on a `
|
|
73
|
+
* if this fires on a `PullfrogDev/preview-*` repo it is an infrastructure bug, not
|
|
72
74
|
* a billing state — those repos have no real billing state to refuse. the
|
|
73
75
|
* original cause was the gate comparing the subscription's originating host
|
|
74
76
|
* with strict equality, which no preview could satisfy against a cloned
|
|
@@ -114,6 +116,7 @@ export declare function formatBillingErrorSummary(error: BillingError, owner: st
|
|
|
114
116
|
/**
|
|
115
117
|
* Render a TransientError as user-facing markdown. Distinct framing from
|
|
116
118
|
* BillingError so the user doesn't read an alarm and assume their card
|
|
117
|
-
* failed, this branch is "our fault, retry shortly", not theirs.
|
|
119
|
+
* failed, this branch is "our fault, retry shortly", not theirs. Both parts are
|
|
120
|
+
* ours and customer-ready; the server's own wording goes to the log.
|
|
118
121
|
*/
|
|
119
|
-
export declare function formatTransientErrorSummary(error: TransientError
|
|
122
|
+
export declare function formatTransientErrorSummary(error: TransientError): string;
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
export declare const PULLFROG_DIVIDER = "<!-- PULLFROG_DIVIDER_DO_NOT_REMOVE_PLZ -->";
|
|
2
|
+
/**
|
|
3
|
+
* A run whose configured model was swapped for one Pullfrog could fund. `trial`
|
|
4
|
+
* carries the account's remaining trial credits, as run-context counted them
|
|
5
|
+
* when the run started, so the disclosure can say how much is left; undefined
|
|
6
|
+
* when the server predates the figure.
|
|
7
|
+
*/
|
|
8
|
+
export type ModelClamp = {
|
|
9
|
+
from: string;
|
|
10
|
+
reason: "card" | "noRouterPath" | "oss";
|
|
11
|
+
} | {
|
|
12
|
+
from: string;
|
|
13
|
+
reason: "trial";
|
|
14
|
+
creditsLeftUsd: number | undefined;
|
|
15
|
+
};
|
|
2
16
|
export interface WorkflowRunFooterInfo {
|
|
3
17
|
owner: string;
|
|
4
18
|
repo: string;
|
|
@@ -27,10 +41,7 @@ export interface BuildPullfrogFooterParams {
|
|
|
27
41
|
* provider-key nudge — so the downgrade is visible rather than silently
|
|
28
42
|
* presenting Kimi as the pick.
|
|
29
43
|
*/
|
|
30
|
-
clamped?:
|
|
31
|
-
from: string;
|
|
32
|
-
reason: "card" | "noRouterPath" | "oss" | "trial";
|
|
33
|
-
} | undefined;
|
|
44
|
+
clamped?: ModelClamp | undefined;
|
|
34
45
|
/**
|
|
35
46
|
* true when the run used the default proxy model only because no model was
|
|
36
47
|
* selected (Router billing + "auto"). the footer appends a note nudging the
|
|
@@ -47,6 +58,8 @@ export interface BuildPullfrogFooterParams {
|
|
|
47
58
|
/** repo owner, used to deep-link the trial disclosure at that account's own
|
|
48
59
|
* console rather than the generic landing page. */
|
|
49
60
|
owner?: string | undefined;
|
|
61
|
+
/** a failure comment: no 𝕏 link, model nudge or trial disclosure under an error. */
|
|
62
|
+
failed?: boolean | undefined;
|
|
50
63
|
}
|
|
51
64
|
/**
|
|
52
65
|
* build a pullfrog footer with configurable parts
|
|
@@ -2,7 +2,6 @@ import { type ToolState } from "../toolState.ts";
|
|
|
2
2
|
interface ReportErrorParams {
|
|
3
3
|
toolState: ToolState;
|
|
4
4
|
error: string;
|
|
5
|
-
title?: string;
|
|
6
5
|
/**
|
|
7
6
|
* When the run has no pre-existing progress comment to update (silent
|
|
8
7
|
* IncrementalReview / pull_request_synchronize, mode-less polls), create
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type FailureLink = {
|
|
2
|
+
label: string;
|
|
3
|
+
url: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* The one shape every failure comment takes: a bold, sentence-case headline that
|
|
7
|
+
* names the cause, then at most a short paragraph or a list of two or more, then
|
|
8
|
+
* the error or the tool's own output, then at most two links. Built here rather
|
|
9
|
+
* than per message so those rules hold for every message at once.
|
|
10
|
+
*
|
|
11
|
+
* `error` is shown open, for when the error IS the explanation (an unrecognized
|
|
12
|
+
* failure). `details` is collapsed, for output that backs up a headline we
|
|
13
|
+
* already wrote. Free of imports: `billingErrors.ts` reaches client bundles
|
|
14
|
+
* through `action/internal`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function renderFailure(params: {
|
|
17
|
+
headline: string;
|
|
18
|
+
detail?: string | undefined;
|
|
19
|
+
list?: [string, string, ...string[]] | undefined;
|
|
20
|
+
error?: string | undefined;
|
|
21
|
+
details?: {
|
|
22
|
+
summary: string;
|
|
23
|
+
text: string;
|
|
24
|
+
} | undefined;
|
|
25
|
+
links?: [] | [FailureLink] | [FailureLink, FailureLink] | undefined;
|
|
26
|
+
}): string;
|
|
27
|
+
export declare const DISCORD_LINK: FailureLink;
|
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: yes.Cached<() => Promise<string>>;
|
|
79
79
|
/**
|
|
80
80
|
* ensure a GitHub token is available in the environment.
|
|
81
81
|
*
|
|
@@ -9,3 +9,12 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export declare const LEAPING_INTO_ACTION_PREFIX = "Leaping into action";
|
|
11
11
|
export declare function isLeapingIntoActionCommentBody(body: string): boolean;
|
|
12
|
+
/** the spinner on a to-do list's in-progress item. */
|
|
13
|
+
export declare const TODO_SPINNER_URL = "https://uploads.pullfrog.com/Progress%20Indicator.gif";
|
|
14
|
+
/**
|
|
15
|
+
* A live to-do list: one item still carries the spinner. Every finished body — a
|
|
16
|
+
* final summary, a salvaged answer, an error report — renders with in-progress
|
|
17
|
+
* items completed, so the spinner is only ever on a list whose run is still going
|
|
18
|
+
* or died without writing again.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isLiveChecklistCommentBody(body: string): boolean;
|
package/dist/utils/payload.d.ts
CHANGED
|
@@ -39,6 +39,11 @@ export declare const JsonPayload: import("arktype/internal/variants/object.ts").
|
|
|
39
39
|
generateSummary?: boolean | undefined;
|
|
40
40
|
codexArm?: boolean | undefined;
|
|
41
41
|
}, {}>;
|
|
42
|
+
/**
|
|
43
|
+
* a run steered by someone resolved as unable to push here. an absent permission
|
|
44
|
+
* is a run no outside author steers (CI fix, a review bot on Pullfrog's own PR).
|
|
45
|
+
*/
|
|
46
|
+
export declare function isOutsideAuthor(event: PayloadEvent): boolean;
|
|
42
47
|
export declare const Inputs: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
43
48
|
prompt?: string | undefined;
|
|
44
49
|
prompt_file?: string | undefined;
|
package/dist/utils/proxy.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ export declare function runProxyResolution(ctx: {
|
|
|
61
61
|
export declare function resolveTrialFallback(ctx: {
|
|
62
62
|
payload: ResolvedPayload;
|
|
63
63
|
configuredModel: string | undefined;
|
|
64
|
+
creditsLeftUsd: number | undefined;
|
|
64
65
|
oidcCredentials: OidcCredentials | null;
|
|
65
66
|
repo: {
|
|
66
67
|
owner: string;
|
|
@@ -42,8 +42,9 @@ import type { GitHubAppPermissions } from "./github.ts";
|
|
|
42
42
|
* wiki/autonomous-maintenance.md's "no injected instruction can cause a
|
|
43
43
|
* merge" still true. Legitimate pushes go through `push_branch`, which
|
|
44
44
|
* enforces the branch rules.
|
|
45
|
-
* - `checks` is
|
|
46
|
-
*
|
|
45
|
+
* - `checks` is `read`, never `write`, for the same class of reason: every role
|
|
46
|
+
* can read a PR's check runs, but no human role can write one, and write would
|
|
47
|
+
* let the agent post its own passing `pullfrog-approval` status
|
|
47
48
|
* (see wiki/review-approval.md).
|
|
48
49
|
* - Every qualifying role therefore receives the SAME set. The role decides
|
|
49
50
|
* whether a token is minted at all, not how wide it is — `admin`, `maintain`
|
|
@@ -100,6 +100,9 @@ export interface RunContext {
|
|
|
100
100
|
* run — the runner may mint a subsidized efficient-tier key if, and only if,
|
|
101
101
|
* its own key search comes up dry. see the run-context route. */
|
|
102
102
|
trialFallback?: boolean | undefined;
|
|
103
|
+
/** the trial account's remaining funded credits, in USD, when it is inside its
|
|
104
|
+
* trial at all. zero or below means the credits are used up. */
|
|
105
|
+
trialCreditsLeftUsd?: number | undefined;
|
|
103
106
|
}
|
|
104
107
|
/**
|
|
105
108
|
* fetch run context from Pullfrog API
|
|
@@ -29,6 +29,8 @@ export interface RunContextData {
|
|
|
29
29
|
* own key search comes up dry. a permission, not a routing decision — the
|
|
30
30
|
* server cannot see workflow `env:` keys. see `RunContext.trialFallback`. */
|
|
31
31
|
trialFallback?: boolean | undefined;
|
|
32
|
+
/** see `RunContext.trialCreditsLeftUsd`. */
|
|
33
|
+
trialCreditsLeftUsd?: number | undefined;
|
|
32
34
|
}
|
|
33
35
|
interface ResolveRunContextDataParams {
|
|
34
36
|
octokit: OctokitWithPlugins;
|
|
@@ -1,99 +1,67 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Classify + render the error thrown out of the main run try-block into
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Classify + render the error thrown out of the main run try-block into the
|
|
3
|
+
* markdown the user reads — the PR progress comment, and the same body under a
|
|
4
|
+
* `### ❌ Pullfrog failed` banner in the GitHub Actions job summary.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* Every body names its cause, so none collapses to a bare "Run failed.": an
|
|
7
|
+
* error nothing below recognizes is shown as-is under "An unrecognized error
|
|
8
|
+
* occurred." The shape is `renderFailure`'s, so the copy rules hold for all of
|
|
9
|
+
* them — see `failureBody.ts`.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
* handled inline) or the agent runtime surfaced an OpenRouter
|
|
13
|
-
* "key budget exhausted" string mid-run. Both render via
|
|
14
|
-
* `formatBillingErrorSummary` so the user sees actionable copy.
|
|
11
|
+
* Classifications, in dispatch order (first match wins):
|
|
15
12
|
*
|
|
16
|
-
*
|
|
13
|
+
* 1. Trial credits — a trial key that ran out mid-run is the account's free
|
|
14
|
+
* credits running out, never the Router wallet the same wire text means
|
|
15
|
+
* on a Router run.
|
|
16
|
+
*
|
|
17
|
+
* 1a. `BillingError` — the agent runtime surfaced an OpenRouter "key budget
|
|
18
|
+
* exhausted" string mid-run on a Router run. Same copy as a proxy-token 402.
|
|
19
|
+
*
|
|
20
|
+
* 1b. Pre-rendered bodies — a throw site that already built the markdown
|
|
17
21
|
* (`MODEL_ACCESS_MARKER`, `SECRETS_UNAVAILABLE_MARKER`,
|
|
18
|
-
* `ROUTER_UNFUNDED_MARKER`, `
|
|
19
|
-
* `CREDENTIAL_POOL_REFUSED_MARKER`) passes
|
|
22
|
+
* `ROUTER_UNFUNDED_MARKER`, `TRIAL_SPENT_MARKER`,
|
|
23
|
+
* `CREDENTIAL_REJECTED_MARKER`, `CREDENTIAL_POOL_REFUSED_MARKER`) passes
|
|
24
|
+
* through verbatim.
|
|
20
25
|
*
|
|
21
26
|
* 2. BYOK provider billing-exhausted (#835) — DeepSeek "Insufficient
|
|
22
27
|
* Balance", Anthropic "credit balance is too low", OpenCode Zen
|
|
23
|
-
* `CreditsError`, Gemini "spending cap"
|
|
24
|
-
* because billing-exhausted responses
|
|
25
|
-
* that `isApiKeyAuthError` would otherwise
|
|
28
|
+
* `CreditsError`, Gemini "spending cap", a ChatGPT workspace out of
|
|
29
|
+
* credits. Checked before api-key auth because billing-exhausted responses
|
|
30
|
+
* often carry 401 status codes that `isApiKeyAuthError` would otherwise
|
|
31
|
+
* mis-classify.
|
|
26
32
|
*
|
|
27
33
|
* 2a. Provider usage limit (#1474) — a capped subscription window or a
|
|
28
34
|
* configured workspace limit; "wait or raise it", never "top up".
|
|
29
35
|
*
|
|
30
36
|
* 3. API-key auth error — `isApiKeyAuthError` sniffs the raw error string
|
|
31
37
|
* (or the activity-timeout hang body when present, since that's where
|
|
32
|
-
* the underlying provider error often lands)
|
|
33
|
-
* renders provider + console-link copy.
|
|
34
|
-
*
|
|
35
|
-
* 4. ProviderModelNotFoundError — configured model id not in the OpenCode
|
|
36
|
-
* catalog (opencode ≥1.18 words it `Model not found: <id>`, #1470);
|
|
37
|
-
* renders a nudge to pick a different model.
|
|
38
|
-
*
|
|
39
|
-
* 4a. No-provider-available (#1077) — the model IS in the catalog but the
|
|
40
|
-
* provider declines to route it on this account's plan (OpenCode Zen's
|
|
41
|
-
* own refusal string). Same "pick another model" CTA, different reason.
|
|
38
|
+
* the underlying provider error often lands).
|
|
42
39
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* 4b. Context-window overflow (#1116) — terminal `Prompt is too long` /
|
|
49
|
-
* `maximum context length is N tokens`. Actionable, so it renders on
|
|
50
|
-
* both surfaces rather than collapsing to the one-line comment.
|
|
51
|
-
*
|
|
52
|
-
* 4b'. Run time limit — the agent was still working when the run's own
|
|
53
|
-
* timeout fired. Actionable (raise the limit), so both surfaces.
|
|
40
|
+
* 4. Model not in OpenCode's catalog (opencode ≥1.18 words it `Model not
|
|
41
|
+
* found: <id>`, #1470), a provider declining the model (#1077), Zen's
|
|
42
|
+
* free-tier gate (#1377), context overflow (#1116), the run's time limit,
|
|
43
|
+
* the repo's stop script, and an agent that never posted its review.
|
|
54
44
|
*
|
|
55
45
|
* 4c. Transient upstream failure (#1173) — Anthropic `529 Overloaded`,
|
|
56
46
|
* OpenRouter `provider_unavailable` / `timeout`, Zen `Streaming response
|
|
57
|
-
* failed: [5xx]
|
|
58
|
-
*
|
|
59
|
-
* which the user can only know if we say so.
|
|
47
|
+
* failed: [5xx]`, Codex's model at capacity. Last of the classified
|
|
48
|
+
* branches so every more specific one wins first.
|
|
60
49
|
*
|
|
61
|
-
* 5. Activity-timeout hang — `
|
|
62
|
-
*
|
|
63
|
-
* above matched. The harness keeps structured diagnostic state on
|
|
64
|
-
* `toolState.agentDiagnostic`; `formatAgentHangBody` renders that into
|
|
65
|
-
* the job summary. The PR comment keeps that same body whenever the hang
|
|
66
|
-
* is EXPLAINED — a classified provider error (#778, #1183) or a provider
|
|
67
|
-
* that never returned a first token — and otherwise collapses to a
|
|
68
|
-
* one-line `**Run failed.** [View the logs →]`, because watchdog jargon,
|
|
69
|
-
* event counts and a benign stderr tail are operator-grade detail that
|
|
70
|
-
* only alarm the average user.
|
|
50
|
+
* 5. Activity-timeout hang — `formatAgentHangBody` says whose side went
|
|
51
|
+
* quiet, with the agent's last output collapsed under it.
|
|
71
52
|
*
|
|
72
53
|
* 6. Unclassified provider error (#1474) — `errorMessage` starts with
|
|
73
|
-
* `provider error:
|
|
74
|
-
* with the provider's text; claude-code (a zero-event exit) and codex (no
|
|
75
|
-
* turn error, no stderr) prefix only our classifier label. Either names
|
|
76
|
-
* something the user can act on, so both surfaces get a lead line plus the
|
|
77
|
-
* raw text in a fenced block.
|
|
54
|
+
* `provider error: `: the provider's own text, shown under a lead line.
|
|
78
55
|
*
|
|
79
|
-
* 7. Default —
|
|
80
|
-
* raw error in a fenced code block under the `### ❌ Pullfrog failed`
|
|
81
|
-
* banner; the PR comment collapses to the same one-line logs link as
|
|
82
|
-
* the hang case, since the raw internal string helps nobody on the PR.
|
|
83
|
-
*
|
|
84
|
-
* Net: the actionable classifications (billing, usage limit, API-key,
|
|
85
|
-
* model-not-found, no-provider-available, context-overflow, run time limit,
|
|
86
|
-
* transient-upstream, unclassified provider error) render identical bodies on
|
|
87
|
-
* both surfaces; the non-actionable ones (unexplained hang, generic) keep the
|
|
88
|
-
* forensics in the Actions job summary and show a calm one-liner in the PR
|
|
89
|
-
* comment, whose footer already carries Pullfrog branding + rerun links.
|
|
56
|
+
* 7. Default — "An unrecognized error occurred." over the error itself.
|
|
90
57
|
*/
|
|
58
|
+
import type { AgentCredential } from "../agents/shared.ts";
|
|
91
59
|
import type { AgentDiagnostic } from "./agentHangReport.ts";
|
|
92
60
|
export type RenderedRunError = {
|
|
93
61
|
summary: string;
|
|
94
62
|
comment: string;
|
|
95
63
|
};
|
|
96
|
-
|
|
64
|
+
type RenderRunErrorInput = {
|
|
97
65
|
errorMessage: string;
|
|
98
66
|
repo: {
|
|
99
67
|
owner: string;
|
|
@@ -104,4 +72,11 @@ export declare function renderRunError(input: {
|
|
|
104
72
|
* the user's own provider credential. `payload.proxyModel` at both call
|
|
105
73
|
* sites. */
|
|
106
74
|
routerActive: boolean;
|
|
107
|
-
|
|
75
|
+
/** the model that ran: it names the provider, and the subscription when one is in play. */
|
|
76
|
+
model?: string | undefined;
|
|
77
|
+
credential?: AgentCredential | undefined;
|
|
78
|
+
/** the run was served by the account's free trial credits. */
|
|
79
|
+
trial?: boolean | undefined;
|
|
80
|
+
};
|
|
81
|
+
export declare function renderRunError(input: RenderRunErrorInput): RenderedRunError;
|
|
82
|
+
export {};
|
|
@@ -1,19 +1,10 @@
|
|
|
1
|
+
export declare function maskSecret(value: string): void;
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Off a runner nothing consumes these commands and `@actions/core` writes the
|
|
6
|
-
* raw value to stdout instead — `setSecret` always, `saveState` / `setOutput`
|
|
7
|
-
* whenever `GITHUB_STATE` / `GITHUB_OUTPUT` are unset. That is a plaintext
|
|
8
|
-
* credential on whatever terminal is running the action, which is how an OpenAI
|
|
9
|
-
* key reached local Codex transcripts and was disabled (2026-09).
|
|
10
|
-
*
|
|
11
|
-
* Route every credential-bearing call through here instead of calling `core`
|
|
12
|
-
* directly — `nub run check:secret-commands` enforces it. Non-credential output
|
|
13
|
-
* (the agent's own `result` text) stays ungated, because the test harness reads
|
|
14
|
-
* it back through `GITHUB_OUTPUT` on a host with no runner.
|
|
3
|
+
* Every value `maskSecret` registered, replaced in `text` as the runner would in
|
|
4
|
+
* a log: whole, then line by line. Parts under 8 characters are skipped, or the
|
|
5
|
+
* `{` and `}` lines of a JSON key would blank every brace in the comment.
|
|
15
6
|
*/
|
|
16
|
-
export declare function
|
|
7
|
+
export declare function redactSecrets(text: string): string;
|
|
17
8
|
/** @see maskSecret — same gate, for state the `post:` hook reads back. */
|
|
18
9
|
export declare function saveSecretState(name: string, value: string): void;
|
|
19
10
|
/** @see maskSecret — same gate, for a step output carrying a credential. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pullfrog",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.102",
|
|
4
4
|
"cliContractVersion": "1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"prepare": "cd .. && husky"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@actions/core": "^
|
|
30
|
+
"@actions/core": "^3.0.1",
|
|
31
31
|
"@anthropic-ai/claude-code": "2.1.293",
|
|
32
32
|
"@ark/fs": "0.56.0",
|
|
33
33
|
"@ark/util": "0.56.0",
|
|
34
34
|
"@clack/prompts": "^1.2.0",
|
|
35
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
35
|
+
"@modelcontextprotocol/sdk": "^1.32.0",
|
|
36
36
|
"@octokit/plugin-throttling": "^11.0.3",
|
|
37
37
|
"@octokit/rest": "^22.0.0",
|
|
38
38
|
"@octokit/webhooks-types": "^7.6.1",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@openai/codex-sdk": "0.159.2",
|
|
41
41
|
"@opencode-ai/sdk": "1.18.29",
|
|
42
42
|
"@standard-schema/spec": "1.1.0",
|
|
43
|
-
"@toon-format/toon": "^
|
|
43
|
+
"@toon-format/toon": "^2.3.1",
|
|
44
44
|
"@types/node": "^24.7.2",
|
|
45
45
|
"@types/semver": "^7.7.1",
|
|
46
46
|
"@types/turndown": "^5.0.5",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"esbuild": "^0.25.9",
|
|
54
54
|
"execa": "^9.6.0",
|
|
55
55
|
"fastmcp": "^3.34.0",
|
|
56
|
-
"file-type": "^21.3.
|
|
56
|
+
"file-type": "^21.3.2",
|
|
57
57
|
"husky": "^9.0.0",
|
|
58
58
|
"opencode-ai": "1.18.29",
|
|
59
59
|
"package-manager-detector": "^1.6.0",
|
|
@@ -64,10 +64,10 @@
|
|
|
64
64
|
"turndown": "^7.2.0",
|
|
65
65
|
"typescript": "^5.9.3",
|
|
66
66
|
"undici": "^7.22.0",
|
|
67
|
-
"vitest": "^4.
|
|
68
|
-
"yaml": "^2.8.
|
|
69
|
-
"yes": "0.2.
|
|
70
|
-
"zod": "4.
|
|
67
|
+
"vitest": "^4.1.12",
|
|
68
|
+
"yaml": "^2.8.3",
|
|
69
|
+
"yes": "0.2.7",
|
|
70
|
+
"zod": "4.6.6"
|
|
71
71
|
},
|
|
72
72
|
"repository": {
|
|
73
73
|
"type": "git",
|