pullfrog 0.1.47 → 0.1.48

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
@@ -101744,6 +101744,36 @@ import { chmodSync as chmodSync2, mkdirSync as mkdirSync4, writeFileSync as writ
101744
101744
  import { join as join5 } from "node:path";
101745
101745
  import { performance as performance5 } from "node:perf_hooks";
101746
101746
 
101747
+ // effort.ts
101748
+ var DEFAULT_EFFORT_POSITION = 0.75;
101749
+ var EFFORT_ALIASES = {
101750
+ low: 0,
101751
+ medium: 0.25,
101752
+ high: 0.5,
101753
+ xhigh: 0.75,
101754
+ max: 1
101755
+ };
101756
+ var DISABLING_RUNGS = ["none", "minimal"];
101757
+ function isEffortPosition(value2) {
101758
+ return Number.isFinite(value2) && value2 >= 0 && value2 <= 1;
101759
+ }
101760
+ function parseEffortPosition(raw2) {
101761
+ const normalized = raw2.trim().toLowerCase();
101762
+ const named = EFFORT_ALIASES[normalized === "med" ? "medium" : normalized];
101763
+ if (named !== void 0) return named;
101764
+ const numeric = Number(normalized);
101765
+ return normalized !== "" && isEffortPosition(numeric) ? numeric : void 0;
101766
+ }
101767
+ function offeredRungs(published) {
101768
+ return published.filter((rung) => !DISABLING_RUNGS.includes(rung));
101769
+ }
101770
+ function resolveRung(params) {
101771
+ const rungs = offeredRungs(params.published);
101772
+ if (rungs.length === 0) return void 0;
101773
+ const clamped = Math.min(1, Math.max(0, params.position));
101774
+ return rungs[Math.floor(clamped * (rungs.length - 1))];
101775
+ }
101776
+
101747
101777
  // models.ts
101748
101778
  function provider(config3) {
101749
101779
  return config3;
@@ -101763,6 +101793,7 @@ var providers = {
101763
101793
  "claude-fable": {
101764
101794
  displayName: "Claude Fable",
101765
101795
  resolve: "anthropic/claude-fable-5",
101796
+ effort: ["low", "medium", "high", "xhigh", "max"],
101766
101797
  // rolling alias: models.dev's OpenRouter mirror lags brand-new pinned
101767
101798
  // versions (claude-fable-5 isn't indexed yet), so track ~…-latest to
101768
101799
  // stay catalog-valid and auto-follow version bumps.
@@ -101772,6 +101803,7 @@ var providers = {
101772
101803
  "claude-opus": {
101773
101804
  displayName: "Claude Opus",
101774
101805
  resolve: "anthropic/claude-opus-5",
101806
+ effort: ["low", "medium", "high", "xhigh", "max"],
101775
101807
  openRouterResolve: "openrouter/anthropic/claude-opus-5",
101776
101808
  preferred: true,
101777
101809
  subagentModel: "claude-sonnet"
@@ -101779,6 +101811,7 @@ var providers = {
101779
101811
  "claude-sonnet": {
101780
101812
  displayName: "Claude Sonnet",
101781
101813
  resolve: "anthropic/claude-sonnet-5",
101814
+ effort: ["low", "medium", "high", "xhigh", "max"],
101782
101815
  openRouterResolve: "openrouter/anthropic/claude-sonnet-5"
101783
101816
  },
101784
101817
  "claude-haiku": {
@@ -101796,6 +101829,7 @@ var providers = {
101796
101829
  gpt: {
101797
101830
  displayName: "GPT Sol",
101798
101831
  resolve: "openai/gpt-5.6-sol",
101832
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101799
101833
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
101800
101834
  preferred: true,
101801
101835
  subagentModel: "gpt-terra"
@@ -101807,6 +101841,7 @@ var providers = {
101807
101841
  displayName: "GPT Sol Pro",
101808
101842
  description: "Maximum reasoning effort",
101809
101843
  resolve: "openai/gpt-5.6-sol",
101844
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101810
101845
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
101811
101846
  subagentModel: "gpt"
101812
101847
  },
@@ -101816,11 +101851,13 @@ var providers = {
101816
101851
  "gpt-terra": {
101817
101852
  displayName: "GPT Terra",
101818
101853
  resolve: "openai/gpt-5.6-terra",
101854
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101819
101855
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
101820
101856
  },
101821
101857
  "gpt-mini": {
101822
101858
  displayName: "GPT Luna",
101823
101859
  resolve: "openai/gpt-5.6-luna",
101860
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101824
101861
  openRouterResolve: "openrouter/openai/gpt-5.6-luna"
101825
101862
  },
101826
101863
  // legacy aliases — openai unified the codex line into the main GPT family
@@ -101850,6 +101887,7 @@ var providers = {
101850
101887
  o3: {
101851
101888
  displayName: "O3",
101852
101889
  resolve: "openai/o3",
101890
+ effort: ["low", "medium", "high"],
101853
101891
  openRouterResolve: "openrouter/openai/o3"
101854
101892
  }
101855
101893
  }
@@ -101861,6 +101899,7 @@ var providers = {
101861
101899
  "gemini-pro": {
101862
101900
  displayName: "Gemini Pro",
101863
101901
  resolve: "google/gemini-3.1-pro-preview",
101902
+ effort: ["low", "medium", "high"],
101864
101903
  openRouterResolve: "openrouter/google/gemini-3.1-pro-preview",
101865
101904
  preferred: true
101866
101905
  // Inherit (subagents stay on Pro). Google has no in-between tier;
@@ -101872,6 +101911,7 @@ var providers = {
101872
101911
  "gemini-flash": {
101873
101912
  displayName: "Gemini Flash",
101874
101913
  resolve: "google/gemini-3.5-flash",
101914
+ effort: ["minimal", "low", "medium", "high"],
101875
101915
  openRouterResolve: "openrouter/google/gemini-3.5-flash"
101876
101916
  }
101877
101917
  }
@@ -101883,6 +101923,7 @@ var providers = {
101883
101923
  grok: {
101884
101924
  displayName: "Grok",
101885
101925
  resolve: "xai/grok-4.3",
101926
+ effort: ["none", "low", "medium", "high"],
101886
101927
  openRouterResolve: "openrouter/x-ai/grok-4.3",
101887
101928
  preferred: true
101888
101929
  },
@@ -101912,12 +101953,16 @@ var providers = {
101912
101953
  "deepseek-pro": {
101913
101954
  displayName: "DeepSeek Pro",
101914
101955
  resolve: "deepseek/deepseek-v4-pro",
101956
+ effort: ["high", "max"],
101957
+ openRouterEffort: ["high", "xhigh"],
101915
101958
  openRouterResolve: "openrouter/deepseek/deepseek-v4-pro",
101916
101959
  preferred: true
101917
101960
  },
101918
101961
  "deepseek-flash": {
101919
101962
  displayName: "DeepSeek Flash",
101920
101963
  resolve: "deepseek/deepseek-v4-flash",
101964
+ effort: ["high", "max"],
101965
+ openRouterEffort: ["high", "xhigh"],
101921
101966
  openRouterResolve: "openrouter/deepseek/deepseek-v4-flash"
101922
101967
  },
101923
101968
  // legacy aliases — deepseek retires these on 2026-07-24; transparently
@@ -101946,6 +101991,7 @@ var providers = {
101946
101991
  "kimi-k3": {
101947
101992
  displayName: "Kimi K3",
101948
101993
  resolve: "moonshotai/kimi-k3",
101994
+ effort: ["low", "high", "max"],
101949
101995
  openRouterResolve: "openrouter/moonshotai/kimi-k3",
101950
101996
  preferred: true,
101951
101997
  subagentModel: "kimi-k2"
@@ -101958,7 +102004,7 @@ var providers = {
101958
102004
  }
101959
102005
  }),
101960
102006
  opencode: provider({
101961
- displayName: "OpenCode",
102007
+ displayName: "OpenCode Zen",
101962
102008
  envVars: ["OPENCODE_API_KEY"],
101963
102009
  models: {
101964
102010
  "big-pickle": {
@@ -101971,12 +102017,14 @@ var providers = {
101971
102017
  "claude-opus": {
101972
102018
  displayName: "Claude Opus",
101973
102019
  resolve: "opencode/claude-opus-5",
102020
+ effort: ["low", "medium", "high", "xhigh", "max"],
101974
102021
  openRouterResolve: "openrouter/anthropic/claude-opus-5",
101975
102022
  subagentModel: "claude-sonnet"
101976
102023
  },
101977
102024
  "claude-sonnet": {
101978
102025
  displayName: "Claude Sonnet",
101979
102026
  resolve: "opencode/claude-sonnet-5",
102027
+ effort: ["low", "medium", "high", "xhigh", "max"],
101980
102028
  openRouterResolve: "openrouter/anthropic/claude-sonnet-5"
101981
102029
  },
101982
102030
  "claude-haiku": {
@@ -101987,6 +102035,7 @@ var providers = {
101987
102035
  gpt: {
101988
102036
  displayName: "GPT Sol",
101989
102037
  resolve: "opencode/gpt-5.6-sol",
102038
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101990
102039
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
101991
102040
  subagentModel: "gpt-terra"
101992
102041
  },
@@ -101995,6 +102044,7 @@ var providers = {
101995
102044
  displayName: "GPT Sol Pro",
101996
102045
  description: "Maximum reasoning effort",
101997
102046
  resolve: "opencode/gpt-5.6-sol",
102047
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101998
102048
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
101999
102049
  subagentModel: "gpt"
102000
102050
  },
@@ -102002,11 +102052,13 @@ var providers = {
102002
102052
  "gpt-terra": {
102003
102053
  displayName: "GPT Terra",
102004
102054
  resolve: "opencode/gpt-5.6-terra",
102055
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102005
102056
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
102006
102057
  },
102007
102058
  "gpt-mini": {
102008
102059
  displayName: "GPT Luna",
102009
102060
  resolve: "opencode/gpt-5.6-luna",
102061
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102010
102062
  openRouterResolve: "openrouter/openai/gpt-5.6-luna"
102011
102063
  },
102012
102064
  // legacy aliases — see openai provider above for context.
@@ -102032,12 +102084,14 @@ var providers = {
102032
102084
  "gemini-pro": {
102033
102085
  displayName: "Gemini Pro",
102034
102086
  resolve: "opencode/gemini-3.1-pro",
102087
+ effort: ["low", "medium", "high"],
102035
102088
  openRouterResolve: "openrouter/google/gemini-3.1-pro-preview"
102036
102089
  // Inherit — see google/gemini-pro for rationale.
102037
102090
  },
102038
102091
  "gemini-flash": {
102039
102092
  displayName: "Gemini Flash",
102040
102093
  resolve: "opencode/gemini-3.5-flash",
102094
+ effort: ["minimal", "low", "medium", "high"],
102041
102095
  openRouterResolve: "openrouter/google/gemini-3.5-flash"
102042
102096
  },
102043
102097
  "kimi-k2": {
@@ -102056,6 +102110,7 @@ var providers = {
102056
102110
  "gpt-5-nano": {
102057
102111
  displayName: "GPT Nano",
102058
102112
  resolve: "opencode/gpt-5-nano",
102113
+ effort: ["minimal", "low", "medium", "high"],
102059
102114
  openRouterResolve: "openrouter/openai/gpt-5-nano"
102060
102115
  },
102061
102116
  "mimo-v2-pro-free": {
@@ -102082,6 +102137,8 @@ var providers = {
102082
102137
  "glm-5.1": {
102083
102138
  displayName: "GLM 5.2",
102084
102139
  resolve: "opencode-go/glm-5.2",
102140
+ effort: ["high", "max"],
102141
+ openRouterEffort: ["high", "xhigh"],
102085
102142
  openRouterResolve: "openrouter/z-ai/glm-5.2",
102086
102143
  preferred: true
102087
102144
  },
@@ -102135,6 +102192,10 @@ var providers = {
102135
102192
  // bring-your-own generic OpenAI-compatible endpoint — Cloudflare AI Gateway,
102136
102193
  // Alibaba DashScope, self-hosted vLLM, or any compatible gateway. base URL +
102137
102194
  // key + model ID are all supplied via env; nothing is cataloged or bumped.
102195
+ // the two token limits are deliberately absent: this list is the auth
102196
+ // heuristic (`hasPullfrogStoredAuthForModel`, `validateAgentApiKey`), and a
102197
+ // stored context number is config, not proof of a key. the console picks
102198
+ // them up from `PROVIDER_EXTRA_SECRET_NAMES` instead.
102138
102199
  envVars: ["OPENAI_COMPATIBLE_BASE_URL", "OPENAI_COMPATIBLE_API_KEY", "OPENAI_COMPATIBLE_MODEL"],
102139
102200
  models: {
102140
102201
  // single routing entry — the actual model ID is read from
@@ -102154,6 +102215,7 @@ var providers = {
102154
102215
  "claude-opus": {
102155
102216
  displayName: "Claude Opus",
102156
102217
  resolve: "openrouter/~anthropic/claude-opus-latest",
102218
+ effort: ["low", "medium", "high", "xhigh", "max"],
102157
102219
  openRouterResolve: "openrouter/~anthropic/claude-opus-latest",
102158
102220
  preferred: true,
102159
102221
  subagentModel: "claude-sonnet"
@@ -102161,6 +102223,7 @@ var providers = {
102161
102223
  "claude-sonnet": {
102162
102224
  displayName: "Claude Sonnet",
102163
102225
  resolve: "openrouter/~anthropic/claude-sonnet-latest",
102226
+ effort: ["low", "medium", "high", "xhigh", "max"],
102164
102227
  openRouterResolve: "openrouter/~anthropic/claude-sonnet-latest"
102165
102228
  },
102166
102229
  "claude-haiku": {
@@ -102175,6 +102238,7 @@ var providers = {
102175
102238
  gpt: {
102176
102239
  displayName: "GPT Sol",
102177
102240
  resolve: "openrouter/openai/gpt-5.6-sol",
102241
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102178
102242
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
102179
102243
  subagentModel: "gpt-terra"
102180
102244
  },
@@ -102183,6 +102247,7 @@ var providers = {
102183
102247
  displayName: "GPT Sol Pro",
102184
102248
  description: "Maximum reasoning effort",
102185
102249
  resolve: "openrouter/openai/gpt-5.6-sol-pro",
102250
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102186
102251
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
102187
102252
  subagentModel: "gpt"
102188
102253
  },
@@ -102190,11 +102255,13 @@ var providers = {
102190
102255
  "gpt-terra": {
102191
102256
  displayName: "GPT Terra",
102192
102257
  resolve: "openrouter/openai/gpt-5.6-terra",
102258
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102193
102259
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
102194
102260
  },
102195
102261
  "gpt-mini": {
102196
102262
  displayName: "GPT Luna",
102197
102263
  resolve: "openrouter/openai/gpt-5.6-luna",
102264
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102198
102265
  openRouterResolve: "openrouter/openai/gpt-5.6-luna"
102199
102266
  },
102200
102267
  // legacy aliases — see openai provider for context.
@@ -102220,32 +102287,38 @@ var providers = {
102220
102287
  "o4-mini": {
102221
102288
  displayName: "O4 Mini",
102222
102289
  resolve: "openrouter/openai/o4-mini",
102290
+ effort: ["low", "medium", "high"],
102223
102291
  openRouterResolve: "openrouter/openai/o4-mini"
102224
102292
  },
102225
102293
  "gemini-pro": {
102226
102294
  displayName: "Gemini Pro",
102227
102295
  resolve: "openrouter/~google/gemini-pro-latest",
102296
+ effort: ["low", "medium", "high"],
102228
102297
  openRouterResolve: "openrouter/~google/gemini-pro-latest"
102229
102298
  // Inherit — see google/gemini-pro for rationale.
102230
102299
  },
102231
102300
  "gemini-flash": {
102232
102301
  displayName: "Gemini Flash",
102233
102302
  resolve: "openrouter/~google/gemini-flash-latest",
102303
+ effort: ["minimal", "low", "medium", "high"],
102234
102304
  openRouterResolve: "openrouter/~google/gemini-flash-latest"
102235
102305
  },
102236
102306
  grok: {
102237
102307
  displayName: "Grok",
102238
102308
  resolve: "openrouter/x-ai/grok-4.3",
102309
+ effort: ["none", "low", "medium", "high"],
102239
102310
  openRouterResolve: "openrouter/x-ai/grok-4.3"
102240
102311
  },
102241
102312
  "deepseek-pro": {
102242
102313
  displayName: "DeepSeek Pro",
102243
102314
  resolve: "openrouter/deepseek/deepseek-v4-pro",
102315
+ effort: ["high", "xhigh"],
102244
102316
  openRouterResolve: "openrouter/deepseek/deepseek-v4-pro"
102245
102317
  },
102246
102318
  "deepseek-flash": {
102247
102319
  displayName: "DeepSeek Flash",
102248
102320
  resolve: "openrouter/deepseek/deepseek-v4-flash",
102321
+ effort: ["high", "xhigh"],
102249
102322
  openRouterResolve: "openrouter/deepseek/deepseek-v4-flash"
102250
102323
  },
102251
102324
  // legacy alias — deepseek retires this on 2026-07-24; transparently
@@ -102264,6 +102337,7 @@ var providers = {
102264
102337
  "kimi-k3": {
102265
102338
  displayName: "Kimi K3",
102266
102339
  resolve: "openrouter/moonshotai/kimi-k3",
102340
+ effort: ["low", "high", "max"],
102267
102341
  openRouterResolve: "openrouter/moonshotai/kimi-k3"
102268
102342
  },
102269
102343
  // slug pins the m2 line for DB stability; resolve tracks the current m2.7.
@@ -102318,6 +102392,8 @@ var modelAliases = Object.entries(providers).flatMap(
102318
102392
  // here to a fully-qualified slug so callers can look up the target alias
102319
102393
  // directly without re-deriving the provider.
102320
102394
  subagentModel: def.subagentModel ? `${providerKey}/${def.subagentModel}` : void 0,
102395
+ effort: def.effort,
102396
+ openRouterEffort: def.openRouterEffort,
102321
102397
  hidden: def.hidden ?? false
102322
102398
  }))
102323
102399
  );
@@ -102356,6 +102432,17 @@ function resolveCliModel(slug2) {
102356
102432
  function resolveOpenRouterModel(slug2) {
102357
102433
  return resolveDisplayAlias(slug2)?.openRouterResolve;
102358
102434
  }
102435
+ function getModelEffortLevels(params) {
102436
+ const alias = resolveDisplayAlias(params.slug);
102437
+ if (!alias) return void 0;
102438
+ if (params.useOpenRouter) return alias.openRouterEffort ?? alias.effort;
102439
+ return alias.effort;
102440
+ }
102441
+ function resolveModelRung(params) {
102442
+ const published = getModelEffortLevels(params);
102443
+ if (!published) return void 0;
102444
+ return resolveRung({ position: params.position, published });
102445
+ }
102359
102446
  var defaultProxyAlias = resolveDisplayAlias(AUTO_EFFICIENT);
102360
102447
  if (!defaultProxyAlias?.openRouterResolve) {
102361
102448
  throw new Error(`DEFAULT_PROXY_MODEL: ${AUTO_EFFICIENT} has no openRouterResolve`);
@@ -103043,6 +103130,40 @@ function extractProviderId(text) {
103043
103130
  return match3 ? match3[1].toLowerCase() : null;
103044
103131
  }
103045
103132
 
103133
+ // utils/runEffort.ts
103134
+ function matchHostedAnthropicAlias(modelId) {
103135
+ const id = modelId.toLowerCase();
103136
+ if (id.startsWith("arn:")) return void 0;
103137
+ return modelAliases.find(
103138
+ (a) => !a.fallback && a.provider === "anthropic" && id.includes(a.resolve.replace(/^anthropic\//, ""))
103139
+ );
103140
+ }
103141
+ function resolveRunAlias(ctx) {
103142
+ const proxyModel = ctx.payload.proxyModel;
103143
+ if (proxyModel) {
103144
+ return modelAliases.find((a) => !a.fallback && a.openRouterResolve === proxyModel);
103145
+ }
103146
+ const model = ctx.resolvedModel;
103147
+ if (!model) return void 0;
103148
+ return modelAliases.find((a) => !a.fallback && a.resolve === model) ?? matchHostedAnthropicAlias(model);
103149
+ }
103150
+ function resolveRunEffort(ctx) {
103151
+ const configured = ctx.payload.effort !== void 0;
103152
+ const position = ctx.payload.effort ?? DEFAULT_EFFORT_POSITION;
103153
+ const alias = resolveRunAlias(ctx);
103154
+ if (!alias) return { position, configured, rung: void 0, alias: void 0 };
103155
+ return {
103156
+ position,
103157
+ configured,
103158
+ rung: resolveModelRung({
103159
+ slug: alias.slug,
103160
+ position,
103161
+ useOpenRouter: !!ctx.payload.proxyModel
103162
+ }),
103163
+ alias
103164
+ };
103165
+ }
103166
+
103046
103167
  // utils/skills.ts
103047
103168
  import { spawnSync as spawnSync2 } from "node:child_process";
103048
103169
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
@@ -103056,7 +103177,7 @@ var import_semver = __toESM(require_semver2(), 1);
103056
103177
  // package.json
103057
103178
  var package_default = {
103058
103179
  name: "pullfrog",
103059
- version: "0.1.47",
103180
+ version: "0.1.48",
103060
103181
  type: "module",
103061
103182
  bin: {
103062
103183
  pullfrog: "dist/cli.mjs",
@@ -104616,8 +104737,18 @@ function stripProviderPrefix(specifier) {
104616
104737
  const slashIndex = specifier.indexOf("/");
104617
104738
  return slashIndex > 0 ? specifier.slice(slashIndex + 1) : specifier;
104618
104739
  }
104619
- function resolveEffort(_model) {
104620
- return "high";
104740
+ var CLAUDE_EFFORT_ENV = "CLAUDE_CODE_EFFORT_LEVEL";
104741
+ var CLAUDE_CODE_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
104742
+ function effortCapabilities(levels) {
104743
+ const topRungs = levels.filter((l) => l === "xhigh" || l === "max").map((l) => `${l}_effort`);
104744
+ return ["effort", ...topRungs, "adaptive_thinking", "thinking"].join(",");
104745
+ }
104746
+ function applyHostedEffortCapabilities(params) {
104747
+ params.env.ANTHROPIC_MODEL ||= params.modelId;
104748
+ params.env.ANTHROPIC_CUSTOM_MODEL_OPTION ||= params.modelId;
104749
+ params.env.ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES ||= effortCapabilities(
104750
+ params.levels
104751
+ );
104621
104752
  }
104622
104753
  function tailLines2(text, maxCodeUnits) {
104623
104754
  if (text.length <= maxCodeUnits) return text;
@@ -105093,7 +105224,7 @@ var claude = agent({
105093
105224
  });
105094
105225
  installBundledSkills({ home: homeEnv.HOME });
105095
105226
  const mcpConfigPath = writeMcpConfig(ctx);
105096
- const effort = resolveEffort(model);
105227
+ const effort = resolveRunEffort(ctx);
105097
105228
  const pretoolGate = writePretoolGateAssets(ctx);
105098
105229
  const stopHookPath = join5(ctx.tmpdir, "pullfrog-stop-hook.sh");
105099
105230
  writeFileSync4(stopHookPath, buildStopHookScript(), { mode: 493 });
@@ -105107,13 +105238,16 @@ var claude = agent({
105107
105238
  "--settings",
105108
105239
  pretoolGate.settingsPath,
105109
105240
  "--verbose",
105110
- "--effort",
105111
- effort,
105112
105241
  "--disallowedTools",
105113
105242
  CLAUDE_DISALLOWED_TOOLS,
105114
105243
  "--agents",
105115
105244
  buildAgentsJson()
105116
105245
  ];
105246
+ if (effort.rung && !CLAUDE_CODE_EFFORTS.includes(effort.rung)) {
105247
+ log.warning(`\xBB effort ${effort.rung} not sent \u2014 claude-code doesn't accept that level`);
105248
+ } else if (effort.rung) {
105249
+ baseArgs.push("--effort", effort.rung);
105250
+ }
105117
105251
  if (model) {
105118
105252
  baseArgs.push("--model", model);
105119
105253
  }
@@ -105131,6 +105265,9 @@ var claude = agent({
105131
105265
  applyClaudeVertexEnv(env2);
105132
105266
  env2.ANTHROPIC_MODEL = specifier;
105133
105267
  }
105268
+ if ((isBedrockRoute || isVertexRoute2) && specifier && effort.alias?.effort) {
105269
+ applyHostedEffortCapabilities({ env: env2, modelId: specifier, levels: effort.alias.effort });
105270
+ }
105134
105271
  if (env2.CLAUDE_CODE_OAUTH_TOKEN && !isBedrockRoute && env2.ANTHROPIC_API_KEY) {
105135
105272
  const preflight = await preflightClaudeSubscription({
105136
105273
  token: env2.CLAUDE_CODE_OAUTH_TOKEN,
@@ -105148,7 +105285,12 @@ var claude = agent({
105148
105285
  delete env2.CLAUDE_CODE_OAUTH_TOKEN;
105149
105286
  }
105150
105287
  }
105151
- log.info(`\xBB effort: ${effort}`);
105288
+ const effortEnvOverride = env2[CLAUDE_EFFORT_ENV]?.trim();
105289
+ if (effortEnvOverride) {
105290
+ log.warning(
105291
+ `\xBB ${CLAUDE_EFFORT_ENV}=${effortEnvOverride} in the run env overrides the effort setting for this session`
105292
+ );
105293
+ }
105152
105294
  log.debug(`\xBB starting Pullfrog (Claude Code): ${cliPath} ${baseArgs.join(" ")}`);
105153
105295
  log.debug(`\xBB working directory: ${repoDir}`);
105154
105296
  const gateServer = __using(_stack, await startGateServer(ctx), true);
@@ -105172,7 +105314,7 @@ var claude = agent({
105172
105314
  }
105173
105315
  });
105174
105316
 
105175
- // agents/opencode_v2.ts
105317
+ // agents/opencode.ts
105176
105318
  var core2 = __toESM(require_core(), 1);
105177
105319
  import { spawn as nodeSpawn2 } from "node:child_process";
105178
105320
  import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "node:fs";
@@ -110582,7 +110724,7 @@ function createOpencodeClient(config3) {
110582
110724
  // node_modules/.pnpm/@opencode-ai+sdk@1.18.5/node_modules/@opencode-ai/sdk/dist/v2/server.js
110583
110725
  var import_cross_spawn = __toESM(require_cross_spawn(), 1);
110584
110726
 
110585
- // agents/opencode_v2.ts
110727
+ // agents/opencode.ts
110586
110728
  var import_undici = __toESM(require_undici2(), 1);
110587
110729
 
110588
110730
  // utils/codexHome.ts
@@ -110855,14 +110997,6 @@ function deriveSubagentModels(orchestratorSpec) {
110855
110997
  }
110856
110998
 
110857
110999
  // agents/opencodeShared.ts
110858
- function geminiHighThinkingOverrides() {
110859
- return Object.fromEntries(
110860
- modelAliases.filter((a) => a.provider === "google").map((a) => [
110861
- a.resolve.replace(/^google\//, ""),
110862
- { options: { thinkingConfig: { thinkingLevel: "high" } } }
110863
- ])
110864
- );
110865
- }
110866
111000
  function openAICompatibleLimit() {
110867
111001
  return {
110868
111002
  context: Number(process.env[OPENAI_COMPATIBLE_CONTEXT_ENV]),
@@ -110895,10 +111029,6 @@ function kimiOpenRouterProviderOverrides() {
110895
111029
  ])
110896
111030
  );
110897
111031
  }
110898
- function deepseekHighEffortOverrides() {
110899
- const orModel = modelAliases.find((a) => a.slug === "deepseek/deepseek-pro")?.openRouterResolve?.replace(/^openrouter\//, "");
110900
- return orModel ? { [orModel]: { options: { reasoning: { effort: "high" } } } } : {};
110901
- }
110902
111032
  function buildReviewerAgentConfig(orchestratorModel) {
110903
111033
  const overrides = deriveSubagentModels(orchestratorModel);
110904
111034
  return {
@@ -110940,7 +111070,7 @@ function autoSelectModel() {
110940
111070
  return void 0;
110941
111071
  }
110942
111072
 
110943
- // agents/opencode_v2.ts
111073
+ // agents/opencode.ts
110944
111074
  var installCli = () => installOpencodeCli({ binPath: "bin/opencode.exe" });
110945
111075
  function buildSecurityConfig(ctx, model) {
110946
111076
  const config3 = {
@@ -110967,17 +111097,13 @@ function buildSecurityConfig(ctx, model) {
110967
111097
  log.info(`\xBB subagent models: reviewfrog=${reviewerModel}`);
110968
111098
  return cfg;
110969
111099
  })(),
110970
- // gemini-3 thinking pinned to high for review depth; deepseek (funded
110971
- // efficient tier) pinned to high reasoning effort, and kimi pinned away
110972
- // from Enforcer-less openrouter providers (siliconflow / together) that
110973
- // drop optional tool-call params both per-model on the openrouter route,
110974
- // so other models are unaffected. gpt/anthropic effort set elsewhere (gpt:
110975
- // upstream default, anthropic: --effort flag in claude.ts). see opencodeShared.ts.
111100
+ // kimi pinned away from Enforcer-less openrouter providers (siliconflow /
111101
+ // together) that drop optional tool-call params per-model on the
111102
+ // openrouter route, so other models are unaffected. this is routing, not
111103
+ // reasoning: every model's effort now rides the per-prompt `variant`.
111104
+ // see opencodeShared.ts.
110976
111105
  provider: {
110977
- google: { models: geminiHighThinkingOverrides() },
110978
- openrouter: {
110979
- models: { ...deepseekHighEffortOverrides(), ...kimiOpenRouterProviderOverrides() }
110980
- },
111106
+ openrouter: { models: kimiOpenRouterProviderOverrides() },
110981
111107
  ...openAICompatibleProvider(model)
110982
111108
  }
110983
111109
  };
@@ -111288,6 +111414,7 @@ async function runPromptTurn(ctx, params) {
111288
111414
  {
111289
111415
  sessionID: ctx.sessionID,
111290
111416
  parts: [part],
111417
+ ...ctx.variant ? { variant: ctx.variant } : {},
111291
111418
  ...params.model ? { model: params.model } : {}
111292
111419
  },
111293
111420
  // wire the inner activity watchdog's abort signal into the SDK request
@@ -111477,6 +111604,10 @@ var opencode = agent({
111477
111604
  const cliPath = await installCli();
111478
111605
  const rawModel = ctx.payload.proxyModel ?? ctx.resolvedModel ?? autoSelectModel();
111479
111606
  if (rawModel) ctx.toolState.model = rawModel;
111607
+ const effort = resolveRunEffort({ ...ctx, resolvedModel: rawModel });
111608
+ if (!ctx.resolvedModel && !ctx.payload.proxyModel) {
111609
+ log.info(`\xBB effort: ${effort.rung ?? "n/a (model has no effort control)"}`);
111610
+ }
111480
111611
  const bedrockModelId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
111481
111612
  const isBedrockRoute = rawModel !== void 0 && bedrockModelId !== void 0 && bedrockModelId === rawModel;
111482
111613
  const vertexModel = resolveVertexOpenCodeModel(rawModel);
@@ -111569,6 +111700,8 @@ var opencode = agent({
111569
111700
  orchestratorSessionID: sessionID,
111570
111701
  labeler,
111571
111702
  toolState: ctx.toolState,
111703
+ // `rawModel` folds in the auto-select pick — see the opencode.ts twin.
111704
+ variant: effort.rung,
111572
111705
  todoTracker: ctx.todoTracker,
111573
111706
  onActivityTimeout: ctx.onActivityTimeout,
111574
111707
  onToolUse: ctx.onToolUse,
@@ -159954,6 +160087,7 @@ var JsonPayload = type({
159954
160087
  version: "string",
159955
160088
  "model?": "string | undefined",
159956
160089
  "modelExplicit?": "boolean | undefined",
160090
+ "effort?": "number | string | undefined",
159957
160091
  prompt: "string",
159958
160092
  "triggerer?": "string | undefined",
159959
160093
  "baseInstructions?": "string | undefined",
@@ -159987,6 +160121,7 @@ var Inputs = type({
159987
160121
  "prompt?": type.string.or("undefined"),
159988
160122
  "prompt_file?": type.string.or("undefined"),
159989
160123
  "model?": type.string.or("undefined"),
160124
+ "effort?": type.string.or("undefined"),
159990
160125
  "timeout?": type.string.or("undefined"),
159991
160126
  "push?": PushPermissionInput.or("undefined"),
159992
160127
  "shell?": ShellPermissionInput.or("undefined"),
@@ -160041,6 +160176,7 @@ function resolvePromptFile(input) {
160041
160176
  function resolveNonPromptInputs() {
160042
160177
  return Inputs.omit("prompt", "prompt_file").assert({
160043
160178
  model: core4.getInput("model") || void 0,
160179
+ effort: core4.getInput("effort") || void 0,
160044
160180
  timeout: core4.getInput("timeout") || void 0,
160045
160181
  cwd: core4.getInput("cwd") || void 0,
160046
160182
  push: core4.getInput("push") || void 0,
@@ -160059,6 +160195,8 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
160059
160195
  const rawEvent = jsonPayload?.event;
160060
160196
  const event = isPayloadEvent(rawEvent) ? rawEvent : { trigger: "unknown" };
160061
160197
  const model = jsonPayload?.model ?? inputs.model ?? repoSettings.model ?? void 0;
160198
+ const rawEffort = jsonPayload?.effort ?? inputs.effort ?? repoSettings.effort ?? void 0;
160199
+ const effort = rawEffort === void 0 ? void 0 : parseEffortPosition(String(rawEffort));
160062
160200
  const isNonCollaborator = !isCollaborator(event);
160063
160201
  const repoShell = repoSettings.shell ?? "restricted";
160064
160202
  const inputShell = inputs.shell;
@@ -160078,6 +160216,7 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
160078
160216
  // explicit only when the model came from a per-run override flag (carried on
160079
160217
  // the JSON payload). a GHA `model` input or the repo default is not explicit.
160080
160218
  modelExplicit: jsonPayload?.modelExplicit ?? false,
160219
+ effort,
160081
160220
  prompt,
160082
160221
  triggerer: jsonPayload?.triggerer ?? // it's not a common use case but GITHUB_ACTOR can be a user when the workflow is manually triggered by a user through GitHub Actions UI
160083
160222
  (!isPullfrog(process.env.GITHUB_ACTOR) ? process.env.GITHUB_ACTOR : void 0),
@@ -165543,6 +165682,140 @@ function formatApiKeyErrorSummary(params) {
165543
165682
  ].join("\n");
165544
165683
  }
165545
165684
 
165685
+ // utils/billingErrors.ts
165686
+ var BillingError = class extends Error {
165687
+ code;
165688
+ declineCode;
165689
+ needsReauthentication;
165690
+ constructor(message, opts = {}) {
165691
+ super(message);
165692
+ this.name = "BillingError";
165693
+ this.code = opts.code ?? null;
165694
+ this.declineCode = opts.declineCode ?? null;
165695
+ this.needsReauthentication = opts.needsReauthentication ?? false;
165696
+ }
165697
+ };
165698
+ var TransientError = class extends Error {
165699
+ constructor(message) {
165700
+ super(message);
165701
+ this.name = "TransientError";
165702
+ }
165703
+ };
165704
+ function billingConsoleUrl(owner) {
165705
+ return `https://pullfrog.com/console/${encodeURIComponent(owner)}#billing`;
165706
+ }
165707
+ function commercialPaywallBody(params) {
165708
+ if (params.reason === "commercial") {
165709
+ return [
165710
+ `**Pullfrog needs a confirmed Pro plan for ${params.ownerLogin}, so this run paused.**`,
165711
+ "",
165712
+ "Open Plan and payment to confirm Pro or review the organization's billing status.",
165713
+ "",
165714
+ `[Review plan and payment \u2192](${params.url})`
165715
+ ].join("\n");
165716
+ }
165717
+ params.reason;
165718
+ return [
165719
+ `**Pullfrog paused runs on ${params.ownerLogin}: the Pro renewal failed.**`,
165720
+ "",
165721
+ "Update the card on file to resume runs.",
165722
+ "",
165723
+ `[Update billing \u2192](${params.url})`
165724
+ ].join("\n");
165725
+ }
165726
+ function formatCommercialGateSummary(params) {
165727
+ return commercialPaywallBody({
165728
+ reason: params.reason,
165729
+ ownerLogin: params.ownerLogin,
165730
+ url: billingConsoleUrl(params.ownerLogin)
165731
+ });
165732
+ }
165733
+ function formatBillingErrorSummary(error49, owner) {
165734
+ if (error49.code === "router_requires_card") {
165735
+ return [
165736
+ "**Your Pullfrog Router balance is empty.**",
165737
+ "",
165738
+ "Add a card to top up your Router balance, or bring your own key. Router usage is billed at provider cost with no platform markup.",
165739
+ "",
165740
+ `[Add a card to top up \u2192](${billingConsoleUrl(owner)}) \xB7 [Bring your own key \u2192](${billingConsoleUrl(owner)})`
165741
+ ].join("\n");
165742
+ }
165743
+ if (error49.code === "router_balance_exhausted") {
165744
+ return [
165745
+ "**Your Pullfrog Router balance is exhausted.**",
165746
+ "",
165747
+ "You have a payment method on file but auto-reload is disabled, so runs paused once your balance went past the overdraft buffer.",
165748
+ "",
165749
+ `[Top up balance \u2192](${billingConsoleUrl(owner)}) \xB7 [Enable auto-reload \u2192](${billingConsoleUrl(owner)})`
165750
+ ].join("\n");
165751
+ }
165752
+ if (error49.code === "router_keylimit_exhausted") {
165753
+ return [
165754
+ "**This run was cut short: your Pullfrog Router balance ran out mid-run.**",
165755
+ "",
165756
+ "OpenRouter stopped the agent because the per-run budget was exhausted. Your wallet is now negative; top up or enable auto-reload to keep runs flowing.",
165757
+ "",
165758
+ `[Top up balance \u2192](${billingConsoleUrl(owner)}) \xB7 [Enable auto-reload \u2192](${billingConsoleUrl(owner)})`
165759
+ ].join("\n");
165760
+ }
165761
+ if (error49.code === "router_monthly_limit") {
165762
+ return [
165763
+ "**Pullfrog Router hit its monthly spend limit.**",
165764
+ "",
165765
+ "Auto-reloads are paused for the rest of this UTC month. Ask your admin to raise the cap, or wait for it to reset at 00:00 UTC on the 1st.",
165766
+ "",
165767
+ `[Adjust limit \u2192](${billingConsoleUrl(owner)})`
165768
+ ].join("\n");
165769
+ }
165770
+ if (error49.code === "commercial_plan_required") {
165771
+ return formatCommercialGateSummary({
165772
+ reason: "commercial",
165773
+ ownerLogin: owner
165774
+ });
165775
+ }
165776
+ if (error49.code === "subscription_unpaid") {
165777
+ return formatCommercialGateSummary({
165778
+ reason: "subscription_unpaid",
165779
+ ownerLogin: owner
165780
+ });
165781
+ }
165782
+ if (error49.needsReauthentication) {
165783
+ const code = error49.declineCode ?? "authentication_required";
165784
+ return [
165785
+ `**Your card issuer requires 3D Secure on every charge** (\`${code}\`).`,
165786
+ "",
165787
+ "Pullfrog can't complete a 3DS challenge from inside a workflow. Top up your Router balance once in Stripe Checkout, subsequent runs draw from the prepaid balance without re-triggering 3DS.",
165788
+ "",
165789
+ `[Top up balance \u2192](${billingConsoleUrl(owner)})`
165790
+ ].join("\n");
165791
+ }
165792
+ if (error49.declineCode) {
165793
+ return [
165794
+ `**Your card was declined** (\`${error49.declineCode}\`).`,
165795
+ "",
165796
+ "Update your payment method and Pullfrog will retry on the next run.",
165797
+ "",
165798
+ `[Update payment method \u2192](${billingConsoleUrl(owner)})`
165799
+ ].join("\n");
165800
+ }
165801
+ return [
165802
+ "**Your Pullfrog balance is empty.**",
165803
+ "",
165804
+ "Top up your balance or enable auto-reload to keep runs flowing.",
165805
+ "",
165806
+ `[Manage billing \u2192](${billingConsoleUrl(owner)})`
165807
+ ].join("\n");
165808
+ }
165809
+ function formatTransientErrorSummary(error49, owner) {
165810
+ return [
165811
+ "**Pullfrog billing is temporarily unavailable.**",
165812
+ "",
165813
+ error49.message,
165814
+ "",
165815
+ `Usually transient; the next dispatch should succeed. If it persists, check [status.pullfrog.com](https://status.pullfrog.com) or [your console](${billingConsoleUrl(owner)}).`
165816
+ ].join("\n");
165817
+ }
165818
+
165546
165819
  // utils/gitAuthServer.ts
165547
165820
  import { randomUUID as randomUUID5 } from "node:crypto";
165548
165821
  import { writeFileSync as writeFileSync14 } from "node:fs";
@@ -166343,102 +166616,6 @@ function applyOverrides(params) {
166343
166616
  // utils/proxy.ts
166344
166617
  var core8 = __toESM(require_core(), 1);
166345
166618
 
166346
- // utils/billingErrors.ts
166347
- var BillingError = class extends Error {
166348
- code;
166349
- declineCode;
166350
- needsReauthentication;
166351
- constructor(message, opts = {}) {
166352
- super(message);
166353
- this.name = "BillingError";
166354
- this.code = opts.code ?? null;
166355
- this.declineCode = opts.declineCode ?? null;
166356
- this.needsReauthentication = opts.needsReauthentication ?? false;
166357
- }
166358
- };
166359
- var TransientError = class extends Error {
166360
- constructor(message) {
166361
- super(message);
166362
- this.name = "TransientError";
166363
- }
166364
- };
166365
- function billingConsoleUrl(owner, anchor) {
166366
- return `https://pullfrog.com/console/${encodeURIComponent(owner)}#${anchor}`;
166367
- }
166368
- function formatBillingErrorSummary(error49, owner) {
166369
- if (error49.code === "router_requires_card") {
166370
- return [
166371
- "**Add a card to start using Pullfrog Router.**",
166372
- "",
166373
- "Router proxies OpenRouter at raw cost \u2014 no platform markup. Add a card and we'll auto-reload your wallet so runs keep flowing.",
166374
- "",
166375
- `[Add a card \u2192](${billingConsoleUrl(owner, "model-access")})`
166376
- ].join("\n");
166377
- }
166378
- if (error49.code === "router_balance_exhausted") {
166379
- return [
166380
- "**Your Pullfrog Router balance is exhausted.**",
166381
- "",
166382
- "You have a payment method on file but auto-reload is disabled, so runs paused once your balance went past the overdraft buffer.",
166383
- "",
166384
- `[Top up balance \u2192](${billingConsoleUrl(owner, "billing")}) \xB7 [Enable auto-reload \u2192](${billingConsoleUrl(owner, "model-access")})`
166385
- ].join("\n");
166386
- }
166387
- if (error49.code === "router_keylimit_exhausted") {
166388
- return [
166389
- "**This run was cut short \u2014 your Pullfrog Router balance ran out mid-run.**",
166390
- "",
166391
- "OpenRouter stopped the agent because the per-run budget was exhausted. Your wallet is now negative; top up or enable auto-reload to keep runs flowing.",
166392
- "",
166393
- `[Top up balance \u2192](${billingConsoleUrl(owner, "billing")}) \xB7 [Enable auto-reload \u2192](${billingConsoleUrl(owner, "model-access")})`
166394
- ].join("\n");
166395
- }
166396
- if (error49.code === "router_monthly_limit") {
166397
- return [
166398
- "**Pullfrog Router hit its monthly spend limit.**",
166399
- "",
166400
- "Auto-reloads are paused for the rest of this UTC month. Ask your admin to raise the cap, or wait for it to reset at 00:00 UTC on the 1st.",
166401
- "",
166402
- `[Adjust limit \u2192](${billingConsoleUrl(owner, "model-access")})`
166403
- ].join("\n");
166404
- }
166405
- if (error49.needsReauthentication) {
166406
- const code = error49.declineCode ?? "authentication_required";
166407
- return [
166408
- `**Your card issuer requires 3D Secure on every charge** (\`${code}\`).`,
166409
- "",
166410
- "Pullfrog can't complete a 3DS challenge from inside a workflow. Top up your Router balance once in Stripe Checkout \u2014 subsequent runs draw from the prepaid balance without re-triggering 3DS.",
166411
- "",
166412
- `[Top up balance \u2192](${billingConsoleUrl(owner, "billing")})`
166413
- ].join("\n");
166414
- }
166415
- if (error49.declineCode) {
166416
- return [
166417
- `**Your card was declined** (\`${error49.declineCode}\`).`,
166418
- "",
166419
- "Update your payment method and Pullfrog will retry on the next run.",
166420
- "",
166421
- `[Update payment method \u2192](${billingConsoleUrl(owner, "billing")})`
166422
- ].join("\n");
166423
- }
166424
- return [
166425
- "**Your Pullfrog balance is empty.**",
166426
- "",
166427
- "Top up your balance or enable auto-reload to keep runs flowing.",
166428
- "",
166429
- `[Manage billing \u2192](${billingConsoleUrl(owner, "billing")})`
166430
- ].join("\n");
166431
- }
166432
- function formatTransientErrorSummary(error49, owner) {
166433
- return [
166434
- "**Pullfrog billing is temporarily unavailable.**",
166435
- "",
166436
- error49.message,
166437
- "",
166438
- `Usually transient \u2014 the next dispatch should succeed. If it persists, check [status.pullfrog.com](https://status.pullfrog.com) or [your console](${billingConsoleUrl(owner, "billing")}).`
166439
- ].join("\n");
166440
- }
166441
-
166442
166619
  // utils/token.ts
166443
166620
  var core7 = __toESM(require_core(), 1);
166444
166621
  import assert2 from "node:assert/strict";
@@ -166972,6 +167149,7 @@ var core9 = __toESM(require_core(), 1);
166972
167149
  // utils/runContext.ts
166973
167150
  var defaultSettings = {
166974
167151
  model: null,
167152
+ effort: null,
166975
167153
  modes: [],
166976
167154
  setupScript: null,
166977
167155
  postCheckoutScript: null,
@@ -167019,6 +167197,11 @@ async function fetchRunContext(params) {
167019
167197
  signal: controller.signal
167020
167198
  });
167021
167199
  clearTimeout(timeoutId);
167200
+ if (response.status === 402) {
167201
+ const body = await response.json().catch(() => null);
167202
+ const reason = typeof body === "object" && body !== null && "reason" in body && body.reason === "subscription_unpaid" ? "subscription_unpaid" : "commercial";
167203
+ return { ...defaultRunContext, commercialRefused: reason };
167204
+ }
167022
167205
  if (!response.ok) {
167023
167206
  return response.status >= 500 ? unknownSecretsRunContext : defaultRunContext;
167024
167207
  }
@@ -167097,6 +167280,7 @@ async function resolveRunContextData(params) {
167097
167280
  plan: runContext.plan,
167098
167281
  proxyModel: runContext.proxyModel,
167099
167282
  dbSecrets: runContext.dbSecrets,
167283
+ commercialRefused: runContext.commercialRefused,
167100
167284
  // a failed mint on a runner that should have been able to mint is the same
167101
167285
  // outcome as the server-side failure: the run never sees stored secrets.
167102
167286
  secretsUnavailable: runContext.secretsUnavailable || !!process.env.ACTIONS_ID_TOKEN_REQUEST_URL && oidcToken === void 0
@@ -167480,6 +167664,7 @@ async function dispatchFollowUpReReview(ctx, reviewedSha) {
167480
167664
  "~pullfrog": true,
167481
167665
  version: ctx.payload.version,
167482
167666
  model: ctx.payload.model,
167667
+ effort: ctx.payload.effort,
167483
167668
  prompt: "",
167484
167669
  eventInstructions: RE_REVIEW_PREAMBLE,
167485
167670
  event
@@ -167732,7 +167917,8 @@ async function writeRunErrorOutputs(input) {
167732
167917
  error: input.rendered.comment,
167733
167918
  createIfMissing: true
167734
167919
  });
167735
- } catch {
167920
+ } catch (error49) {
167921
+ log.warning(`error comment failed: ${error49 instanceof Error ? error49.message : String(error49)}`);
167736
167922
  }
167737
167923
  }
167738
167924
 
@@ -167772,6 +167958,13 @@ function resolveModelForLog(ctx) {
167772
167958
  if (ctx.payload.model) return `${ctx.payload.model} (unresolved)`;
167773
167959
  return "auto";
167774
167960
  }
167961
+ function resolveEffortForLog(ctx) {
167962
+ const effort = resolveRunEffort(ctx);
167963
+ if (!ctx.resolvedModel && !ctx.payload.proxyModel) return "pending \u2014 model not chosen yet";
167964
+ if (!effort.alias) return "not applied \u2014 model not recognized";
167965
+ if (!effort.rung) return "n/a (model has no effort control)";
167966
+ return effort.configured ? effort.rung : `${effort.rung} (default)`;
167967
+ }
167775
167968
  function resolveAgentForLog(ctx) {
167776
167969
  const envAgent = process.env.PULLFROG_AGENT?.trim();
167777
167970
  if (envAgent && envAgent === ctx.agentName) {
@@ -167786,6 +167979,9 @@ function logRunStartup(ctx) {
167786
167979
  log.info(
167787
167980
  `\xBB model: ${resolveModelForLog({ payload: ctx.payload, resolvedModel: ctx.resolvedModel })}`
167788
167981
  );
167982
+ log.info(
167983
+ `\xBB effort: ${resolveEffortForLog({ payload: ctx.payload, resolvedModel: ctx.resolvedModel })}`
167984
+ );
167789
167985
  log.info(
167790
167986
  `\xBB agent: ${resolveAgentForLog({ agentName: ctx.agentName, resolvedModel: ctx.resolvedModel })}`
167791
167987
  );
@@ -167951,7 +168147,7 @@ async function resolveRun(params) {
167951
168147
 
167952
168148
  // main.ts
167953
168149
  async function main() {
167954
- var _stack2 = [];
168150
+ var _stack3 = [];
167955
168151
  try {
167956
168152
  normalizeEnv();
167957
168153
  const overridesRaw = process.env.UNSAFE_OVERRIDES ?? "";
@@ -167979,12 +168175,48 @@ async function main() {
167979
168175
  const initialOctokit = createOctokit(jobToken);
167980
168176
  const runContext = await resolveRunContextData({ octokit: initialOctokit, token: jobToken });
167981
168177
  timer.checkpoint("runContextData");
168178
+ const payload = resolvePayload(resolvedPromptInput, runContext.repoSettings);
167982
168179
  const toolState = initToolState({
167983
168180
  progressComment: typeof resolvedPromptInput !== "string" ? resolvedPromptInput.progressComment : void 0,
167984
168181
  owner: runContext.repo.owner,
167985
168182
  name: runContext.repo.name,
167986
168183
  dir: process.cwd()
167987
168184
  });
168185
+ toolState.model = payload.model;
168186
+ toolState.oss = runContext.oss;
168187
+ toolState.shaPinned = isActionPinnedToSha();
168188
+ if (payload.event.issue_number !== void 0) {
168189
+ primaryRepoState(toolState).issueNumber = payload.event.issue_number;
168190
+ }
168191
+ if (payload.event.trigger === "pull_request_synchronize") {
168192
+ primaryRepoState(toolState).beforeSha = payload.event.before_sha;
168193
+ }
168194
+ const oidcCredentials = process.env.ACTIONS_ID_TOKEN_REQUEST_URL && process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN ? {
168195
+ requestUrl: process.env.ACTIONS_ID_TOKEN_REQUEST_URL,
168196
+ requestToken: process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN
168197
+ } : null;
168198
+ if (runContext.commercialRefused) {
168199
+ var _stack = [];
168200
+ try {
168201
+ const _commentTokenRef = __using(_stack, await resolveTokens({
168202
+ push: "disabled",
168203
+ oidc: oidcCredentials
168204
+ }), true);
168205
+ const errorMessage = runContext.commercialRefused === "subscription_unpaid" ? "Pro renewal failed for this organization" : "Pro plan required for this organization";
168206
+ log.error(errorMessage);
168207
+ const body = formatCommercialGateSummary({
168208
+ reason: runContext.commercialRefused,
168209
+ ownerLogin: runContext.repo.owner
168210
+ });
168211
+ await writeRunErrorOutputs({ rendered: { summary: body, comment: body }, toolState });
168212
+ return { success: false, error: errorMessage };
168213
+ } catch (_2) {
168214
+ var _error = _2, _hasError = true;
168215
+ } finally {
168216
+ var _promise2 = __callDispose(_stack, _error, _hasError);
168217
+ _promise2 && await _promise2;
168218
+ }
168219
+ }
167988
168220
  createTempDirectory();
167989
168221
  const opencodeCliPath = await agents.opencode.install();
167990
168222
  captureBaselineModels(opencodeCliPath);
@@ -168003,27 +168235,13 @@ async function main() {
168003
168235
  if (runContext.repoSettings.envAllowlist) {
168004
168236
  setEnvAllowlist(runContext.repoSettings.envAllowlist);
168005
168237
  }
168006
- const payload = resolvePayload(resolvedPromptInput, runContext.repoSettings);
168007
- toolState.model = payload.model;
168008
- toolState.oss = runContext.oss;
168009
- toolState.shaPinned = isActionPinnedToSha();
168010
- if (payload.event.issue_number !== void 0) {
168011
- primaryRepoState(toolState).issueNumber = payload.event.issue_number;
168012
- }
168013
- if (payload.event.trigger === "pull_request_synchronize") {
168014
- primaryRepoState(toolState).beforeSha = payload.event.before_sha;
168015
- }
168016
- const oidcCredentials = process.env.ACTIONS_ID_TOKEN_REQUEST_URL && process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN ? {
168017
- requestUrl: process.env.ACTIONS_ID_TOKEN_REQUEST_URL,
168018
- requestToken: process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN
168019
- } : null;
168020
168238
  const xrepoUnavailable = payload.xrepo?.unavailable ?? [];
168021
168239
  if (xrepoUnavailable.length > 0) {
168022
168240
  log.warning(
168023
168241
  `\xBB --xrepo: requested but not granted: ${xrepoUnavailable.join(", ")} (unknown repo, different owner, or you lack access)`
168024
168242
  );
168025
168243
  }
168026
- const tokenRef = __using(_stack2, await resolveTokens({
168244
+ const tokenRef = __using(_stack3, await resolveTokens({
168027
168245
  push: payload.push,
168028
168246
  xrepo: payload.xrepo,
168029
168247
  oidc: oidcCredentials
@@ -168048,7 +168266,7 @@ async function main() {
168048
168266
  let todoTracker;
168049
168267
  let vertexCredentials;
168050
168268
  try {
168051
- var _stack = [];
168269
+ var _stack2 = [];
168052
168270
  try {
168053
168271
  if (payload.cwd && process.cwd() !== payload.cwd) {
168054
168272
  process.chdir(payload.cwd);
@@ -168068,7 +168286,7 @@ async function main() {
168068
168286
  payload.prompt = payload.prompt.replace(originalBody, resolvedBody ?? "");
168069
168287
  }
168070
168288
  }
168071
- const gitAuthServer = __using(_stack, await startGitAuthServer(tmpdir4), true);
168289
+ const gitAuthServer = __using(_stack2, await startGitAuthServer(tmpdir4), true);
168072
168290
  setGitAuthServer(gitAuthServer);
168073
168291
  const access = decideModelAccess({
168074
168292
  modelExplicit: payload.modelExplicit ?? false,
@@ -168091,6 +168309,7 @@ async function main() {
168091
168309
  }
168092
168310
  if (access.kind === "proxy") payload.proxyModel = access.target;
168093
168311
  if (access.kind === "byok") payload.proxyModel = void 0;
168312
+ if (runContext.oss && payload.proxyModel) payload.effort = 0;
168094
168313
  const resolvedModel = payload.proxyModel ? void 0 : resolveModel({ slug: payload.model });
168095
168314
  vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
168096
168315
  const agent2 = resolveAgent({ model: resolvedModel });
@@ -168171,7 +168390,7 @@ async function main() {
168171
168390
  plan: runContext.plan,
168172
168391
  resolvedModel
168173
168392
  };
168174
- const mcpHttpServer = __using(_stack, await startMcpHttpServer(toolContext, { outputSchema }), true);
168393
+ const mcpHttpServer = __using(_stack2, await startMcpHttpServer(toolContext, { outputSchema }), true);
168175
168394
  toolContext.mcpServerUrl = mcpHttpServer.url;
168176
168395
  log.info(`\xBB MCP server started at ${mcpHttpServer.url}`);
168177
168396
  timer.checkpoint("mcpServer");
@@ -168354,7 +168573,7 @@ ${instructions.user}` : null,
168354
168573
  const timeoutMs = usable ?? 36e5;
168355
168574
  const actualTimeout = usable !== null ? payload.timeout : "1h";
168356
168575
  let timeoutId;
168357
- const timeoutPromise = new Promise((_4, reject) => {
168576
+ const timeoutPromise = new Promise((_5, reject) => {
168358
168577
  timeoutId = setTimeout(() => {
168359
168578
  reject(new Error(`agent run timed out after ${actualTimeout}`));
168360
168579
  }, timeoutMs);
@@ -168381,11 +168600,11 @@ ${instructions.user}` : null,
168381
168600
  toolContext,
168382
168601
  silent: payload.event.silent ?? false
168383
168602
  });
168384
- } catch (_2) {
168385
- var _error = _2, _hasError = true;
168603
+ } catch (_3) {
168604
+ var _error2 = _3, _hasError2 = true;
168386
168605
  } finally {
168387
- var _promise2 = __callDispose(_stack, _error, _hasError);
168388
- _promise2 && await _promise2;
168606
+ var _promise3 = __callDispose(_stack2, _error2, _hasError2);
168607
+ _promise3 && await _promise3;
168389
168608
  }
168390
168609
  } catch (error49) {
168391
168610
  const errorMessage = error49 instanceof Error ? error49.message : "unknown error occurred";
@@ -168429,11 +168648,11 @@ ${instructions.user}` : null,
168429
168648
  }
168430
168649
  cleanupVertexCredentials(vertexCredentials);
168431
168650
  }
168432
- } catch (_3) {
168433
- var _error2 = _3, _hasError2 = true;
168651
+ } catch (_4) {
168652
+ var _error3 = _4, _hasError3 = true;
168434
168653
  } finally {
168435
- var _promise3 = __callDispose(_stack2, _error2, _hasError2);
168436
- _promise3 && await _promise3;
168654
+ var _promise4 = __callDispose(_stack3, _error3, _hasError3);
168655
+ _promise4 && await _promise4;
168437
168656
  }
168438
168657
  }
168439
168658
 
@@ -169431,7 +169650,7 @@ async function runCli4(input) {
169431
169650
  }
169432
169651
 
169433
169652
  // cli.ts
169434
- var VERSION10 = "0.1.47";
169653
+ var VERSION10 = "0.1.48";
169435
169654
  var bin = basename2(process.argv[1] || "");
169436
169655
  var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
169437
169656
  var rawArgs = process.argv.slice(2);