pullfrog 0.1.24 → 0.1.26

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.
@@ -54,8 +54,17 @@ export declare const CLAUDE_PRETOOL_GATE_SOURCE: string;
54
54
  * literal JSON string per claude-code source `src/main.tsx` (`Path to a
55
55
  * settings JSON file or a JSON string`), but we use a path so the script
56
56
  * and its config sit side-by-side under `ctx.tmpdir`.
57
+ *
58
+ * `execToolDenyRules` are the native exec tools (Bash/Monitor/REPL/Workflow +
59
+ * their `Agent(...)` forms) to deny at a settings-source rule — the
60
+ * authoritative, bypass-immune layer. `--disallowedTools` alone (a `cliArg`
61
+ * deny) was observed to leak under `--dangerously-skip-permissions`, so the
62
+ * deny is carried here too. Both consumers use both returned fields: the flag
63
+ * `--settings` JSON (covers non-CI runs) writes the whole object, and
64
+ * `buildManagedSettings` (CI, /etc managed settings) spreads `hooks` and folds
65
+ * `permissions.deny` into its richer deny list.
57
66
  */
58
- export declare function buildClaudePretoolGateSettings(scriptAbsolutePath: string): {
67
+ export declare function buildClaudePretoolGateSettings(scriptAbsolutePath: string, execToolDenyRules: string[]): {
59
68
  hooks: {
60
69
  PreToolUse: Array<{
61
70
  matcher: string;
@@ -66,4 +75,7 @@ export declare function buildClaudePretoolGateSettings(scriptAbsolutePath: strin
66
75
  }>;
67
76
  }>;
68
77
  };
78
+ permissions: {
79
+ deny: string[];
80
+ };
69
81
  };
package/dist/cli.mjs CHANGED
@@ -100992,7 +100992,7 @@ var providers = {
100992
100992
  openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
100993
100993
  },
100994
100994
  "minimax-m2.5": {
100995
- displayName: "MiniMax M2.5",
100995
+ displayName: "MiniMax M2",
100996
100996
  resolve: "opencode/minimax-m2.5",
100997
100997
  openRouterResolve: "openrouter/minimax/minimax-m2.5"
100998
100998
  },
@@ -101009,7 +101009,7 @@ var providers = {
101009
101009
  fallback: "opencode/big-pickle"
101010
101010
  },
101011
101011
  "minimax-m2.5-free": {
101012
- displayName: "MiniMax M2.5",
101012
+ displayName: "MiniMax M2",
101013
101013
  resolve: "opencode/minimax-m2.5-free",
101014
101014
  envVars: [],
101015
101015
  isFree: true,
@@ -101166,7 +101166,7 @@ var providers = {
101166
101166
  openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
101167
101167
  },
101168
101168
  "minimax-m2.5": {
101169
- displayName: "MiniMax M2.5",
101169
+ displayName: "MiniMax M2",
101170
101170
  resolve: "openrouter/minimax/minimax-m2.5",
101171
101171
  openRouterResolve: "openrouter/minimax/minimax-m2.5"
101172
101172
  }
@@ -101867,7 +101867,7 @@ var import_semver = __toESM(require_semver2(), 1);
101867
101867
  // package.json
101868
101868
  var package_default = {
101869
101869
  name: "pullfrog",
101870
- version: "0.1.24",
101870
+ version: "0.1.26",
101871
101871
  type: "module",
101872
101872
  bin: {
101873
101873
  pullfrog: "dist/cli.mjs",
@@ -102520,7 +102520,7 @@ process.stdin.on("end", () => {
102520
102520
  process.exit(2);
102521
102521
  });
102522
102522
  `;
102523
- function buildClaudePretoolGateSettings(scriptAbsolutePath) {
102523
+ function buildClaudePretoolGateSettings(scriptAbsolutePath, execToolDenyRules) {
102524
102524
  return {
102525
102525
  hooks: {
102526
102526
  PreToolUse: [
@@ -102539,7 +102539,8 @@ function buildClaudePretoolGateSettings(scriptAbsolutePath) {
102539
102539
  ]
102540
102540
  }
102541
102541
  ]
102542
- }
102542
+ },
102543
+ permissions: { deny: execToolDenyRules }
102543
102544
  };
102544
102545
  }
102545
102546
 
@@ -103565,10 +103566,11 @@ async function installClaudeCli() {
103565
103566
  });
103566
103567
  }
103567
103568
  var CLAUDE_EXEC_TOOLS = ["Bash", "Monitor", "REPL", "Workflow"];
103568
- var CLAUDE_DISALLOWED_TOOLS = [
103569
+ var CLAUDE_EXEC_TOOL_DENY_RULES = [
103569
103570
  ...CLAUDE_EXEC_TOOLS,
103570
103571
  ...CLAUDE_EXEC_TOOLS.map((t2) => `Agent(${t2})`)
103571
- ].join(",");
103572
+ ];
103573
+ var CLAUDE_DISALLOWED_TOOLS = CLAUDE_EXEC_TOOL_DENY_RULES.join(",");
103572
103574
  function writeMcpConfig(ctx) {
103573
103575
  const configDir = join5(ctx.tmpdir, ".claude");
103574
103576
  mkdirSync4(configDir, { recursive: true });
@@ -103588,7 +103590,8 @@ function writePretoolGateAssets(ctx) {
103588
103590
  writeFileSync4(scriptPath, CLAUDE_PRETOOL_GATE_SOURCE);
103589
103591
  chmodSync2(scriptPath, 493);
103590
103592
  const settingsPath = join5(ctx.tmpdir, "pullfrog-claude-settings.json");
103591
- writeFileSync4(settingsPath, JSON.stringify(buildClaudePretoolGateSettings(scriptPath)));
103593
+ const settings = buildClaudePretoolGateSettings(scriptPath, CLAUDE_EXEC_TOOL_DENY_RULES);
103594
+ writeFileSync4(settingsPath, JSON.stringify(settings));
103592
103595
  return { scriptPath, settingsPath };
103593
103596
  }
103594
103597
  function buildAgentsJson() {
@@ -103990,11 +103993,20 @@ function buildManagedSettings(params) {
103990
103993
  `Glob(${path4}/**)`,
103991
103994
  `Glob(/${path4}/**)`
103992
103995
  ]);
103996
+ const gate = buildClaudePretoolGateSettings(
103997
+ params.pretoolGateScriptPath,
103998
+ CLAUDE_EXEC_TOOL_DENY_RULES
103999
+ );
103993
104000
  const base = {
103994
104001
  allowManagedPermissionRulesOnly: true,
103995
104002
  allowManagedHooksOnly: true,
103996
104003
  permissions: {
103997
104004
  deny: [
104005
+ // native exec tools — the authoritative, bypass-immune deny.
104006
+ // `--disallowedTools` (a cliArg-source deny) leaked under
104007
+ // `--dangerously-skip-permissions`; policySettings denies survive
104008
+ // bypassPermissions mode. covers top-level + Agent(...) subagent use.
104009
+ ...gate.permissions.deny,
103998
104010
  "Read(//proc/**)",
103999
104011
  "Read(//sys/**)",
104000
104012
  "Grep(//proc/**)",
@@ -104020,7 +104032,7 @@ function buildManagedSettings(params) {
104020
104032
  }
104021
104033
  };
104022
104034
  const hooks = {
104023
- ...buildClaudePretoolGateSettings(params.pretoolGateScriptPath).hooks
104035
+ ...gate.hooks
104024
104036
  };
104025
104037
  if (params.stopHookPath) {
104026
104038
  hooks.Stop = [
@@ -117954,6 +117966,9 @@ var addTools = (ctx, server, tools) => {
117954
117966
  };
117955
117967
 
117956
117968
  // mcp/comment.ts
117969
+ function isNotFoundError(error49) {
117970
+ return error49 instanceof Error && error49.message.includes("Not Found");
117971
+ }
117957
117972
  function buildCommentFooter(ctx, customParts) {
117958
117973
  const runId = ctx.runId;
117959
117974
  return buildPullfrogFooter({
@@ -118110,7 +118125,30 @@ async function reportProgress(ctx, params) {
118110
118125
  const bodyWithoutFooter = stripExistingFooter(body);
118111
118126
  const footer = buildCommentFooter(ctx, customParts);
118112
118127
  const bodyWithFooter = `${bodyWithoutFooter}${footer}`;
118113
- const result = await updateProgressComment(apiCtx, existingComment, bodyWithFooter);
118128
+ let result;
118129
+ try {
118130
+ result = await updateProgressComment(apiCtx, existingComment, bodyWithFooter);
118131
+ } catch (error49) {
118132
+ if (params.liveProgress || existingComment.type !== "review" || !isNotFoundError(error49) || issueNumber === void 0) {
118133
+ throw error49;
118134
+ }
118135
+ log.warning(
118136
+ `progress review comment ${existingComment.id} is gone (404); posting a top-level comment on #${issueNumber} instead`
118137
+ );
118138
+ const created2 = await createLeapingProgressComment(
118139
+ apiCtx,
118140
+ { kind: "issue", issueNumber },
118141
+ bodyWithFooter
118142
+ );
118143
+ ctx.toolState.progressComment = created2.comment;
118144
+ if (!params.liveProgress) ctx.toolState.wasUpdated = true;
118145
+ return {
118146
+ commentId: created2.comment.id,
118147
+ url: created2.html_url,
118148
+ body: created2.body || "",
118149
+ action: "created"
118150
+ };
118151
+ }
118114
118152
  if (!params.liveProgress) ctx.toolState.wasUpdated = true;
118115
118153
  if (isPlanMode && result.node_id) {
118116
118154
  await patchWorkflowRunFields(ctx, { planCommentNodeId: result.node_id });
@@ -118213,10 +118251,7 @@ async function deleteProgressComment(ctx) {
118213
118251
  existing
118214
118252
  );
118215
118253
  } catch (error49) {
118216
- if (error49 instanceof Error && error49.message.includes("Not Found")) {
118217
- } else {
118218
- throw error49;
118219
- }
118254
+ if (!isNotFoundError(error49)) throw error49;
118220
118255
  }
118221
118256
  ctx.toolState.progressComment = null;
118222
118257
  return true;
@@ -151958,7 +151993,7 @@ function classifyPushError(msg) {
151958
151993
  if (TRANSIENT_PATTERNS.some((p2) => p2.test(msg))) return "transient";
151959
151994
  return "unknown";
151960
151995
  }
151961
- var TRANSIENT_RETRY_DELAYS_MS = [2e3, 5e3];
151996
+ var TRANSIENT_RETRY_DELAYS_MS = [2e3, 4e3, 8e3, 16e3, 3e4];
151962
151997
  async function pushWithRetry(args2, token) {
151963
151998
  let lastErr;
151964
151999
  for (let attempt = 0; attempt <= TRANSIENT_RETRY_DELAYS_MS.length; attempt++) {
@@ -155836,6 +155871,7 @@ function selectFallbackModelIfNeeded(input) {
155836
155871
  if (!input.resolvedModel) return { fallback: false };
155837
155872
  if (input.resolvedModel === FREE_FALLBACK_SLUG) return { fallback: false };
155838
155873
  if (!input.resolvedModel.includes("/")) return { fallback: false };
155874
+ if (input.agentName === "claude") return { fallback: false };
155839
155875
  if (input.authorized.has(input.resolvedModel)) return { fallback: false };
155840
155876
  return {
155841
155877
  fallback: true,
@@ -161816,7 +161852,8 @@ async function main() {
161816
161852
  const fallback = selectFallbackModelIfNeeded({
161817
161853
  resolvedModel: initialResolvedModel,
161818
161854
  proxyModel: payload.proxyModel,
161819
- authorized: authorized2
161855
+ authorized: authorized2,
161856
+ agentName: resolveAgent({ model: initialResolvedModel }).name
161820
161857
  });
161821
161858
  const effectiveSlug = fallback.fallback ? fallback.to : payload.model;
161822
161859
  const resolvedModel = fallback.fallback ? fallback.to : initialResolvedModel;
@@ -163005,7 +163042,7 @@ async function run2() {
163005
163042
  }
163006
163043
 
163007
163044
  // cli.ts
163008
- var VERSION10 = "0.1.24";
163045
+ var VERSION10 = "0.1.26";
163009
163046
  var bin = basename2(process.argv[1] || "");
163010
163047
  var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
163011
163048
  var rawArgs = process.argv.slice(2);
package/dist/index.js CHANGED
@@ -99192,7 +99192,7 @@ var providers = {
99192
99192
  openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
99193
99193
  },
99194
99194
  "minimax-m2.5": {
99195
- displayName: "MiniMax M2.5",
99195
+ displayName: "MiniMax M2",
99196
99196
  resolve: "opencode/minimax-m2.5",
99197
99197
  openRouterResolve: "openrouter/minimax/minimax-m2.5"
99198
99198
  },
@@ -99209,7 +99209,7 @@ var providers = {
99209
99209
  fallback: "opencode/big-pickle"
99210
99210
  },
99211
99211
  "minimax-m2.5-free": {
99212
- displayName: "MiniMax M2.5",
99212
+ displayName: "MiniMax M2",
99213
99213
  resolve: "opencode/minimax-m2.5-free",
99214
99214
  envVars: [],
99215
99215
  isFree: true,
@@ -99366,7 +99366,7 @@ var providers = {
99366
99366
  openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
99367
99367
  },
99368
99368
  "minimax-m2.5": {
99369
- displayName: "MiniMax M2.5",
99369
+ displayName: "MiniMax M2",
99370
99370
  resolve: "openrouter/minimax/minimax-m2.5",
99371
99371
  openRouterResolve: "openrouter/minimax/minimax-m2.5"
99372
99372
  }
@@ -100067,7 +100067,7 @@ var import_semver = __toESM(require_semver2(), 1);
100067
100067
  // package.json
100068
100068
  var package_default = {
100069
100069
  name: "pullfrog",
100070
- version: "0.1.24",
100070
+ version: "0.1.26",
100071
100071
  type: "module",
100072
100072
  bin: {
100073
100073
  pullfrog: "dist/cli.mjs",
@@ -100720,7 +100720,7 @@ process.stdin.on("end", () => {
100720
100720
  process.exit(2);
100721
100721
  });
100722
100722
  `;
100723
- function buildClaudePretoolGateSettings(scriptAbsolutePath) {
100723
+ function buildClaudePretoolGateSettings(scriptAbsolutePath, execToolDenyRules) {
100724
100724
  return {
100725
100725
  hooks: {
100726
100726
  PreToolUse: [
@@ -100739,7 +100739,8 @@ function buildClaudePretoolGateSettings(scriptAbsolutePath) {
100739
100739
  ]
100740
100740
  }
100741
100741
  ]
100742
- }
100742
+ },
100743
+ permissions: { deny: execToolDenyRules }
100743
100744
  };
100744
100745
  }
100745
100746
 
@@ -101765,10 +101766,11 @@ async function installClaudeCli() {
101765
101766
  });
101766
101767
  }
101767
101768
  var CLAUDE_EXEC_TOOLS = ["Bash", "Monitor", "REPL", "Workflow"];
101768
- var CLAUDE_DISALLOWED_TOOLS = [
101769
+ var CLAUDE_EXEC_TOOL_DENY_RULES = [
101769
101770
  ...CLAUDE_EXEC_TOOLS,
101770
101771
  ...CLAUDE_EXEC_TOOLS.map((t) => `Agent(${t})`)
101771
- ].join(",");
101772
+ ];
101773
+ var CLAUDE_DISALLOWED_TOOLS = CLAUDE_EXEC_TOOL_DENY_RULES.join(",");
101772
101774
  function writeMcpConfig(ctx) {
101773
101775
  const configDir = join4(ctx.tmpdir, ".claude");
101774
101776
  mkdirSync4(configDir, { recursive: true });
@@ -101788,7 +101790,8 @@ function writePretoolGateAssets(ctx) {
101788
101790
  writeFileSync3(scriptPath, CLAUDE_PRETOOL_GATE_SOURCE);
101789
101791
  chmodSync2(scriptPath, 493);
101790
101792
  const settingsPath = join4(ctx.tmpdir, "pullfrog-claude-settings.json");
101791
- writeFileSync3(settingsPath, JSON.stringify(buildClaudePretoolGateSettings(scriptPath)));
101793
+ const settings = buildClaudePretoolGateSettings(scriptPath, CLAUDE_EXEC_TOOL_DENY_RULES);
101794
+ writeFileSync3(settingsPath, JSON.stringify(settings));
101792
101795
  return { scriptPath, settingsPath };
101793
101796
  }
101794
101797
  function buildAgentsJson() {
@@ -102190,11 +102193,20 @@ function buildManagedSettings(params) {
102190
102193
  `Glob(${path4}/**)`,
102191
102194
  `Glob(/${path4}/**)`
102192
102195
  ]);
102196
+ const gate = buildClaudePretoolGateSettings(
102197
+ params.pretoolGateScriptPath,
102198
+ CLAUDE_EXEC_TOOL_DENY_RULES
102199
+ );
102193
102200
  const base = {
102194
102201
  allowManagedPermissionRulesOnly: true,
102195
102202
  allowManagedHooksOnly: true,
102196
102203
  permissions: {
102197
102204
  deny: [
102205
+ // native exec tools — the authoritative, bypass-immune deny.
102206
+ // `--disallowedTools` (a cliArg-source deny) leaked under
102207
+ // `--dangerously-skip-permissions`; policySettings denies survive
102208
+ // bypassPermissions mode. covers top-level + Agent(...) subagent use.
102209
+ ...gate.permissions.deny,
102198
102210
  "Read(//proc/**)",
102199
102211
  "Read(//sys/**)",
102200
102212
  "Grep(//proc/**)",
@@ -102220,7 +102232,7 @@ function buildManagedSettings(params) {
102220
102232
  }
102221
102233
  };
102222
102234
  const hooks = {
102223
- ...buildClaudePretoolGateSettings(params.pretoolGateScriptPath).hooks
102235
+ ...gate.hooks
102224
102236
  };
102225
102237
  if (params.stopHookPath) {
102226
102238
  hooks.Stop = [
@@ -116196,6 +116208,9 @@ var addTools = (ctx, server, tools) => {
116196
116208
  };
116197
116209
 
116198
116210
  // mcp/comment.ts
116211
+ function isNotFoundError(error49) {
116212
+ return error49 instanceof Error && error49.message.includes("Not Found");
116213
+ }
116199
116214
  function buildCommentFooter(ctx, customParts) {
116200
116215
  const runId = ctx.runId;
116201
116216
  return buildPullfrogFooter({
@@ -116352,7 +116367,30 @@ async function reportProgress(ctx, params) {
116352
116367
  const bodyWithoutFooter = stripExistingFooter(body);
116353
116368
  const footer = buildCommentFooter(ctx, customParts);
116354
116369
  const bodyWithFooter = `${bodyWithoutFooter}${footer}`;
116355
- const result = await updateProgressComment(apiCtx, existingComment, bodyWithFooter);
116370
+ let result;
116371
+ try {
116372
+ result = await updateProgressComment(apiCtx, existingComment, bodyWithFooter);
116373
+ } catch (error49) {
116374
+ if (params.liveProgress || existingComment.type !== "review" || !isNotFoundError(error49) || issueNumber === void 0) {
116375
+ throw error49;
116376
+ }
116377
+ log.warning(
116378
+ `progress review comment ${existingComment.id} is gone (404); posting a top-level comment on #${issueNumber} instead`
116379
+ );
116380
+ const created2 = await createLeapingProgressComment(
116381
+ apiCtx,
116382
+ { kind: "issue", issueNumber },
116383
+ bodyWithFooter
116384
+ );
116385
+ ctx.toolState.progressComment = created2.comment;
116386
+ if (!params.liveProgress) ctx.toolState.wasUpdated = true;
116387
+ return {
116388
+ commentId: created2.comment.id,
116389
+ url: created2.html_url,
116390
+ body: created2.body || "",
116391
+ action: "created"
116392
+ };
116393
+ }
116356
116394
  if (!params.liveProgress) ctx.toolState.wasUpdated = true;
116357
116395
  if (isPlanMode && result.node_id) {
116358
116396
  await patchWorkflowRunFields(ctx, { planCommentNodeId: result.node_id });
@@ -116455,10 +116493,7 @@ async function deleteProgressComment(ctx) {
116455
116493
  existing
116456
116494
  );
116457
116495
  } catch (error49) {
116458
- if (error49 instanceof Error && error49.message.includes("Not Found")) {
116459
- } else {
116460
- throw error49;
116461
- }
116496
+ if (!isNotFoundError(error49)) throw error49;
116462
116497
  }
116463
116498
  ctx.toolState.progressComment = null;
116464
116499
  return true;
@@ -150200,7 +150235,7 @@ function classifyPushError(msg) {
150200
150235
  if (TRANSIENT_PATTERNS.some((p) => p.test(msg))) return "transient";
150201
150236
  return "unknown";
150202
150237
  }
150203
- var TRANSIENT_RETRY_DELAYS_MS = [2e3, 5e3];
150238
+ var TRANSIENT_RETRY_DELAYS_MS = [2e3, 4e3, 8e3, 16e3, 3e4];
150204
150239
  async function pushWithRetry(args2, token) {
150205
150240
  let lastErr;
150206
150241
  for (let attempt = 0; attempt <= TRANSIENT_RETRY_DELAYS_MS.length; attempt++) {
@@ -154078,6 +154113,7 @@ function selectFallbackModelIfNeeded(input) {
154078
154113
  if (!input.resolvedModel) return { fallback: false };
154079
154114
  if (input.resolvedModel === FREE_FALLBACK_SLUG) return { fallback: false };
154080
154115
  if (!input.resolvedModel.includes("/")) return { fallback: false };
154116
+ if (input.agentName === "claude") return { fallback: false };
154081
154117
  if (input.authorized.has(input.resolvedModel)) return { fallback: false };
154082
154118
  return {
154083
154119
  fallback: true,
@@ -160058,7 +160094,8 @@ async function main() {
160058
160094
  const fallback = selectFallbackModelIfNeeded({
160059
160095
  resolvedModel: initialResolvedModel,
160060
160096
  proxyModel: payload.proxyModel,
160061
- authorized: authorized2
160097
+ authorized: authorized2,
160098
+ agentName: resolveAgent({ model: initialResolvedModel }).name
160062
160099
  });
160063
160100
  const effectiveSlug = fallback.fallback ? fallback.to : payload.model;
160064
160101
  const resolvedModel = fallback.fallback ? fallback.to : initialResolvedModel;
package/dist/internal.js CHANGED
@@ -258,7 +258,7 @@ var providers = {
258
258
  openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
259
259
  },
260
260
  "minimax-m2.5": {
261
- displayName: "MiniMax M2.5",
261
+ displayName: "MiniMax M2",
262
262
  resolve: "opencode/minimax-m2.5",
263
263
  openRouterResolve: "openrouter/minimax/minimax-m2.5"
264
264
  },
@@ -275,7 +275,7 @@ var providers = {
275
275
  fallback: "opencode/big-pickle"
276
276
  },
277
277
  "minimax-m2.5-free": {
278
- displayName: "MiniMax M2.5",
278
+ displayName: "MiniMax M2",
279
279
  resolve: "opencode/minimax-m2.5-free",
280
280
  envVars: [],
281
281
  isFree: true,
@@ -432,7 +432,7 @@ var providers = {
432
432
  openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
433
433
  },
434
434
  "minimax-m2.5": {
435
- displayName: "MiniMax M2.5",
435
+ displayName: "MiniMax M2",
436
436
  resolve: "openrouter/minimax/minimax-m2.5",
437
437
  openRouterResolve: "openrouter/minimax/minimax-m2.5"
438
438
  }
@@ -1,3 +1,4 @@
1
+ import type { AgentId } from "../external.ts";
1
2
  /**
2
3
  * Slug we fall back to when a BYOK-required model is configured but the
3
4
  * runner has no provider key in env. Picked because it's free, stable, and
@@ -30,9 +31,14 @@ export type FallbackDecision = {
30
31
  * - Resolved model is a raw Bedrock / Vertex ID (no `/`): the routing
31
32
  * validators (`validateBedrockSetup` / `validateVertexSetup`) cover
32
33
  * auth + region/location/model-id; `opencode models` does not.
34
+ * - The selected agent is `claude`: the Claude Code harness brings its own
35
+ * auth and `resolveAgent` only returns it when that auth is present.
36
+ * `opencode models` can't see `CLAUDE_CODE_OAUTH_TOKEN`, so without this
37
+ * an OAuth-subscription run on an Anthropic model would wrongly fall back.
33
38
  */
34
39
  export declare function selectFallbackModelIfNeeded(input: {
35
40
  resolvedModel: string | undefined;
36
41
  proxyModel: string | undefined;
37
42
  authorized: Set<string>;
43
+ agentName: AgentId;
38
44
  }): FallbackDecision;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pullfrog",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "pullfrog": "dist/cli.mjs",