pullfrog 0.1.10 → 0.1.12

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.
@@ -3,7 +3,7 @@
3
3
  * Re-exports shared types, values, and utilities needed by the Next.js app.
4
4
  */
5
5
  export type { AuthorPermission, ModelAlias, ModelProvider, Payload, PayloadEvent, ProviderConfig, PushPermission, ShellPermission, ToolPermission, WriteablePayload, } from "../external.ts";
6
- export { getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, modelAliases, parseModel, providers, pullfrogMcpName, resolveCliModel, resolveDisplayAlias, resolveModelSlug, resolveOpenRouterModel, } from "../external.ts";
6
+ export { DEFAULT_PROXY_MODEL, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, modelAliases, parseModel, providers, pullfrogMcpName, resolveCliModel, resolveDisplayAlias, resolveModelSlug, resolveOpenRouterModel, } from "../external.ts";
7
7
  export type { Mode } from "../modes.ts";
8
8
  export { modes } from "../modes.ts";
9
9
  export type { BuildPullfrogFooterParams, WorkflowRunFooterInfo, } from "../utils/buildPullfrogFooter.ts";
package/dist/internal.js CHANGED
@@ -257,6 +257,11 @@ var providers = {
257
257
  resolve: "opencode/kimi-k2.6",
258
258
  openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
259
259
  },
260
+ "minimax-m2.5": {
261
+ displayName: "MiniMax M2.5",
262
+ resolve: "opencode/minimax-m2.5",
263
+ openRouterResolve: "openrouter/minimax/minimax-m2.5"
264
+ },
260
265
  "gpt-5-nano": {
261
266
  displayName: "GPT Nano",
262
267
  resolve: "opencode/gpt-5-nano",
@@ -273,7 +278,9 @@ var providers = {
273
278
  displayName: "MiniMax M2.5",
274
279
  resolve: "opencode/minimax-m2.5-free",
275
280
  envVars: [],
276
- isFree: true
281
+ isFree: true,
282
+ fallback: "opencode/big-pickle",
283
+ hidden: true
277
284
  }
278
285
  }
279
286
  }),
@@ -291,6 +298,25 @@ var providers = {
291
298
  }
292
299
  }
293
300
  }),
301
+ vertex: provider({
302
+ displayName: "Google Vertex AI",
303
+ envVars: [
304
+ "VERTEX_SERVICE_ACCOUNT_JSON",
305
+ "GOOGLE_CLOUD_PROJECT",
306
+ "VERTEX_LOCATION",
307
+ "VERTEX_MODEL_ID"
308
+ ],
309
+ models: {
310
+ // single routing entry — the actual Vertex AI model ID is read from
311
+ // VERTEX_MODEL_ID at run time. see ModelRouting docs for why we don't
312
+ // catalog individual Vertex models.
313
+ byok: {
314
+ displayName: "Google Vertex AI",
315
+ resolve: "vertex",
316
+ routing: "vertex"
317
+ }
318
+ }
319
+ }),
294
320
  openrouter: provider({
295
321
  displayName: "OpenRouter",
296
322
  envVars: ["OPENROUTER_API_KEY"],
@@ -392,6 +418,11 @@ var providers = {
392
418
  displayName: "Kimi K2",
393
419
  resolve: "openrouter/moonshotai/kimi-k2.6",
394
420
  openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
421
+ },
422
+ "minimax-m2.5": {
423
+ displayName: "MiniMax M2.5",
424
+ resolve: "openrouter/minimax/minimax-m2.5",
425
+ openRouterResolve: "openrouter/minimax/minimax-m2.5"
395
426
  }
396
427
  }
397
428
  })
@@ -445,6 +476,11 @@ var modelAliases = Object.entries(providers).flatMap(
445
476
  hidden: def.hidden ?? false
446
477
  }))
447
478
  );
479
+ var defaultProxyAlias = modelAliases.find((a) => a.slug === "moonshotai/kimi-k2");
480
+ if (!defaultProxyAlias?.openRouterResolve) {
481
+ throw new Error("DEFAULT_PROXY_MODEL: moonshotai/kimi-k2 missing openRouterResolve");
482
+ }
483
+ var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
448
484
  function resolveModelSlug(slug) {
449
485
  return modelAliases.find((a) => a.slug === slug)?.resolve;
450
486
  }
@@ -668,7 +704,25 @@ function computeModes(agentId) {
668
704
 
669
705
  Otherwise delegate the \`${REVIEWER_AGENT_NAME}\` subagent to review your diff with fresh eyes against YOUR TASK. The subagent's baked-in system prompt enforces a non-mutative + non-recursive contract: read-only file/search/web tools and read-only MCP queries only; no writes, shell side effects, state-changing MCP calls, or nested subagent dispatch. Enforcement is prose-only \u2014 restate the constraint in your dispatch instructions and do not relax it.
670
706
 
671
- Provide the subagent with YOUR TASK, the output of \`git diff origin/<base-branch>\` (single-rev form, no \`HEAD\` \u2014 this compares the working tree against the remote base and captures committed + staged + unstaged work; \`main...HEAD\` and \`--cached\` both miss the uncommitted edits Build self-review runs on, since self-review happens BEFORE the commit), and a tight summary (not raw output) of any lint/typecheck/test failures you fixed during build \u2014 what broke, root cause, the fix \u2014 so it can check that fixes addressed root causes rather than suppressed symptoms; say "no build-phase failures" if the build path was clean. Instruct it to flag bugs, logic errors, missing edge cases, gaps between request and diff, and unintended changes.
707
+ Compose your \`${REVIEWER_AGENT_NAME}\` dispatch prompt using this template verbatim, substituting the \`<...>\` placeholders. The preamble aligns the orchestrator side of the dispatch contract with the reviewer's baked-in system prompt \u2014 both ends say the same thing about where the work lives and what to do on an empty diff.
708
+
709
+ \`\`\`
710
+ ## What you're reviewing
711
+ This is a PRE-COMMIT Build-mode self-review. The work to review lives in the working tree (uncommitted), NOT in committed history.
712
+
713
+ Branch: <branch> (off <base>)
714
+ Canonical diff command: git diff origin/<base>
715
+
716
+ If that command returns empty, treat it as "no changes \u2014 nothing to review" and stop per your system prompt. Do not search for the work elsewhere.
717
+
718
+ ## Your task
719
+ <YOUR TASK content>
720
+
721
+ ## Build-phase failures
722
+ <tight summary \u2014 what broke, root cause, the fix \u2014 or "no build-phase failures">
723
+ \`\`\`
724
+
725
+ Follow the template with the diff content (\`git diff origin/<base-branch>\`, single-rev form \u2014 \`main...HEAD\` and \`--cached\` both miss the uncommitted edits self-review runs on) and your task brief. Instruct the subagent to flag bugs, logic errors, missing edge cases, gaps between request and diff, and unintended changes.
672
726
 
673
727
  Delegation + research discipline (distilled from \`/anneal\` canonical \u2014 these are codified learnings from many review rounds, not theoretical best practices):
674
728
  - Do NOT summarize what you implemented \u2014 that biases the subagent toward validating the shape of your solution rather than questioning it.
@@ -1235,6 +1289,7 @@ function isValidTimeString(input) {
1235
1289
  return parseTimeString(input) !== null;
1236
1290
  }
1237
1291
  export {
1292
+ DEFAULT_PROXY_MODEL,
1238
1293
  LEAPING_INTO_ACTION_PREFIX,
1239
1294
  MAX_LEARNINGS_LENGTH,
1240
1295
  PULLFROG_DIVIDER,
@@ -48,7 +48,7 @@ export type CheckoutPrResult = {
48
48
  * this is the core diff formatting logic, extracted for testability.
49
49
  */
50
50
  export declare function fetchAndFormatPrDiff(ctx: ToolContext, pullNumber: number): Promise<FetchAndFormatPrDiffResult>;
51
- import type { GitContext } from "../utils/setup.ts";
51
+ import { type GitContext } from "../utils/setup.ts";
52
52
  export type PrData = {
53
53
  number: number;
54
54
  headSha: string;
package/dist/models.d.ts CHANGED
@@ -10,15 +10,17 @@
10
10
  *
11
11
  * `"bedrock"` means the actual model ID comes from `BEDROCK_MODEL_ID`
12
12
  * (an AWS-canonical Bedrock model ID like `us.anthropic.claude-opus-4-7`
13
- * or `amazon.nova-pro-v1:0`). enterprise Bedrock customers self-select for
14
- * version control silent alias bumps would break compliance review,
15
- * model-access enrollment, and provisioned-throughput contracts. so the
16
- * single `bedrock/byok` entry is a routing slug, not a model alias: the
17
- * harness reads `BEDROCK_MODEL_ID` and routes to claude-code (when the ID
18
- * contains "anthropic") or opencode (everything else, with an
19
- * `amazon-bedrock/` prefix).
13
+ * or `amazon.nova-pro-v1:0`). `"vertex"` means the actual model ID comes
14
+ * from `VERTEX_MODEL_ID` (a Vertex AI model ID like
15
+ * `claude-opus-4-1@20250805` or `gemini-2.5-pro`). enterprise hosted-model
16
+ * customers self-select for version control silent alias bumps would break
17
+ * compliance review, model-access enrollment, and provisioned-throughput
18
+ * contracts. so the single `bedrock/byok` and `vertex/byok` entries are
19
+ * routing slugs, not model aliases: the harness reads the backend-specific
20
+ * env var and routes to claude-code for Anthropic IDs or opencode for
21
+ * everything else.
20
22
  */
21
- export type ModelRouting = "bedrock";
23
+ export type ModelRouting = "bedrock" | "vertex";
22
24
  export interface ModelAlias {
23
25
  /** stable alias stored in DB, e.g. "anthropic/claude-opus" */
24
26
  slug: string;
@@ -84,6 +86,7 @@ export declare const providers: {
84
86
  moonshotai: ProviderConfig;
85
87
  opencode: ProviderConfig;
86
88
  bedrock: ProviderConfig;
89
+ vertex: ProviderConfig;
87
90
  openrouter: ProviderConfig;
88
91
  };
89
92
  export type ModelProvider = keyof typeof providers;
@@ -100,6 +103,7 @@ export declare function getModelEnvVars(slug: string): string[];
100
103
  * see `provider.managedCredentials` and wiki/codex-auth.md. */
101
104
  export declare function getModelManagedCredentials(slug: string): string[];
102
105
  export declare const modelAliases: ModelAlias[];
106
+ export declare const DEFAULT_PROXY_MODEL: string;
103
107
  /** resolve a model slug to its concrete models.dev specifier (e.g. "anthropic/claude-opus-4-6") */
104
108
  export declare function resolveModelSlug(slug: string): string | undefined;
105
109
  /**
@@ -127,6 +131,8 @@ export declare function resolveCliModel(slug: string): string | undefined;
127
131
  export declare function resolveOpenRouterModel(slug: string): string | undefined;
128
132
  /** env var that supplies the Bedrock model ID for the `bedrock/byok` slug. */
129
133
  export declare const BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
134
+ /** env var that supplies the Vertex AI model ID for the `vertex/byok` slug. */
135
+ export declare const VERTEX_MODEL_ID_ENV = "VERTEX_MODEL_ID";
130
136
  /**
131
137
  * the Bedrock model ID passed to claude-code or opencode is whatever the
132
138
  * user set in `BEDROCK_MODEL_ID` — Pullfrog never resolves or upgrades it.
@@ -153,4 +159,11 @@ export declare const BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
153
159
  * include the foundation segment in the profile name.
154
160
  */
155
161
  export declare function isBedrockAnthropicId(bedrockModelId: string): boolean;
162
+ /**
163
+ * Vertex Anthropic model IDs start with the Claude family name, e.g.
164
+ * `claude-opus-4-1@20250805`. partner-model resource paths can contain the
165
+ * substring "anthropic" elsewhere, so the Bedrock segment check does not
166
+ * transfer — anchor on the model ID prefix instead.
167
+ */
168
+ export declare function isVertexAnthropicId(vertexModelId: string): boolean;
156
169
  export {};
@@ -57,6 +57,13 @@ export type CommentableLines = {
57
57
  export interface ToolState {
58
58
  pushUrl?: string;
59
59
  pushDest?: StoredPushDest;
60
+ initialHead?: {
61
+ kind: "branch";
62
+ name: string;
63
+ } | {
64
+ kind: "detached";
65
+ sha: string;
66
+ };
60
67
  issueNumber?: number;
61
68
  checkoutSha?: string;
62
69
  commentableLinesByFile?: Map<string, CommentableLines>;
@@ -2,15 +2,14 @@
2
2
  * Slug we fall back to when a BYOK-required model is configured but the
3
3
  * runner has no provider key in env. Picked because it's free
4
4
  * (`isFree: true`, `envVars: []` — see `action/models.ts`), stable, and
5
- * currently the strongest free OpenCode model in the catalog. If a
6
- * smarter free model is added later, update this single constant.
5
+ * currently served by OpenCode Zen without a key.
7
6
  *
8
7
  * The slug is intentionally hard-coded and not a config knob — the
9
8
  * fallback is a safety net, not a user-facing preference, and adding a
10
9
  * config surface here would just push the same "what to fall back to"
11
10
  * decision into another setting that goes stale the same way.
12
11
  */
13
- export declare const FREE_FALLBACK_SLUG = "opencode/minimax-m2.5-free";
12
+ export declare const FREE_FALLBACK_SLUG = "opencode/big-pickle";
14
13
  export type FallbackDecision = {
15
14
  fallback: false;
16
15
  } | {
@@ -13,11 +13,3 @@ export interface InstalledCodexAuth {
13
13
  * returns null when the env var is absent, malformed, or wrong auth mode —
14
14
  * caller treats null as "no codex auth, fall through to API key flow". */
15
15
  export declare function installCodexAuth(): InstalledCodexAuth | null;
16
- /** convert an on-disk OpenCode auth.json back to the Codex CLI shape so the
17
- * post-hook can write it to the Pullfrog secret store. returns null when the
18
- * file's `openai` entry is missing, has the wrong type, or hasn't actually
19
- * refreshed (refresh token unchanged from `originalRefresh`). */
20
- export declare function detectCodexRefresh(params: {
21
- authFileContent: string;
22
- originalRefresh: string;
23
- }): string | null;
@@ -24,7 +24,7 @@
24
24
  import type { AgentResult } from "../agents/shared.ts";
25
25
  import type { ToolContext } from "../mcp/server.ts";
26
26
  import type { ToolState } from "../toolState.ts";
27
- import type { RenderedRunError } from "./runErrorRenderer.ts";
27
+ import { type RenderedRunError } from "./runErrorRenderer.ts";
28
28
  /**
29
29
  * Best-effort cleanup shared by both run-end paths:
30
30
  * 1. post-review cleanup (dispatch follow-up re-review on submitted reviews)
@@ -40,9 +40,12 @@ export declare function persistRunArtifacts(toolContext: ToolContext): Promise<v
40
40
  *
41
41
  * 1. shared best-effort cleanup via `persistRunArtifacts`
42
42
  * 2. when the harness returned `success=false` (e.g. unsubmitted-review
43
- * gate exhausted retries, stop-hook persistently failing), surface
44
- * the error in the progress comment so the user sees it instead of a
45
- * deleted-comment void
43
+ * gate exhausted retries, stop-hook persistently failing), render via
44
+ * `renderRunError` and surface the error in BOTH the progress comment
45
+ * (rendered.comment) and the Actions job summary (rendered.summary,
46
+ * prepended below in step 4) — same classifier as the catch path so
47
+ * the user sees it instead of a deleted-comment void / empty summary
48
+ * tab
46
49
  * 3. when the run succeeded and the progress comment was never finalized
47
50
  * via `report_progress`, delete it (three sub-cases — orphan
48
51
  * "Leaping into action" comment, abandoned checklist, agent wrote
@@ -8,6 +8,32 @@ export interface SetupOptions {
8
8
  * Create a shared temp directory for the action
9
9
  */
10
10
  export declare function createTempDirectory(): string;
11
+ /**
12
+ * snapshot-and-delete the GHA runner's known credential leak surfaces inside
13
+ * `$RUNNER_TEMP` before the agent spawns. without this, a shell-capable agent
14
+ * can grep:
15
+ * - `_runner_file_commands/set_output_*` for `core.setOutput('token', ghs_…)`
16
+ * calls made by earlier composite-action steps (e.g.
17
+ * pullfrog/pullfrog/get-installation-token);
18
+ * - `<uuid>.sh` rendered step scripts whose `run: |` body embeds
19
+ * `${{ steps.token.outputs.token }}` literally (GHA expands BEFORE writing);
20
+ * - `git-credentials-*.config` written by `actions/checkout@v6` for the
21
+ * workflow GITHUB_TOKEN.
22
+ *
23
+ * the running bash process already has its own `.sh` open via fd, so the
24
+ * unlink is safe — `unlink` removes the dirent, the kernel keeps reading.
25
+ *
26
+ * preserves every `_runner_file_commands/` file path the runner pre-allocated
27
+ * for OUR step — `$GITHUB_OUTPUT`, `$GITHUB_ENV`, `$GITHUB_PATH`,
28
+ * `$GITHUB_STATE`, `$GITHUB_STEP_SUMMARY`. those are read by the runner
29
+ * AFTER we exit (or by our own `post:` hook), and wiping them would break
30
+ * pullfrog's `result` output, `post:` state handoff, and job summary.
31
+ *
32
+ * silent no-op when `$RUNNER_TEMP` is unset (local dev, `pnpm play`).
33
+ * per-file errors are tolerated — the runner may delete files between
34
+ * our readdir and our unlink.
35
+ */
36
+ export declare function wipeRunnerLeakSurface(): void;
11
37
  /**
12
38
  * Setup the test repository for running actions
13
39
  */
@@ -44,3 +70,21 @@ export type SetupGitParams = GitContext;
44
70
  * it is assumed to be potentially exfiltratable, so it has limited scope.
45
71
  */
46
72
  export declare function setupGit(params: SetupGitParams): Promise<void>;
73
+ /**
74
+ * snapshot the current HEAD as either a branch name (when on a named branch)
75
+ * or a literal SHA (when detached). used by setupGit to pin the run-entry
76
+ * position and by checkout_pr to compare the live HEAD against it.
77
+ *
78
+ * splitting the two cases is load-bearing: `git rev-parse --abbrev-ref HEAD`
79
+ * returns the sentinel string `"HEAD"` on detached entry — which is the
80
+ * default `actions/checkout` state for `pull_request` events. storing that
81
+ * raw string would make any future detached state (including a subagent's
82
+ * `git checkout --detach <sha>`) compare equal.
83
+ */
84
+ export declare function captureInitialHead(repoDir: string): {
85
+ kind: "branch";
86
+ name: string;
87
+ } | {
88
+ kind: "detached";
89
+ sha: string;
90
+ };
@@ -0,0 +1,16 @@
1
+ export declare const VERTEX_SERVICE_ACCOUNT_JSON_ENV = "VERTEX_SERVICE_ACCOUNT_JSON";
2
+ export declare const GOOGLE_APPLICATION_CREDENTIALS_ENV = "GOOGLE_APPLICATION_CREDENTIALS";
3
+ export declare const GOOGLE_CLOUD_PROJECT_ENV = "GOOGLE_CLOUD_PROJECT";
4
+ export declare const VERTEX_LOCATION_ENV = "VERTEX_LOCATION";
5
+ export type VertexCredentials = {
6
+ credentialsPath: string;
7
+ secretDir: string;
8
+ };
9
+ export declare function isVertexRoute(model: string | undefined): boolean;
10
+ export declare function readProjectIdFromVertexServiceAccountJson(): string | undefined;
11
+ export declare function materializeVertexCredentials(params: {
12
+ model: string | undefined;
13
+ }): VertexCredentials | undefined;
14
+ export declare function cleanupVertexCredentials(credentials: VertexCredentials | undefined): void;
15
+ export declare function applyClaudeVertexEnv(env: Record<string, string | undefined>): void;
16
+ export declare function resolveVertexOpenCodeModel(model: string | undefined): string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pullfrog",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "pullfrog": "dist/cli.mjs",