pullfrog 0.1.46 → 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
@@ -101356,6 +101356,10 @@ async function setPullfrogSecret(ctx) {
101356
101356
  }
101357
101357
  return { saved: false, error: result.data.error || `api returned ${result.status}` };
101358
101358
  }
101359
+ function describeSecretTarget(ctx) {
101360
+ if (ctx.scope === "account") return `account ${import_picocolors.default.cyan(`@${ctx.owner}`)}`;
101361
+ return `repo ${import_picocolors.default.cyan(`${ctx.owner}/${ctx.repo}`)}`;
101362
+ }
101359
101363
  async function promptScope(ctx) {
101360
101364
  const scope2 = await _t({
101361
101365
  message: "secret scope",
@@ -101579,7 +101583,8 @@ async function runCodexAuth() {
101579
101583
  O2.warn(err instanceof Error ? err.message : String(err));
101580
101584
  savable = auth2;
101581
101585
  }
101582
- spin.start(`saving ${import_picocolors2.default.cyan(CODEX_AUTH_SECRET)} to Pullfrog`);
101586
+ const target = describeSecretTarget({ owner: remote.owner, repo: remote.repo, scope: scope2 });
101587
+ spin.start(`saving ${import_picocolors2.default.cyan(CODEX_AUTH_SECRET)} to ${target}`);
101583
101588
  const result = await setPullfrogSecret({
101584
101589
  token,
101585
101590
  owner: remote.owner,
@@ -101596,7 +101601,7 @@ async function runCodexAuth() {
101596
101601
  );
101597
101602
  process.exit(1);
101598
101603
  }
101599
- spin.stop(`saved ${import_picocolors2.default.cyan(CODEX_AUTH_SECRET)} to Pullfrog (${scope2})`);
101604
+ spin.stop(`saved ${import_picocolors2.default.cyan(CODEX_AUTH_SECRET)} to ${target}`);
101600
101605
  setActiveSpin(null);
101601
101606
  gt("done.");
101602
101607
  } catch (error49) {
@@ -101693,7 +101698,8 @@ async function runClaudeAuth() {
101693
101698
  `that doesn't look like a ${import_picocolors2.default.cyan("claude setup-token")} token (expected ${import_picocolors2.default.cyan(`${CLAUDE_OAUTH_TOKEN_PREFIX}\u2026`)}). saving it anyway.`
101694
101699
  );
101695
101700
  }
101696
- spin.start(`saving ${import_picocolors2.default.cyan(CLAUDE_OAUTH_SECRET)} to Pullfrog`);
101701
+ const target = describeSecretTarget({ owner: remote.owner, repo: remote.repo, scope: scope2 });
101702
+ spin.start(`saving ${import_picocolors2.default.cyan(CLAUDE_OAUTH_SECRET)} to ${target}`);
101697
101703
  const result = await setPullfrogSecret({
101698
101704
  token,
101699
101705
  owner: remote.owner,
@@ -101710,7 +101716,7 @@ async function runClaudeAuth() {
101710
101716
  );
101711
101717
  process.exit(1);
101712
101718
  }
101713
- spin.stop(`saved ${import_picocolors2.default.cyan(CLAUDE_OAUTH_SECRET)} to Pullfrog (${scope2})`);
101719
+ spin.stop(`saved ${import_picocolors2.default.cyan(CLAUDE_OAUTH_SECRET)} to ${target}`);
101714
101720
  setActiveSpin(null);
101715
101721
  gt("done.");
101716
101722
  } catch (error49) {
@@ -101738,6 +101744,36 @@ import { chmodSync as chmodSync2, mkdirSync as mkdirSync4, writeFileSync as writ
101738
101744
  import { join as join5 } from "node:path";
101739
101745
  import { performance as performance5 } from "node:perf_hooks";
101740
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
+
101741
101777
  // models.ts
101742
101778
  function provider(config3) {
101743
101779
  return config3;
@@ -101757,6 +101793,7 @@ var providers = {
101757
101793
  "claude-fable": {
101758
101794
  displayName: "Claude Fable",
101759
101795
  resolve: "anthropic/claude-fable-5",
101796
+ effort: ["low", "medium", "high", "xhigh", "max"],
101760
101797
  // rolling alias: models.dev's OpenRouter mirror lags brand-new pinned
101761
101798
  // versions (claude-fable-5 isn't indexed yet), so track ~…-latest to
101762
101799
  // stay catalog-valid and auto-follow version bumps.
@@ -101766,6 +101803,7 @@ var providers = {
101766
101803
  "claude-opus": {
101767
101804
  displayName: "Claude Opus",
101768
101805
  resolve: "anthropic/claude-opus-5",
101806
+ effort: ["low", "medium", "high", "xhigh", "max"],
101769
101807
  openRouterResolve: "openrouter/anthropic/claude-opus-5",
101770
101808
  preferred: true,
101771
101809
  subagentModel: "claude-sonnet"
@@ -101773,6 +101811,7 @@ var providers = {
101773
101811
  "claude-sonnet": {
101774
101812
  displayName: "Claude Sonnet",
101775
101813
  resolve: "anthropic/claude-sonnet-5",
101814
+ effort: ["low", "medium", "high", "xhigh", "max"],
101776
101815
  openRouterResolve: "openrouter/anthropic/claude-sonnet-5"
101777
101816
  },
101778
101817
  "claude-haiku": {
@@ -101790,6 +101829,7 @@ var providers = {
101790
101829
  gpt: {
101791
101830
  displayName: "GPT Sol",
101792
101831
  resolve: "openai/gpt-5.6-sol",
101832
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101793
101833
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
101794
101834
  preferred: true,
101795
101835
  subagentModel: "gpt-terra"
@@ -101801,6 +101841,7 @@ var providers = {
101801
101841
  displayName: "GPT Sol Pro",
101802
101842
  description: "Maximum reasoning effort",
101803
101843
  resolve: "openai/gpt-5.6-sol",
101844
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101804
101845
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
101805
101846
  subagentModel: "gpt"
101806
101847
  },
@@ -101810,11 +101851,13 @@ var providers = {
101810
101851
  "gpt-terra": {
101811
101852
  displayName: "GPT Terra",
101812
101853
  resolve: "openai/gpt-5.6-terra",
101854
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101813
101855
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
101814
101856
  },
101815
101857
  "gpt-mini": {
101816
101858
  displayName: "GPT Luna",
101817
101859
  resolve: "openai/gpt-5.6-luna",
101860
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101818
101861
  openRouterResolve: "openrouter/openai/gpt-5.6-luna"
101819
101862
  },
101820
101863
  // legacy aliases — openai unified the codex line into the main GPT family
@@ -101844,6 +101887,7 @@ var providers = {
101844
101887
  o3: {
101845
101888
  displayName: "O3",
101846
101889
  resolve: "openai/o3",
101890
+ effort: ["low", "medium", "high"],
101847
101891
  openRouterResolve: "openrouter/openai/o3"
101848
101892
  }
101849
101893
  }
@@ -101855,6 +101899,7 @@ var providers = {
101855
101899
  "gemini-pro": {
101856
101900
  displayName: "Gemini Pro",
101857
101901
  resolve: "google/gemini-3.1-pro-preview",
101902
+ effort: ["low", "medium", "high"],
101858
101903
  openRouterResolve: "openrouter/google/gemini-3.1-pro-preview",
101859
101904
  preferred: true
101860
101905
  // Inherit (subagents stay on Pro). Google has no in-between tier;
@@ -101866,6 +101911,7 @@ var providers = {
101866
101911
  "gemini-flash": {
101867
101912
  displayName: "Gemini Flash",
101868
101913
  resolve: "google/gemini-3.5-flash",
101914
+ effort: ["minimal", "low", "medium", "high"],
101869
101915
  openRouterResolve: "openrouter/google/gemini-3.5-flash"
101870
101916
  }
101871
101917
  }
@@ -101877,6 +101923,7 @@ var providers = {
101877
101923
  grok: {
101878
101924
  displayName: "Grok",
101879
101925
  resolve: "xai/grok-4.3",
101926
+ effort: ["none", "low", "medium", "high"],
101880
101927
  openRouterResolve: "openrouter/x-ai/grok-4.3",
101881
101928
  preferred: true
101882
101929
  },
@@ -101906,12 +101953,16 @@ var providers = {
101906
101953
  "deepseek-pro": {
101907
101954
  displayName: "DeepSeek Pro",
101908
101955
  resolve: "deepseek/deepseek-v4-pro",
101956
+ effort: ["high", "max"],
101957
+ openRouterEffort: ["high", "xhigh"],
101909
101958
  openRouterResolve: "openrouter/deepseek/deepseek-v4-pro",
101910
101959
  preferred: true
101911
101960
  },
101912
101961
  "deepseek-flash": {
101913
101962
  displayName: "DeepSeek Flash",
101914
101963
  resolve: "deepseek/deepseek-v4-flash",
101964
+ effort: ["high", "max"],
101965
+ openRouterEffort: ["high", "xhigh"],
101915
101966
  openRouterResolve: "openrouter/deepseek/deepseek-v4-flash"
101916
101967
  },
101917
101968
  // legacy aliases — deepseek retires these on 2026-07-24; transparently
@@ -101940,6 +101991,7 @@ var providers = {
101940
101991
  "kimi-k3": {
101941
101992
  displayName: "Kimi K3",
101942
101993
  resolve: "moonshotai/kimi-k3",
101994
+ effort: ["low", "high", "max"],
101943
101995
  openRouterResolve: "openrouter/moonshotai/kimi-k3",
101944
101996
  preferred: true,
101945
101997
  subagentModel: "kimi-k2"
@@ -101952,7 +102004,7 @@ var providers = {
101952
102004
  }
101953
102005
  }),
101954
102006
  opencode: provider({
101955
- displayName: "OpenCode",
102007
+ displayName: "OpenCode Zen",
101956
102008
  envVars: ["OPENCODE_API_KEY"],
101957
102009
  models: {
101958
102010
  "big-pickle": {
@@ -101965,12 +102017,14 @@ var providers = {
101965
102017
  "claude-opus": {
101966
102018
  displayName: "Claude Opus",
101967
102019
  resolve: "opencode/claude-opus-5",
102020
+ effort: ["low", "medium", "high", "xhigh", "max"],
101968
102021
  openRouterResolve: "openrouter/anthropic/claude-opus-5",
101969
102022
  subagentModel: "claude-sonnet"
101970
102023
  },
101971
102024
  "claude-sonnet": {
101972
102025
  displayName: "Claude Sonnet",
101973
102026
  resolve: "opencode/claude-sonnet-5",
102027
+ effort: ["low", "medium", "high", "xhigh", "max"],
101974
102028
  openRouterResolve: "openrouter/anthropic/claude-sonnet-5"
101975
102029
  },
101976
102030
  "claude-haiku": {
@@ -101981,6 +102035,7 @@ var providers = {
101981
102035
  gpt: {
101982
102036
  displayName: "GPT Sol",
101983
102037
  resolve: "opencode/gpt-5.6-sol",
102038
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101984
102039
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
101985
102040
  subagentModel: "gpt-terra"
101986
102041
  },
@@ -101989,6 +102044,7 @@ var providers = {
101989
102044
  displayName: "GPT Sol Pro",
101990
102045
  description: "Maximum reasoning effort",
101991
102046
  resolve: "opencode/gpt-5.6-sol",
102047
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101992
102048
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
101993
102049
  subagentModel: "gpt"
101994
102050
  },
@@ -101996,11 +102052,13 @@ var providers = {
101996
102052
  "gpt-terra": {
101997
102053
  displayName: "GPT Terra",
101998
102054
  resolve: "opencode/gpt-5.6-terra",
102055
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
101999
102056
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
102000
102057
  },
102001
102058
  "gpt-mini": {
102002
102059
  displayName: "GPT Luna",
102003
102060
  resolve: "opencode/gpt-5.6-luna",
102061
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102004
102062
  openRouterResolve: "openrouter/openai/gpt-5.6-luna"
102005
102063
  },
102006
102064
  // legacy aliases — see openai provider above for context.
@@ -102026,12 +102084,14 @@ var providers = {
102026
102084
  "gemini-pro": {
102027
102085
  displayName: "Gemini Pro",
102028
102086
  resolve: "opencode/gemini-3.1-pro",
102087
+ effort: ["low", "medium", "high"],
102029
102088
  openRouterResolve: "openrouter/google/gemini-3.1-pro-preview"
102030
102089
  // Inherit — see google/gemini-pro for rationale.
102031
102090
  },
102032
102091
  "gemini-flash": {
102033
102092
  displayName: "Gemini Flash",
102034
102093
  resolve: "opencode/gemini-3.5-flash",
102094
+ effort: ["minimal", "low", "medium", "high"],
102035
102095
  openRouterResolve: "openrouter/google/gemini-3.5-flash"
102036
102096
  },
102037
102097
  "kimi-k2": {
@@ -102050,6 +102110,7 @@ var providers = {
102050
102110
  "gpt-5-nano": {
102051
102111
  displayName: "GPT Nano",
102052
102112
  resolve: "opencode/gpt-5-nano",
102113
+ effort: ["minimal", "low", "medium", "high"],
102053
102114
  openRouterResolve: "openrouter/openai/gpt-5-nano"
102054
102115
  },
102055
102116
  "mimo-v2-pro-free": {
@@ -102076,6 +102137,8 @@ var providers = {
102076
102137
  "glm-5.1": {
102077
102138
  displayName: "GLM 5.2",
102078
102139
  resolve: "opencode-go/glm-5.2",
102140
+ effort: ["high", "max"],
102141
+ openRouterEffort: ["high", "xhigh"],
102079
102142
  openRouterResolve: "openrouter/z-ai/glm-5.2",
102080
102143
  preferred: true
102081
102144
  },
@@ -102129,6 +102192,10 @@ var providers = {
102129
102192
  // bring-your-own generic OpenAI-compatible endpoint — Cloudflare AI Gateway,
102130
102193
  // Alibaba DashScope, self-hosted vLLM, or any compatible gateway. base URL +
102131
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.
102132
102199
  envVars: ["OPENAI_COMPATIBLE_BASE_URL", "OPENAI_COMPATIBLE_API_KEY", "OPENAI_COMPATIBLE_MODEL"],
102133
102200
  models: {
102134
102201
  // single routing entry — the actual model ID is read from
@@ -102148,6 +102215,7 @@ var providers = {
102148
102215
  "claude-opus": {
102149
102216
  displayName: "Claude Opus",
102150
102217
  resolve: "openrouter/~anthropic/claude-opus-latest",
102218
+ effort: ["low", "medium", "high", "xhigh", "max"],
102151
102219
  openRouterResolve: "openrouter/~anthropic/claude-opus-latest",
102152
102220
  preferred: true,
102153
102221
  subagentModel: "claude-sonnet"
@@ -102155,6 +102223,7 @@ var providers = {
102155
102223
  "claude-sonnet": {
102156
102224
  displayName: "Claude Sonnet",
102157
102225
  resolve: "openrouter/~anthropic/claude-sonnet-latest",
102226
+ effort: ["low", "medium", "high", "xhigh", "max"],
102158
102227
  openRouterResolve: "openrouter/~anthropic/claude-sonnet-latest"
102159
102228
  },
102160
102229
  "claude-haiku": {
@@ -102169,6 +102238,7 @@ var providers = {
102169
102238
  gpt: {
102170
102239
  displayName: "GPT Sol",
102171
102240
  resolve: "openrouter/openai/gpt-5.6-sol",
102241
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102172
102242
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
102173
102243
  subagentModel: "gpt-terra"
102174
102244
  },
@@ -102177,6 +102247,7 @@ var providers = {
102177
102247
  displayName: "GPT Sol Pro",
102178
102248
  description: "Maximum reasoning effort",
102179
102249
  resolve: "openrouter/openai/gpt-5.6-sol-pro",
102250
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102180
102251
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
102181
102252
  subagentModel: "gpt"
102182
102253
  },
@@ -102184,11 +102255,13 @@ var providers = {
102184
102255
  "gpt-terra": {
102185
102256
  displayName: "GPT Terra",
102186
102257
  resolve: "openrouter/openai/gpt-5.6-terra",
102258
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102187
102259
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
102188
102260
  },
102189
102261
  "gpt-mini": {
102190
102262
  displayName: "GPT Luna",
102191
102263
  resolve: "openrouter/openai/gpt-5.6-luna",
102264
+ effort: ["none", "low", "medium", "high", "xhigh", "max"],
102192
102265
  openRouterResolve: "openrouter/openai/gpt-5.6-luna"
102193
102266
  },
102194
102267
  // legacy aliases — see openai provider for context.
@@ -102214,32 +102287,38 @@ var providers = {
102214
102287
  "o4-mini": {
102215
102288
  displayName: "O4 Mini",
102216
102289
  resolve: "openrouter/openai/o4-mini",
102290
+ effort: ["low", "medium", "high"],
102217
102291
  openRouterResolve: "openrouter/openai/o4-mini"
102218
102292
  },
102219
102293
  "gemini-pro": {
102220
102294
  displayName: "Gemini Pro",
102221
102295
  resolve: "openrouter/~google/gemini-pro-latest",
102296
+ effort: ["low", "medium", "high"],
102222
102297
  openRouterResolve: "openrouter/~google/gemini-pro-latest"
102223
102298
  // Inherit — see google/gemini-pro for rationale.
102224
102299
  },
102225
102300
  "gemini-flash": {
102226
102301
  displayName: "Gemini Flash",
102227
102302
  resolve: "openrouter/~google/gemini-flash-latest",
102303
+ effort: ["minimal", "low", "medium", "high"],
102228
102304
  openRouterResolve: "openrouter/~google/gemini-flash-latest"
102229
102305
  },
102230
102306
  grok: {
102231
102307
  displayName: "Grok",
102232
102308
  resolve: "openrouter/x-ai/grok-4.3",
102309
+ effort: ["none", "low", "medium", "high"],
102233
102310
  openRouterResolve: "openrouter/x-ai/grok-4.3"
102234
102311
  },
102235
102312
  "deepseek-pro": {
102236
102313
  displayName: "DeepSeek Pro",
102237
102314
  resolve: "openrouter/deepseek/deepseek-v4-pro",
102315
+ effort: ["high", "xhigh"],
102238
102316
  openRouterResolve: "openrouter/deepseek/deepseek-v4-pro"
102239
102317
  },
102240
102318
  "deepseek-flash": {
102241
102319
  displayName: "DeepSeek Flash",
102242
102320
  resolve: "openrouter/deepseek/deepseek-v4-flash",
102321
+ effort: ["high", "xhigh"],
102243
102322
  openRouterResolve: "openrouter/deepseek/deepseek-v4-flash"
102244
102323
  },
102245
102324
  // legacy alias — deepseek retires this on 2026-07-24; transparently
@@ -102258,6 +102337,7 @@ var providers = {
102258
102337
  "kimi-k3": {
102259
102338
  displayName: "Kimi K3",
102260
102339
  resolve: "openrouter/moonshotai/kimi-k3",
102340
+ effort: ["low", "high", "max"],
102261
102341
  openRouterResolve: "openrouter/moonshotai/kimi-k3"
102262
102342
  },
102263
102343
  // slug pins the m2 line for DB stability; resolve tracks the current m2.7.
@@ -102312,6 +102392,8 @@ var modelAliases = Object.entries(providers).flatMap(
102312
102392
  // here to a fully-qualified slug so callers can look up the target alias
102313
102393
  // directly without re-deriving the provider.
102314
102394
  subagentModel: def.subagentModel ? `${providerKey}/${def.subagentModel}` : void 0,
102395
+ effort: def.effort,
102396
+ openRouterEffort: def.openRouterEffort,
102315
102397
  hidden: def.hidden ?? false
102316
102398
  }))
102317
102399
  );
@@ -102350,6 +102432,17 @@ function resolveCliModel(slug2) {
102350
102432
  function resolveOpenRouterModel(slug2) {
102351
102433
  return resolveDisplayAlias(slug2)?.openRouterResolve;
102352
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
+ }
102353
102446
  var defaultProxyAlias = resolveDisplayAlias(AUTO_EFFICIENT);
102354
102447
  if (!defaultProxyAlias?.openRouterResolve) {
102355
102448
  throw new Error(`DEFAULT_PROXY_MODEL: ${AUTO_EFFICIENT} has no openRouterResolve`);
@@ -103037,6 +103130,40 @@ function extractProviderId(text) {
103037
103130
  return match3 ? match3[1].toLowerCase() : null;
103038
103131
  }
103039
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
+
103040
103167
  // utils/skills.ts
103041
103168
  import { spawnSync as spawnSync2 } from "node:child_process";
103042
103169
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
@@ -103050,7 +103177,7 @@ var import_semver = __toESM(require_semver2(), 1);
103050
103177
  // package.json
103051
103178
  var package_default = {
103052
103179
  name: "pullfrog",
103053
- version: "0.1.46",
103180
+ version: "0.1.48",
103054
103181
  type: "module",
103055
103182
  bin: {
103056
103183
  pullfrog: "dist/cli.mjs",
@@ -104610,8 +104737,18 @@ function stripProviderPrefix(specifier) {
104610
104737
  const slashIndex = specifier.indexOf("/");
104611
104738
  return slashIndex > 0 ? specifier.slice(slashIndex + 1) : specifier;
104612
104739
  }
104613
- function resolveEffort(_model) {
104614
- 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
+ );
104615
104752
  }
104616
104753
  function tailLines2(text, maxCodeUnits) {
104617
104754
  if (text.length <= maxCodeUnits) return text;
@@ -105087,7 +105224,7 @@ var claude = agent({
105087
105224
  });
105088
105225
  installBundledSkills({ home: homeEnv.HOME });
105089
105226
  const mcpConfigPath = writeMcpConfig(ctx);
105090
- const effort = resolveEffort(model);
105227
+ const effort = resolveRunEffort(ctx);
105091
105228
  const pretoolGate = writePretoolGateAssets(ctx);
105092
105229
  const stopHookPath = join5(ctx.tmpdir, "pullfrog-stop-hook.sh");
105093
105230
  writeFileSync4(stopHookPath, buildStopHookScript(), { mode: 493 });
@@ -105101,13 +105238,16 @@ var claude = agent({
105101
105238
  "--settings",
105102
105239
  pretoolGate.settingsPath,
105103
105240
  "--verbose",
105104
- "--effort",
105105
- effort,
105106
105241
  "--disallowedTools",
105107
105242
  CLAUDE_DISALLOWED_TOOLS,
105108
105243
  "--agents",
105109
105244
  buildAgentsJson()
105110
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
+ }
105111
105251
  if (model) {
105112
105252
  baseArgs.push("--model", model);
105113
105253
  }
@@ -105125,6 +105265,9 @@ var claude = agent({
105125
105265
  applyClaudeVertexEnv(env2);
105126
105266
  env2.ANTHROPIC_MODEL = specifier;
105127
105267
  }
105268
+ if ((isBedrockRoute || isVertexRoute2) && specifier && effort.alias?.effort) {
105269
+ applyHostedEffortCapabilities({ env: env2, modelId: specifier, levels: effort.alias.effort });
105270
+ }
105128
105271
  if (env2.CLAUDE_CODE_OAUTH_TOKEN && !isBedrockRoute && env2.ANTHROPIC_API_KEY) {
105129
105272
  const preflight = await preflightClaudeSubscription({
105130
105273
  token: env2.CLAUDE_CODE_OAUTH_TOKEN,
@@ -105142,7 +105285,12 @@ var claude = agent({
105142
105285
  delete env2.CLAUDE_CODE_OAUTH_TOKEN;
105143
105286
  }
105144
105287
  }
105145
- 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
+ }
105146
105294
  log.debug(`\xBB starting Pullfrog (Claude Code): ${cliPath} ${baseArgs.join(" ")}`);
105147
105295
  log.debug(`\xBB working directory: ${repoDir}`);
105148
105296
  const gateServer = __using(_stack, await startGateServer(ctx), true);
@@ -105166,7 +105314,7 @@ var claude = agent({
105166
105314
  }
105167
105315
  });
105168
105316
 
105169
- // agents/opencode_v2.ts
105317
+ // agents/opencode.ts
105170
105318
  var core2 = __toESM(require_core(), 1);
105171
105319
  import { spawn as nodeSpawn2 } from "node:child_process";
105172
105320
  import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "node:fs";
@@ -110576,7 +110724,7 @@ function createOpencodeClient(config3) {
110576
110724
  // node_modules/.pnpm/@opencode-ai+sdk@1.18.5/node_modules/@opencode-ai/sdk/dist/v2/server.js
110577
110725
  var import_cross_spawn = __toESM(require_cross_spawn(), 1);
110578
110726
 
110579
- // agents/opencode_v2.ts
110727
+ // agents/opencode.ts
110580
110728
  var import_undici = __toESM(require_undici2(), 1);
110581
110729
 
110582
110730
  // utils/codexHome.ts
@@ -110849,14 +110997,6 @@ function deriveSubagentModels(orchestratorSpec) {
110849
110997
  }
110850
110998
 
110851
110999
  // agents/opencodeShared.ts
110852
- function geminiHighThinkingOverrides() {
110853
- return Object.fromEntries(
110854
- modelAliases.filter((a) => a.provider === "google").map((a) => [
110855
- a.resolve.replace(/^google\//, ""),
110856
- { options: { thinkingConfig: { thinkingLevel: "high" } } }
110857
- ])
110858
- );
110859
- }
110860
111000
  function openAICompatibleLimit() {
110861
111001
  return {
110862
111002
  context: Number(process.env[OPENAI_COMPATIBLE_CONTEXT_ENV]),
@@ -110889,10 +111029,6 @@ function kimiOpenRouterProviderOverrides() {
110889
111029
  ])
110890
111030
  );
110891
111031
  }
110892
- function deepseekHighEffortOverrides() {
110893
- const orModel = modelAliases.find((a) => a.slug === "deepseek/deepseek-pro")?.openRouterResolve?.replace(/^openrouter\//, "");
110894
- return orModel ? { [orModel]: { options: { reasoning: { effort: "high" } } } } : {};
110895
- }
110896
111032
  function buildReviewerAgentConfig(orchestratorModel) {
110897
111033
  const overrides = deriveSubagentModels(orchestratorModel);
110898
111034
  return {
@@ -110934,7 +111070,7 @@ function autoSelectModel() {
110934
111070
  return void 0;
110935
111071
  }
110936
111072
 
110937
- // agents/opencode_v2.ts
111073
+ // agents/opencode.ts
110938
111074
  var installCli = () => installOpencodeCli({ binPath: "bin/opencode.exe" });
110939
111075
  function buildSecurityConfig(ctx, model) {
110940
111076
  const config3 = {
@@ -110961,17 +111097,13 @@ function buildSecurityConfig(ctx, model) {
110961
111097
  log.info(`\xBB subagent models: reviewfrog=${reviewerModel}`);
110962
111098
  return cfg;
110963
111099
  })(),
110964
- // gemini-3 thinking pinned to high for review depth; deepseek (funded
110965
- // efficient tier) pinned to high reasoning effort, and kimi pinned away
110966
- // from Enforcer-less openrouter providers (siliconflow / together) that
110967
- // drop optional tool-call params both per-model on the openrouter route,
110968
- // so other models are unaffected. gpt/anthropic effort set elsewhere (gpt:
110969
- // 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.
110970
111105
  provider: {
110971
- google: { models: geminiHighThinkingOverrides() },
110972
- openrouter: {
110973
- models: { ...deepseekHighEffortOverrides(), ...kimiOpenRouterProviderOverrides() }
110974
- },
111106
+ openrouter: { models: kimiOpenRouterProviderOverrides() },
110975
111107
  ...openAICompatibleProvider(model)
110976
111108
  }
110977
111109
  };
@@ -111282,6 +111414,7 @@ async function runPromptTurn(ctx, params) {
111282
111414
  {
111283
111415
  sessionID: ctx.sessionID,
111284
111416
  parts: [part],
111417
+ ...ctx.variant ? { variant: ctx.variant } : {},
111285
111418
  ...params.model ? { model: params.model } : {}
111286
111419
  },
111287
111420
  // wire the inner activity watchdog's abort signal into the SDK request
@@ -111471,6 +111604,10 @@ var opencode = agent({
111471
111604
  const cliPath = await installCli();
111472
111605
  const rawModel = ctx.payload.proxyModel ?? ctx.resolvedModel ?? autoSelectModel();
111473
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
+ }
111474
111611
  const bedrockModelId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
111475
111612
  const isBedrockRoute = rawModel !== void 0 && bedrockModelId !== void 0 && bedrockModelId === rawModel;
111476
111613
  const vertexModel = resolveVertexOpenCodeModel(rawModel);
@@ -111563,6 +111700,8 @@ var opencode = agent({
111563
111700
  orchestratorSessionID: sessionID,
111564
111701
  labeler,
111565
111702
  toolState: ctx.toolState,
111703
+ // `rawModel` folds in the auto-select pick — see the opencode.ts twin.
111704
+ variant: effort.rung,
111566
111705
  todoTracker: ctx.todoTracker,
111567
111706
  onActivityTimeout: ctx.onActivityTimeout,
111568
111707
  onToolUse: ctx.onToolUse,
@@ -159948,6 +160087,7 @@ var JsonPayload = type({
159948
160087
  version: "string",
159949
160088
  "model?": "string | undefined",
159950
160089
  "modelExplicit?": "boolean | undefined",
160090
+ "effort?": "number | string | undefined",
159951
160091
  prompt: "string",
159952
160092
  "triggerer?": "string | undefined",
159953
160093
  "baseInstructions?": "string | undefined",
@@ -159967,6 +160107,9 @@ var JsonPayload = type({
159967
160107
  id: "string",
159968
160108
  type: "'issue' | 'review'"
159969
160109
  }).or("undefined"),
160110
+ // optional so a payload from an older server build (pre-`checkRun`) still parses
160111
+ // against a newer action across a rolling deploy.
160112
+ "checkRun?": type({ id: "string" }).or("undefined"),
159970
160113
  "generateSummary?": "boolean | undefined"
159971
160114
  });
159972
160115
  var COLLABORATOR_PERMISSIONS = ["admin", "maintain", "write"];
@@ -159978,6 +160121,7 @@ var Inputs = type({
159978
160121
  "prompt?": type.string.or("undefined"),
159979
160122
  "prompt_file?": type.string.or("undefined"),
159980
160123
  "model?": type.string.or("undefined"),
160124
+ "effort?": type.string.or("undefined"),
159981
160125
  "timeout?": type.string.or("undefined"),
159982
160126
  "push?": PushPermissionInput.or("undefined"),
159983
160127
  "shell?": ShellPermissionInput.or("undefined"),
@@ -160032,6 +160176,7 @@ function resolvePromptFile(input) {
160032
160176
  function resolveNonPromptInputs() {
160033
160177
  return Inputs.omit("prompt", "prompt_file").assert({
160034
160178
  model: core4.getInput("model") || void 0,
160179
+ effort: core4.getInput("effort") || void 0,
160035
160180
  timeout: core4.getInput("timeout") || void 0,
160036
160181
  cwd: core4.getInput("cwd") || void 0,
160037
160182
  push: core4.getInput("push") || void 0,
@@ -160050,6 +160195,8 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
160050
160195
  const rawEvent = jsonPayload?.event;
160051
160196
  const event = isPayloadEvent(rawEvent) ? rawEvent : { trigger: "unknown" };
160052
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));
160053
160200
  const isNonCollaborator = !isCollaborator(event);
160054
160201
  const repoShell = repoSettings.shell ?? "restricted";
160055
160202
  const inputShell = inputs.shell;
@@ -160069,6 +160216,7 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
160069
160216
  // explicit only when the model came from a per-run override flag (carried on
160070
160217
  // the JSON payload). a GHA `model` input or the repo default is not explicit.
160071
160218
  modelExplicit: jsonPayload?.modelExplicit ?? false,
160219
+ effort,
160072
160220
  prompt,
160073
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
160074
160222
  (!isPullfrog(process.env.GITHUB_ACTOR) ? process.env.GITHUB_ACTOR : void 0),
@@ -160080,13 +160228,19 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
160080
160228
  timeout: inputs.timeout ?? jsonPayload?.timeout,
160081
160229
  cwd: resolveCwd(inputs.cwd),
160082
160230
  progressComment: jsonPayload?.progressComment,
160231
+ checkRun: jsonPayload?.checkRun,
160083
160232
  generateSummary: jsonPayload?.generateSummary,
160084
160233
  // permissions: inputs > repoSettings > fallbacks
160085
160234
  push: inputs.push ?? repoSettings.push ?? "restricted",
160086
160235
  shell: resolvedShell,
160087
- // opt-in commit-status check-runs (branch protection). workflow-level
160088
- // static input, off unless the repo's pullfrog.yml sets status_checks: enabled.
160089
- statusChecks: inputs.status_checks === "enabled",
160236
+ // the `pullfrog` run-lifecycle check. ON by default — the whole point is that a PR
160237
+ // shows whether Pullfrog is running without anyone having to opt in. the workflow
160238
+ // input is the source of truth when set (mirrors `push`); otherwise the repo
160239
+ // setting decides.
160240
+ runStatusCheck: inputs.status_checks === void 0 ? repoSettings.statusChecks : inputs.status_checks === "enabled",
160241
+ // the `pullfrog-approval` verdict check stays opt-in and workflow-only. it exists to
160242
+ // be *required* by branch protection, so it must never turn itself on.
160243
+ approvalCheck: inputs.status_checks === "enabled",
160090
160244
  // temporary progress chrome. the workflow input is the source of truth when
160091
160245
  // set (mirrors `push`); otherwise the repo setting decides. defaults to true.
160092
160246
  progressComments: inputs.progress_comments === void 0 ? repoSettings.progressComments : inputs.progress_comments === "enabled",
@@ -160614,7 +160768,11 @@ async function approveAfterFix(ctx) {
160614
160768
  approved: true,
160615
160769
  hasComments: false
160616
160770
  });
160617
- ctx.toolState.approval = { wouldApprove: true, sha: headSha };
160771
+ ctx.toolState.approval = {
160772
+ wouldApprove: true,
160773
+ sha: headSha,
160774
+ url: result.data.html_url
160775
+ };
160618
160776
  log.info(`\xBB auto-approved #${pullNumber} after fix run (review ${result.data.id})`);
160619
160777
  await deleteProgressComment(ctx).catch((err) => {
160620
160778
  log.debug(`progress comment cleanup after fix auto-approval failed: ${err}`);
@@ -160947,6 +161105,7 @@ function CreatePullRequestReviewTool(ctx) {
160947
161105
  }
160948
161106
  const reviewId = result.data.id;
160949
161107
  const reviewNodeId = result.data.node_id;
161108
+ if (ctx.toolState.approval) ctx.toolState.approval.url = result.data.html_url;
160950
161109
  log.info(`\xBB created review ${reviewId} on pull request #${pull_number}`);
160951
161110
  const actuallyReviewedSha = primary.checkoutSha ?? params.commit_id;
160952
161111
  ctx.toolState.review = {
@@ -165523,6 +165682,140 @@ function formatApiKeyErrorSummary(params) {
165523
165682
  ].join("\n");
165524
165683
  }
165525
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
+
165526
165819
  // utils/gitAuthServer.ts
165527
165820
  import { randomUUID as randomUUID5 } from "node:crypto";
165528
165821
  import { writeFileSync as writeFileSync14 } from "node:fs";
@@ -166323,102 +166616,6 @@ function applyOverrides(params) {
166323
166616
  // utils/proxy.ts
166324
166617
  var core8 = __toESM(require_core(), 1);
166325
166618
 
166326
- // utils/billingErrors.ts
166327
- var BillingError = class extends Error {
166328
- code;
166329
- declineCode;
166330
- needsReauthentication;
166331
- constructor(message, opts = {}) {
166332
- super(message);
166333
- this.name = "BillingError";
166334
- this.code = opts.code ?? null;
166335
- this.declineCode = opts.declineCode ?? null;
166336
- this.needsReauthentication = opts.needsReauthentication ?? false;
166337
- }
166338
- };
166339
- var TransientError = class extends Error {
166340
- constructor(message) {
166341
- super(message);
166342
- this.name = "TransientError";
166343
- }
166344
- };
166345
- function billingConsoleUrl(owner, anchor) {
166346
- return `https://pullfrog.com/console/${encodeURIComponent(owner)}#${anchor}`;
166347
- }
166348
- function formatBillingErrorSummary(error49, owner) {
166349
- if (error49.code === "router_requires_card") {
166350
- return [
166351
- "**Add a card to start using Pullfrog Router.**",
166352
- "",
166353
- "Router proxies OpenRouter at raw cost \u2014 no platform markup. Add a card and we'll auto-reload your wallet so runs keep flowing.",
166354
- "",
166355
- `[Add a card \u2192](${billingConsoleUrl(owner, "model-access")})`
166356
- ].join("\n");
166357
- }
166358
- if (error49.code === "router_balance_exhausted") {
166359
- return [
166360
- "**Your Pullfrog Router balance is exhausted.**",
166361
- "",
166362
- "You have a payment method on file but auto-reload is disabled, so runs paused once your balance went past the overdraft buffer.",
166363
- "",
166364
- `[Top up balance \u2192](${billingConsoleUrl(owner, "billing")}) \xB7 [Enable auto-reload \u2192](${billingConsoleUrl(owner, "model-access")})`
166365
- ].join("\n");
166366
- }
166367
- if (error49.code === "router_keylimit_exhausted") {
166368
- return [
166369
- "**This run was cut short \u2014 your Pullfrog Router balance ran out mid-run.**",
166370
- "",
166371
- "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.",
166372
- "",
166373
- `[Top up balance \u2192](${billingConsoleUrl(owner, "billing")}) \xB7 [Enable auto-reload \u2192](${billingConsoleUrl(owner, "model-access")})`
166374
- ].join("\n");
166375
- }
166376
- if (error49.code === "router_monthly_limit") {
166377
- return [
166378
- "**Pullfrog Router hit its monthly spend limit.**",
166379
- "",
166380
- "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.",
166381
- "",
166382
- `[Adjust limit \u2192](${billingConsoleUrl(owner, "model-access")})`
166383
- ].join("\n");
166384
- }
166385
- if (error49.needsReauthentication) {
166386
- const code = error49.declineCode ?? "authentication_required";
166387
- return [
166388
- `**Your card issuer requires 3D Secure on every charge** (\`${code}\`).`,
166389
- "",
166390
- "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.",
166391
- "",
166392
- `[Top up balance \u2192](${billingConsoleUrl(owner, "billing")})`
166393
- ].join("\n");
166394
- }
166395
- if (error49.declineCode) {
166396
- return [
166397
- `**Your card was declined** (\`${error49.declineCode}\`).`,
166398
- "",
166399
- "Update your payment method and Pullfrog will retry on the next run.",
166400
- "",
166401
- `[Update payment method \u2192](${billingConsoleUrl(owner, "billing")})`
166402
- ].join("\n");
166403
- }
166404
- return [
166405
- "**Your Pullfrog balance is empty.**",
166406
- "",
166407
- "Top up your balance or enable auto-reload to keep runs flowing.",
166408
- "",
166409
- `[Manage billing \u2192](${billingConsoleUrl(owner, "billing")})`
166410
- ].join("\n");
166411
- }
166412
- function formatTransientErrorSummary(error49, owner) {
166413
- return [
166414
- "**Pullfrog billing is temporarily unavailable.**",
166415
- "",
166416
- error49.message,
166417
- "",
166418
- `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")}).`
166419
- ].join("\n");
166420
- }
166421
-
166422
166619
  // utils/token.ts
166423
166620
  var core7 = __toESM(require_core(), 1);
166424
166621
  import assert2 from "node:assert/strict";
@@ -166952,6 +167149,7 @@ var core9 = __toESM(require_core(), 1);
166952
167149
  // utils/runContext.ts
166953
167150
  var defaultSettings = {
166954
167151
  model: null,
167152
+ effort: null,
166955
167153
  modes: [],
166956
167154
  setupScript: null,
166957
167155
  postCheckoutScript: null,
@@ -166963,6 +167161,7 @@ var defaultSettings = {
166963
167161
  autoMergeEnabled: false,
166964
167162
  signedCommits: false,
166965
167163
  progressComments: true,
167164
+ statusChecks: true,
166966
167165
  modeInstructions: {},
166967
167166
  learnings: null,
166968
167167
  learningsHeadings: [],
@@ -166998,6 +167197,11 @@ async function fetchRunContext(params) {
166998
167197
  signal: controller.signal
166999
167198
  });
167000
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
+ }
167001
167205
  if (!response.ok) {
167002
167206
  return response.status >= 500 ? unknownSecretsRunContext : defaultRunContext;
167003
167207
  }
@@ -167076,6 +167280,7 @@ async function resolveRunContextData(params) {
167076
167280
  plan: runContext.plan,
167077
167281
  proxyModel: runContext.proxyModel,
167078
167282
  dbSecrets: runContext.dbSecrets,
167283
+ commercialRefused: runContext.commercialRefused,
167079
167284
  // a failed mint on a runner that should have been able to mint is the same
167080
167285
  // outcome as the server-side failure: the run never sees stored secrets.
167081
167286
  secretsUnavailable: runContext.secretsUnavailable || !!process.env.ACTIONS_ID_TOKEN_REQUEST_URL && oidcToken === void 0
@@ -167459,6 +167664,7 @@ async function dispatchFollowUpReReview(ctx, reviewedSha) {
167459
167664
  "~pullfrog": true,
167460
167665
  version: ctx.payload.version,
167461
167666
  model: ctx.payload.model,
167667
+ effort: ctx.payload.effort,
167462
167668
  prompt: "",
167463
167669
  eventInstructions: RE_REVIEW_PREAMBLE,
167464
167670
  event
@@ -167484,30 +167690,123 @@ function getCurrentWorkflowFilename() {
167484
167690
  return match3?.[1] ?? "pullfrog.yml";
167485
167691
  }
167486
167692
 
167487
- // utils/statusChecks.ts
167488
- var COMPLETION_CHECK = "pullfrog";
167489
- var APPROVAL_CHECK = "pullfrog-approval";
167490
- async function createCheckRun(ctx, params) {
167693
+ // utils/runStatusCheck.ts
167694
+ var RUN_STATUS_CHECK_NAME = "Pullfrog";
167695
+ var APPROVAL_CHECK_NAME = "Pullfrog approval";
167696
+ function parseCheckRunId(raw2) {
167697
+ if (!raw2?.id) return void 0;
167698
+ const id = parseInt(raw2.id, 10);
167699
+ if (Number.isNaN(id) || id <= 0) return void 0;
167700
+ return id;
167701
+ }
167702
+ function disableCheckLine(owner, repo) {
167703
+ const url4 = `https://pullfrog.com/console/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}#auto-review-prs`;
167704
+ return `
167705
+
167706
+ [Turn off this check \u2192](${url4}) \u2014 it reports run status only and gates nothing unless you required it in branch protection.`;
167707
+ }
167708
+ var TERMINAL_OUTPUT = {
167709
+ success: {
167710
+ title: "Pullfrog run completed",
167711
+ summary: "The Pullfrog run finished successfully."
167712
+ },
167713
+ failure: {
167714
+ title: "Pullfrog run failed",
167715
+ summary: "The Pullfrog run failed. See the run logs for details."
167716
+ },
167717
+ cancelled: {
167718
+ title: "Pullfrog run cancelled",
167719
+ summary: "The Pullfrog run was cancelled before it finished."
167720
+ },
167721
+ timed_out: {
167722
+ title: "Pullfrog run timed out",
167723
+ summary: "The Pullfrog run exceeded its timeout. See the run logs for details."
167724
+ },
167725
+ action_required: {
167726
+ title: "Pullfrog run needs attention",
167727
+ summary: "The Pullfrog run stopped and needs attention. See the run logs for details."
167728
+ },
167729
+ neutral: {
167730
+ title: "Pullfrog run finished",
167731
+ summary: "The Pullfrog run finished without a pass or fail outcome."
167732
+ },
167733
+ skipped: {
167734
+ title: "Pullfrog run skipped",
167735
+ summary: "This run was superseded by another Pullfrog run."
167736
+ },
167737
+ stale: {
167738
+ title: "Pullfrog run didn't finish",
167739
+ summary: "Pullfrog never received a completion signal for this run. See the run logs for details."
167740
+ }
167741
+ };
167742
+ function terminalOutput(params) {
167743
+ const base = TERMINAL_OUTPUT[params.conclusion];
167744
+ const review = params.reviewUrl ? `
167745
+
167746
+ [View the review Pullfrog posted \u2192](${params.reviewUrl})` : "";
167747
+ const disable = params.conclusion === "success" ? "" : disableCheckLine(params.owner, params.repo);
167748
+ return { title: base.title, summary: base.summary + review + disable };
167749
+ }
167750
+ async function finalizeRunStatusCheck(params) {
167751
+ const updateParams = {
167752
+ owner: params.owner,
167753
+ repo: params.repo,
167754
+ check_run_id: params.checkRunId,
167755
+ status: "completed",
167756
+ conclusion: params.conclusion,
167757
+ output: terminalOutput({
167758
+ conclusion: params.conclusion,
167759
+ owner: params.owner,
167760
+ repo: params.repo,
167761
+ reviewUrl: params.reviewUrl
167762
+ })
167763
+ };
167764
+ if (params.detailsUrl) updateParams.details_url = params.detailsUrl;
167765
+ await params.octokit.rest.checks.update(updateParams);
167766
+ }
167767
+ async function createTerminalRunStatusCheck(params) {
167491
167768
  const createParams = {
167492
- owner: ctx.repo.owner,
167493
- repo: ctx.repo.name,
167494
- name: params.name,
167769
+ owner: params.owner,
167770
+ repo: params.repo,
167771
+ name: RUN_STATUS_CHECK_NAME,
167495
167772
  head_sha: params.headSha,
167496
167773
  status: "completed",
167497
167774
  conclusion: params.conclusion,
167498
- output: { title: params.title, summary: params.summary }
167775
+ output: terminalOutput({
167776
+ conclusion: params.conclusion,
167777
+ owner: params.owner,
167778
+ repo: params.repo,
167779
+ reviewUrl: params.reviewUrl
167780
+ })
167499
167781
  };
167500
- if (ctx.runId) {
167501
- createParams.details_url = `https://github.com/${ctx.repo.owner}/${ctx.repo.name}/actions/runs/${ctx.runId}`;
167502
- }
167503
- await ctx.octokit.rest.checks.create(createParams);
167504
- log.info(`\xBB posted ${params.name} check (${params.conclusion}) on ${params.headSha.slice(0, 7)}`);
167782
+ if (params.detailsUrl) createParams.details_url = params.detailsUrl;
167783
+ await params.octokit.rest.checks.create(createParams);
167505
167784
  }
167785
+
167786
+ // utils/statusChecks.ts
167506
167787
  async function reportStatusChecks(ctx, params) {
167507
- if (!ctx.payload.statusChecks) return;
167508
167788
  const event = ctx.payload.event;
167509
167789
  const pullNumber = event.issue_number;
167510
167790
  if (event.is_pr !== true || typeof pullNumber !== "number") return;
167791
+ const checkRunId = parseCheckRunId(ctx.payload.checkRun);
167792
+ if (checkRunId === void 0 && !ctx.payload.runStatusCheck && !ctx.payload.approvalCheck) return;
167793
+ const conclusion = params.runSucceeded ? "success" : "failure";
167794
+ const detailsUrl = ctx.runId ? `https://github.com/${ctx.repo.owner}/${ctx.repo.name}/actions/runs/${ctx.runId}` : void 0;
167795
+ if (checkRunId !== void 0) {
167796
+ await finalizeRunStatusCheck({
167797
+ octokit: ctx.octokit,
167798
+ owner: ctx.repo.owner,
167799
+ repo: ctx.repo.name,
167800
+ checkRunId,
167801
+ conclusion,
167802
+ detailsUrl,
167803
+ reviewUrl: ctx.toolState.approval?.url
167804
+ }).then(() => log.info(`\xBB finalized ${RUN_STATUS_CHECK_NAME} check (${conclusion})`)).catch((err) => log.debug(`status checks: ${RUN_STATUS_CHECK_NAME} finalize failed: ${err}`));
167805
+ }
167806
+ const approval = ctx.toolState.approval;
167807
+ const needsApprovalCheck = ctx.payload.approvalCheck && params.runSucceeded && approval;
167808
+ const needsFallbackRunCheck = ctx.payload.runStatusCheck && checkRunId === void 0;
167809
+ if (!needsApprovalCheck && !needsFallbackRunCheck) return;
167511
167810
  let headSha;
167512
167811
  try {
167513
167812
  const pr = await ctx.octokit.rest.pulls.get({
@@ -167520,24 +167819,32 @@ async function reportStatusChecks(ctx, params) {
167520
167819
  log.debug(`status checks: failed to resolve PR #${pullNumber} head sha: ${err}`);
167521
167820
  return;
167522
167821
  }
167523
- const completionSha = primaryRepoState(ctx.toolState).checkoutSha ?? headSha;
167524
- await createCheckRun(ctx, {
167525
- name: COMPLETION_CHECK,
167526
- headSha: completionSha,
167527
- conclusion: params.runSucceeded ? "success" : "failure",
167528
- title: params.runSucceeded ? "Pullfrog run completed" : "Pullfrog run failed",
167529
- summary: params.runSucceeded ? "The Pullfrog run finished successfully." : "The Pullfrog run failed or timed out. See the run logs for details."
167530
- }).catch((err) => log.debug(`status checks: ${COMPLETION_CHECK} post failed: ${err}`));
167531
- const approval = ctx.toolState.approval;
167532
- if (params.runSucceeded && approval) {
167533
- await createCheckRun(ctx, {
167534
- name: APPROVAL_CHECK,
167535
- headSha: approval.sha ?? headSha,
167536
- conclusion: approval.wouldApprove ? "success" : "failure",
167822
+ if (needsFallbackRunCheck) {
167823
+ await createTerminalRunStatusCheck({
167824
+ octokit: ctx.octokit,
167825
+ owner: ctx.repo.owner,
167826
+ repo: ctx.repo.name,
167827
+ headSha: primaryRepoState(ctx.toolState).checkoutSha ?? headSha,
167828
+ conclusion,
167829
+ detailsUrl,
167830
+ reviewUrl: ctx.toolState.approval?.url
167831
+ }).then(() => log.info(`\xBB posted ${RUN_STATUS_CHECK_NAME} check (${conclusion})`)).catch((err) => log.debug(`status checks: ${RUN_STATUS_CHECK_NAME} post failed: ${err}`));
167832
+ }
167833
+ if (!needsApprovalCheck || !approval) return;
167834
+ const createParams = {
167835
+ owner: ctx.repo.owner,
167836
+ repo: ctx.repo.name,
167837
+ name: APPROVAL_CHECK_NAME,
167838
+ head_sha: approval.sha ?? headSha,
167839
+ status: "completed",
167840
+ conclusion: approval.wouldApprove ? "success" : "failure",
167841
+ output: {
167537
167842
  title: approval.wouldApprove ? "Pullfrog would approve" : "Pullfrog would not approve",
167538
167843
  summary: approval.wouldApprove ? "Pullfrog has no outstanding review feedback on this PR." : "Pullfrog has outstanding review feedback or requested changes on this PR."
167539
- }).catch((err) => log.debug(`status checks: ${APPROVAL_CHECK} post failed: ${err}`));
167540
- }
167844
+ }
167845
+ };
167846
+ if (detailsUrl) createParams.details_url = detailsUrl;
167847
+ await ctx.octokit.rest.checks.create(createParams).then(() => log.info(`\xBB posted ${APPROVAL_CHECK_NAME} check`)).catch((err) => log.debug(`status checks: ${APPROVAL_CHECK_NAME} post failed: ${err}`));
167541
167848
  }
167542
167849
 
167543
167850
  // utils/runLifecycle.ts
@@ -167610,7 +167917,8 @@ async function writeRunErrorOutputs(input) {
167610
167917
  error: input.rendered.comment,
167611
167918
  createIfMissing: true
167612
167919
  });
167613
- } catch {
167920
+ } catch (error49) {
167921
+ log.warning(`error comment failed: ${error49 instanceof Error ? error49.message : String(error49)}`);
167614
167922
  }
167615
167923
  }
167616
167924
 
@@ -167650,6 +167958,13 @@ function resolveModelForLog(ctx) {
167650
167958
  if (ctx.payload.model) return `${ctx.payload.model} (unresolved)`;
167651
167959
  return "auto";
167652
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
+ }
167653
167968
  function resolveAgentForLog(ctx) {
167654
167969
  const envAgent = process.env.PULLFROG_AGENT?.trim();
167655
167970
  if (envAgent && envAgent === ctx.agentName) {
@@ -167664,6 +167979,9 @@ function logRunStartup(ctx) {
167664
167979
  log.info(
167665
167980
  `\xBB model: ${resolveModelForLog({ payload: ctx.payload, resolvedModel: ctx.resolvedModel })}`
167666
167981
  );
167982
+ log.info(
167983
+ `\xBB effort: ${resolveEffortForLog({ payload: ctx.payload, resolvedModel: ctx.resolvedModel })}`
167984
+ );
167667
167985
  log.info(
167668
167986
  `\xBB agent: ${resolveAgentForLog({ agentName: ctx.agentName, resolvedModel: ctx.resolvedModel })}`
167669
167987
  );
@@ -167829,7 +168147,7 @@ async function resolveRun(params) {
167829
168147
 
167830
168148
  // main.ts
167831
168149
  async function main() {
167832
- var _stack2 = [];
168150
+ var _stack3 = [];
167833
168151
  try {
167834
168152
  normalizeEnv();
167835
168153
  const overridesRaw = process.env.UNSAFE_OVERRIDES ?? "";
@@ -167857,12 +168175,48 @@ async function main() {
167857
168175
  const initialOctokit = createOctokit(jobToken);
167858
168176
  const runContext = await resolveRunContextData({ octokit: initialOctokit, token: jobToken });
167859
168177
  timer.checkpoint("runContextData");
168178
+ const payload = resolvePayload(resolvedPromptInput, runContext.repoSettings);
167860
168179
  const toolState = initToolState({
167861
168180
  progressComment: typeof resolvedPromptInput !== "string" ? resolvedPromptInput.progressComment : void 0,
167862
168181
  owner: runContext.repo.owner,
167863
168182
  name: runContext.repo.name,
167864
168183
  dir: process.cwd()
167865
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
+ }
167866
168220
  createTempDirectory();
167867
168221
  const opencodeCliPath = await agents.opencode.install();
167868
168222
  captureBaselineModels(opencodeCliPath);
@@ -167881,27 +168235,13 @@ async function main() {
167881
168235
  if (runContext.repoSettings.envAllowlist) {
167882
168236
  setEnvAllowlist(runContext.repoSettings.envAllowlist);
167883
168237
  }
167884
- const payload = resolvePayload(resolvedPromptInput, runContext.repoSettings);
167885
- toolState.model = payload.model;
167886
- toolState.oss = runContext.oss;
167887
- toolState.shaPinned = isActionPinnedToSha();
167888
- if (payload.event.issue_number !== void 0) {
167889
- primaryRepoState(toolState).issueNumber = payload.event.issue_number;
167890
- }
167891
- if (payload.event.trigger === "pull_request_synchronize") {
167892
- primaryRepoState(toolState).beforeSha = payload.event.before_sha;
167893
- }
167894
- const oidcCredentials = process.env.ACTIONS_ID_TOKEN_REQUEST_URL && process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN ? {
167895
- requestUrl: process.env.ACTIONS_ID_TOKEN_REQUEST_URL,
167896
- requestToken: process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN
167897
- } : null;
167898
168238
  const xrepoUnavailable = payload.xrepo?.unavailable ?? [];
167899
168239
  if (xrepoUnavailable.length > 0) {
167900
168240
  log.warning(
167901
168241
  `\xBB --xrepo: requested but not granted: ${xrepoUnavailable.join(", ")} (unknown repo, different owner, or you lack access)`
167902
168242
  );
167903
168243
  }
167904
- const tokenRef = __using(_stack2, await resolveTokens({
168244
+ const tokenRef = __using(_stack3, await resolveTokens({
167905
168245
  push: payload.push,
167906
168246
  xrepo: payload.xrepo,
167907
168247
  oidc: oidcCredentials
@@ -167926,7 +168266,7 @@ async function main() {
167926
168266
  let todoTracker;
167927
168267
  let vertexCredentials;
167928
168268
  try {
167929
- var _stack = [];
168269
+ var _stack2 = [];
167930
168270
  try {
167931
168271
  if (payload.cwd && process.cwd() !== payload.cwd) {
167932
168272
  process.chdir(payload.cwd);
@@ -167946,7 +168286,7 @@ async function main() {
167946
168286
  payload.prompt = payload.prompt.replace(originalBody, resolvedBody ?? "");
167947
168287
  }
167948
168288
  }
167949
- const gitAuthServer = __using(_stack, await startGitAuthServer(tmpdir4), true);
168289
+ const gitAuthServer = __using(_stack2, await startGitAuthServer(tmpdir4), true);
167950
168290
  setGitAuthServer(gitAuthServer);
167951
168291
  const access = decideModelAccess({
167952
168292
  modelExplicit: payload.modelExplicit ?? false,
@@ -167969,6 +168309,7 @@ async function main() {
167969
168309
  }
167970
168310
  if (access.kind === "proxy") payload.proxyModel = access.target;
167971
168311
  if (access.kind === "byok") payload.proxyModel = void 0;
168312
+ if (runContext.oss && payload.proxyModel) payload.effort = 0;
167972
168313
  const resolvedModel = payload.proxyModel ? void 0 : resolveModel({ slug: payload.model });
167973
168314
  vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
167974
168315
  const agent2 = resolveAgent({ model: resolvedModel });
@@ -168049,7 +168390,7 @@ async function main() {
168049
168390
  plan: runContext.plan,
168050
168391
  resolvedModel
168051
168392
  };
168052
- const mcpHttpServer = __using(_stack, await startMcpHttpServer(toolContext, { outputSchema }), true);
168393
+ const mcpHttpServer = __using(_stack2, await startMcpHttpServer(toolContext, { outputSchema }), true);
168053
168394
  toolContext.mcpServerUrl = mcpHttpServer.url;
168054
168395
  log.info(`\xBB MCP server started at ${mcpHttpServer.url}`);
168055
168396
  timer.checkpoint("mcpServer");
@@ -168232,7 +168573,7 @@ ${instructions.user}` : null,
168232
168573
  const timeoutMs = usable ?? 36e5;
168233
168574
  const actualTimeout = usable !== null ? payload.timeout : "1h";
168234
168575
  let timeoutId;
168235
- const timeoutPromise = new Promise((_4, reject) => {
168576
+ const timeoutPromise = new Promise((_5, reject) => {
168236
168577
  timeoutId = setTimeout(() => {
168237
168578
  reject(new Error(`agent run timed out after ${actualTimeout}`));
168238
168579
  }, timeoutMs);
@@ -168259,11 +168600,11 @@ ${instructions.user}` : null,
168259
168600
  toolContext,
168260
168601
  silent: payload.event.silent ?? false
168261
168602
  });
168262
- } catch (_2) {
168263
- var _error = _2, _hasError = true;
168603
+ } catch (_3) {
168604
+ var _error2 = _3, _hasError2 = true;
168264
168605
  } finally {
168265
- var _promise2 = __callDispose(_stack, _error, _hasError);
168266
- _promise2 && await _promise2;
168606
+ var _promise3 = __callDispose(_stack2, _error2, _hasError2);
168607
+ _promise3 && await _promise3;
168267
168608
  }
168268
168609
  } catch (error49) {
168269
168610
  const errorMessage = error49 instanceof Error ? error49.message : "unknown error occurred";
@@ -168307,11 +168648,11 @@ ${instructions.user}` : null,
168307
168648
  }
168308
168649
  cleanupVertexCredentials(vertexCredentials);
168309
168650
  }
168310
- } catch (_3) {
168311
- var _error2 = _3, _hasError2 = true;
168651
+ } catch (_4) {
168652
+ var _error3 = _4, _hasError3 = true;
168312
168653
  } finally {
168313
- var _promise3 = __callDispose(_stack2, _error2, _hasError2);
168314
- _promise3 && await _promise3;
168654
+ var _promise4 = __callDispose(_stack3, _error3, _hasError3);
168655
+ _promise4 && await _promise4;
168315
168656
  }
168316
168657
  }
168317
168658
 
@@ -168938,7 +169279,8 @@ async function handleSecret(ctx) {
168938
169279
  }
168939
169280
  if (method === "pullfrog") {
168940
169281
  const scope2 = ctx.secrets.isOrg ? await promptScope2(ctx) : "account";
168941
- activeSpin2.start(`saving ${envVar}`);
169282
+ const target = describeSecretTarget({ owner: ctx.owner, repo: ctx.repo, scope: scope2 });
169283
+ activeSpin2.start(`saving ${import_picocolors3.default.cyan(envVar)} to ${target}`);
168942
169284
  let saveResult;
168943
169285
  try {
168944
169286
  saveResult = await setPullfrogSecret2({
@@ -168958,7 +169300,7 @@ async function handleSecret(ctx) {
168958
169300
  return;
168959
169301
  }
168960
169302
  if (saveResult.saved) {
168961
- activeSpin2.stop(`saved ${import_picocolors3.default.cyan(envVar)} to Pullfrog`);
169303
+ activeSpin2.stop(`saved ${import_picocolors3.default.cyan(envVar)} to ${target}`);
168962
169304
  } else {
168963
169305
  activeSpin2.stop(import_picocolors3.default.red("could not save secret"));
168964
169306
  O2.warn(
@@ -169308,7 +169650,7 @@ async function runCli4(input) {
169308
169650
  }
169309
169651
 
169310
169652
  // cli.ts
169311
- var VERSION10 = "0.1.46";
169653
+ var VERSION10 = "0.1.48";
169312
169654
  var bin = basename2(process.argv[1] || "");
169313
169655
  var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
169314
169656
  var rawArgs = process.argv.slice(2);