pullfrog 0.1.67 → 0.1.68

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
@@ -110208,6 +110208,7 @@ import { performance as performance5 } from "node:perf_hooks";
110208
110208
 
110209
110209
  // effort.ts
110210
110210
  var DEFAULT_EFFORT_POSITION = 0.5;
110211
+ var SUBSIDY_RUNG = "high";
110211
110212
  var EFFORT_ALIASES = {
110212
110213
  low: 0,
110213
110214
  medium: 0.25,
@@ -110611,6 +110612,15 @@ var providers = {
110611
110612
  // the model does cost nothing.
110612
110613
  isFree: true
110613
110614
  },
110615
+ // Zen meters Fable like any other model, so this route reaches it without
110616
+ // the Anthropic access grant `anthropic/claude-fable` still needs.
110617
+ "claude-fable": {
110618
+ displayName: "Claude Fable",
110619
+ resolve: "opencode/claude-fable-5-1",
110620
+ effort: ["low", "medium", "high", "xhigh", "max"],
110621
+ openRouterResolve: "openrouter/~anthropic/claude-fable-latest",
110622
+ subagentModel: "claude-sonnet"
110623
+ },
110614
110624
  "claude-opus": {
110615
110625
  displayName: "Claude Opus",
110616
110626
  resolve: "opencode/claude-opus-5",
@@ -110724,6 +110734,17 @@ var providers = {
110724
110734
  effort: ["minimal", "low", "medium", "high"],
110725
110735
  openRouterResolve: "openrouter/google/gemini-3.6-flash"
110726
110736
  },
110737
+ // Zen serves K3, but rule 7 can only move a mirror when its upstream moves,
110738
+ // so the K3 generation could never reach this block by bumping `kimi-k2`.
110739
+ "kimi-k3": {
110740
+ displayName: "Kimi K3",
110741
+ resolve: "opencode/kimi-k3",
110742
+ // Zen publishes a single rung for K3 where OpenRouter publishes three.
110743
+ effort: ["max"],
110744
+ openRouterEffort: ["low", "high", "max"],
110745
+ openRouterResolve: "openrouter/moonshotai/kimi-k3",
110746
+ subagentModel: "kimi-k2"
110747
+ },
110727
110748
  "kimi-k2": {
110728
110749
  displayName: "Kimi K2",
110729
110750
  // k2.7-code is UNDEPLOYED on Zen — still listed in /zen/v1/models, but
@@ -110735,25 +110756,58 @@ var providers = {
110735
110756
  resolve: "opencode/kimi-k2.6",
110736
110757
  openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
110737
110758
  },
110759
+ // M3 is its own line beside M2, not a bump of it — same reason `kimi-k3`
110760
+ // sits beside `kimi-k2` rather than replacing it.
110761
+ "minimax-m3": {
110762
+ displayName: "MiniMax M3",
110763
+ resolve: "opencode/minimax-m3",
110764
+ openRouterResolve: "openrouter/minimax/minimax-m3"
110765
+ },
110738
110766
  // slug pins the m2 line for DB stability; resolve tracks the current m2.7.
110739
110767
  "minimax-m2.5": {
110740
110768
  displayName: "MiniMax M2",
110741
110769
  resolve: "opencode/minimax-m2.7",
110742
110770
  openRouterResolve: "openrouter/minimax/minimax-m2.7"
110743
110771
  },
110772
+ // Z.ai and xAI reach Zen subscribers only here — before this, `opencode-go`
110773
+ // was the catalog's only GLM route, and Grok had no Zen route at all.
110774
+ glm: {
110775
+ displayName: "GLM",
110776
+ resolve: "opencode/glm-5.2",
110777
+ effort: ["high", "max"],
110778
+ openRouterEffort: ["high", "xhigh"],
110779
+ openRouterResolve: "openrouter/z-ai/glm-5.2"
110780
+ },
110781
+ grok: {
110782
+ displayName: "Grok",
110783
+ resolve: "opencode/grok-4.6",
110784
+ effort: ["low", "medium", "high", "xhigh"],
110785
+ openRouterResolve: "openrouter/x-ai/grok-4.6"
110786
+ },
110744
110787
  "gpt-5-nano": {
110745
110788
  displayName: "GPT Nano",
110746
110789
  resolve: "opencode/gpt-5-nano",
110747
110790
  effort: ["minimal", "low", "medium", "high"],
110748
110791
  openRouterResolve: "openrouter/openai/gpt-5-nano"
110749
110792
  },
110793
+ // Zen's live free MiMo, and the second free row in a menu that big-pickle
110794
+ // was alone in since `mimo-v2-pro-free` lost its model.
110795
+ mimo: {
110796
+ displayName: "MiMo",
110797
+ resolve: "opencode/mimo-v2.5-free",
110798
+ // free to run, still gated on the provider's own OPENCODE_API_KEY —
110799
+ // see the big-pickle note above (#1077).
110800
+ isFree: true
110801
+ },
110750
110802
  "mimo-v2-pro-free": {
110751
110803
  displayName: "MiMo V2 Pro",
110752
110804
  resolve: "opencode/mimo-v2-pro-free",
110753
110805
  // free to run, still gated on the provider's own OPENCODE_API_KEY —
110754
110806
  // see the big-pickle note above (#1077).
110755
110807
  isFree: true,
110756
- fallback: "opencode/big-pickle"
110808
+ // the model id Zen dropped; land a stored MiMo pick back on MiMo rather
110809
+ // than on the unrelated model it had to settle for while none was live.
110810
+ fallback: "opencode/mimo"
110757
110811
  },
110758
110812
  "minimax-m2.5-free": {
110759
110813
  displayName: "MiniMax M2",
@@ -110848,6 +110902,16 @@ var providers = {
110848
110902
  resolve: "opencode-go/qwen3.7-plus",
110849
110903
  openRouterResolve: "openrouter/qwen/qwen3.7-plus"
110850
110904
  },
110905
+ // the cheap rung Alibaba added under Plus (0.15/0.47 against 0.5/3), and
110906
+ // the only model either OpenCode plan has added since this block was written.
110907
+ "qwen-flash": {
110908
+ displayName: "Qwen Flash",
110909
+ resolve: "opencode-go/qwen3.8-flash",
110910
+ effort: ["low", "medium", "xhigh"],
110911
+ // the Go route publishes rungs where OpenRouter publishes none.
110912
+ openRouterEffort: [],
110913
+ openRouterResolve: "openrouter/qwen/qwen3.8-flash"
110914
+ },
110851
110915
  // MiniMax — parity with opencode/* and openrouter/*; the m2 slug pins the
110852
110916
  // line for DB stability while the resolve tracks the current m2.7.
110853
110917
  "minimax-m3": {
@@ -111972,6 +112036,7 @@ async function installFromNpmTarball(params) {
111972
112036
  // utils/providerErrors.ts
111973
112037
  var PROVIDER_BILLING_EXHAUSTED_LABEL = "provider billing exhausted";
111974
112038
  var PROVIDER_NO_ENDPOINTS_LABEL = "provider no routable endpoints";
112039
+ var PROVIDER_USAGE_LIMIT_LABEL = "provider usage limit reached";
111975
112040
  var statusKey = `\\b(?:status[_ ]?code|http[_ ]?status|status)["']?\\s*[:=]\\s*["']?`;
111976
112041
  var ANTHROPIC_SPEND_CAP_PATTERN = /reached your specified API usage limits\.?(?:\s*You will regain access on ([^"\n]+?)\.)?/i;
111977
112042
  function findAnthropicSpendCap(text) {
@@ -112017,6 +112082,14 @@ var PROVIDER_ERROR_PATTERNS = [
112017
112082
  // the wallet-shaped patterns above reach, and its 400 sits nowhere near a
112018
112083
  // `status:` key either — so the whole message was dropped on the floor (#1208).
112019
112084
  { regex: ANTHROPIC_SPEND_CAP_PATTERN, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
112085
+ // OpenCode Zen / Codex-subscription cap: `AI_APICallError: The usage limit has
112086
+ // been reached`. Its noun is "usage limit" with no "rate", no status code and
112087
+ // no wallet wording, so every pattern here missed it and `lastProviderError`
112088
+ // stayed unset — which suppresses nothing, so the run was reported as "The
112089
+ // model produced no output at all … usually transient; re-running often
112090
+ // succeeds" while the same log held nine of these. Measured on a live account
112091
+ // whose ChatGPT subscription was capped.
112092
+ { regex: /\bthe usage limit has been reached\b/i, label: PROVIDER_USAGE_LIMIT_LABEL },
112020
112093
  // the OpenRouter shapes `isRouterKeylimitExhaustedError` matches. on a Router
112021
112094
  // run those mean the PULLFROG wallet is empty and `renderRunError` returns a
112022
112095
  // `BillingError` before ever reaching this list; on a BYOK run the very same
@@ -112147,7 +112220,7 @@ function ossEffortFloor(ctx) {
112147
112220
  const alias = resolveRunAlias(ctx);
112148
112221
  const published = alias?.openRouterEffort ?? alias?.effort;
112149
112222
  if (!published) return 0;
112150
- return rungPosition({ rung: "high", published }) ?? 0;
112223
+ return rungPosition({ rung: SUBSIDY_RUNG, published }) ?? 0;
112151
112224
  }
112152
112225
  function resolveRunEffort(ctx) {
112153
112226
  const configured = ctx.payload.effort !== void 0;
@@ -112179,7 +112252,7 @@ var import_semver = __toESM(require_semver2(), 1);
112179
112252
  // package.json
112180
112253
  var package_default = {
112181
112254
  name: "pullfrog",
112182
- version: "0.1.67",
112255
+ version: "0.1.68",
112183
112256
  type: "module",
112184
112257
  bin: {
112185
112258
  pullfrog: "dist/cli.mjs",
@@ -194790,6 +194863,9 @@ function formatModelLabel(params) {
194790
194863
  if (params.fallbackFrom) {
194791
194864
  return `${base} (credentials for ${providerDisplayName(params.fallbackFrom)} were rejected by the provider)`;
194792
194865
  }
194866
+ if (params.clamped?.reason === "trial") {
194867
+ return `${base} (free trial)`;
194868
+ }
194793
194869
  if (params.clamped) {
194794
194870
  const target = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
194795
194871
  return params.clamped.reason === "card" ? `${base} (${target} needs a [card on file](https://docs.pullfrog.com/models))` : `${base} (${target} needs a [provider key](https://docs.pullfrog.com/models) \u2014 no Router support yet)`;
@@ -194799,6 +194875,15 @@ function formatModelLabel(params) {
194799
194875
  }
194800
194876
  return base;
194801
194877
  }
194878
+ function buildTrialDisclosure(owner) {
194879
+ const consoleUrl2 = owner ? `https://pullfrog.com/console/${owner}` : "https://pullfrog.com/console";
194880
+ return [
194881
+ "---",
194882
+ "",
194883
+ "> [!IMPORTANT]",
194884
+ `> **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})`
194885
+ ].join("\n");
194886
+ }
194802
194887
  function buildPullfrogFooter(params) {
194803
194888
  const parts = [];
194804
194889
  if (params.shaPinned) {
@@ -194831,10 +194916,13 @@ function buildPullfrogFooter(params) {
194831
194916
  );
194832
194917
  }
194833
194918
  const allParts = [...parts, "[\u{1D54F}](https://x.com/pullfrogai)"];
194919
+ const disclosure = params.clamped?.reason === "trial" ? `${buildTrialDisclosure(params.owner)}
194920
+
194921
+ ` : "";
194834
194922
  return `
194835
194923
 
194836
194924
  ${PULLFROG_DIVIDER}
194837
- <sup>${FROG_LOGO}&nbsp;&nbsp;\uFF5C ${allParts.join(" \uFF5C ")}</sup>`;
194925
+ ${disclosure}<sup>${FROG_LOGO}&nbsp;&nbsp;\uFF5C ${allParts.join(" \uFF5C ")}</sup>`;
194838
194926
  }
194839
194927
  function stripExistingFooter(body) {
194840
194928
  const dividerIndex = body.indexOf(PULLFROG_DIVIDER);
@@ -194988,7 +195076,8 @@ function buildCommentFooter(ctx, customParts) {
194988
195076
  clamped: ctx.toolState.modelClamped,
194989
195077
  unselectedProxyDefault: ctx.toolState.unselectedProxyDefault,
194990
195078
  shaPinned: ctx.toolState.shaPinned,
194991
- oss: ctx.oss
195079
+ oss: ctx.oss,
195080
+ owner: ctx.repo.owner
194992
195081
  });
194993
195082
  }
194994
195083
  function buildImplementPlanLink(ctx, issueNumber, commentId) {
@@ -195987,7 +196076,8 @@ async function createAndSubmitWithFooter(ctx, params, opts) {
195987
196076
  clamped: ctx.toolState.modelClamped,
195988
196077
  unselectedProxyDefault: ctx.toolState.unselectedProxyDefault,
195989
196078
  shaPinned: ctx.toolState.shaPinned,
195990
- oss: ctx.oss
196079
+ oss: ctx.oss,
196080
+ owner: ctx.repo.owner
195991
196081
  });
195992
196082
  return await ctx.octokit.rest.pulls.submitReview({
195993
196083
  owner: params.owner,
@@ -198748,7 +198838,8 @@ function buildPrBodyWithFooter(ctx, body) {
198748
198838
  clamped: ctx.toolState.modelClamped,
198749
198839
  unselectedProxyDefault: ctx.toolState.unselectedProxyDefault,
198750
198840
  shaPinned: ctx.toolState.shaPinned,
198751
- oss: ctx.oss
198841
+ oss: ctx.oss,
198842
+ owner: ctx.repo.owner
198752
198843
  });
198753
198844
  const bodyWithoutFooter = stripExistingFooter(fixDoubleEscapedString(body));
198754
198845
  return `${bodyWithoutFooter}${footer}`;
@@ -200055,10 +200146,12 @@ function isByokSetupError(text) {
200055
200146
  var SECRETS_UNAVAILABLE_MARKER = "couldn't load your Pullfrog secrets";
200056
200147
  var ROUTER_UNFUNDED_MARKER = "your Pullfrog Router balance is empty";
200057
200148
  var CREDENTIAL_REJECTED_MARKER = "was rejected by its provider";
200058
- function buildKeyError(params) {
200059
- if (params.secretsUnavailable) return buildSecretsUnavailableError(params);
200060
- if (params.routerUnfunded) return buildRouterUnfundedError(params);
200061
- return buildMissingApiKeyError(params);
200149
+ var NoUsableCredentialError = class extends Error {
200150
+ };
200151
+ function throwKeyError(params) {
200152
+ if (params.secretsUnavailable) throw new Error(buildSecretsUnavailableError(params));
200153
+ if (params.routerUnfunded) throw new NoUsableCredentialError(buildRouterUnfundedError(params));
200154
+ throw new NoUsableCredentialError(buildMissingApiKeyError(params));
200062
200155
  }
200063
200156
  function buildRouterUnfundedError(params) {
200064
200157
  const billingUrl = `${getApiUrl()}/console/${params.owner}#billing`;
@@ -200257,57 +200350,51 @@ function validateAgentApiKey(params) {
200257
200350
  validateVertexSetup({ owner: params.owner, name: params.name });
200258
200351
  return;
200259
200352
  }
200260
- validateBedrockSetup({ owner: params.owner, name: params.name });
200261
- return;
200353
+ if (process.env[BEDROCK_MODEL_ID_ENV]?.trim() === params.model) {
200354
+ validateBedrockSetup({ owner: params.owner, name: params.name });
200355
+ return;
200356
+ }
200262
200357
  }
200263
200358
  if (params.agent.name === "opencode") {
200264
200359
  if (params.authorized.has(params.model)) return;
200265
200360
  const reason = getModelsFailure();
200266
200361
  if (reason) throw new Error(reason);
200267
200362
  if (getModelEnvVars(params.model).some(hasEnvVar2)) return;
200268
- throw new Error(
200269
- buildKeyError({
200270
- owner: params.owner,
200271
- name: params.name,
200272
- model: params.model,
200273
- secretsUnavailable: params.secretsUnavailable,
200274
- routerUnfunded: params.routerUnfunded
200275
- })
200276
- );
200277
- }
200278
- if (hasSingleProviderAuth(params.agent.name)) return;
200279
- throw new Error(
200280
- buildKeyError({
200363
+ throwKeyError({
200281
200364
  owner: params.owner,
200282
200365
  name: params.name,
200283
200366
  model: params.model,
200284
200367
  secretsUnavailable: params.secretsUnavailable,
200285
200368
  routerUnfunded: params.routerUnfunded
200286
- })
200287
- );
200369
+ });
200370
+ }
200371
+ if (hasSingleProviderAuth(params.agent.name)) return;
200372
+ throwKeyError({
200373
+ owner: params.owner,
200374
+ name: params.name,
200375
+ model: params.model,
200376
+ secretsUnavailable: params.secretsUnavailable,
200377
+ routerUnfunded: params.routerUnfunded
200378
+ });
200288
200379
  }
200289
200380
  if (params.agent.name === "opencode") {
200290
200381
  if ([...params.authorized].some(modelHasRuntimeAuth)) return;
200291
200382
  const reason = getModelsFailure();
200292
200383
  if (reason) throw new Error(reason);
200293
- throw new Error(
200294
- buildKeyError({
200295
- owner: params.owner,
200296
- name: params.name,
200297
- secretsUnavailable: params.secretsUnavailable,
200298
- routerUnfunded: params.routerUnfunded
200299
- })
200300
- );
200301
- }
200302
- if (hasSingleProviderAuth(params.agent.name)) return;
200303
- throw new Error(
200304
- buildKeyError({
200384
+ throwKeyError({
200305
200385
  owner: params.owner,
200306
200386
  name: params.name,
200307
200387
  secretsUnavailable: params.secretsUnavailable,
200308
200388
  routerUnfunded: params.routerUnfunded
200309
- })
200310
- );
200389
+ });
200390
+ }
200391
+ if (hasSingleProviderAuth(params.agent.name)) return;
200392
+ throwKeyError({
200393
+ owner: params.owner,
200394
+ name: params.name,
200395
+ secretsUnavailable: params.secretsUnavailable,
200396
+ routerUnfunded: params.routerUnfunded
200397
+ });
200311
200398
  }
200312
200399
  function isApiKeyAuthError(text) {
200313
200400
  if (!text) return false;
@@ -200432,9 +200519,9 @@ function formatApiKeyErrorSummary(params) {
200432
200519
  ].join("\n");
200433
200520
  }
200434
200521
  return [
200435
- `**Your LLM provider API key was rejected.** Rotate the key in your provider dashboard, then update the matching GitHub Actions secret.`,
200522
+ `**Your LLM provider API key was rejected.** Rotate the key in your provider dashboard, then update the copy Pullfrog uses \u2014 wherever you saved it.`,
200436
200523
  "",
200437
- `[Update repo secret \u2192](${githubSecretsUrl}) \xB7 [Model settings \u2192](${settingsUrl}) \xB7 [Setup docs \u2192](https://docs.pullfrog.com/keys) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`
200524
+ `[Pullfrog secrets \u2192](${getApiUrl()}/console/${params.owner}) \xB7 [Repo secrets \u2192](${githubSecretsUrl}) \xB7 [Model settings \u2192](${settingsUrl}) \xB7 [Setup docs \u2192](https://docs.pullfrog.com/keys) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`
200438
200525
  ].join("\n");
200439
200526
  }
200440
200527
 
@@ -201660,6 +201747,9 @@ var DebugInput = type.enumerated("disabled", "enabled");
201660
201747
  var JsonPayload = type({
201661
201748
  "~pullfrog": "true",
201662
201749
  version: "string",
201750
+ // the server's run type, forwarded verbatim to run-context. optional so a
201751
+ // payload from an older server build still parses against a newer action.
201752
+ "type?": "string | undefined",
201663
201753
  "model?": "string | undefined",
201664
201754
  "modelExplicit?": "boolean | undefined",
201665
201755
  "effort?": "number | string | undefined",
@@ -202145,7 +202235,8 @@ ${ctx.error}` : ctx.error;
202145
202235
  clamped: ctx.toolState.modelClamped,
202146
202236
  unselectedProxyDefault: ctx.toolState.unselectedProxyDefault,
202147
202237
  shaPinned: ctx.toolState.shaPinned,
202148
- oss: ctx.toolState.oss
202238
+ oss: ctx.toolState.oss,
202239
+ owner: repoContext.owner
202149
202240
  });
202150
202241
  const body = `${formattedError}${footer}`;
202151
202242
  const comment = ctx.toolState.progressComment;
@@ -202228,7 +202319,7 @@ async function mintProxyKey(ctx) {
202228
202319
  }
202229
202320
  }
202230
202321
  async function buildProxyTokenHeaders(ctx) {
202231
- const fundingSource = ctx.oss ? "oss" : "router";
202322
+ const fundingSource = ctx.fundingSource;
202232
202323
  if (ctx.oidcCredentials) {
202233
202324
  const creds = ctx.oidcCredentials;
202234
202325
  const oidcToken = await op(() => fetchIdTokenFromStash(creds), {
@@ -202260,7 +202351,7 @@ async function resolveProxyModel(ctx) {
202260
202351
  const key = await mintProxyKey({
202261
202352
  oidcCredentials: ctx.oidcCredentials,
202262
202353
  repo: ctx.repo,
202263
- oss: ctx.oss
202354
+ fundingSource: ctx.oss ? "oss" : "router"
202264
202355
  });
202265
202356
  if (!key) return;
202266
202357
  process.env.OPENROUTER_API_KEY = key;
@@ -202332,6 +202423,26 @@ async function runProxyResolution(ctx) {
202332
202423
  throw error62;
202333
202424
  }
202334
202425
  }
202426
+ async function resolveTrialFallback(ctx) {
202427
+ if (process.env.PULLFROG_MODEL?.trim()) return false;
202428
+ if (!ctx.oidcCredentials && !isLocalApiUrl()) return false;
202429
+ const key = await mintProxyKey({
202430
+ oidcCredentials: ctx.oidcCredentials,
202431
+ repo: ctx.repo,
202432
+ fundingSource: "trial"
202433
+ });
202434
+ if (!key) return false;
202435
+ process.env.OPENROUTER_API_KEY = key;
202436
+ core9.setSecret(key);
202437
+ ctx.payload.proxyModel = DEFAULT_PROXY_MODEL;
202438
+ ctx.toolState.model = DEFAULT_PROXY_MODEL;
202439
+ ctx.toolState.modelClamped = {
202440
+ from: ctx.configuredModel ?? DEFAULT_PROXY_MODEL,
202441
+ reason: "trial"
202442
+ };
202443
+ log2.info(`\xBB proxy: trial \u2192 ${DEFAULT_PROXY_MODEL}`);
202444
+ return true;
202445
+ }
202335
202446
 
202336
202447
  // utils/prSummary.ts
202337
202448
  import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
@@ -202509,8 +202620,9 @@ async function fetchRunContext(params) {
202509
202620
  if (params.oidcToken) {
202510
202621
  headers["X-GitHub-OIDC-Token"] = params.oidcToken;
202511
202622
  }
202623
+ const query = params.runType ? `?type=${encodeURIComponent(params.runType)}` : "";
202512
202624
  const response = await apiFetch({
202513
- path: `/api/repo/${params.repoContext.owner}/${params.repoContext.name}/run-context`,
202625
+ path: `/api/repo/${params.repoContext.owner}/${params.repoContext.name}/run-context${query}`,
202514
202626
  headers,
202515
202627
  signal: controller.signal
202516
202628
  });
@@ -202547,7 +202659,8 @@ async function fetchRunContext(params) {
202547
202659
  proxyModel: data.proxyModel,
202548
202660
  dbSecrets: data.dbSecrets,
202549
202661
  secretsUnavailable: data.secretsUnavailable,
202550
- routerUnfunded: data.routerUnfunded
202662
+ routerUnfunded: data.routerUnfunded,
202663
+ trialFallback: data.trialFallback
202551
202664
  };
202552
202665
  } catch {
202553
202666
  clearTimeout(timeoutId);
@@ -202588,7 +202701,7 @@ async function resolveRunContextData(params) {
202588
202701
  retries: [100, 500],
202589
202702
  bail: (error62) => !isTransientOctokitError(error62)
202590
202703
  })(),
202591
- fetchRunContext({ token: params.token, repoContext, oidcToken })
202704
+ fetchRunContext({ token: params.token, repoContext, oidcToken, runType: params.runType })
202592
202705
  ]);
202593
202706
  return {
202594
202707
  repo: {
@@ -202606,7 +202719,8 @@ async function resolveRunContextData(params) {
202606
202719
  // a failed mint on a runner that should have been able to mint is the same
202607
202720
  // outcome as the server-side failure: the run never sees stored secrets.
202608
202721
  secretsUnavailable: runContext.secretsUnavailable || !!process.env.ACTIONS_ID_TOKEN_REQUEST_URL && oidcToken === void 0,
202609
- routerUnfunded: runContext.routerUnfunded
202722
+ routerUnfunded: runContext.routerUnfunded,
202723
+ trialFallback: runContext.trialFallback
202610
202724
  };
202611
202725
  }
202612
202726
 
@@ -203686,7 +203800,11 @@ async function main() {
203686
203800
  resolveGit();
203687
203801
  const jobToken = getJobToken();
203688
203802
  const initialOctokit = createOctokit(jobToken);
203689
- const runContext = await resolveRunContextData({ octokit: initialOctokit, token: jobToken });
203803
+ const runContext = await resolveRunContextData({
203804
+ octokit: initialOctokit,
203805
+ token: jobToken,
203806
+ runType: typeof resolvedPromptInput === "string" ? void 0 : resolvedPromptInput.type
203807
+ });
203690
203808
  timer.checkpoint("runContextData");
203691
203809
  const payload = resolvePayload(resolvedPromptInput, runContext.repoSettings);
203692
203810
  const toolState = initToolState({
@@ -203867,7 +203985,7 @@ async function main() {
203867
203985
  }
203868
203986
  const resolvedModel = credentials.kind === "fellBack" ? credentials.replacement : configuredModel;
203869
203987
  vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
203870
- const agent2 = resolveAgent({
203988
+ let agent2 = resolveAgent({
203871
203989
  model: resolvedModel,
203872
203990
  proxyModel: payload.proxyModel,
203873
203991
  // the account opt-in and the canary arm are both admissions to codex, so
@@ -203879,15 +203997,32 @@ async function main() {
203879
203997
  const effectiveModel = payload.proxyModel ?? resolvedModel ?? payload.model;
203880
203998
  toolState.model = effectiveModel;
203881
203999
  if (!payload.proxyModel) {
203882
- validateAgentApiKey({
203883
- agent: agent2,
203884
- model: effectiveModel,
203885
- authorized: getAuthorizedModels(),
203886
- owner: runContext.repo.owner,
203887
- name: runContext.repo.name,
203888
- secretsUnavailable: runContext.secretsUnavailable,
203889
- routerUnfunded: runContext.routerUnfunded
203890
- });
204000
+ try {
204001
+ validateAgentApiKey({
204002
+ agent: agent2,
204003
+ model: effectiveModel,
204004
+ authorized: getAuthorizedModels(),
204005
+ owner: runContext.repo.owner,
204006
+ name: runContext.repo.name,
204007
+ secretsUnavailable: runContext.secretsUnavailable,
204008
+ routerUnfunded: runContext.routerUnfunded
204009
+ });
204010
+ } catch (missingKey) {
204011
+ const funded = runContext.trialFallback && missingKey instanceof NoUsableCredentialError ? await resolveTrialFallback({
204012
+ payload,
204013
+ configuredModel: effectiveModel,
204014
+ oidcCredentials,
204015
+ repo: runContext.repo,
204016
+ toolState
204017
+ }) : false;
204018
+ if (!funded) throw missingKey;
204019
+ agent2 = resolveAgent({
204020
+ model: resolvedModel,
204021
+ proxyModel: payload.proxyModel,
204022
+ codexAgent: runContext.repoSettings.codexAgent || payload.codexArm === true
204023
+ });
204024
+ toolState.agent = agent2.name;
204025
+ }
203891
204026
  }
203892
204027
  await setupGit({
203893
204028
  gitToken: tokenRef.gitToken,
@@ -204797,7 +204932,7 @@ function resolveTarget(repo) {
204797
204932
  return { owner: match3[1], repo: match3[2] };
204798
204933
  }
204799
204934
  function cliVersion() {
204800
- const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.67");
204935
+ const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.68");
204801
204936
  if (!parts) return "0.0.0";
204802
204937
  return `${Number(parts[1])}.${Number(parts[2])}.${Number(parts[3])}`;
204803
204938
  }
@@ -204964,7 +205099,7 @@ async function runCli5(input2) {
204964
205099
  }
204965
205100
 
204966
205101
  // cli.ts
204967
- var VERSION10 = "0.1.67";
205102
+ var VERSION10 = "0.1.68";
204968
205103
  var bin = basename2(process.argv[1] || "");
204969
205104
  var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
204970
205105
  var rawArgs = process.argv.slice(2);
package/dist/effort.d.ts CHANGED
@@ -32,6 +32,16 @@ export type EffortPosition = number;
32
32
  * ran at before this setting existed.
33
33
  */
34
34
  export declare const DEFAULT_EFFORT_POSITION: EffortPosition;
35
+ /**
36
+ * the rung a Pullfrog-subsidised OSS run is pinned to, whatever the repo or a
37
+ * per-kind-of-work row has stored — see `ossEffortFloor`, which spends it, and
38
+ * the console's Model card, which stops offering the control because of it.
39
+ *
40
+ * shared rather than written twice: the runtime pins the run and the console
41
+ * says so, and a console that names a different rung than the one that runs is
42
+ * the same class of bug as the Router opt-out the two surfaces disagreed on.
43
+ */
44
+ export declare const SUBSIDY_RUNG = "high";
35
45
  /**
36
46
  * names we accept on user-facing surfaces (`--effort=`, the action input),
37
47
  * mapped to fixed points on the axis. these are a typing convenience, NOT an
@@ -50,7 +50,7 @@ export declare function findDanglingPromptToolRefs(params: {
50
50
  toolNames: string[];
51
51
  }): string[];
52
52
  export type { EffortPosition } from "./effort.ts";
53
- export { DEFAULT_EFFORT_POSITION, EFFORT_ALIASES, isEffortPosition, offeredRungs, parseEffortPosition, resolveRung, rungLabel, rungPosition, } from "./effort.ts";
53
+ export { DEFAULT_EFFORT_POSITION, EFFORT_ALIASES, isEffortPosition, offeredRungs, parseEffortPosition, resolveRung, rungLabel, rungPosition, SUBSIDY_RUNG, } from "./effort.ts";
54
54
  export type { AutoTier, ModelAlias, ModelProvider, ProviderConfig } from "./models.ts";
55
55
  export { AUTO_EFFICIENT, AUTO_INTELLIGENT, DEFAULT_PROXY_MODEL, defaultAutoTier, getAutoSelectHintModel, getModelEffortLevels, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, isAutoTier, isCardGatedModel, isOssAllowedModel, modelAliases, modelHasStoredAuth, OSS_MODEL_ALLOWLIST, OSS_RECOMMENDED_MODEL, ossFundedModelNames, parseModel, providers, resolveAutoTier, resolveCliModel, resolveDisplayAlias, resolveModelRung, resolveModelSlug, resolveOpenRouterModel, } from "./models.ts";
56
56
  export type ToolPermission = "disabled" | "enabled";
@@ -257,6 +257,14 @@ export interface WriteablePayload {
257
257
  "~pullfrog": true;
258
258
  /** semantic version of the payload to ensure compatibility */
259
259
  version: string;
260
+ /**
261
+ * which kind of work this run is (`pr-created`, `issue-created`, …). the
262
+ * server's own run-type vocabulary, opaque here: the action only forwards it
263
+ * to `run-context`, which resolves the repo's per-trigger model override
264
+ * against it. absent ⇒ the repo default, which is what every run got before
265
+ * overrides existed.
266
+ */
267
+ type?: string | undefined;
260
268
  /** provider/model slug (e.g. "anthropic/claude-opus") */
261
269
  model?: string | undefined;
262
270
  /**