pullfrog 0.1.30 → 0.1.31
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/agents/claudePretoolGate.d.ts +5 -1
- package/dist/agents/opencodePlugin.d.ts +2 -2
- package/dist/agents/postRun.d.ts +8 -31
- package/dist/agents/shared.d.ts +6 -0
- package/dist/agents/subagentToolGates.d.ts +22 -40
- package/dist/cli.mjs +63441 -59740
- package/dist/external.d.ts +45 -2
- package/dist/index.js +61939 -58238
- package/dist/internal/index.d.ts +2 -2
- package/dist/internal.js +89 -22
- package/dist/mcp/checkSuite.d.ts +3 -1
- package/dist/mcp/checkout.d.ts +4 -2
- package/dist/mcp/comment.d.ts +12 -4
- package/dist/mcp/commitInfo.d.ts +3 -1
- package/dist/mcp/dependencies.d.ts +6 -2
- package/dist/mcp/git.d.ts +26 -7
- package/dist/mcp/issue.d.ts +26 -1
- package/dist/mcp/issueComments.d.ts +3 -1
- package/dist/mcp/issueEvents.d.ts +3 -1
- package/dist/mcp/issueInfo.d.ts +3 -1
- package/dist/mcp/labels.d.ts +16 -1
- package/dist/mcp/output.d.ts +6 -2
- package/dist/mcp/pr.d.ts +19 -2
- package/dist/mcp/prInfo.d.ts +3 -1
- package/dist/mcp/resolveRepoCtx.d.ts +34 -0
- package/dist/mcp/review.d.ts +9 -3
- package/dist/mcp/reviewComments.d.ts +9 -3
- package/dist/mcp/selectMode.d.ts +3 -1
- package/dist/mcp/server.d.ts +6 -1
- package/dist/mcp/shared.d.ts +18 -1
- package/dist/mcp/shell.d.ts +6 -2
- package/dist/mcp/upload.d.ts +3 -1
- package/dist/mcp/xrepo.d.ts +15 -0
- package/dist/models.d.ts +58 -5
- package/dist/toolState.d.ts +69 -16
- package/dist/utils/apiKeys.d.ts +4 -0
- package/dist/utils/buildPullfrogFooter.d.ts +34 -0
- package/dist/utils/errorReport.d.ts +2 -2
- package/dist/utils/github.d.ts +1 -1
- package/dist/utils/instructions.d.ts +8 -0
- package/dist/utils/isTransientNetworkError.d.ts +10 -0
- package/dist/utils/learnings.d.ts +14 -0
- package/dist/utils/modelAccess.d.ts +64 -0
- package/dist/utils/payload.d.ts +16 -0
- package/dist/utils/runContext.d.ts +3 -0
- package/dist/utils/runContextData.d.ts +10 -0
- package/dist/utils/setup.d.ts +18 -3
- package/dist/utils/token.d.ts +10 -2
- package/dist/yes/index.d.ts +32 -0
- package/dist/yes/standard-schema.d.ts +117 -0
- package/dist/yes.js +1244 -0
- package/package.json +19 -10
- package/dist/utils/retry.d.ts +0 -13
|
@@ -147,7 +147,9 @@ export declare function GetReviewCommentsTool(ctx: ToolContext): import("fastmcp
|
|
|
147
147
|
}, {
|
|
148
148
|
pull_number: number;
|
|
149
149
|
review_id: number;
|
|
150
|
-
}
|
|
150
|
+
}>> & {
|
|
151
|
+
mutates?: boolean;
|
|
152
|
+
};
|
|
151
153
|
export declare const ListPullRequestReviews: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
152
154
|
pull_number: number;
|
|
153
155
|
}, {}>;
|
|
@@ -155,7 +157,9 @@ export declare function ListPullRequestReviewsTool(ctx: ToolContext): import("fa
|
|
|
155
157
|
pull_number: number;
|
|
156
158
|
}, {
|
|
157
159
|
pull_number: number;
|
|
158
|
-
}
|
|
160
|
+
}>> & {
|
|
161
|
+
mutates?: boolean;
|
|
162
|
+
};
|
|
159
163
|
export declare const ResolveReviewThread: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
160
164
|
thread_id: string;
|
|
161
165
|
}, {}>;
|
|
@@ -163,5 +167,7 @@ export declare function ResolveReviewThreadTool(ctx: ToolContext): import("fastm
|
|
|
163
167
|
thread_id: string;
|
|
164
168
|
}, {
|
|
165
169
|
thread_id: string;
|
|
166
|
-
}
|
|
170
|
+
}>> & {
|
|
171
|
+
mutates?: boolean;
|
|
172
|
+
};
|
|
167
173
|
export {};
|
package/dist/mcp/selectMode.d.ts
CHANGED
package/dist/mcp/server.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import "./arkConfig.ts";
|
|
2
|
-
import { type AgentId } from "../external.ts";
|
|
2
|
+
import { type AgentId, type XrepoConfig } from "../external.ts";
|
|
3
3
|
import type { Mode } from "../modes.ts";
|
|
4
4
|
import type { ToolState } from "../toolState.ts";
|
|
5
5
|
import type { OctokitWithPlugins } from "../utils/github.ts";
|
|
6
6
|
import type { ResolvedPayload } from "../utils/payload.ts";
|
|
7
7
|
import type { AccountPlan } from "../utils/runContext.ts";
|
|
8
8
|
import type { RunContextData } from "../utils/runContextData.ts";
|
|
9
|
+
import { type PullfrogTool } from "./shared.ts";
|
|
9
10
|
export interface ToolContext {
|
|
10
11
|
agentId: AgentId;
|
|
11
12
|
repo: RunContextData["repo"];
|
|
@@ -13,6 +14,9 @@ export interface ToolContext {
|
|
|
13
14
|
octokit: OctokitWithPlugins;
|
|
14
15
|
githubInstallationToken: string;
|
|
15
16
|
gitToken: string;
|
|
17
|
+
refreshGitToken: ((stale: string) => Promise<string>) | undefined;
|
|
18
|
+
readToken: string | undefined;
|
|
19
|
+
xrepo: XrepoConfig | undefined;
|
|
16
20
|
apiToken: string;
|
|
17
21
|
modes: Mode[];
|
|
18
22
|
postCheckoutScript: string | null;
|
|
@@ -30,6 +34,7 @@ export interface ToolContext {
|
|
|
30
34
|
resolvedModel: string | undefined;
|
|
31
35
|
}
|
|
32
36
|
type JsonSchema = Record<string, unknown>;
|
|
37
|
+
export declare function buildOrchestratorTools(ctx: ToolContext, outputSchema?: JsonSchema): PullfrogTool[];
|
|
33
38
|
type McpHttpServerOptions = {
|
|
34
39
|
outputSchema?: JsonSchema | undefined;
|
|
35
40
|
};
|
package/dist/mcp/shared.d.ts
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
2
|
import type { FastMCP, Tool } from "fastmcp";
|
|
3
3
|
import type { ToolContext } from "./server.ts";
|
|
4
|
-
|
|
4
|
+
/** extract the HTTP status from an unknown thrown value (octokit RequestError etc.), or undefined. */
|
|
5
|
+
export declare function getHttpStatus(err: unknown): number | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* a Pullfrog MCP tool definition. `mutates` marks a named state-changing tool
|
|
8
|
+
* that must be reserved for the orchestrator and denied to subagents — it is
|
|
9
|
+
* the single source of truth the subagent deny list derives from (see
|
|
10
|
+
* action/agents/subagentToolGates.ts). general-purpose execution tools (`git`,
|
|
11
|
+
* `shell`) are deliberately left unmarked: they can mutate but are allowed for
|
|
12
|
+
* subagents and gated by command-arg validation instead.
|
|
13
|
+
*/
|
|
14
|
+
export type PullfrogTool = Tool<any, any> & {
|
|
15
|
+
mutates?: boolean;
|
|
16
|
+
};
|
|
17
|
+
export declare const tool: <const params>(toolDef: Tool<any, StandardSchemaV1<params>> & {
|
|
18
|
+
mutates?: boolean;
|
|
19
|
+
}) => Tool<any, StandardSchemaV1<params>> & {
|
|
20
|
+
mutates?: boolean;
|
|
21
|
+
};
|
|
5
22
|
export interface ToolResult {
|
|
6
23
|
content: {
|
|
7
24
|
type: "text";
|
package/dist/mcp/shell.d.ts
CHANGED
|
@@ -26,7 +26,9 @@ export declare function ShellTool(ctx: ToolContext): import("fastmcp").Tool<any,
|
|
|
26
26
|
timeout?: number;
|
|
27
27
|
working_directory?: string;
|
|
28
28
|
background?: boolean;
|
|
29
|
-
}
|
|
29
|
+
}>> & {
|
|
30
|
+
mutates?: boolean;
|
|
31
|
+
};
|
|
30
32
|
export declare const KillBackgroundParams: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
31
33
|
handle: string;
|
|
32
34
|
}, {}>;
|
|
@@ -34,4 +36,6 @@ export declare function KillBackgroundTool(ctx: ToolContext): import("fastmcp").
|
|
|
34
36
|
handle: string;
|
|
35
37
|
}, {
|
|
36
38
|
handle: string;
|
|
37
|
-
}
|
|
39
|
+
}>> & {
|
|
40
|
+
mutates?: boolean;
|
|
41
|
+
};
|
package/dist/mcp/upload.d.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ToolContext } from "./server.ts";
|
|
2
|
+
export declare const ListRepos: import("arktype/internal/variants/object.ts").ObjectType<object, {}>;
|
|
3
|
+
export declare function ListReposTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<object, object>> & {
|
|
4
|
+
mutates?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare const CheckoutRepo: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
7
|
+
repo: string;
|
|
8
|
+
}, {}>;
|
|
9
|
+
export declare function CheckoutRepoTool(ctx: ToolContext): import("fastmcp").Tool<any, import("@standard-schema/spec").StandardSchemaV1<{
|
|
10
|
+
repo: string;
|
|
11
|
+
}, {
|
|
12
|
+
repo: string;
|
|
13
|
+
}>> & {
|
|
14
|
+
mutates?: boolean;
|
|
15
|
+
};
|
package/dist/models.d.ts
CHANGED
|
@@ -36,7 +36,11 @@ export interface ModelAlias {
|
|
|
36
36
|
preferred: boolean;
|
|
37
37
|
/** whether this alias is free and requires no API key */
|
|
38
38
|
isFree: boolean;
|
|
39
|
-
/** slug of a replacement model
|
|
39
|
+
/** slug of a replacement model to resolve through. presence means this alias
|
|
40
|
+
* never runs as-is — resolution redirects to the replacement and it's hidden
|
|
41
|
+
* from pickers. covers permanent deprecation AND riding out a temporarily
|
|
42
|
+
* unavailable model: point it at a cheaper tier (downgrade) or a working
|
|
43
|
+
* sibling/higher tier (upgrade), then clear it when the model returns. */
|
|
40
44
|
fallback: string | undefined;
|
|
41
45
|
/** dynamic-resolution discriminant — see ModelRouting docs */
|
|
42
46
|
routing: ModelRouting | undefined;
|
|
@@ -57,7 +61,9 @@ interface ModelDef {
|
|
|
57
61
|
preferred?: boolean;
|
|
58
62
|
envVars?: readonly string[];
|
|
59
63
|
isFree?: boolean;
|
|
60
|
-
/** slug of a replacement model
|
|
64
|
+
/** slug of a replacement model to resolve through — permanent deprecation or
|
|
65
|
+
* temporary unavailability (downgrade/upgrade until the model returns). see
|
|
66
|
+
* ModelAlias.fallback. */
|
|
61
67
|
fallback?: string;
|
|
62
68
|
/** dynamic-resolution discriminant — see ModelRouting docs */
|
|
63
69
|
routing?: ModelRouting;
|
|
@@ -104,9 +110,53 @@ export declare function getModelEnvVars(slug: string): string[];
|
|
|
104
110
|
* see `provider.managedCredentials` and wiki/codex-auth.md. */
|
|
105
111
|
export declare function getModelManagedCredentials(slug: string): string[];
|
|
106
112
|
export declare const modelAliases: ModelAlias[];
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
113
|
+
/**
|
|
114
|
+
* `repo.model` sentinels for the two managed auto tiers. stored verbatim in
|
|
115
|
+
* the DB (they pass the `provider/model` shape check) and resolved to a
|
|
116
|
+
* concrete alias by `resolveDisplayAlias` below, so every downstream consumer
|
|
117
|
+
* (CLI resolve, OpenRouter resolve, footer label) handles them transparently.
|
|
118
|
+
*
|
|
119
|
+
* `efficient` mirrors the OSS/default subsidy model (Kimi K2 — fast + cheap);
|
|
120
|
+
* `intelligent` is the frontier pick (Claude Opus). a `null` model means the
|
|
121
|
+
* tier hasn't been pinned: callers default by card status via `defaultAutoTier`.
|
|
122
|
+
*/
|
|
123
|
+
export declare const AUTO_EFFICIENT = "auto/efficient";
|
|
124
|
+
export declare const AUTO_INTELLIGENT = "auto/intelligent";
|
|
125
|
+
export type AutoTier = typeof AUTO_EFFICIENT | typeof AUTO_INTELLIGENT;
|
|
126
|
+
export declare function isAutoTier(slug: string | null | undefined): slug is AutoTier;
|
|
127
|
+
/**
|
|
128
|
+
* the tier to default to when the user hasn't pinned one. card on file →
|
|
129
|
+
* intelligent (they've signalled willingness to pay for frontier reviews);
|
|
130
|
+
* otherwise → efficient (safe, cheap). server (`run-context`) and the console
|
|
131
|
+
* picker both call this so the displayed default and the runtime default agree.
|
|
132
|
+
*/
|
|
133
|
+
export declare function defaultAutoTier(hasCard: boolean): AutoTier;
|
|
134
|
+
/**
|
|
135
|
+
* the auto tier that actually runs for an account, enforcing the card gate:
|
|
136
|
+
* the intelligent tier (Opus) requires a card on file, so a no-card account is
|
|
137
|
+
* always clamped to efficient (Kimi) — whether intelligent was the card-based
|
|
138
|
+
* default or an explicit pick made while a card was once present. keeps a trial
|
|
139
|
+
* balance from being torched on a premium model before the user has a card.
|
|
140
|
+
* `model` may be null, an `auto/*` sentinel, or a concrete pick being
|
|
141
|
+
* clamped — callers route concrete picks here only when `!hasCard` (carded
|
|
142
|
+
* concrete picks resolve directly), so a concrete `model` always lands on the
|
|
143
|
+
* efficient tier via the no-card early return.
|
|
144
|
+
*/
|
|
145
|
+
export declare function resolveAutoTier(params: {
|
|
146
|
+
model: string | null;
|
|
147
|
+
hasCard: boolean;
|
|
148
|
+
}): AutoTier;
|
|
149
|
+
/**
|
|
150
|
+
* Router-resolvable — the set a card on file unlocks. custom (non-Auto) picks
|
|
151
|
+
* are card-gated wholesale on the Router: the console locks the Custom tab
|
|
152
|
+
* without a card and the server clamps any stored pick to the efficient tier.
|
|
153
|
+
* a pick with no openRouterResolve (a model OpenRouter doesn't serve yet)
|
|
154
|
+
* lands on the efficient default with or without a card, so "add a card to
|
|
155
|
+
* run this model" messaging would be false for it — hence the predicate.
|
|
156
|
+
* resolveOpenRouterModel walks display aliases, so auto sentinels and
|
|
157
|
+
* deprecated slugs are judged by the model that actually runs.
|
|
158
|
+
*/
|
|
159
|
+
export declare function isCardGatedModel(slug: string): boolean;
|
|
110
160
|
/** resolve a model slug to its concrete models.dev specifier (e.g. "anthropic/claude-opus-4-6") */
|
|
111
161
|
export declare function resolveModelSlug(slug: string): string | undefined;
|
|
112
162
|
/**
|
|
@@ -132,6 +182,9 @@ export declare function resolveCliModel(slug: string): string | undefined;
|
|
|
132
182
|
* (e.g. free opencode models).
|
|
133
183
|
*/
|
|
134
184
|
export declare function resolveOpenRouterModel(slug: string): string | undefined;
|
|
185
|
+
export declare const DEFAULT_PROXY_MODEL: string;
|
|
186
|
+
/** short label for the model auto-select picks today (console hint copy). */
|
|
187
|
+
export declare function getAutoSelectHintModel(): string;
|
|
135
188
|
/** env var that supplies the Bedrock model ID for the `bedrock/byok` slug. */
|
|
136
189
|
export declare const BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
|
|
137
190
|
/** env var that supplies the Vertex AI model ID for the `vertex/byok` slug. */
|
package/dist/toolState.d.ts
CHANGED
|
@@ -32,6 +32,40 @@ export type CommentableLines = {
|
|
|
32
32
|
RIGHT: Set<number>;
|
|
33
33
|
LEFT: Set<number>;
|
|
34
34
|
};
|
|
35
|
+
/** access tier of a checked-out repo, drives token routing + push gating. */
|
|
36
|
+
export type RepoAccess = "primary" | "write" | "read";
|
|
37
|
+
/**
|
|
38
|
+
* per-repo working-tree + PR state. the primary repo is keyed like any other
|
|
39
|
+
* in `toolState.repos`; secondaries are added by `checkout_repo`. this is the
|
|
40
|
+
* single source of truth for all repo-scoped git/PR state — there are no
|
|
41
|
+
* parallel inline fields on `ToolState`. read via `primaryRepoState(toolState)`
|
|
42
|
+
* for primary-only call sites, or `requireRepoState(toolState, owner, name)`
|
|
43
|
+
* when a `repo` param routes to a specific checkout.
|
|
44
|
+
*/
|
|
45
|
+
export interface RepoToolState {
|
|
46
|
+
owner: string;
|
|
47
|
+
name: string;
|
|
48
|
+
/** working directory: primary = `process.cwd()`; secondary = `ctx.tmpdir/xrepo/<name>` */
|
|
49
|
+
dir: string;
|
|
50
|
+
access: RepoAccess;
|
|
51
|
+
defaultBranch?: string;
|
|
52
|
+
pushUrl?: string;
|
|
53
|
+
pushDest?: StoredPushDest;
|
|
54
|
+
initialHead?: {
|
|
55
|
+
kind: "branch";
|
|
56
|
+
name: string;
|
|
57
|
+
} | {
|
|
58
|
+
kind: "detached";
|
|
59
|
+
sha: string;
|
|
60
|
+
};
|
|
61
|
+
issueNumber?: number;
|
|
62
|
+
checkoutSha?: string;
|
|
63
|
+
commentableLinesByFile?: Map<string, CommentableLines>;
|
|
64
|
+
commentableLinesPullNumber?: number;
|
|
65
|
+
commentableLinesCheckoutSha?: string | undefined;
|
|
66
|
+
beforeSha?: string;
|
|
67
|
+
diffCoverage?: DiffCoverageState | undefined;
|
|
68
|
+
}
|
|
35
69
|
/**
|
|
36
70
|
* mutable per-run record of facts that occurred during execution. shared
|
|
37
71
|
* between the action process and the MCP server (one process — toolState is
|
|
@@ -55,21 +89,8 @@ export type CommentableLines = {
|
|
|
55
89
|
* MCP tool already records.
|
|
56
90
|
*/
|
|
57
91
|
export interface ToolState {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
initialHead?: {
|
|
61
|
-
kind: "branch";
|
|
62
|
-
name: string;
|
|
63
|
-
} | {
|
|
64
|
-
kind: "detached";
|
|
65
|
-
sha: string;
|
|
66
|
-
};
|
|
67
|
-
issueNumber?: number;
|
|
68
|
-
checkoutSha?: string;
|
|
69
|
-
commentableLinesByFile?: Map<string, CommentableLines>;
|
|
70
|
-
commentableLinesPullNumber?: number;
|
|
71
|
-
commentableLinesCheckoutSha?: string | undefined;
|
|
72
|
-
beforeSha?: string;
|
|
92
|
+
repos: Map<string, RepoToolState>;
|
|
93
|
+
primaryRepoKey: string;
|
|
73
94
|
selectedMode?: string;
|
|
74
95
|
prepushFailureCount: number;
|
|
75
96
|
backgroundProcesses: Map<string, BackgroundProcess>;
|
|
@@ -94,6 +115,7 @@ export interface ToolState {
|
|
|
94
115
|
lastProgressBody?: string;
|
|
95
116
|
wasUpdated?: boolean;
|
|
96
117
|
finalSummaryWritten?: boolean;
|
|
118
|
+
answerCommentPosted?: boolean;
|
|
97
119
|
existingPlanCommentId?: number;
|
|
98
120
|
previousPlanBody?: string;
|
|
99
121
|
summaryFilePath?: string;
|
|
@@ -102,12 +124,23 @@ export interface ToolState {
|
|
|
102
124
|
learningsFilePath?: string;
|
|
103
125
|
learningsSeed?: string;
|
|
104
126
|
learningsPersistAttempted?: boolean;
|
|
127
|
+
xrepoLearningsFilePath?: string;
|
|
128
|
+
xrepoLearningsSeed?: string;
|
|
129
|
+
xrepoLearningsPersistAttempted?: boolean;
|
|
105
130
|
output?: string | undefined;
|
|
106
131
|
usageEntries: AgentUsage[];
|
|
107
132
|
model?: string | undefined;
|
|
133
|
+
modelFallback?: {
|
|
134
|
+
from: string;
|
|
135
|
+
} | undefined;
|
|
136
|
+
unselectedProxyDefault?: boolean | undefined;
|
|
137
|
+
modelClamped?: {
|
|
138
|
+
from: string;
|
|
139
|
+
reason: "card" | "noRouterPath";
|
|
140
|
+
} | undefined;
|
|
141
|
+
shaPinned?: boolean | undefined;
|
|
108
142
|
oss?: boolean | undefined;
|
|
109
143
|
todoTracker?: TodoTracker | undefined;
|
|
110
|
-
diffCoverage?: DiffCoverageState | undefined;
|
|
111
144
|
agentDiagnostic?: AgentDiagnostic | undefined;
|
|
112
145
|
}
|
|
113
146
|
interface InitToolStateParams {
|
|
@@ -115,6 +148,26 @@ interface InitToolStateParams {
|
|
|
115
148
|
id: string;
|
|
116
149
|
type: ProgressCommentType;
|
|
117
150
|
} | undefined;
|
|
151
|
+
owner: string;
|
|
152
|
+
name: string;
|
|
153
|
+
dir: string;
|
|
118
154
|
}
|
|
119
155
|
export declare function initToolState(params: InitToolStateParams): ToolState;
|
|
156
|
+
/** stable "owner/name" key for the `repos` map. lowercased — GitHub repo names are case-insensitive. */
|
|
157
|
+
export declare function repoKey(owner: string, name: string): string;
|
|
158
|
+
/** the primary (triggering) repo's state. throws if init hasn't run. */
|
|
159
|
+
export declare function primaryRepoState(toolState: ToolState): RepoToolState;
|
|
160
|
+
/**
|
|
161
|
+
* state for a specific checked-out repo. throws when the repo isn't a
|
|
162
|
+
* registered checkout — keeps the push/PR allow-set honest (the only way a
|
|
163
|
+
* secondary becomes registered is via `checkout_repo`).
|
|
164
|
+
*/
|
|
165
|
+
export declare function requireRepoState(toolState: ToolState, owner: string, name: string): RepoToolState;
|
|
166
|
+
/** get-or-create a repo's state (used by checkout_repo when registering a secondary). */
|
|
167
|
+
export declare function ensureRepoState(toolState: ToolState, init: {
|
|
168
|
+
owner: string;
|
|
169
|
+
name: string;
|
|
170
|
+
dir: string;
|
|
171
|
+
access: RepoAccess;
|
|
172
|
+
}): RepoToolState;
|
|
120
173
|
export {};
|
package/dist/utils/apiKeys.d.ts
CHANGED
|
@@ -33,6 +33,10 @@ export declare function validateAgentApiKey(params: {
|
|
|
33
33
|
* "Token refresh failed: 401". the Bedrock pattern is anchored to the
|
|
34
34
|
* Claude CLI emission ("Failed to authenticate. API Error:") so generic
|
|
35
35
|
* auth chatter in agent stderr can't misclassify a hang as a key error.
|
|
36
|
+
* - DeepSeek invalid key (#960): `Authentication Fails, Your api key:
|
|
37
|
+
* ****XXXX is invalid`. anchored to "Your api key: ... is invalid" so it
|
|
38
|
+
* can't collide with DeepSeek's already-handled `Insufficient balance`
|
|
39
|
+
* billing shape (which routes to formatProviderBillingExhausted).
|
|
36
40
|
*/
|
|
37
41
|
export declare function isApiKeyAuthError(text: string): boolean;
|
|
38
42
|
/**
|
|
@@ -17,6 +17,40 @@ export interface BuildPullfrogFooterParams {
|
|
|
17
17
|
customParts?: string[] | undefined;
|
|
18
18
|
/** model slug from payload (e.g., "anthropic/claude-opus"). shown in footer as "Using `Model Name`" */
|
|
19
19
|
model?: string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* When the action engaged the BYOK fallback, this is the slug the user
|
|
22
|
+
* had configured (e.g. "anthropic/claude-opus") — the footer renders
|
|
23
|
+
* `Using <free model> (credentials for <configured> not configured)`
|
|
24
|
+
* so the substitution is visible in PR comments + reviews.
|
|
25
|
+
*/
|
|
26
|
+
fallbackFrom?: string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* When a Router account had a model (or the intelligent tier) selected that
|
|
29
|
+
* the server clamped to the efficient default — custom picks are card-gated
|
|
30
|
+
* wholesale. `from` is the configured slug (e.g. "anthropic/claude-opus");
|
|
31
|
+
* `reason` names the binding constraint — "card" (no card on file) renders
|
|
32
|
+
* `Using <Kimi K2> (<Claude Opus> needs a card on file)`, "noRouterPath"
|
|
33
|
+
* (no openRouterResolve yet and no stored provider key) renders a
|
|
34
|
+
* provider-key nudge — so the downgrade is visible rather than silently
|
|
35
|
+
* presenting Kimi as the pick.
|
|
36
|
+
*/
|
|
37
|
+
clamped?: {
|
|
38
|
+
from: string;
|
|
39
|
+
reason: "card" | "noRouterPath";
|
|
40
|
+
} | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* true when the run used the default proxy model only because no model was
|
|
43
|
+
* selected (Router billing + "auto"). the footer appends a note nudging the
|
|
44
|
+
* user to pick a model — the cost-optimized default is a weaker reviewer
|
|
45
|
+
* than a frontier model.
|
|
46
|
+
*/
|
|
47
|
+
unselectedProxyDefault?: boolean | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* true when the action is pinned to a full commit SHA — the footer leads
|
|
50
|
+
* with a maintenance nudge to switch to the moving `@v0` tag (a SHA pin
|
|
51
|
+
* freezes the post-run cleanup step, which silently fails the workflow).
|
|
52
|
+
*/
|
|
53
|
+
shaPinned?: boolean | undefined;
|
|
20
54
|
/**
|
|
21
55
|
* true when the run's model costs are covered by the Pullfrog for OSS
|
|
22
56
|
* program — the footer renders `Using <model> (free via Pullfrog for OSS)`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ToolState } from "../toolState.ts";
|
|
2
2
|
interface ReportErrorParams {
|
|
3
3
|
toolState: ToolState;
|
|
4
4
|
error: string;
|
|
@@ -6,7 +6,7 @@ interface ReportErrorParams {
|
|
|
6
6
|
/**
|
|
7
7
|
* When the run has no pre-existing progress comment to update (silent
|
|
8
8
|
* IncrementalReview / pull_request_synchronize, mode-less polls), create
|
|
9
|
-
* a fresh issue comment on `
|
|
9
|
+
* a fresh issue comment on the primary repo state's `issueNumber` instead of returning
|
|
10
10
|
* silently. Used for terminal errors (BillingError, TransientError) where
|
|
11
11
|
* the GH job summary is the only other surface and most users never open
|
|
12
12
|
* it. see #775.
|
package/dist/utils/github.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ type GitHubAppPermissions = {
|
|
|
40
40
|
workflows?: WriteOnly;
|
|
41
41
|
};
|
|
42
42
|
type AcquireTokenOptions = {
|
|
43
|
-
repos?: string[];
|
|
43
|
+
repos?: string[] | undefined;
|
|
44
44
|
permissions?: GitHubAppPermissions;
|
|
45
45
|
/**
|
|
46
46
|
* stashed OIDC credentials for minting after restricted mode deletes
|
|
@@ -24,6 +24,14 @@ interface InstructionsContext {
|
|
|
24
24
|
* `describeSetupFailure`), rendered as a SETUP HOOK FAILED banner. empty
|
|
25
25
|
* string when the hook succeeded, was skipped, or wasn't configured. */
|
|
26
26
|
setupHookFailure: string;
|
|
27
|
+
/** operator-authored cross-repo brief (`Account.xrepoBrief`), rendered in
|
|
28
|
+
* the CROSS-REPO section on --xrepo runs. null/empty otherwise. */
|
|
29
|
+
xrepoBrief: string | null;
|
|
30
|
+
/** absolute path to the seeded cross-repo learnings tmpfile (--xrepo runs
|
|
31
|
+
* only), or null. */
|
|
32
|
+
xrepoLearningsFilePath: string | null;
|
|
33
|
+
/** server-parsed TOC for the cross-repo learnings body. */
|
|
34
|
+
xrepoLearningsHeadings: LearningsHeading[];
|
|
27
35
|
}
|
|
28
36
|
export interface ResolvedInstructions {
|
|
29
37
|
full: string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Predicate for transient network errors that should be retried (vs. fail fast
|
|
3
|
+
* on explicit HTTP status / validation errors that carry their own message).
|
|
4
|
+
*
|
|
5
|
+
* Matches errors from `fetch` (`fetch failed`), TCP-level interruption
|
|
6
|
+
* (`ECONNRESET`, `ETIMEDOUT`), and `AbortSignal.timeout` (`AbortError`).
|
|
7
|
+
* Callers may pass `extraPatterns` to whitelist additional transient
|
|
8
|
+
* substrings on `error.message` (e.g. provider-specific framings).
|
|
9
|
+
*/
|
|
10
|
+
export declare function isTransientNetworkError(error: unknown, extraPatterns?: string[]): boolean;
|
|
@@ -29,7 +29,9 @@ export { MAX_LEARNINGS_LENGTH, truncateAtLineBoundary };
|
|
|
29
29
|
* agent-targetable on long-lived repos; there is no fixed taxonomy.
|
|
30
30
|
*/
|
|
31
31
|
export declare const LEARNINGS_FILE_NAME = "pullfrog-learnings.md";
|
|
32
|
+
export declare const XREPO_LEARNINGS_FILE_NAME = "pullfrog-xrepo-learnings.md";
|
|
32
33
|
export declare function learningsFilePath(tmpdir: string): string;
|
|
34
|
+
export declare function xrepoLearningsFilePath(tmpdir: string): string;
|
|
33
35
|
/** seed the rolling learnings tmpfile with the verbatim DB body (or empty
|
|
34
36
|
* string for fresh repos). returns the absolute path. the parsed TOC is
|
|
35
37
|
* carried separately via `RepoSettings.learningsHeadings` and rendered
|
|
@@ -39,6 +41,11 @@ export declare function seedLearningsFile(params: {
|
|
|
39
41
|
tmpdir: string;
|
|
40
42
|
current: string | null;
|
|
41
43
|
}): Promise<string>;
|
|
44
|
+
/** seed the org-level cross-repo learnings tmpfile (--xrepo runs only). */
|
|
45
|
+
export declare function seedXrepoLearningsFile(params: {
|
|
46
|
+
tmpdir: string;
|
|
47
|
+
current: string | null;
|
|
48
|
+
}): Promise<string>;
|
|
42
49
|
/** read the agent-edited learnings file. returns null when the file is
|
|
43
50
|
* missing or unreadable (treated as "no change"). caps content at the
|
|
44
51
|
* server's max length to avoid a 400 round-trip. */
|
|
@@ -60,3 +67,10 @@ export declare function readLearningsFile(path: string): Promise<string | null>;
|
|
|
60
67
|
* normal end-of-run path and the SIGINT/SIGTERM handler.
|
|
61
68
|
*/
|
|
62
69
|
export declare function persistLearnings(ctx: ToolContext): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Read the agent-edited cross-repo learnings tmpfile and PATCH it to
|
|
72
|
+
* `Account.xrepoLearnings`. Org-level analogue of `persistLearnings` —
|
|
73
|
+
* same best-effort + unchanged-from-seed gating. Only seeded on --xrepo runs,
|
|
74
|
+
* so this is a no-op when `xrepoLearningsFilePath` is unset.
|
|
75
|
+
*/
|
|
76
|
+
export declare function persistXrepoLearnings(ctx: ToolContext): Promise<void>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model-access gate for explicitly-requested per-run models (`--opus`,
|
|
3
|
+
* `--model=<slug>`). An explicit model the run can't serve hard-fails *before*
|
|
4
|
+
* the agent starts with one consistent, reason-tailored error.
|
|
5
|
+
*
|
|
6
|
+
* The provenance split lives upstream: `payload.modelExplicit` is true only for
|
|
7
|
+
* a flag in the triggerer's own @pullfrog prompt. A standing default (repo
|
|
8
|
+
* setting, a model flag in org/repo `baseInstructions`, or a trigger's fallback
|
|
9
|
+
* instructions) keeps `modelExplicit = false` and never reaches the error
|
|
10
|
+
* branches here — a missing key for a standing default surfaces through
|
|
11
|
+
* `validateAgentApiKey`'s missing-key error instead (#938).
|
|
12
|
+
*
|
|
13
|
+
* `decideModelAccess` is pure (no env / IO) so the branching is unit-testable;
|
|
14
|
+
* `buildModelAccessError` renders the user-facing markdown that `main.ts`
|
|
15
|
+
* throws and `runErrorRenderer.ts` re-surfaces on both run surfaces.
|
|
16
|
+
*/
|
|
17
|
+
export type ModelAccessReason = "oss" | "byok_no_key" | "router";
|
|
18
|
+
export type ModelAccessDecision = {
|
|
19
|
+
kind: "ok";
|
|
20
|
+
}
|
|
21
|
+
/** route through the Router/OSS proxy, re-targeted to the requested model. */
|
|
22
|
+
| {
|
|
23
|
+
kind: "proxy";
|
|
24
|
+
target: string;
|
|
25
|
+
}
|
|
26
|
+
/** run BYOK with the requested model — clear the minted proxy target. */
|
|
27
|
+
| {
|
|
28
|
+
kind: "byok";
|
|
29
|
+
} | {
|
|
30
|
+
kind: "error";
|
|
31
|
+
reason: ModelAccessReason;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* decide whether an (already-resolved) requested model can run, and how.
|
|
35
|
+
*
|
|
36
|
+
* - non-explicit / no model → `ok` (caller's missing-key validation applies).
|
|
37
|
+
* - proxy active + OSS → only the funded subsidy target routes; a different
|
|
38
|
+
* model needs the repo's own key (`byok`) else `error("oss")`.
|
|
39
|
+
* - proxy active + Router → honor any Router-servable model (`proxy`); fall to
|
|
40
|
+
* BYOK when locally authorized, else `error("router")`.
|
|
41
|
+
* - no proxy → the resolved model must be locally authorized, else
|
|
42
|
+
* `error("byok_no_key")`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function decideModelAccess(input: {
|
|
45
|
+
modelExplicit: boolean;
|
|
46
|
+
model: string | undefined;
|
|
47
|
+
oss: boolean;
|
|
48
|
+
proxyActive: boolean;
|
|
49
|
+
subsidyTarget: string | undefined;
|
|
50
|
+
resolvedModel: string | undefined;
|
|
51
|
+
authorized: Set<string>;
|
|
52
|
+
}): ModelAccessDecision;
|
|
53
|
+
/** marker on the throw message so `runErrorRenderer` can reclassify it. */
|
|
54
|
+
export declare const MODEL_ACCESS_MARKER = "requested model is not available";
|
|
55
|
+
/**
|
|
56
|
+
* render the model-access failure body (used for both the thrown error and the
|
|
57
|
+
* PR comment / job summary). one shape, reason-branched why → CTA.
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildModelAccessError(input: {
|
|
60
|
+
reason: ModelAccessReason;
|
|
61
|
+
model: string;
|
|
62
|
+
owner: string;
|
|
63
|
+
name: string;
|
|
64
|
+
}): string;
|
package/dist/utils/payload.d.ts
CHANGED
|
@@ -5,10 +5,18 @@ export declare const JsonPayload: import("arktype/internal/variants/object.ts").
|
|
|
5
5
|
version: string;
|
|
6
6
|
prompt: string;
|
|
7
7
|
model?: string | undefined;
|
|
8
|
+
modelExplicit?: boolean | undefined;
|
|
8
9
|
triggerer?: string | undefined;
|
|
10
|
+
baseInstructions?: string | undefined;
|
|
9
11
|
eventInstructions?: string;
|
|
10
12
|
previousRunsNote?: string;
|
|
11
13
|
event?: object;
|
|
14
|
+
xrepo?: {
|
|
15
|
+
mode: "all" | "explicit";
|
|
16
|
+
read: string[];
|
|
17
|
+
write: string[];
|
|
18
|
+
unavailable?: string[];
|
|
19
|
+
} | undefined;
|
|
12
20
|
timeout?: string | undefined;
|
|
13
21
|
progressComment?: {
|
|
14
22
|
id: string;
|
|
@@ -32,11 +40,19 @@ export declare function resolvePayload(resolvedPromptInput: ResolvedPromptInput,
|
|
|
32
40
|
"~pullfrog": true;
|
|
33
41
|
version: string;
|
|
34
42
|
model: string | undefined;
|
|
43
|
+
modelExplicit: boolean;
|
|
35
44
|
prompt: string;
|
|
36
45
|
triggerer: string | undefined;
|
|
46
|
+
baseInstructions: string | undefined;
|
|
37
47
|
eventInstructions: string | undefined;
|
|
38
48
|
previousRunsNote: string | undefined;
|
|
39
49
|
event: PayloadEvent;
|
|
50
|
+
xrepo: {
|
|
51
|
+
mode: "all" | "explicit";
|
|
52
|
+
read: string[];
|
|
53
|
+
write: string[];
|
|
54
|
+
unavailable?: string[];
|
|
55
|
+
} | undefined;
|
|
40
56
|
timeout: string | undefined;
|
|
41
57
|
cwd: string | undefined;
|
|
42
58
|
progressComment: {
|
|
@@ -36,6 +36,9 @@ export interface RepoSettings {
|
|
|
36
36
|
learnings: string | null;
|
|
37
37
|
learningsHeadings: LearningsHeading[];
|
|
38
38
|
envAllowlist: string | null;
|
|
39
|
+
xrepoBrief: string | null;
|
|
40
|
+
xrepoLearnings: string | null;
|
|
41
|
+
xrepoLearningsHeadings: LearningsHeading[];
|
|
39
42
|
}
|
|
40
43
|
/**
|
|
41
44
|
* Account-level billing plan. Orthogonal to repo-level OSS status. Mirrors
|
|
@@ -18,6 +18,16 @@ interface ResolveRunContextDataParams {
|
|
|
18
18
|
octokit: OctokitWithPlugins;
|
|
19
19
|
token: string;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* true when the action is pinned to a full commit SHA (vs the moving `@v0`
|
|
23
|
+
* tag or a branch). GitHub runs the action's `post:` hook (and reads
|
|
24
|
+
* `action.yml`) straight from the checked-out action ref, so a SHA pin freezes
|
|
25
|
+
* that checkout forever: the main agent still floats to the latest `^semver`
|
|
26
|
+
* via the npm bootstrap (this code is proof — it ran), but the post-run
|
|
27
|
+
* cleanup step keeps executing the pinned commit's source and never receives
|
|
28
|
+
* fixes. surfaced in the log and PR footers to nudge repos back to `@v0`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isActionPinnedToSha(): boolean;
|
|
21
31
|
/**
|
|
22
32
|
* initialize run context data: parse context, fetch repo info and settings
|
|
23
33
|
*/
|