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 +38 -25
- package/dist/index.js +36 -23
- package/dist/internal.js +17 -16
- package/dist/models.d.ts +24 -0
- package/package.json +1 -1
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.
|
|
110418
|
-
effort: ["
|
|
110419
|
-
openRouterResolve: "openrouter/google/gemini-3.
|
|
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.
|
|
110748
|
-
effort: ["
|
|
110749
|
-
openRouterResolve: "openrouter/google/gemini-3.
|
|
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
|
-
//
|
|
111178
|
-
//
|
|
111179
|
-
//
|
|
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.
|
|
111295
|
-
effort: ["
|
|
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.
|
|
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 =
|
|
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} (
|
|
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
|
-
`> **
|
|
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
|
|
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 = [...
|
|
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 (
|
|
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 (
|
|
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.
|
|
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.
|
|
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.
|
|
107928
|
-
effort: ["
|
|
107929
|
-
openRouterResolve: "openrouter/google/gemini-3.
|
|
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.
|
|
108258
|
-
effort: ["
|
|
108259
|
-
openRouterResolve: "openrouter/google/gemini-3.
|
|
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
|
-
//
|
|
108688
|
-
//
|
|
108689
|
-
//
|
|
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.
|
|
108805
|
-
effort: ["
|
|
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.
|
|
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 =
|
|
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} (
|
|
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
|
-
`> **
|
|
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
|
|
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 = [...
|
|
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 (
|
|
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 (
|
|
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.
|
|
224
|
-
effort: ["
|
|
225
|
-
openRouterResolve: "openrouter/google/gemini-3.
|
|
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.
|
|
554
|
-
effort: ["
|
|
555
|
-
openRouterResolve: "openrouter/google/gemini-3.
|
|
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
|
-
//
|
|
984
|
-
//
|
|
985
|
-
//
|
|
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.
|
|
1101
|
-
effort: ["
|
|
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:
|
|
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} (
|
|
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
|
-
`> **
|
|
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
|