pullfrog 0.1.70 → 0.1.72

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 CHANGED
@@ -110414,9 +110414,9 @@ var providers = {
110414
110414
  },
110415
110415
  "gemini-flash": {
110416
110416
  displayName: "Gemini Flash",
110417
- resolve: "google/gemini-3.6-flash",
110418
- effort: ["minimal", "low", "medium", "high"],
110419
- openRouterResolve: "openrouter/google/gemini-3.6-flash"
110417
+ resolve: "google/gemini-3.8-flash",
110418
+ effort: ["low", "medium", "high"],
110419
+ openRouterResolve: "openrouter/google/gemini-3.8-flash"
110420
110420
  }
110421
110421
  }
110422
110422
  }),
@@ -110744,9 +110744,9 @@ var providers = {
110744
110744
  },
110745
110745
  "gemini-flash": {
110746
110746
  displayName: "Gemini Flash",
110747
- resolve: "opencode/gemini-3.6-flash",
110748
- effort: ["minimal", "low", "medium", "high"],
110749
- openRouterResolve: "openrouter/google/gemini-3.6-flash"
110747
+ resolve: "opencode/gemini-3.8-flash",
110748
+ effort: ["low", "medium", "high"],
110749
+ openRouterResolve: "openrouter/google/gemini-3.8-flash"
110750
110750
  },
110751
110751
  // Zen serves K3, but rule 7 can only move a mirror when its upstream moves,
110752
110752
  // so the K3 generation could never reach this block by bumping `kimi-k2`.
@@ -111174,10 +111174,9 @@ var providers = {
111174
111174
  "gemini-flash": {
111175
111175
  displayName: "Gemini Flash",
111176
111176
  resolve: "openrouter/~google/gemini-flash-latest",
111177
- // no `minimal` here, unlike the google/ and opencode/ entries for the
111178
- // same model: OpenRouter's floating `~google/gemini-flash-latest` stopped
111179
- // publishing that rung. mirroring it is not cosmetic — claude-code
111180
- // hard-errors on an out-of-range `--effort` before it calls the API.
111177
+ // a floating pointer, not a pinned id — it already serves 3.8, so this
111178
+ // entry tracks its siblings' generation bumps for free. the ladder still
111179
+ // mirrors exactly: claude-code hard-errors on an out-of-range `--effort`.
111181
111180
  effort: ["low", "medium", "high"],
111182
111181
  openRouterResolve: "openrouter/~google/gemini-flash-latest"
111183
111182
  },
@@ -111291,8 +111290,8 @@ var providers = {
111291
111290
  },
111292
111291
  "gemini-flash": {
111293
111292
  displayName: "Gemini Flash",
111294
- resolve: "vercel/google/gemini-3.6-flash",
111295
- effort: ["minimal", "low", "medium", "high"]
111293
+ resolve: "vercel/google/gemini-3.8-flash",
111294
+ effort: ["low", "medium", "high"]
111296
111295
  },
111297
111296
  "deepseek-pro": {
111298
111297
  displayName: "DeepSeek Pro",
@@ -111311,7 +111310,8 @@ var providers = {
111311
111310
  },
111312
111311
  "kimi-k3": {
111313
111312
  displayName: "Kimi K3",
111314
- resolve: "vercel/moonshotai/kimi-k3"
111313
+ resolve: "vercel/moonshotai/kimi-k3",
111314
+ effort: ["low", "high", "max"]
111315
111315
  }
111316
111316
  }
111317
111317
  })
@@ -111347,6 +111347,10 @@ function getModelManagedCredentials(slug2) {
111347
111347
  const providerConfig = providers[parsed2.provider];
111348
111348
  return providerConfig?.managedCredentials?.slice() ?? [];
111349
111349
  }
111350
+ var CLAUDE_CODE_ONLY_CREDENTIALS = ["ANTHROPIC_AUTH_TOKEN", "CLAUDE_CODE_OAUTH_TOKEN"];
111351
+ function getOpenCodeEnvVars(slug2) {
111352
+ return getModelEnvVars(slug2).filter((v) => !CLAUDE_CODE_ONLY_CREDENTIALS.includes(v));
111353
+ }
111350
111354
  var modelAliases = Object.entries(providers).flatMap(
111351
111355
  ([providerKey, config3]) => Object.entries(config3.models).map(([modelId, def]) => ({
111352
111356
  slug: `${providerKey}/${modelId}`,
@@ -112281,7 +112285,7 @@ var import_semver = __toESM(require_semver2(), 1);
112281
112285
  // package.json
112282
112286
  var package_default = {
112283
112287
  name: "pullfrog",
112284
- version: "0.1.70",
112288
+ version: "0.1.72",
112285
112289
  type: "module",
112286
112290
  bin: {
112287
112291
  pullfrog: "dist/cli.mjs",
@@ -114320,6 +114324,11 @@ function installManagedSettings(params) {
114320
114324
  return false;
114321
114325
  }
114322
114326
  }
114327
+ function autoSelectClaudeModel() {
114328
+ return modelAliases.find(
114329
+ (a2) => a2.provider === "anthropic" && a2.preferred && !a2.hidden && !a2.fallback && !a2.routing
114330
+ )?.resolve;
114331
+ }
114323
114332
  var claude = agent({
114324
114333
  name: "claude",
114325
114334
  install: installClaudeCli,
@@ -114327,7 +114336,8 @@ var claude = agent({
114327
114336
  var _stack = [];
114328
114337
  try {
114329
114338
  const cliPath = await installClaudeCli();
114330
- const specifier = ctx.payload.proxyModel ?? ctx.resolvedModel;
114339
+ const specifier = ctx.payload.proxyModel ?? ctx.resolvedModel ?? autoSelectClaudeModel();
114340
+ if (specifier) ctx.toolState.model = specifier;
114331
114341
  const bedrockModelId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
114332
114342
  const isBedrockRoute = specifier !== void 0 && bedrockModelId !== void 0 && bedrockModelId === specifier;
114333
114343
  const vertexModelId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
@@ -114347,7 +114357,10 @@ var claude = agent({
114347
114357
  });
114348
114358
  installBundledSkills({ home: homeEnv.HOME });
114349
114359
  const mcpConfigPath = writeMcpConfig(ctx);
114350
- const effort = resolveRunEffort(ctx);
114360
+ const effort = resolveRunEffort({ ...ctx, resolvedModel: specifier });
114361
+ if (!ctx.resolvedModel && !ctx.payload.proxyModel) {
114362
+ log2.info(`\xBB effort: ${effort.rung ?? "n/a (model has no effort control)"}`);
114363
+ }
114351
114364
  const stopHookPath = join5(ctx.tmpdir, "pullfrog-stop-hook.sh");
114352
114365
  writeFileSync4(stopHookPath, buildStopHookScript(), { mode: 493 });
114353
114366
  const pretoolGate = writePretoolGateAssets({ ctx, stopHookPath });
@@ -120995,7 +121008,7 @@ function autoSelectModel() {
120995
121008
  const authorized2 = getAuthorizedModels();
120996
121009
  const selectable = modelAliases.filter((a2) => !a2.hidden && !a2.fallback && !a2.routing);
120997
121010
  const servable = selectable.filter((a2) => {
120998
- const envVars = getModelEnvVars(a2.resolve);
121011
+ const envVars = getOpenCodeEnvVars(a2.resolve);
120999
121012
  return envVars.length === 0 || envVars.some((name) => process.env[name]);
121000
121013
  });
121001
121014
  const pick4 = (list) => list.find((a2) => a2.preferred) ?? list[0];
@@ -194895,7 +194908,7 @@ function formatModelLabel(params) {
194895
194908
  return `${base} (credentials for ${providerDisplayName(params.fallbackFrom)} were rejected by the provider)`;
194896
194909
  }
194897
194910
  if (params.clamped?.reason === "trial") {
194898
- return `${base} (free trial)`;
194911
+ return `${base} (model usage covered by Pullfrog)`;
194899
194912
  }
194900
194913
  if (params.clamped) {
194901
194914
  const target = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
@@ -194912,7 +194925,7 @@ function buildTrialDisclosure(owner) {
194912
194925
  "---",
194913
194926
  "",
194914
194927
  "> [!IMPORTANT]",
194915
- `> **This run used the free trial model.** \`DeepSeek Flash\` is fast and cheap \u2014 expect lighter work than a frontier model. [Connect a subscription or API key \u2192](${consoleUrl2})`
194928
+ `> **Pullfrog covered this run's model usage.** \`DeepSeek Flash\` is fast and cheap \u2014 expect lighter work than a frontier model. This model allowance is temporary and separate from your Pullfrog plan. [Connect a model-provider subscription or API key \u2192](${consoleUrl2})`
194916
194929
  ].join("\n");
194917
194930
  }
194918
194931
  function buildPullfrogFooter(params) {
@@ -200234,7 +200247,7 @@ function buildMissingApiKeyError(params) {
200234
200247
  const envVars = params.model?.includes("/") ? getModelEnvVars(params.model) : [];
200235
200248
  const [primary, ...alternates] = envVars;
200236
200249
  const envVarList = primary ? `\`${primary}\`${alternates.length > 0 ? ` (or ${alternates.map((v) => `\`${v}\``).join(" / ")})` : ""}` : void 0;
200237
- const lead = envVarList ? `**${MISSING_KEY_MARKER}** \u2014 this repo is configured to use \`${params.model}\`, which needs ${envVarList}, but the runner has no key for it.` : `**${MISSING_KEY_MARKER}** \u2014 Pullfrog needs at least one LLM provider API key (e.g. \`ANTHROPIC_API_KEY\`, \`OPENAI_API_KEY\`, \`GEMINI_API_KEY\`) configured as a GitHub Actions secret.`;
200250
+ const lead = envVarList ? `**${MISSING_KEY_MARKER}** \u2014 this run used \`${params.model}\`, which needs ${envVarList}, but the runner has no key for it.` : `**${MISSING_KEY_MARKER}** \u2014 Pullfrog needs at least one LLM provider API key (e.g. \`ANTHROPIC_API_KEY\`, \`OPENAI_API_KEY\`, \`GEMINI_API_KEY\`) configured as a GitHub Actions secret.`;
200238
200251
  return [
200239
200252
  lead,
200240
200253
  "",
@@ -200317,7 +200330,7 @@ function hasEnvVar2(name) {
200317
200330
  return typeof value2 === "string" && value2.length > 0;
200318
200331
  }
200319
200332
  function modelHasRuntimeAuth(model) {
200320
- const authVars = [...getModelEnvVars(model), ...getModelManagedCredentials(model)];
200333
+ const authVars = [...getOpenCodeEnvVars(model), ...getModelManagedCredentials(model)];
200321
200334
  return authVars.length === 0 || authVars.some(hasEnvVar2);
200322
200335
  }
200323
200336
  function hasPositiveNumberEnvVar(name) {
@@ -200411,7 +200424,7 @@ function validateAgentApiKey(params) {
200411
200424
  if (params.authorized.has(params.model)) return;
200412
200425
  const reason = getModelsFailure();
200413
200426
  if (reason) throw new Error(reason);
200414
- if (getModelEnvVars(params.model).some(hasEnvVar2)) return;
200427
+ if (getOpenCodeEnvVars(params.model).some(hasEnvVar2)) return;
200415
200428
  throwKeyError({
200416
200429
  owner: params.owner,
200417
200430
  name: params.name,
@@ -200677,7 +200690,7 @@ function resolveAgent(ctx) {
200677
200690
  }
200678
200691
  }
200679
200692
  if (!ctx.model) {
200680
- if (hasEnvVar3("ANTHROPIC_AUTH_TOKEN") && !hasEnvVar3("ANTHROPIC_API_KEY") && !hasEnvVar3("CLAUDE_CODE_OAUTH_TOKEN")) {
200693
+ if (!hasEnvVar3("ANTHROPIC_API_KEY") && CLAUDE_CODE_ONLY_CREDENTIALS.some(hasEnvVar3)) {
200681
200694
  return agents.claude;
200682
200695
  }
200683
200696
  if (ctx.codexAgent && hasCodexAuth() && !hasClaudeCodeAuth()) return agents.codex;
@@ -204984,7 +204997,7 @@ function resolveTarget(repo) {
204984
204997
  return { owner: match3[1], repo: match3[2] };
204985
204998
  }
204986
204999
  function cliVersion() {
204987
- const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.70");
205000
+ const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.72");
204988
205001
  if (!parts) return "0.0.0";
204989
205002
  return `${Number(parts[1])}.${Number(parts[2])}.${Number(parts[3])}`;
204990
205003
  }
@@ -205151,7 +205164,7 @@ async function runCli5(input2) {
205151
205164
  }
205152
205165
 
205153
205166
  // cli.ts
205154
- var VERSION10 = "0.1.70";
205167
+ var VERSION10 = "0.1.72";
205155
205168
  var bin = basename2(process.argv[1] || "");
205156
205169
  var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
205157
205170
  var rawArgs = process.argv.slice(2);
package/dist/index.js CHANGED
@@ -107924,9 +107924,9 @@ var providers = {
107924
107924
  },
107925
107925
  "gemini-flash": {
107926
107926
  displayName: "Gemini Flash",
107927
- resolve: "google/gemini-3.6-flash",
107928
- effort: ["minimal", "low", "medium", "high"],
107929
- openRouterResolve: "openrouter/google/gemini-3.6-flash"
107927
+ resolve: "google/gemini-3.8-flash",
107928
+ effort: ["low", "medium", "high"],
107929
+ openRouterResolve: "openrouter/google/gemini-3.8-flash"
107930
107930
  }
107931
107931
  }
107932
107932
  }),
@@ -108254,9 +108254,9 @@ var providers = {
108254
108254
  },
108255
108255
  "gemini-flash": {
108256
108256
  displayName: "Gemini Flash",
108257
- resolve: "opencode/gemini-3.6-flash",
108258
- effort: ["minimal", "low", "medium", "high"],
108259
- openRouterResolve: "openrouter/google/gemini-3.6-flash"
108257
+ resolve: "opencode/gemini-3.8-flash",
108258
+ effort: ["low", "medium", "high"],
108259
+ openRouterResolve: "openrouter/google/gemini-3.8-flash"
108260
108260
  },
108261
108261
  // Zen serves K3, but rule 7 can only move a mirror when its upstream moves,
108262
108262
  // so the K3 generation could never reach this block by bumping `kimi-k2`.
@@ -108684,10 +108684,9 @@ var providers = {
108684
108684
  "gemini-flash": {
108685
108685
  displayName: "Gemini Flash",
108686
108686
  resolve: "openrouter/~google/gemini-flash-latest",
108687
- // no `minimal` here, unlike the google/ and opencode/ entries for the
108688
- // same model: OpenRouter's floating `~google/gemini-flash-latest` stopped
108689
- // publishing that rung. mirroring it is not cosmetic — claude-code
108690
- // hard-errors on an out-of-range `--effort` before it calls the API.
108687
+ // a floating pointer, not a pinned id — it already serves 3.8, so this
108688
+ // entry tracks its siblings' generation bumps for free. the ladder still
108689
+ // mirrors exactly: claude-code hard-errors on an out-of-range `--effort`.
108691
108690
  effort: ["low", "medium", "high"],
108692
108691
  openRouterResolve: "openrouter/~google/gemini-flash-latest"
108693
108692
  },
@@ -108801,8 +108800,8 @@ var providers = {
108801
108800
  },
108802
108801
  "gemini-flash": {
108803
108802
  displayName: "Gemini Flash",
108804
- resolve: "vercel/google/gemini-3.6-flash",
108805
- effort: ["minimal", "low", "medium", "high"]
108803
+ resolve: "vercel/google/gemini-3.8-flash",
108804
+ effort: ["low", "medium", "high"]
108806
108805
  },
108807
108806
  "deepseek-pro": {
108808
108807
  displayName: "DeepSeek Pro",
@@ -108821,7 +108820,8 @@ var providers = {
108821
108820
  },
108822
108821
  "kimi-k3": {
108823
108822
  displayName: "Kimi K3",
108824
- resolve: "vercel/moonshotai/kimi-k3"
108823
+ resolve: "vercel/moonshotai/kimi-k3",
108824
+ effort: ["low", "high", "max"]
108825
108825
  }
108826
108826
  }
108827
108827
  })
@@ -108857,6 +108857,10 @@ function getModelManagedCredentials(slug2) {
108857
108857
  const providerConfig = providers[parsed2.provider];
108858
108858
  return providerConfig?.managedCredentials?.slice() ?? [];
108859
108859
  }
108860
+ var CLAUDE_CODE_ONLY_CREDENTIALS = ["ANTHROPIC_AUTH_TOKEN", "CLAUDE_CODE_OAUTH_TOKEN"];
108861
+ function getOpenCodeEnvVars(slug2) {
108862
+ return getModelEnvVars(slug2).filter((v) => !CLAUDE_CODE_ONLY_CREDENTIALS.includes(v));
108863
+ }
108860
108864
  var modelAliases = Object.entries(providers).flatMap(
108861
108865
  ([providerKey, config3]) => Object.entries(config3.models).map(([modelId, def]) => ({
108862
108866
  slug: `${providerKey}/${modelId}`,
@@ -109791,7 +109795,7 @@ var import_semver = __toESM(require_semver2(), 1);
109791
109795
  // package.json
109792
109796
  var package_default = {
109793
109797
  name: "pullfrog",
109794
- version: "0.1.70",
109798
+ version: "0.1.72",
109795
109799
  type: "module",
109796
109800
  bin: {
109797
109801
  pullfrog: "dist/cli.mjs",
@@ -111830,6 +111834,11 @@ function installManagedSettings(params) {
111830
111834
  return false;
111831
111835
  }
111832
111836
  }
111837
+ function autoSelectClaudeModel() {
111838
+ return modelAliases.find(
111839
+ (a) => a.provider === "anthropic" && a.preferred && !a.hidden && !a.fallback && !a.routing
111840
+ )?.resolve;
111841
+ }
111833
111842
  var claude = agent({
111834
111843
  name: "claude",
111835
111844
  install: installClaudeCli,
@@ -111837,7 +111846,8 @@ var claude = agent({
111837
111846
  var _stack = [];
111838
111847
  try {
111839
111848
  const cliPath = await installClaudeCli();
111840
- const specifier = ctx.payload.proxyModel ?? ctx.resolvedModel;
111849
+ const specifier = ctx.payload.proxyModel ?? ctx.resolvedModel ?? autoSelectClaudeModel();
111850
+ if (specifier) ctx.toolState.model = specifier;
111841
111851
  const bedrockModelId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
111842
111852
  const isBedrockRoute = specifier !== void 0 && bedrockModelId !== void 0 && bedrockModelId === specifier;
111843
111853
  const vertexModelId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
@@ -111857,7 +111867,10 @@ var claude = agent({
111857
111867
  });
111858
111868
  installBundledSkills({ home: homeEnv.HOME });
111859
111869
  const mcpConfigPath = writeMcpConfig(ctx);
111860
- const effort = resolveRunEffort(ctx);
111870
+ const effort = resolveRunEffort({ ...ctx, resolvedModel: specifier });
111871
+ if (!ctx.resolvedModel && !ctx.payload.proxyModel) {
111872
+ log.info(`\xBB effort: ${effort.rung ?? "n/a (model has no effort control)"}`);
111873
+ }
111861
111874
  const stopHookPath = join4(ctx.tmpdir, "pullfrog-stop-hook.sh");
111862
111875
  writeFileSync3(stopHookPath, buildStopHookScript(), { mode: 493 });
111863
111876
  const pretoolGate = writePretoolGateAssets({ ctx, stopHookPath });
@@ -118578,7 +118591,7 @@ function autoSelectModel() {
118578
118591
  const authorized2 = getAuthorizedModels();
118579
118592
  const selectable = modelAliases.filter((a) => !a.hidden && !a.fallback && !a.routing);
118580
118593
  const servable = selectable.filter((a) => {
118581
- const envVars = getModelEnvVars(a.resolve);
118594
+ const envVars = getOpenCodeEnvVars(a.resolve);
118582
118595
  return envVars.length === 0 || envVars.some((name) => process.env[name]);
118583
118596
  });
118584
118597
  const pick4 = (list) => list.find((a) => a.preferred) ?? list[0];
@@ -192478,7 +192491,7 @@ function formatModelLabel(params) {
192478
192491
  return `${base} (credentials for ${providerDisplayName(params.fallbackFrom)} were rejected by the provider)`;
192479
192492
  }
192480
192493
  if (params.clamped?.reason === "trial") {
192481
- return `${base} (free trial)`;
192494
+ return `${base} (model usage covered by Pullfrog)`;
192482
192495
  }
192483
192496
  if (params.clamped) {
192484
192497
  const target = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
@@ -192495,7 +192508,7 @@ function buildTrialDisclosure(owner) {
192495
192508
  "---",
192496
192509
  "",
192497
192510
  "> [!IMPORTANT]",
192498
- `> **This run used the free trial model.** \`DeepSeek Flash\` is fast and cheap \u2014 expect lighter work than a frontier model. [Connect a subscription or API key \u2192](${consoleUrl})`
192511
+ `> **Pullfrog covered this run's model usage.** \`DeepSeek Flash\` is fast and cheap \u2014 expect lighter work than a frontier model. This model allowance is temporary and separate from your Pullfrog plan. [Connect a model-provider subscription or API key \u2192](${consoleUrl})`
192499
192512
  ].join("\n");
192500
192513
  }
192501
192514
  function buildPullfrogFooter(params) {
@@ -197817,7 +197830,7 @@ function buildMissingApiKeyError(params) {
197817
197830
  const envVars = params.model?.includes("/") ? getModelEnvVars(params.model) : [];
197818
197831
  const [primary, ...alternates] = envVars;
197819
197832
  const envVarList = primary ? `\`${primary}\`${alternates.length > 0 ? ` (or ${alternates.map((v) => `\`${v}\``).join(" / ")})` : ""}` : void 0;
197820
- const lead = envVarList ? `**${MISSING_KEY_MARKER}** \u2014 this repo is configured to use \`${params.model}\`, which needs ${envVarList}, but the runner has no key for it.` : `**${MISSING_KEY_MARKER}** \u2014 Pullfrog needs at least one LLM provider API key (e.g. \`ANTHROPIC_API_KEY\`, \`OPENAI_API_KEY\`, \`GEMINI_API_KEY\`) configured as a GitHub Actions secret.`;
197833
+ const lead = envVarList ? `**${MISSING_KEY_MARKER}** \u2014 this run used \`${params.model}\`, which needs ${envVarList}, but the runner has no key for it.` : `**${MISSING_KEY_MARKER}** \u2014 Pullfrog needs at least one LLM provider API key (e.g. \`ANTHROPIC_API_KEY\`, \`OPENAI_API_KEY\`, \`GEMINI_API_KEY\`) configured as a GitHub Actions secret.`;
197821
197834
  return [
197822
197835
  lead,
197823
197836
  "",
@@ -197900,7 +197913,7 @@ function hasEnvVar2(name) {
197900
197913
  return typeof value2 === "string" && value2.length > 0;
197901
197914
  }
197902
197915
  function modelHasRuntimeAuth(model) {
197903
- const authVars = [...getModelEnvVars(model), ...getModelManagedCredentials(model)];
197916
+ const authVars = [...getOpenCodeEnvVars(model), ...getModelManagedCredentials(model)];
197904
197917
  return authVars.length === 0 || authVars.some(hasEnvVar2);
197905
197918
  }
197906
197919
  function hasPositiveNumberEnvVar(name) {
@@ -197994,7 +198007,7 @@ function validateAgentApiKey(params) {
197994
198007
  if (params.authorized.has(params.model)) return;
197995
198008
  const reason = getModelsFailure();
197996
198009
  if (reason) throw new Error(reason);
197997
- if (getModelEnvVars(params.model).some(hasEnvVar2)) return;
198010
+ if (getOpenCodeEnvVars(params.model).some(hasEnvVar2)) return;
197998
198011
  throwKeyError({
197999
198012
  owner: params.owner,
198000
198013
  name: params.name,
@@ -198260,7 +198273,7 @@ function resolveAgent(ctx) {
198260
198273
  }
198261
198274
  }
198262
198275
  if (!ctx.model) {
198263
- if (hasEnvVar3("ANTHROPIC_AUTH_TOKEN") && !hasEnvVar3("ANTHROPIC_API_KEY") && !hasEnvVar3("CLAUDE_CODE_OAUTH_TOKEN")) {
198276
+ if (!hasEnvVar3("ANTHROPIC_API_KEY") && CLAUDE_CODE_ONLY_CREDENTIALS.some(hasEnvVar3)) {
198264
198277
  return agents.claude;
198265
198278
  }
198266
198279
  if (ctx.codexAgent && hasCodexAuth() && !hasClaudeCodeAuth()) return agents.codex;
package/dist/internal.js CHANGED
@@ -220,9 +220,9 @@ var providers = {
220
220
  },
221
221
  "gemini-flash": {
222
222
  displayName: "Gemini Flash",
223
- resolve: "google/gemini-3.6-flash",
224
- effort: ["minimal", "low", "medium", "high"],
225
- openRouterResolve: "openrouter/google/gemini-3.6-flash"
223
+ resolve: "google/gemini-3.8-flash",
224
+ effort: ["low", "medium", "high"],
225
+ openRouterResolve: "openrouter/google/gemini-3.8-flash"
226
226
  }
227
227
  }
228
228
  }),
@@ -550,9 +550,9 @@ var providers = {
550
550
  },
551
551
  "gemini-flash": {
552
552
  displayName: "Gemini Flash",
553
- resolve: "opencode/gemini-3.6-flash",
554
- effort: ["minimal", "low", "medium", "high"],
555
- openRouterResolve: "openrouter/google/gemini-3.6-flash"
553
+ resolve: "opencode/gemini-3.8-flash",
554
+ effort: ["low", "medium", "high"],
555
+ openRouterResolve: "openrouter/google/gemini-3.8-flash"
556
556
  },
557
557
  // Zen serves K3, but rule 7 can only move a mirror when its upstream moves,
558
558
  // so the K3 generation could never reach this block by bumping `kimi-k2`.
@@ -980,10 +980,9 @@ var providers = {
980
980
  "gemini-flash": {
981
981
  displayName: "Gemini Flash",
982
982
  resolve: "openrouter/~google/gemini-flash-latest",
983
- // no `minimal` here, unlike the google/ and opencode/ entries for the
984
- // same model: OpenRouter's floating `~google/gemini-flash-latest` stopped
985
- // publishing that rung. mirroring it is not cosmetic — claude-code
986
- // hard-errors on an out-of-range `--effort` before it calls the API.
983
+ // a floating pointer, not a pinned id — it already serves 3.8, so this
984
+ // entry tracks its siblings' generation bumps for free. the ladder still
985
+ // mirrors exactly: claude-code hard-errors on an out-of-range `--effort`.
987
986
  effort: ["low", "medium", "high"],
988
987
  openRouterResolve: "openrouter/~google/gemini-flash-latest"
989
988
  },
@@ -1097,8 +1096,8 @@ var providers = {
1097
1096
  },
1098
1097
  "gemini-flash": {
1099
1098
  displayName: "Gemini Flash",
1100
- resolve: "vercel/google/gemini-3.6-flash",
1101
- effort: ["minimal", "low", "medium", "high"]
1099
+ resolve: "vercel/google/gemini-3.8-flash",
1100
+ effort: ["low", "medium", "high"]
1102
1101
  },
1103
1102
  "deepseek-pro": {
1104
1103
  displayName: "DeepSeek Pro",
@@ -1117,7 +1116,8 @@ var providers = {
1117
1116
  },
1118
1117
  "kimi-k3": {
1119
1118
  displayName: "Kimi K3",
1120
- resolve: "vercel/moonshotai/kimi-k3"
1119
+ resolve: "vercel/moonshotai/kimi-k3",
1120
+ effort: ["low", "high", "max"]
1121
1121
  }
1122
1122
  }
1123
1123
  })
@@ -1153,8 +1153,9 @@ function getModelManagedCredentials(slug) {
1153
1153
  const providerConfig = providers[parsed.provider];
1154
1154
  return providerConfig?.managedCredentials?.slice() ?? [];
1155
1155
  }
1156
+ var CLAUDE_CODE_ONLY_CREDENTIALS = ["ANTHROPIC_AUTH_TOKEN", "CLAUDE_CODE_OAUTH_TOKEN"];
1156
1157
  var HARNESS_ONLY_CREDENTIALS = {
1157
- anthropic: ["ANTHROPIC_AUTH_TOKEN"]
1158
+ anthropic: CLAUDE_CODE_ONLY_CREDENTIALS
1158
1159
  };
1159
1160
  function modelHasStoredAuth(params) {
1160
1161
  const slug = resolveDisplayAlias(params.model)?.slug ?? params.model;
@@ -1730,7 +1731,7 @@ function formatModelLabel(params) {
1730
1731
  return `${base} (credentials for ${providerDisplayName(params.fallbackFrom)} were rejected by the provider)`;
1731
1732
  }
1732
1733
  if (params.clamped?.reason === "trial") {
1733
- return `${base} (free trial)`;
1734
+ return `${base} (model usage covered by Pullfrog)`;
1734
1735
  }
1735
1736
  if (params.clamped) {
1736
1737
  const target = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
@@ -1747,7 +1748,7 @@ function buildTrialDisclosure(owner) {
1747
1748
  "---",
1748
1749
  "",
1749
1750
  "> [!IMPORTANT]",
1750
- `> **This run used the free trial model.** \`DeepSeek Flash\` is fast and cheap \u2014 expect lighter work than a frontier model. [Connect a subscription or API key \u2192](${consoleUrl})`
1751
+ `> **Pullfrog covered this run's model usage.** \`DeepSeek Flash\` is fast and cheap \u2014 expect lighter work than a frontier model. This model allowance is temporary and separate from your Pullfrog plan. [Connect a model-provider subscription or API key \u2192](${consoleUrl})`
1751
1752
  ].join("\n");
1752
1753
  }
1753
1754
  function buildPullfrogFooter(params) {
package/dist/models.d.ts CHANGED
@@ -145,6 +145,30 @@ export declare function getModelEnvVars(slug: string): string[];
145
145
  * a manual-paste option in `init` or the AgentSettings env-var button row.
146
146
  * see `provider.managedCredentials` and wiki/codex-auth.md. */
147
147
  export declare function getModelManagedCredentials(slug: string): string[];
148
+ /**
149
+ * Anthropic credentials that ONLY claude-code can present. opencode's anthropic
150
+ * provider authenticates from `ANTHROPIC_API_KEY` and nothing else (see
151
+ * `packages/llm/src/providers/anthropic.ts` upstream), so holding one of these
152
+ * is not evidence opencode can serve a Claude model.
153
+ *
154
+ * `ANTHROPIC_AUTH_TOKEN` (the gateway variable) is kept out of
155
+ * `providers.anthropic.envVars` entirely. `CLAUDE_CODE_OAUTH_TOKEN` cannot be:
156
+ * the console offers it as a paste target and `credentialFallback` preflights
157
+ * it, both of which read `getModelEnvVars`. So it stays in `envVars` and is
158
+ * subtracted here instead, via `getOpenCodeEnvVars` at every opencode-facing
159
+ * gate. Leaving it un-subtracted let `autoSelectModel` pin
160
+ * `anthropic/claude-opus-5` on a subscription-only account and hand it to
161
+ * opencode, which died with `Model not found` before the first turn.
162
+ */
163
+ export declare const CLAUDE_CODE_ONLY_CREDENTIALS: string[];
164
+ /**
165
+ * `getModelEnvVars` minus the credentials only claude-code can present — the
166
+ * right question for every opencode-facing gate (auto-select, key validation).
167
+ * `getModelEnvVars` answers "which credentials can serve this model", which is
168
+ * the product's question; this answers "which can serve it UNDER OPENCODE",
169
+ * which is the only one those gates may act on.
170
+ */
171
+ export declare function getOpenCodeEnvVars(slug: string): string[];
148
172
  /**
149
173
  * Whether one of `secretNames` can run `model` — the Router opt-out predicate,
150
174
  * shared so every caller decides the same way. Auto-tier sentinels and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pullfrog",
3
- "version": "0.1.70",
3
+ "version": "0.1.72",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "pullfrog": "dist/cli.mjs",