pullfrog 0.1.105 → 0.1.107

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
@@ -78971,8 +78971,8 @@ var require_resolve = __commonJS({
78971
78971
  }
78972
78972
  return count;
78973
78973
  }
78974
- function getFullPath(resolver, id = "", normalize3) {
78975
- if (normalize3 !== false)
78974
+ function getFullPath(resolver, id = "", normalize4) {
78975
+ if (normalize4 !== false)
78976
78976
  id = normalizeId(id);
78977
78977
  const p = resolver.parse(id);
78978
78978
  return _getFullPath(resolver, p);
@@ -80601,7 +80601,7 @@ var require_fast_uri = __commonJS({
80601
80601
  }
80602
80602
  return stringScheme;
80603
80603
  }
80604
- function normalize3(uri, options) {
80604
+ function normalize4(uri, options) {
80605
80605
  if (typeof uri === "string") {
80606
80606
  uri = /** @type {T} */
80607
80607
  normalizeString(uri, options);
@@ -81001,7 +81001,7 @@ var require_fast_uri = __commonJS({
81001
81001
  }
81002
81002
  var fastUri = {
81003
81003
  SCHEMES,
81004
- normalize: normalize3,
81004
+ normalize: normalize4,
81005
81005
  resolve: resolve3,
81006
81006
  resolveComponent,
81007
81007
  equal,
@@ -112919,7 +112919,7 @@ var import_picocolors = __toESM(require_picocolors(), 1);
112919
112919
  // package.json
112920
112920
  var package_default = {
112921
112921
  name: "pullfrog",
112922
- version: "0.1.105",
112922
+ version: "0.1.107",
112923
112923
  cliContractVersion: "1",
112924
112924
  type: "module",
112925
112925
  bin: {
@@ -116293,7 +116293,7 @@ function rungPosition(params) {
116293
116293
  function provider(config3) {
116294
116294
  return config3;
116295
116295
  }
116296
- var providers2 = {
116296
+ var bundledProviders = {
116297
116297
  anthropic: provider({
116298
116298
  displayName: "Anthropic",
116299
116299
  envVars: ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"],
@@ -116313,7 +116313,8 @@ var providers2 = {
116313
116313
  // versions (claude-fable-5 was missing there when this was added), so track ~…-latest to
116314
116314
  // stay catalog-valid and auto-follow version bumps.
116315
116315
  openRouterResolve: "openrouter/~anthropic/claude-fable-latest",
116316
- subagentModel: "claude-sonnet"
116316
+ subagentModel: "claude-sonnet",
116317
+ pinned: true
116317
116318
  },
116318
116319
  "claude-opus": {
116319
116320
  displayName: "Claude Opus",
@@ -116371,7 +116372,8 @@ var providers2 = {
116371
116372
  resolve: "openai/gpt-6.1-sol",
116372
116373
  effort: ["low", "medium", "high", "xhigh", "max"],
116373
116374
  openRouterResolve: "openrouter/openai/gpt-6.1-sol-pro",
116374
- subagentModel: "gpt-sol"
116375
+ subagentModel: "gpt-sol",
116376
+ pinned: true
116375
116377
  },
116376
116378
  // gpt-5.6's balanced mid-tier. selectable on its own and doubles as Sol's
116377
116379
  // cheaper lens-fanout subagent — replaces the old hidden gpt-5.4 target.
@@ -116559,7 +116561,8 @@ var providers2 = {
116559
116561
  resolve: "deepseek/deepseek-flash",
116560
116562
  effort: ["low", "high", "max"],
116561
116563
  openRouterEffort: ["none", "low", "high", "max"],
116562
- openRouterResolve: "openrouter/deepseek/deepseek-v4.1-flash"
116564
+ openRouterResolve: "openrouter/deepseek/deepseek-v4.1-flash",
116565
+ pinned: true
116563
116566
  },
116564
116567
  // legacy aliases — deepseek retires these on 2026-07-24; transparently
116565
116568
  // upgrade existing users to the v4 family via the fallback chain.
@@ -116734,7 +116737,8 @@ var providers2 = {
116734
116737
  resolve: "opencode/claude-fable-5-1",
116735
116738
  effort: ["low", "medium", "high", "xhigh", "max"],
116736
116739
  openRouterResolve: "openrouter/~anthropic/claude-fable-latest",
116737
- subagentModel: "claude-sonnet"
116740
+ subagentModel: "claude-sonnet",
116741
+ pinned: true
116738
116742
  },
116739
116743
  "claude-opus": {
116740
116744
  displayName: "Claude Opus",
@@ -116782,7 +116786,8 @@ var providers2 = {
116782
116786
  resolve: "opencode/gpt-6.1-sol",
116783
116787
  effort: ["low", "medium", "high", "xhigh", "max"],
116784
116788
  openRouterResolve: "openrouter/openai/gpt-6.1-sol-pro",
116785
- subagentModel: "gpt-sol"
116789
+ subagentModel: "gpt-sol",
116790
+ pinned: true
116786
116791
  },
116787
116792
  // gpt-5.6 balanced mid-tier — selectable + Sol's subagent. see openai above.
116788
116793
  "gpt-terra": {
@@ -116869,7 +116874,8 @@ var providers2 = {
116869
116874
  // id. k2.6 is the newest build Zen will actually serve, and the mirror
116870
116875
  // guard permits the step down because k2.7-code is in ZEN_UNDEPLOYED.
116871
116876
  resolve: "opencode/kimi-k2.6",
116872
- openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
116877
+ openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code",
116878
+ pinned: true
116873
116879
  },
116874
116880
  // M3 is its own line beside M2, not a bump of it — same reason `kimi-k3`
116875
116881
  // sits beside `kimi-k2` rather than replacing it.
@@ -117338,13 +117344,15 @@ var providers2 = {
117338
117344
  effort: ["low", "medium", "high", "xhigh", "max"],
117339
117345
  openRouterResolve: "openrouter/~anthropic/claude-opus-latest",
117340
117346
  preferred: true,
117341
- subagentModel: "claude-sonnet"
117347
+ subagentModel: "claude-sonnet",
117348
+ pinned: true
117342
117349
  },
117343
117350
  "claude-sonnet": {
117344
117351
  displayName: "Claude Sonnet",
117345
117352
  resolve: "openrouter/~anthropic/claude-sonnet-latest",
117346
117353
  effort: ["low", "medium", "high", "xhigh", "max"],
117347
- openRouterResolve: "openrouter/~anthropic/claude-sonnet-latest"
117354
+ openRouterResolve: "openrouter/~anthropic/claude-sonnet-latest",
117355
+ pinned: true
117348
117356
  },
117349
117357
  "claude-haiku": {
117350
117358
  displayName: "Claude Haiku",
@@ -117352,7 +117360,8 @@ var providers2 = {
117352
117360
  // the rolling alias moved to Haiku 5.5 on 2026-10-07, which publishes
117353
117361
  // the ladder Haiku 4.5 did not.
117354
117362
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
117355
- openRouterResolve: "openrouter/~anthropic/claude-haiku-latest"
117363
+ openRouterResolve: "openrouter/~anthropic/claude-haiku-latest",
117364
+ pinned: true
117356
117365
  },
117357
117366
  // pinned to the explicit Sol/Terra/Luna tiers (not the ~openai/gpt-latest
117358
117367
  // rolling alias): after that rename, ~gpt-mini-latest no longer maps
@@ -117379,7 +117388,8 @@ var providers2 = {
117379
117388
  resolve: "openrouter/openai/gpt-6.1-sol-pro",
117380
117389
  effort: ["low", "medium", "high", "xhigh", "max"],
117381
117390
  openRouterResolve: "openrouter/openai/gpt-6.1-sol-pro",
117382
- subagentModel: "gpt-sol"
117391
+ subagentModel: "gpt-sol",
117392
+ pinned: true
117383
117393
  },
117384
117394
  // gpt-5.6 balanced mid-tier — selectable + Sol's subagent. see openai above.
117385
117395
  "gpt-terra": {
@@ -117444,8 +117454,9 @@ var providers2 = {
117444
117454
  displayName: "Gemini Pro",
117445
117455
  resolve: "openrouter/~google/gemini-pro-latest",
117446
117456
  effort: ["low", "medium", "high"],
117447
- openRouterResolve: "openrouter/~google/gemini-pro-latest"
117457
+ openRouterResolve: "openrouter/~google/gemini-pro-latest",
117448
117458
  // Inherit — see google/gemini-pro for rationale.
117459
+ pinned: true
117449
117460
  },
117450
117461
  "gemini-flash": {
117451
117462
  displayName: "Gemini Flash",
@@ -117454,7 +117465,8 @@ var providers2 = {
117454
117465
  // entry tracks its siblings' generation bumps for free. the ladder still
117455
117466
  // mirrors exactly: claude-code hard-errors on an out-of-range `--effort`.
117456
117467
  effort: ["low", "medium", "high"],
117457
- openRouterResolve: "openrouter/~google/gemini-flash-latest"
117468
+ openRouterResolve: "openrouter/~google/gemini-flash-latest",
117469
+ pinned: true
117458
117470
  },
117459
117471
  grok: {
117460
117472
  displayName: "Grok",
@@ -117477,7 +117489,8 @@ var providers2 = {
117477
117489
  displayName: "DeepSeek Flash",
117478
117490
  resolve: "openrouter/deepseek/deepseek-v4.1-flash",
117479
117491
  effort: ["none", "low", "high", "max"],
117480
- openRouterResolve: "openrouter/deepseek/deepseek-v4.1-flash"
117492
+ openRouterResolve: "openrouter/deepseek/deepseek-v4.1-flash",
117493
+ pinned: true
117481
117494
  },
117482
117495
  // legacy alias — deepseek retires this on 2026-07-24; transparently
117483
117496
  // upgrade existing users to the v4 family via the fallback chain.
@@ -117634,6 +117647,7 @@ var providers2 = {
117634
117647
  }
117635
117648
  })
117636
117649
  };
117650
+ var providers2 = bundledProviders;
117637
117651
  function parseModel(slug2) {
117638
117652
  const slashIdx = slug2.indexOf("/");
117639
117653
  if (slashIdx === -1) {
@@ -117672,27 +117686,30 @@ var CLAUDE_CODE_ONLY_CREDENTIALS = ["ANTHROPIC_AUTH_TOKEN", "CLAUDE_CODE_OAUTH_T
117672
117686
  function getOpenCodeEnvVars(slug2) {
117673
117687
  return getModelEnvVars(slug2).filter((v) => !CLAUDE_CODE_ONLY_CREDENTIALS.includes(v));
117674
117688
  }
117675
- var modelAliases = Object.entries(providers2).flatMap(
117676
- ([providerKey, config3]) => Object.entries(config3.models).map(([modelId, def]) => ({
117677
- slug: `${providerKey}/${modelId}`,
117678
- provider: providerKey,
117679
- displayName: def.displayName,
117680
- description: def.description,
117681
- resolve: def.resolve,
117682
- openRouterResolve: def.openRouterResolve,
117683
- preferred: def.preferred ?? false,
117684
- isFree: def.isFree ?? false,
117685
- fallback: def.fallback,
117686
- routing: def.routing,
117687
- // subagentModel is stored as an alias key local to the provider; expand
117688
- // here to a fully-qualified slug so callers can look up the target alias
117689
- // directly without re-deriving the provider.
117690
- subagentModel: def.subagentModel ? `${providerKey}/${def.subagentModel}` : void 0,
117691
- effort: def.effort,
117692
- openRouterEffort: def.openRouterEffort,
117693
- hidden: def.hidden ?? false
117694
- }))
117695
- );
117689
+ function flattenAliases(source) {
117690
+ return Object.entries(source).flatMap(
117691
+ ([providerKey, config3]) => Object.entries(config3.models).map(([modelId, def]) => ({
117692
+ slug: `${providerKey}/${modelId}`,
117693
+ provider: providerKey,
117694
+ displayName: def.displayName,
117695
+ description: def.description,
117696
+ resolve: def.resolve,
117697
+ openRouterResolve: def.openRouterResolve,
117698
+ preferred: def.preferred ?? false,
117699
+ isFree: def.isFree ?? false,
117700
+ fallback: def.fallback,
117701
+ routing: def.routing,
117702
+ // subagentModel is stored as an alias key local to the provider; expand
117703
+ // here to a fully-qualified slug so callers can look up the target alias
117704
+ // directly without re-deriving the provider.
117705
+ subagentModel: def.subagentModel ? `${providerKey}/${def.subagentModel}` : void 0,
117706
+ effort: def.effort,
117707
+ openRouterEffort: def.openRouterEffort,
117708
+ hidden: def.hidden ?? false
117709
+ }))
117710
+ );
117711
+ }
117712
+ var modelAliases = flattenAliases(providers2);
117696
117713
  var AUTO_EFFICIENT = "auto/efficient";
117697
117714
  var AUTO_INTELLIGENT = "auto/intelligent";
117698
117715
  var AUTO_TIER_TARGET = {
@@ -117764,9 +117781,7 @@ function autoLadder(slug2) {
117764
117781
  const target = slug2.slice(AUTO_PREFIX.length);
117765
117782
  return target === "router" ? ROUTER_LADDER : PROVIDER_LADDERS[target];
117766
117783
  }
117767
- var ROUTED_PROVIDERS = Object.keys(
117768
- PROVIDER_LADDERS
117769
- ).map((key) => ({ key, displayName: providers2[key].displayName }));
117784
+ var ROUTED_PROVIDERS;
117770
117785
  function isCardGatedModel(slug2) {
117771
117786
  return resolveOpenRouterModel(slug2) !== void 0;
117772
117787
  }
@@ -117804,27 +117819,21 @@ function resolveModelRung(params) {
117804
117819
  if (!published) return void 0;
117805
117820
  return resolveRung({ position: params.position, published });
117806
117821
  }
117807
- var defaultProxyAlias = resolveDisplayAlias(AUTO_EFFICIENT);
117808
- if (!defaultProxyAlias?.openRouterResolve) {
117809
- throw new Error(`DEFAULT_PROXY_MODEL: ${AUTO_EFFICIENT} has no openRouterResolve`);
117810
- }
117811
- var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
117812
- var defaultProxyDisplayName = defaultProxyAlias.displayName;
117813
- var trialProxyAlias = resolveDisplayAlias("openai/gpt-luna");
117814
- if (!trialProxyAlias?.openRouterResolve) {
117815
- throw new Error("TRIAL_PROXY_MODEL: openai/gpt-luna has no openRouterResolve");
117816
- }
117817
- var TRIAL_PROXY_MODEL = trialProxyAlias.openRouterResolve;
117818
- var TRIAL_PROXY_DISPLAY_NAME = trialProxyAlias.displayName;
117822
+ var DEFAULT_PROXY_MODEL;
117823
+ var defaultProxyDisplayName;
117824
+ var TRIAL_PROXY_MODEL;
117825
+ var TRIAL_PROXY_DISPLAY_NAME;
117819
117826
  var TRIAL_FUNDED_USD_LIMIT = 10;
117820
- for (const [name, ladder] of Object.entries({ ...PROVIDER_LADDERS, router: ROUTER_LADDER })) {
117821
- const terminal = /* @__PURE__ */ new Set();
117822
- for (const slug2 of Object.values(ladder)) {
117823
- const alias = resolveDisplayAlias(slug2);
117824
- if (!alias) throw new Error(`${name} ladder names unknown alias ${slug2}`);
117825
- terminal.add(alias.slug);
117827
+ function checkLadders() {
117828
+ for (const [name, ladder] of Object.entries({ ...PROVIDER_LADDERS, router: ROUTER_LADDER })) {
117829
+ const terminal = /* @__PURE__ */ new Set();
117830
+ for (const slug2 of Object.values(ladder)) {
117831
+ const alias = resolveDisplayAlias(slug2);
117832
+ if (!alias) throw new Error(`${name} ladder names unknown alias ${slug2}`);
117833
+ terminal.add(alias.slug);
117834
+ }
117835
+ if (terminal.size < 2) throw new Error(`${name} ladder runs every tier on ${[...terminal][0]}`);
117826
117836
  }
117827
- if (terminal.size < 2) throw new Error(`${name} ladder runs every tier on ${[...terminal][0]}`);
117828
117837
  }
117829
117838
  var OSS_MODEL_ALLOWLIST = [
117830
117839
  // opt-in: 0.86x the old default on the measured mix, and Meta trains on the
@@ -117839,13 +117848,46 @@ var OSS_RECOMMENDED_MODEL = AUTO_TIER_TARGET[AUTO_EFFICIENT];
117839
117848
  function ossFundedModelNames() {
117840
117849
  return OSS_MODEL_ALLOWLIST.map((slug2) => resolveDisplayAlias(slug2)?.displayName ?? slug2);
117841
117850
  }
117842
- var ossAllowedTargets = new Set(
117843
- OSS_MODEL_ALLOWLIST.map((slug2) => {
117851
+ var ossAllowedTargets;
117852
+ function deriveFromProviders() {
117853
+ const efficient = resolveDisplayAlias(AUTO_EFFICIENT);
117854
+ if (!efficient?.openRouterResolve) {
117855
+ throw new Error(`DEFAULT_PROXY_MODEL: ${AUTO_EFFICIENT} has no openRouterResolve`);
117856
+ }
117857
+ const trial = resolveDisplayAlias("openai/gpt-luna");
117858
+ if (!trial?.openRouterResolve) {
117859
+ throw new Error("TRIAL_PROXY_MODEL: openai/gpt-luna has no openRouterResolve");
117860
+ }
117861
+ checkLadders();
117862
+ const allowed = OSS_MODEL_ALLOWLIST.map((slug2) => {
117844
117863
  const target = resolveOpenRouterModel(slug2);
117845
117864
  if (!target) throw new Error(`OSS_MODEL_ALLOWLIST: ${slug2} has no openRouterResolve`);
117846
117865
  return target;
117847
- })
117848
- );
117866
+ });
117867
+ DEFAULT_PROXY_MODEL = efficient.openRouterResolve;
117868
+ defaultProxyDisplayName = efficient.displayName;
117869
+ TRIAL_PROXY_MODEL = trial.openRouterResolve;
117870
+ TRIAL_PROXY_DISPLAY_NAME = trial.displayName;
117871
+ ossAllowedTargets = new Set(allowed);
117872
+ ROUTED_PROVIDERS = Object.keys(PROVIDER_LADDERS).map((key) => ({
117873
+ key,
117874
+ displayName: providers2[key]?.displayName ?? key
117875
+ }));
117876
+ }
117877
+ deriveFromProviders();
117878
+ function installProviders(next2) {
117879
+ const previous = providers2;
117880
+ try {
117881
+ providers2 = next2;
117882
+ modelAliases = flattenAliases(next2);
117883
+ deriveFromProviders();
117884
+ } catch (error63) {
117885
+ providers2 = previous;
117886
+ modelAliases = flattenAliases(previous);
117887
+ deriveFromProviders();
117888
+ throw error63;
117889
+ }
117890
+ }
117849
117891
  function isOssAllowedModel(slug2) {
117850
117892
  if (!slug2) return false;
117851
117893
  const target = resolveOpenRouterModel(slug2);
@@ -118054,12 +118096,15 @@ function createProcessOutputActivityTimeout(ctx) {
118054
118096
 
118055
118097
  // utils/claudeSubscription.ts
118056
118098
  var CLAUDE_CODE_IDENTITY = "You are Claude Code, Anthropic's official CLI for Claude.";
118057
- var fallbackResolve = resolveModelSlug("anthropic/claude-haiku");
118058
- if (!fallbackResolve) {
118059
- throw new Error("claudeSubscription preflight: anthropic/claude-haiku missing from registry");
118099
+ function fallbackProbeModel() {
118100
+ const resolve3 = resolveModelSlug("anthropic/claude-haiku");
118101
+ if (!resolve3) {
118102
+ throw new Error("claudeSubscription preflight: anthropic/claude-haiku missing from registry");
118103
+ }
118104
+ return resolve3.slice(resolve3.indexOf("/") + 1);
118060
118105
  }
118061
- var FALLBACK_PROBE_MODEL = fallbackResolve.slice(fallbackResolve.indexOf("/") + 1);
118062
118106
  async function preflightClaudeSubscription(params) {
118107
+ const model = params.model ?? fallbackProbeModel();
118063
118108
  let res;
118064
118109
  try {
118065
118110
  res = await fetch("https://api.anthropic.com/v1/messages", {
@@ -118072,7 +118117,7 @@ async function preflightClaudeSubscription(params) {
118072
118117
  "x-app": "cli"
118073
118118
  },
118074
118119
  body: JSON.stringify({
118075
- model: params.model ?? FALLBACK_PROBE_MODEL,
118120
+ model,
118076
118121
  max_tokens: 1,
118077
118122
  system: CLAUDE_CODE_IDENTITY,
118078
118123
  messages: [{ role: "user", content: "ok" }]
@@ -118421,7 +118466,7 @@ import { chmodSync, createWriteStream, existsSync as existsSync4, mkdirSync } fr
118421
118466
  import { join as join2 } from "node:path";
118422
118467
  import { pipeline } from "node:stream/promises";
118423
118468
  function resolveNpm() {
118424
- const npmCli = process.env.npm_execpath;
118469
+ const npmCli = process.env.NPM_EXECPATH;
118425
118470
  if (npmCli?.endsWith("npm-cli.js")) return { command: process.execPath, args: [npmCli] };
118426
118471
  return { command: "npm", args: [] };
118427
118472
  }
@@ -118756,6 +118801,10 @@ function getDevDependencyVersion(name) {
118756
118801
  }
118757
118802
  return version3;
118758
118803
  }
118804
+ var HARNESS_PACKAGES = ["@anthropic-ai/claude-code", "@openai/codex", "opencode-ai"];
118805
+ function getHarnessPins() {
118806
+ return Object.fromEntries(HARNESS_PACKAGES.map((name) => [name, getDevDependencyVersion(name)]));
118807
+ }
118759
118808
 
118760
118809
  // utils/skills.ts
118761
118810
  var skillsVersion = getDevDependencyVersion("skills");
@@ -119424,8 +119473,12 @@ Every body \`### \` section carries one; an inline comment carries one when its
119424
119473
  The 4-backtick fence lets the block hold its own 3-backtick fences and stay one-click copyable. Skip the optional sections when they'd add nothing.
119425
119474
 
119426
119475
  Backtick-wrap identifiers and file names. Don't repeat diff content, don't include raw \`+123 / -45\` stats, no changelog, no horizontal rules, and no \`### Key changes\` / \`### Issues found\` / \`<b>TL;DR</b>\` heading \u2014 each \`### \` heading IS the issue.`;
119427
- function computeModes(agentId, signedCommits = false) {
119476
+ function computeModes(params) {
119477
+ const agentId = params.agentId;
119478
+ const signedCommits = params.signedCommits ?? false;
119479
+ const botLogin = params.botLogin ?? "pullfrog[bot]";
119428
119480
  const t2 = (toolName) => formatMcpToolRef(agentId, toolName);
119481
+ const selfAuthor = botLogin === "pullfrog[bot]" ? "`author=pullfrog[bot]`" : `\`author=${botLogin}\` or \`author=pullfrog[bot]\``;
119429
119482
  const commitStep = signedCommits ? `commit via \`${t2("commit_changes")}\` \u2014 it lands a GitHub-signed commit directly on the remote branch (no push step)` : `commit locally via shell (\`git add . && git commit -m "..."\`)`;
119430
119483
  const finalizeStep = signedCommits ? `confirm a clean working tree (\`git status\`) \u2014 your \`${t2("commit_changes")}\` calls already landed the work on the remote` : `confirm a clean working tree, then push via \`${t2("push_branch")}\``;
119431
119484
  return [
@@ -119599,7 +119652,7 @@ ${PR_SUMMARY_FORMAT}`
119599
119652
 
119600
119653
  4. **prior feedback \u2014 read AND retire it**: fetch previous reviews via \`${t2("list_pull_request_reviews")}\`, then call \`${t2("get_review_comments")}\` on each prior Pullfrog review. Each thread renders as a section whose first line is a fenced tag \`comment author=<login> id=<fullDatabaseId> review=<reviewId> thread=<graphqlId>\`; section headers carry \`[RESOLVED]\` / \`[OUTDATED]\` when relevant. For every **open, Pullfrog-originated** thread, decide and act:
119601
119654
 
119602
- - **Pullfrog-originated** means the FIRST \`comment author=...\` tag in the section is \`author=pullfrog[bot]\`. The \`*\` marker on individual comments is unrelated \u2014 it flags whether a comment belongs to the queried review, not whether it is the thread root.
119655
+ - **Pullfrog-originated** means the FIRST \`comment author=...\` tag in the section is ${selfAuthor}. The \`*\` marker on individual comments is unrelated \u2014 it flags whether a comment belongs to the queried review, not whether it is the thread root.
119603
119656
  - **addressed?** read the file at the thread's anchor and judge whether the substantive concern is now resolved by the new commits. Lines being modified isn't enough: reformatting, renaming, or moving the same code elsewhere doesn't address a concern. If the comment raised multiple distinct concerns, ALL must be addressed. The \`[OUTDATED]\` tag means GitHub moved the anchor (line shift, force-push, rename) \u2014 it does NOT mean the concern was addressed; re-read the code at its new location before deciding.
119604
119657
  - **if addressed**: call \`${t2("reply_to_review_comment")}\` with the root tag's numeric \`id=\` as \`comment_id\` (NOT the \`thread=\` value \u2014 that's a separate GraphQL ID used only by resolve) and a one-line body (e.g. \`Addressed in <short-sha>.\`), then call \`${t2("resolve_review_thread")}\` with the root tag's \`thread=\` value as \`thread_id\`. Do this BEFORE drafting the new review so the GitHub thread state aligns with the new review by the time it lands.
119605
119658
  - **if uncertain or partially addressed**: leave open. False-positive resolutions erode trust faster than false negatives.
@@ -119740,7 +119793,7 @@ ${PR_SUMMARY_FORMAT}`
119740
119793
  }
119741
119794
  ];
119742
119795
  }
119743
- var modes = computeModes("opencode");
119796
+ var modes = computeModes({ agentId: "opencode" });
119744
119797
  var NON_COMMITTING_MODES = /* @__PURE__ */ new Set([
119745
119798
  "Review",
119746
119799
  "IncrementalReview",
@@ -121960,7 +122013,7 @@ var codex = agent({
121960
122013
 
121961
122014
  // agents/opencode.ts
121962
122015
  import { spawn as nodeSpawn2 } from "node:child_process";
121963
- import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "node:fs";
122016
+ import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "node:fs";
121964
122017
  import { totalmem } from "node:os";
121965
122018
  import { join as join9 } from "node:path";
121966
122019
  import { performance as performance7 } from "node:perf_hooks";
@@ -127373,10 +127426,770 @@ var import_undici2 = __toESM(require_undici2(), 1);
127373
127426
 
127374
127427
  // utils/openCodeModels.ts
127375
127428
  import { spawnSync as spawnSync4 } from "node:child_process";
127429
+ import { createHash as createHash2 } from "node:crypto";
127430
+ import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "node:fs";
127376
127431
  import { join as join8 } from "node:path";
127432
+
127433
+ // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/cache/adapter.js
127434
+ var AdapterError = class extends Error {
127435
+ /** the adapter method that failed */
127436
+ method;
127437
+ /** the full store key, or the op's prefix when the call covered many keys. never the raw input. */
127438
+ key;
127439
+ constructor(method, key, cause) {
127440
+ super(`cache ${method} failed for ${key}: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
127441
+ this.name = "AdapterError";
127442
+ this.method = method;
127443
+ this.key = key;
127444
+ }
127445
+ };
127446
+
127447
+ // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/cache/memory.js
127448
+ function memory({ maxItems = 1e3 } = {}) {
127449
+ const store = /* @__PURE__ */ new Map();
127450
+ const peek = (key) => {
127451
+ const slot = store.get(key);
127452
+ if (slot === void 0)
127453
+ return;
127454
+ if (slot.until > Date.now())
127455
+ return slot;
127456
+ store.delete(key);
127457
+ };
127458
+ const evict = () => {
127459
+ for (const [key, slot] of store) {
127460
+ store.delete(key);
127461
+ if (!slot.used)
127462
+ return;
127463
+ slot.used = false;
127464
+ store.set(key, slot);
127465
+ }
127466
+ };
127467
+ return {
127468
+ get: (key) => {
127469
+ const slot = peek(key);
127470
+ if (slot === void 0)
127471
+ return;
127472
+ slot.used = true;
127473
+ return slot.entry;
127474
+ },
127475
+ peek: (key) => peek(key)?.entry,
127476
+ // the TTL rides on each entry, so ops with different lifetimes can share one store
127477
+ // evicted before the new slot goes in, so the entry being written is never the one dropped: after it, a full store
127478
+ // whose every slot was read would pass each over and drop the new, unread one
127479
+ set: (key, entry, ttlMs) => {
127480
+ store.delete(key);
127481
+ if (store.size >= maxItems)
127482
+ evict();
127483
+ store.set(key, { entry, until: Date.now() + ttlMs, used: false });
127484
+ },
127485
+ delete: (keys) => {
127486
+ for (const key of keys)
127487
+ store.delete(key);
127488
+ },
127489
+ // a snapshot, so deleting while iterating is safe
127490
+ list: (prefix) => {
127491
+ const now = Date.now();
127492
+ const listed = [];
127493
+ for (const [key, slot] of store)
127494
+ if (slot.until > now && key.startsWith(prefix))
127495
+ listed.push([key, slot.entry]);
127496
+ return listed;
127497
+ }
127498
+ };
127499
+ }
127500
+
127501
+ // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/issues.js
127502
+ function issueJSON(issue4) {
127503
+ const segments = issue4.path ?? [];
127504
+ const path4 = [];
127505
+ for (let i2 = 0; i2 < segments.length; i2++) {
127506
+ const segment = segments[i2];
127507
+ const wrapped = typeof segment === "object" && segment !== null;
127508
+ const key = wrapped ? segment.key : segment;
127509
+ if (typeof key === "string" || typeof key === "number" && Number.isFinite(key))
127510
+ path4.push(key);
127511
+ else if (typeof key === "symbol")
127512
+ path4.push(String(key));
127513
+ else if (!(wrapped && key === null && segment.type === "set"))
127514
+ break;
127515
+ }
127516
+ const { keyword } = issue4;
127517
+ return typeof keyword === "string" ? { message: issue4.message, path: path4, keyword } : { message: issue4.message, path: path4 };
127518
+ }
127519
+ function issuesJSON(issues) {
127520
+ const out = [];
127521
+ for (let i2 = 0; i2 < issues.length; i2++)
127522
+ if (issues[i2])
127523
+ out.push(issueJSON(issues[i2]));
127524
+ return out;
127525
+ }
127526
+ var identifier = /^[A-Za-z_$][\w$]*$/;
127527
+ var longestKey = 40;
127528
+ function renderPath(path4) {
127529
+ let out = "";
127530
+ for (const key of path4) {
127531
+ if (typeof key === "number")
127532
+ out += `[${key}]`;
127533
+ else if (key.length <= longestKey && identifier.test(key))
127534
+ out += out ? `.${key}` : key;
127535
+ else
127536
+ out += `[${JSON.stringify(key.length <= longestKey ? key : `${key.slice(0, longestKey)}\u2026`)}]`;
127537
+ }
127538
+ return out;
127539
+ }
127540
+ var shown = 10;
127541
+ function summary2(issues, truncated2) {
127542
+ const lines = [];
127543
+ let i2 = 0;
127544
+ for (; i2 < issues.length && lines.length < shown; i2++) {
127545
+ const issue4 = issues[i2];
127546
+ if (!issue4)
127547
+ continue;
127548
+ const { message: message2, path: path4 } = issueJSON(issue4);
127549
+ lines.push(path4.length ? `${renderPath(path4)}: ${message2}` : message2);
127550
+ }
127551
+ let more = 0;
127552
+ for (; i2 < issues.length; i2++)
127553
+ if (issues[i2])
127554
+ more++;
127555
+ if (more > 0)
127556
+ lines.push(truncated2 ? `and over ${more} more` : `and ${more} more`);
127557
+ else if (truncated2)
127558
+ lines.push("and more");
127559
+ return `validation failed: ${lines.join("; ")}`;
127560
+ }
127561
+ var ValidationError = class extends Error {
127562
+ name = "ValidationError";
127563
+ constructor(result) {
127564
+ super(message(result));
127565
+ Object.defineProperty(this, "result", { value: result });
127566
+ Object.assign(this, { issues: result.issues });
127567
+ }
127568
+ /**
127569
+ * The error as plain data, each issue projected to its message, path and keyword, so what else a validator keeps on
127570
+ * one (Valibot's and Zod's `input`) is left out. The messages are the validator's own, and some quote the value.
127571
+ */
127572
+ toJSON() {
127573
+ const json4 = { name: "ValidationError", message: this.message, issues: issuesJSON(this.issues) };
127574
+ return truncated(this.result) ? { ...json4, truncated: true } : json4;
127575
+ }
127576
+ };
127577
+ function message(result) {
127578
+ try {
127579
+ return ownSummary(result) ?? summary2(result.issues, truncated(result));
127580
+ } catch {
127581
+ return "validation failed";
127582
+ }
127583
+ }
127584
+ function ownSummary(result) {
127585
+ const own2 = result;
127586
+ return typeof own2.message === "string" ? own2.message : typeof own2.summary === "string" ? own2.summary : void 0;
127587
+ }
127588
+ var truncated = (result) => result.truncated === true;
127589
+
127590
+ // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/env.js
127591
+ var debugging = () => debug2 ??= read();
127592
+ var read = () => {
127593
+ try {
127594
+ return globalThis.process?.env?.LOG_LEVEL === "debug";
127595
+ } catch {
127596
+ return false;
127597
+ }
127598
+ };
127599
+ var debug2;
127600
+
127601
+ // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/hash-node.js
127602
+ import { createRequire } from "node:module";
127603
+ var sha1 = (text) => {
127604
+ crypto3 ??= load();
127605
+ return crypto3.hash("sha1", text);
127606
+ };
127607
+ var crypto3;
127608
+ var load = () => globalThis.process?.getBuiltinModule?.("node:crypto") ?? createRequire("/")("node:crypto");
127609
+
127610
+ // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/key.js
127611
+ function cacheKey(value2) {
127612
+ if (value2 === null)
127613
+ throw new Error("null cannot be part of a cache key");
127614
+ if (value2 === void 0)
127615
+ return "~void";
127616
+ const json4 = canonical(value2);
127617
+ return json4.length > longKey ? `#${sha1(json4)}` : json4;
127618
+ }
127619
+ var longKey = 4096;
127620
+ function hashKey(key) {
127621
+ if (key === "~void")
127622
+ return key;
127623
+ return key[0] === "#" ? key.slice(1) : sha1(key);
127624
+ }
127625
+ function canonical(value2) {
127626
+ return serialize(value2, 0);
127627
+ }
127628
+ function serialize(value2, depth) {
127629
+ switch (typeof value2) {
127630
+ case "number":
127631
+ if (Number.isFinite(value2))
127632
+ return String(value2);
127633
+ throw new Error(`${value2} cannot be part of a cache key`);
127634
+ case "string":
127635
+ case "boolean":
127636
+ return JSON.stringify(value2);
127637
+ case "undefined":
127638
+ throw new Error("undefined cannot be part of a cache key, except as an object property");
127639
+ case "object":
127640
+ break;
127641
+ default:
127642
+ throw new Error(`a ${typeof value2} cannot be part of a cache key`);
127643
+ }
127644
+ if (value2 === null)
127645
+ return "null";
127646
+ if (depth++ === 64)
127647
+ throw new Error("an input nested more than 64 levels deep, or circular");
127648
+ if (Array.isArray(value2)) {
127649
+ let out2 = "[";
127650
+ for (let i2 = 0; i2 < value2.length; i2++)
127651
+ out2 += `${i2 ? "," : ""}${serialize(value2[i2], depth)}`;
127652
+ return `${out2}]`;
127653
+ }
127654
+ const proto = Object.getPrototypeOf(value2);
127655
+ if (proto !== Object.prototype && proto !== null) {
127656
+ const name = proto.constructor?.name || "class instance";
127657
+ throw new Error(`a ${name} cannot be part of a cache key: only JSON data can`);
127658
+ }
127659
+ let out = "";
127660
+ for (const key of Object.keys(value2).sort()) {
127661
+ const v = value2[key];
127662
+ if (v !== void 0)
127663
+ out += `${out ? "," : ""}${JSON.stringify(key)}:${serialize(v, depth)}`;
127664
+ }
127665
+ return `{${out}}`;
127666
+ }
127667
+
127668
+ // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/plain.js
127669
+ var isPlain = (value2) => {
127670
+ if (typeof value2 !== "object" || value2 === null)
127671
+ return false;
127672
+ const proto = Object.getPrototypeOf(value2);
127673
+ return proto === Object.prototype || proto === null;
127674
+ };
127675
+
127676
+ // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/sleep.js
127677
+ function sleep(ms, signal) {
127678
+ return new Promise((resolve3) => {
127679
+ if (signal?.aborted)
127680
+ return resolve3();
127681
+ const done = () => {
127682
+ clearTimeout(timer);
127683
+ signal?.removeEventListener("abort", done);
127684
+ resolve3();
127685
+ };
127686
+ const timer = setTimeout(done, ms);
127687
+ signal?.addEventListener("abort", done, { once: true });
127688
+ });
127689
+ }
127690
+
127691
+ // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/api.js
127692
+ function backoff(schedule, attempt) {
127693
+ const d = schedule[attempt - 1];
127694
+ return d === void 0 ? -1 : Math.round(d / 2 + Math.random() * d / 2);
127695
+ }
127696
+ async function assertSchema(schema2, value2) {
127697
+ const result = await schema2["~standard"].validate(value2);
127698
+ if (result.issues)
127699
+ throw new ValidationError(result);
127700
+ return result.value;
127701
+ }
127702
+ var TimeoutError = class extends Error {
127703
+ name = "TimeoutError";
127704
+ /** the op's `timeout`, in ms */
127705
+ timeout;
127706
+ constructor(timeout) {
127707
+ super(`attempt timed out after ${timeout}ms`);
127708
+ this.timeout = timeout;
127709
+ }
127710
+ };
127711
+ var gates = /* @__PURE__ */ new WeakMap();
127712
+ function semaphore(size) {
127713
+ let free = size;
127714
+ const line = [];
127715
+ return {
127716
+ acquire: (signal) => free > 0 ? void free-- : wait(line, signal),
127717
+ release: () => {
127718
+ const next2 = line.shift();
127719
+ if (next2)
127720
+ next2();
127721
+ else
127722
+ free++;
127723
+ }
127724
+ };
127725
+ }
127726
+ function wait(line, signal, left) {
127727
+ return new Promise((resolve3, reject) => {
127728
+ const abort = () => {
127729
+ line.splice(line.indexOf(next2), 1);
127730
+ left?.();
127731
+ reject(signal.reason);
127732
+ };
127733
+ const next2 = () => {
127734
+ signal?.removeEventListener("abort", abort);
127735
+ resolve3();
127736
+ };
127737
+ signal?.addEventListener("abort", abort, { once: true });
127738
+ line.push(next2);
127739
+ });
127740
+ }
127741
+ function op(options) {
127742
+ return build(options, true);
127743
+ }
127744
+ function build(options, cacheMethods) {
127745
+ const { name, input: inputSchema, output: outputSchema, run: run4, dedupe, ttl, cache: adapter, timeout } = options;
127746
+ const { retry, concurrency } = options;
127747
+ const delayFor = Array.isArray(retry) ? (_, attempt) => backoff(retry, attempt) : retry;
127748
+ if (ttl !== void 0 && typeof ttl !== "function" && !isLifetime(ttl)) {
127749
+ throw new TypeError(`yes.op: ttl must be a positive number of milliseconds, got ${ttl}`);
127750
+ }
127751
+ if (timeout !== void 0 && !(isLifetime(timeout) && timeout <= maxDelay)) {
127752
+ throw new TypeError(`yes.op: timeout must be a positive number of milliseconds up to ${maxDelay}, got ${timeout}`);
127753
+ }
127754
+ if (concurrency !== void 0 && !(Number.isInteger(concurrency) && concurrency > 0)) {
127755
+ throw new TypeError(`yes.op: concurrency must be a positive integer, got ${concurrency}`);
127756
+ }
127757
+ const lifetime = typeof ttl === "function" ? ttl : (result) => result == null || result instanceof Error ? 0 : ttl;
127758
+ if (adapter && (!name || name.includes(":"))) {
127759
+ throw new TypeError(`yes.op: an op with a cache adapter needs a name without ":", got ${JSON.stringify(name)}`);
127760
+ }
127761
+ if (adapter && ttl === void 0)
127762
+ throw new TypeError(`yes.op: a cache adapter does nothing without a ttl`);
127763
+ const store = ttl === void 0 ? void 0 : adapter ?? memory({ maxItems: options.maxItems });
127764
+ const keepsErrors = !!store && "peek" in store;
127765
+ const prefix = adapter ? `yes:${name}:` : "";
127766
+ const storeKey = adapter ? (key) => prefix + hashedKey(key) : (key) => key.local;
127767
+ const reported = adapter ? void 0 : hashKey;
127768
+ const label = name ? `[${name}] ` : "";
127769
+ const slots = concurrency === void 0 ? void 0 : semaphore(concurrency);
127770
+ const gate = options.rateLimit === void 0 ? void 0 : gates.get(options.rateLimit);
127771
+ if (options.rateLimit !== void 0 && !gate)
127772
+ throw new TypeError(`yes.op: rateLimit takes a yes.rateLimiter`);
127773
+ const take = gate?.take;
127774
+ const admit = slots || take ? async (signal, limitKey) => {
127775
+ await slots?.acquire(signal);
127776
+ try {
127777
+ await take?.(signal, limitKey);
127778
+ } catch (error63) {
127779
+ slots?.release();
127780
+ throw error63;
127781
+ }
127782
+ } : void 0;
127783
+ const keyOf = (input2) => {
127784
+ try {
127785
+ return { local: cacheKey(input2), hashed: void 0 };
127786
+ } catch (error63) {
127787
+ throw new Error(`${label}${error63.message}. dedupe and ttl key the input, and a query always dedupes; a write is yes.mutation, which never keys.`, { cause: error63 });
127788
+ }
127789
+ };
127790
+ const report = (attempt, message2, error63, key) => {
127791
+ console.log(`${label}attempt ${attempt} ${message2}`);
127792
+ const data = key === void 0 ? { error: error63, attempt } : { key, error: error63, attempt };
127793
+ console.log(...label ? [label, data] : [data]);
127794
+ };
127795
+ const on = options.on ?? {};
127796
+ const onHit = on.hit ?? void 0;
127797
+ const onRun = on.run ?? void 0;
127798
+ const onAttempt = on.attempt ?? void 0;
127799
+ const onRetry = hookOr(on.retry, delayFor && ((event) => report(event.attempt, `failed, retrying in ${event.wait}ms`, event.error, event.key)));
127800
+ const onSuccess = on.success ?? void 0;
127801
+ const onFailure = hookOr(on.failure, delayFor && ((event) => report(event.attempts, "failed, not retrying", event.error, event.key)));
127802
+ const failureLine = on.failure === void 0;
127803
+ const runOnce = (input2, ctx, signal) => {
127804
+ if (timeout === void 0)
127805
+ return run4(input2, ctx);
127806
+ const controller = timeout !== void 0 && ownsSignal(ctx) ? new AbortController() : void 0;
127807
+ const follow = controller && signal && (() => controller.abort(signal.reason));
127808
+ return new Promise((resolve3, reject) => {
127809
+ let settled = false;
127810
+ let pending;
127811
+ const settle2 = (done) => (value2) => {
127812
+ if (settled)
127813
+ return;
127814
+ settled = true;
127815
+ clearTimeout(pending);
127816
+ if (follow)
127817
+ signal.removeEventListener("abort", follow);
127818
+ done(value2);
127819
+ };
127820
+ if (timeout !== void 0) {
127821
+ pending = setTimeout(() => {
127822
+ const error63 = new TimeoutError(timeout);
127823
+ settle2(reject)(error63);
127824
+ controller?.abort(error63);
127825
+ }, timeout);
127826
+ }
127827
+ if (follow) {
127828
+ if (signal.aborted)
127829
+ follow();
127830
+ else
127831
+ signal.addEventListener("abort", follow, { once: true });
127832
+ }
127833
+ try {
127834
+ const own2 = controller ? { ...ctx, signal: controller.signal } : ctx;
127835
+ Promise.resolve(run4(input2, own2)).then(settle2(resolve3), settle2(reject));
127836
+ } catch (error63) {
127837
+ settle2(reject)(error63);
127838
+ }
127839
+ });
127840
+ };
127841
+ const attempts = async (input2, ctx, key, trace, signal, tally) => {
127842
+ const limitKey = gate?.by?.(input2, ctx);
127843
+ const own2 = inject(ctx);
127844
+ for (let attempt = 1; ; attempt++) {
127845
+ signal?.throwIfAborted();
127846
+ if (admit)
127847
+ await admit(signal, limitKey);
127848
+ if (tally)
127849
+ tally.started = attempt;
127850
+ try {
127851
+ let returned;
127852
+ try {
127853
+ if (onAttempt) {
127854
+ const awaited = onAttempt({ name, input: input2, ctx, key: hashedKey(key), attempt });
127855
+ if (isThenable(awaited))
127856
+ await awaited;
127857
+ }
127858
+ returned = await runOnce(input2, own2, signal);
127859
+ } finally {
127860
+ slots?.release();
127861
+ }
127862
+ const result = outputSchema ? await assertSchema(outputSchema, returned) : returned;
127863
+ trace?.(`run resolved on attempt ${attempt}`);
127864
+ return result;
127865
+ } catch (thrown) {
127866
+ let error63 = thrown;
127867
+ let wait2 = -1;
127868
+ let stopped = false;
127869
+ if (gate && !(error63 instanceof ValidationError)) {
127870
+ try {
127871
+ const paused = gate.failed(error63, limitKey);
127872
+ if (paused)
127873
+ trace?.(`rate limit paused for ${paused}ms`);
127874
+ } catch (stop2) {
127875
+ error63 = stop2;
127876
+ stopped = true;
127877
+ }
127878
+ }
127879
+ if (delayFor && !stopped && !(error63 instanceof ValidationError) && !signal?.aborted) {
127880
+ try {
127881
+ wait2 = delayFor(error63, attempt);
127882
+ } catch (stop2) {
127883
+ error63 = stop2;
127884
+ }
127885
+ if (typeof wait2 !== "number") {
127886
+ error63 = new TypeError(`yes.op: a retry waits a number of ms, got ${typeof wait2}`, { cause: error63 });
127887
+ wait2 = -1;
127888
+ } else if (wait2 > maxDelay) {
127889
+ error63 = new RangeError(`yes.op: a retry waits at most ${maxDelay}ms, got ${wait2}`, { cause: error63 });
127890
+ wait2 = -1;
127891
+ }
127892
+ }
127893
+ if (wait2 >= 0 && onRetry) {
127894
+ try {
127895
+ const returned = onRetry({ name, input: input2, ctx, key: hashedKey(key), error: error63, attempt, wait: wait2 });
127896
+ if (isThenable(returned))
127897
+ await returned;
127898
+ } catch (stop2) {
127899
+ error63 = stop2;
127900
+ wait2 = -1;
127901
+ }
127902
+ }
127903
+ if (wait2 >= 0) {
127904
+ await sleep(wait2, signal);
127905
+ continue;
127906
+ }
127907
+ trace?.(`run failed on attempt ${attempt}`, { error: error63 });
127908
+ throw error63;
127909
+ }
127910
+ }
127911
+ };
127912
+ const execution = onRun || onSuccess || onFailure ? async (input2, ctx, key, trace, signal, write2) => {
127913
+ const tally = { started: 0 };
127914
+ let result;
127915
+ try {
127916
+ if (onRun) {
127917
+ const awaited = onRun({ name, input: input2, ctx, key: hashedKey(key) });
127918
+ if (isThenable(awaited))
127919
+ await awaited;
127920
+ }
127921
+ result = await attempts(input2, ctx, key, trace, signal, tally);
127922
+ if (write2)
127923
+ result = await write2(result);
127924
+ } catch (error63) {
127925
+ if (onFailure && !signal?.aborted && !(failureLine && tally.started <= 1)) {
127926
+ const awaited = onFailure({ name, input: input2, ctx, key: hashedKey(key), error: error63, attempts: tally.started });
127927
+ if (isThenable(awaited))
127928
+ await awaited;
127929
+ }
127930
+ throw error63;
127931
+ }
127932
+ if (onSuccess) {
127933
+ const awaited = onSuccess({ name, input: input2, ctx, key: hashedKey(key), result, attempts: tally.started });
127934
+ if (isThenable(awaited))
127935
+ await awaited;
127936
+ }
127937
+ return result;
127938
+ } : (input2, ctx, key, trace, signal, write2) => {
127939
+ const running = attempts(input2, ctx, key, trace, signal);
127940
+ return write2 ? running.then(write2) : running;
127941
+ };
127942
+ const hit = (input2, ctx, key, trace, from, value2) => {
127943
+ trace?.(`cache hit (${from})`);
127944
+ const awaited = onHit?.({ name, input: input2, ctx, key: hashedKey(key), from });
127945
+ if (!isThenable(awaited))
127946
+ return value2;
127947
+ if (isThenable(value2))
127948
+ value2.then(void 0, () => {
127949
+ });
127950
+ return awaited.then(() => value2);
127951
+ };
127952
+ const inFlight = /* @__PURE__ */ new Map();
127953
+ const writers = /* @__PURE__ */ new Map();
127954
+ let executions = 0;
127955
+ const execute2 = async (rawInput, ctx, refresh) => {
127956
+ const input2 = inputSchema ? await assertSchema(inputSchema, rawInput) : rawInput;
127957
+ const signal = signalOf(ctx);
127958
+ if (!dedupe && !store)
127959
+ return execution(input2, ctx, void 0, debugTrace(label), signal);
127960
+ const key = keyOf(input2);
127961
+ const trace = debugTrace(label, key);
127962
+ const shared = inFlight.get(key.local);
127963
+ if (shared && !refresh) {
127964
+ const [execution2, leader] = shared;
127965
+ return hit(input2, ctx, key, trace, "in-flight", leader ? execution2.catch((error63) => {
127966
+ if (!leader.aborted)
127967
+ throw error63;
127968
+ signal?.throwIfAborted();
127969
+ return execute2(rawInput, ctx, false);
127970
+ }) : execution2);
127971
+ }
127972
+ const fullKey = storeKey(key);
127973
+ const read3 = store && !refresh ? callAdapter("get", fullKey, () => store.get(fullKey), reported) : void 0;
127974
+ const entry = freshEntry(read3);
127975
+ if (entry)
127976
+ return hit(input2, ctx, key, trace, "store", entry.value);
127977
+ const number6 = ++executions;
127978
+ let writer;
127979
+ if (store) {
127980
+ writer = writers.get(key.local);
127981
+ if (!writer) {
127982
+ writer = { running: 0, refreshed: 0 };
127983
+ writers.set(key.local, writer);
127984
+ }
127985
+ writer.running++;
127986
+ if (refresh)
127987
+ writer.refreshed = number6;
127988
+ }
127989
+ const write2 = store && (async (result) => {
127990
+ const ms = lifetime(result);
127991
+ if (!(isLifetime(ms) && writer.refreshed <= number6 && (keepsErrors || !(result instanceof Error)))) {
127992
+ return result;
127993
+ }
127994
+ const created = Date.now();
127995
+ try {
127996
+ await store.set(fullKey, { value: result, created, expires: created + ms, input: input2 }, ms);
127997
+ } catch (error63) {
127998
+ console.error(`${label}cache write failed, returning the result uncached`, new AdapterError("set", reported ? reported(fullKey) : fullKey, error63));
127999
+ }
128000
+ return result;
128001
+ });
128002
+ const promise2 = (async () => {
128003
+ const stored = isThenable(read3) ? freshEntry(await read3) : void 0;
128004
+ if (stored)
128005
+ return hit(input2, ctx, key, trace, "store", stored.value);
128006
+ trace?.(refresh ? "refreshing, running" : "cache miss, running");
128007
+ return execution(input2, ctx, key, trace, signal, write2);
128008
+ })();
128009
+ const settled = writer ? promise2.finally(() => --writer.running || writers.delete(key.local)) : promise2;
128010
+ if (!dedupe)
128011
+ return settled;
128012
+ const flight = [settled, signal];
128013
+ inFlight.set(key.local, flight);
128014
+ return settled.finally(() => inFlight.get(key.local) === flight && inFlight.delete(key.local));
128015
+ };
128016
+ const call = (rawInput, ctx) => execute2(rawInput, ctx, false);
128017
+ const jsonSchema2 = inputSchema?.["~standard"].jsonSchema;
128018
+ if (jsonSchema2) {
128019
+ call["~standard"] = {
128020
+ version: 1,
128021
+ vendor: "yes",
128022
+ name: name ?? "",
128023
+ description: options.description ?? "",
128024
+ jsonSchema: {
128025
+ input: (params) => jsonSchema2.input(params),
128026
+ // what the op returns is what its output schema returns; without one that can say so, any value
128027
+ output: (params) => outputSchema?.["~standard"].jsonSchema?.output(params) ?? {}
128028
+ },
128029
+ ...run4.length < 2 && {
128030
+ execute: (input2, options2) => call(input2, options2?.signal ? { signal: options2.signal } : void 0)
128031
+ }
128032
+ };
128033
+ }
128034
+ if (!cacheMethods)
128035
+ return call;
128036
+ const withKey = (input2, use) => {
128037
+ const toKey = (result2) => use(storeKey(keyOf(result2 && !result2.issues ? result2.value : input2)));
128038
+ const result = inputSchema?.["~standard"].validate(input2);
128039
+ return result instanceof Promise ? result.then(toKey) : toKey(result);
128040
+ };
128041
+ return Object.assign(call, {
128042
+ clear: async (input2) => {
128043
+ if (!store)
128044
+ return;
128045
+ if (input2 === void 0)
128046
+ await sweep(store, prefix, () => true);
128047
+ else
128048
+ await withKey(input2, (key) => callAdapter("delete", key, () => store.delete([key]), reported));
128049
+ },
128050
+ // the memory store peeks, so asking whether a key is cached does not change which key is evicted next
128051
+ has: async (input2) => !!store && !!freshEntry(await withKey(input2, (key) => callAdapter("get", key, () => "peek" in store ? store.peek(key) : store.get(key), reported))),
128052
+ // not `async`: on the memory store a predicate that throws throws here, not in a promise nobody awaits
128053
+ invalidate: (match3) => {
128054
+ const accepts = typeof match3 === "function" ? match3 : fieldsMatch(match3);
128055
+ return Promise.resolve(store ? sweep(store, prefix, accepts) : 0);
128056
+ },
128057
+ refresh: (rawInput, ctx) => execute2(rawInput, ctx, true)
128058
+ });
128059
+ }
128060
+ function query(options) {
128061
+ return op({ ...options, dedupe: true });
128062
+ }
128063
+ function mutation({ dedupe: _dedupe, ttl: _ttl, cache: _cache, ...options }) {
128064
+ return build(options, false);
128065
+ }
128066
+ var hookOr = (given, line) => given === void 0 ? line || void 0 : given ?? void 0;
128067
+ var ownsSignal = (ctx) => {
128068
+ if (ctx === void 0)
128069
+ return true;
128070
+ if (!isPlain(ctx))
128071
+ return false;
128072
+ const signal = ctx.signal;
128073
+ return signal === void 0 || isSignal(signal);
128074
+ };
128075
+ var inject = (ctx) => {
128076
+ if (ctx === void 0)
128077
+ return { signal: idleSignal() };
128078
+ return isPlain(ctx) && ctx.signal === void 0 ? { ...ctx, signal: idleSignal() } : ctx;
128079
+ };
128080
+ var idle;
128081
+ var idleSignal = () => {
128082
+ if (idle === void 0 && typeof AbortController === "function")
128083
+ idle = new AbortController().signal;
128084
+ return idle;
128085
+ };
128086
+ var signalOf = (ctx) => {
128087
+ const signal = ctx?.signal;
128088
+ return isSignal(signal) ? signal : void 0;
128089
+ };
128090
+ var isSignal = (value2) => typeof AbortSignal === "function" && value2 instanceof AbortSignal;
128091
+ function debugTrace(label, callKey) {
128092
+ if (!debugging())
128093
+ return;
128094
+ const prefix = `${label}[${(/* @__PURE__ */ new Date()).toISOString()}]`;
128095
+ const start = performance.now();
128096
+ const key = hashedKey(callKey);
128097
+ return (message2, data) => console.log(`${prefix} ${message2} +${Math.round(performance.now() - start)}ms`, { ...key && { key }, ...data });
128098
+ }
128099
+ function hashedKey(key) {
128100
+ if (key)
128101
+ key.hashed ??= hashKey(key.local);
128102
+ return key?.hashed;
128103
+ }
128104
+ var maxDelay = 2 ** 31 - 1;
128105
+ var isLifetime = (ms) => typeof ms === "number" && ms > 0 && Number.isFinite(ms);
128106
+ function fieldsMatch(partial3) {
128107
+ const fields = Object.entries(partial3).map(([field, value2]) => [
128108
+ field,
128109
+ value2 === void 0 ? void 0 : canonical(value2)
128110
+ ]);
128111
+ return (input2) => typeof input2 === "object" && input2 !== null && fields.every(([field, value2]) => {
128112
+ const actual = input2[field];
128113
+ return actual === void 0 ? value2 === void 0 : value2 !== void 0 && canonical(actual) === value2;
128114
+ });
128115
+ }
128116
+ var isThenable = (value2) => typeof value2?.then === "function";
128117
+ function freshEntry(value2) {
128118
+ return typeof value2?.expires === "number" && value2.expires > Date.now() && "value" in value2 ? value2 : void 0;
128119
+ }
128120
+ function callAdapter(method, key, run4, reported) {
128121
+ try {
128122
+ const result = run4();
128123
+ if (!isThenable(result))
128124
+ return result;
128125
+ return result.then(void 0, (error63) => {
128126
+ throw new AdapterError(method, reported ? reported(key) : key, error63);
128127
+ });
128128
+ } catch (error63) {
128129
+ throw new AdapterError(method, reported ? reported(key) : key, error63);
128130
+ }
128131
+ }
128132
+ function sweep(store, prefix, match3) {
128133
+ const purge = (listed2) => {
128134
+ const now = Date.now();
128135
+ const keys = [];
128136
+ let count = 0;
128137
+ for (const [key, { input: input2, expires }] of listed2) {
128138
+ if (!(expires > now))
128139
+ keys.push(key);
128140
+ else if (match3(input2)) {
128141
+ keys.push(key);
128142
+ count++;
128143
+ }
128144
+ }
128145
+ const remove = (from) => {
128146
+ if (from >= keys.length)
128147
+ return count;
128148
+ const deleted = callAdapter("delete", prefix, () => store.delete(keys.slice(from, from + 1e3)));
128149
+ return isThenable(deleted) ? Promise.resolve(deleted).then(() => remove(from + 1e3)) : remove(from + 1e3);
128150
+ };
128151
+ return remove(0);
128152
+ };
128153
+ const listed = callAdapter("list", prefix, () => {
128154
+ const listed2 = store.list(prefix);
128155
+ if (Array.isArray(listed2))
128156
+ return listed2;
128157
+ return (async () => {
128158
+ const items = [];
128159
+ for await (const item of await listed2)
128160
+ items.push(item);
128161
+ return items;
128162
+ })();
128163
+ });
128164
+ return Array.isArray(listed) ? purge(listed) : listed.then(purge);
128165
+ }
128166
+
128167
+ // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/try.js
128168
+ function asError(value2) {
128169
+ if (value2 instanceof Error)
128170
+ return value2;
128171
+ let message2;
128172
+ try {
128173
+ message2 = String(value2);
128174
+ } catch {
128175
+ message2 = "a value that is not an Error";
128176
+ }
128177
+ return new Error(message2, { cause: value2 });
128178
+ }
128179
+ var tryCall = async (call) => {
128180
+ try {
128181
+ return await (typeof call === "function" ? call() : call);
128182
+ } catch (error63) {
128183
+ return asError(error63);
128184
+ }
128185
+ };
128186
+
128187
+ // utils/openCodeModels.ts
127377
128188
  var baseline;
127378
128189
  var authorized;
127379
128190
  var failure2;
128191
+ var catalogFailure;
128192
+ var DEFAULT_MODELS_URL = "https://models.opencode.ai";
127380
128193
  var ANSI_PATTERN = /\[[0-9;]*m/g;
127381
128194
  function openCodeHomeEnv(tmpdir5) {
127382
128195
  return {
@@ -127387,6 +128200,36 @@ function openCodeHomeEnv(tmpdir5) {
127387
128200
  XDG_STATE_HOME: join8(tmpdir5, ".local", "state")
127388
128201
  };
127389
128202
  }
128203
+ var fetchCatalog = query({
128204
+ run: async (url4, ctx) => {
128205
+ const response = await fetch(url4, { signal: ctx.signal });
128206
+ if (!response.ok) throw new Error(`${url4} answered ${response.status}`);
128207
+ const text = await response.text();
128208
+ JSON.parse(text);
128209
+ return text;
128210
+ },
128211
+ name: "models catalog",
128212
+ timeout: 1e4,
128213
+ retry: [1e3]
128214
+ });
128215
+ async function seedModelsCatalog(tmpdir5) {
128216
+ const source = process.env.OPENCODE_MODELS_URL || DEFAULT_MODELS_URL;
128217
+ const name = source === DEFAULT_MODELS_URL ? "models.json" : `models-${createHash2("sha1").update(source).digest("hex")}.json`;
128218
+ const result = await tryCall(fetchCatalog(`${source}/api.json`));
128219
+ if (result instanceof Error) {
128220
+ catalogFailure = result.cause instanceof Error ? `${result.message}: ${result.cause.message}` : result.message;
128221
+ log2.warning(
128222
+ `\xBB could not download opencode's model catalog (${catalogFailure}). opencode falls back to the snapshot built into it, which lacks models released since that build.`
128223
+ );
128224
+ return;
128225
+ }
128226
+ const dir = join8(openCodeHomeEnv(tmpdir5).XDG_CACHE_HOME, "opencode");
128227
+ mkdirSync7(dir, { recursive: true });
128228
+ writeFileSync7(join8(dir, name), result);
128229
+ }
128230
+ function getModelsCatalogFailure() {
128231
+ return catalogFailure;
128232
+ }
127390
128233
  function readModels(params) {
127391
128234
  const result = spawnSync4(params.cliPath, ["models"], {
127392
128235
  encoding: "utf-8",
@@ -128387,8 +129230,8 @@ var opencode = agent({
128387
129230
  const xaiAuth = installXaiAuth();
128388
129231
  const homeEnv = openCodeHomeEnv(ctx.tmpdir);
128389
129232
  const opencodePluginDir = join9(homeEnv.XDG_CONFIG_HOME, "opencode", "plugin");
128390
- mkdirSync7(opencodePluginDir, { recursive: true });
128391
- writeFileSync7(
129233
+ mkdirSync8(opencodePluginDir, { recursive: true });
129234
+ writeFileSync8(
128392
129235
  join9(opencodePluginDir, PULLFROG_OPENCODE_GATE_PLUGIN_FILENAME),
128393
129236
  buildOpencodeSubagentGateSource(ctx)
128394
129237
  );
@@ -136496,7 +137339,7 @@ var Hono3 = class extends Hono {
136496
137339
  };
136497
137340
 
136498
137341
  // node_modules/.pnpm/mcp-proxy@6.7.21/node_modules/mcp-proxy/dist/startStdioServer-SHdEnYLY.mjs
136499
- import { createRequire } from "node:module";
137342
+ import { createRequire as createRequire2 } from "node:module";
136500
137343
  import { randomUUID as randomUUID3, timingSafeEqual } from "node:crypto";
136501
137344
 
136502
137345
  // node_modules/.pnpm/@modelcontextprotocol+server@2.3.1/node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
@@ -138899,7 +139742,7 @@ var rev2025Codec = {
138899
139742
  encodeErrorCode: (code) => code === -32002 ? -32602 : code,
138900
139743
  checkInboundEnvelope: (_material) => void 0
138901
139744
  };
138902
- function build() {
139745
+ function build2() {
138903
139746
  const JSONValueSchema$1 = lazy(() => union([
138904
139747
  string2(),
138905
139748
  number2(),
@@ -139774,7 +140617,7 @@ function build() {
139774
140617
  }
139775
140618
  var memo2;
139776
140619
  function buildSchemas2026() {
139777
- return memo2 ??= build();
140620
+ return memo2 ??= build2();
139778
140621
  }
139779
140622
  var CACHEABLE_RESULT_METHODS = [
139780
140623
  "tools/list",
@@ -141204,7 +142047,7 @@ var REQUEST_STATE_ONLY_LEG_PACING_MS = 250;
141204
142047
  function inputRequiredRoundsExceededMessage(method, maxRounds) {
141205
142048
  return `Multi-round-trip request '${method}' still required input after ${maxRounds} rounds (inputRequired.maxRounds)`;
141206
142049
  }
141207
- function sleep(ms, signal) {
142050
+ function sleep2(ms, signal) {
141208
142051
  return new Promise((resolve3, reject) => {
141209
142052
  if (signal?.aborted) {
141210
142053
  reject(signal.reason instanceof SdkError ? signal.reason : new SdkError(SdkErrorCode.RequestTimeout, String(signal.reason)));
@@ -144363,8 +145206,8 @@ var require_resolve2 = /* @__PURE__ */ __commonJSMin(((exports) => {
144363
145206
  }
144364
145207
  return count;
144365
145208
  }
144366
- function getFullPath(resolver, id = "", normalize3) {
144367
- if (normalize3 !== false) id = normalizeId(id);
145209
+ function getFullPath(resolver, id = "", normalize4) {
145210
+ if (normalize4 !== false) id = normalizeId(id);
144368
145211
  return _getFullPath(resolver, resolver.parse(id));
144369
145212
  }
144370
145213
  exports.getFullPath = getFullPath;
@@ -145459,7 +146302,7 @@ var require_schemes2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
145459
146302
  var require_fast_uri2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
145460
146303
  const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils5();
145461
146304
  const { SCHEMES, getSchemeHandler } = require_schemes2();
145462
- function normalize3(uri, options) {
146305
+ function normalize4(uri, options) {
145463
146306
  if (typeof uri === "string") uri = serialize2(parse6(uri, options), options);
145464
146307
  else if (typeof uri === "object") uri = parse6(serialize2(uri, options), options);
145465
146308
  return uri;
@@ -145637,7 +146480,7 @@ var require_fast_uri2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
145637
146480
  }
145638
146481
  const fastUri = {
145639
146482
  SCHEMES,
145640
- normalize: normalize3,
146483
+ normalize: normalize4,
145641
146484
  resolve: resolve3,
145642
146485
  resolveComponent,
145643
146486
  equal,
@@ -149836,7 +150679,7 @@ var LegacyInputRequiredShim = class {
149836
150679
  } finally {
149837
150680
  roundAbort.dispose();
149838
150681
  }
149839
- } else await sleep(REQUEST_STATE_ONLY_LEG_PACING_MS, outerSignal);
150682
+ } else await sleep2(REQUEST_STATE_ONLY_LEG_PACING_MS, outerSignal);
149840
150683
  let ctxNext = {
149841
150684
  ...ctx,
149842
150685
  mcpReq: {
@@ -152425,7 +153268,7 @@ function createMcpHandler(factory, options = {}) {
152425
153268
  import http2 from "http";
152426
153269
  import { Http2ServerRequest } from "http2";
152427
153270
  import { Readable } from "stream";
152428
- import crypto4 from "crypto";
153271
+ import crypto5 from "crypto";
152429
153272
  import { TLSSocket } from "node:tls";
152430
153273
  import fs4 from "fs";
152431
153274
  import https2 from "https";
@@ -153805,7 +154648,7 @@ var rev2025Codec2 = {
153805
154648
  encodeErrorCode: (code) => code === -32002 ? -32602 : code,
153806
154649
  checkInboundEnvelope: (_material) => void 0
153807
154650
  };
153808
- function build2() {
154651
+ function build3() {
153809
154652
  const JSONValueSchema$1 = lazy(() => union([
153810
154653
  string2(),
153811
154654
  number2(),
@@ -154680,7 +155523,7 @@ function build2() {
154680
155523
  }
154681
155524
  var memo3;
154682
155525
  function buildSchemas20262() {
154683
- return memo3 ??= build2();
155526
+ return memo3 ??= build3();
154684
155527
  }
154685
155528
  var CACHEABLE_RESULT_METHODS2 = [
154686
155529
  "tools/list",
@@ -158700,8 +159543,8 @@ var require_resolve3 = /* @__PURE__ */ __commonJSMin2(((exports) => {
158700
159543
  }
158701
159544
  return count;
158702
159545
  }
158703
- function getFullPath(resolver, id = "", normalize3) {
158704
- if (normalize3 !== false) id = normalizeId(id);
159546
+ function getFullPath(resolver, id = "", normalize4) {
159547
+ if (normalize4 !== false) id = normalizeId(id);
158705
159548
  return _getFullPath(resolver, resolver.parse(id));
158706
159549
  }
158707
159550
  exports.getFullPath = getFullPath;
@@ -159796,7 +160639,7 @@ var require_schemes3 = /* @__PURE__ */ __commonJSMin2(((exports, module) => {
159796
160639
  var require_fast_uri3 = /* @__PURE__ */ __commonJSMin2(((exports, module) => {
159797
160640
  const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils6();
159798
160641
  const { SCHEMES, getSchemeHandler } = require_schemes3();
159799
- function normalize3(uri, options) {
160642
+ function normalize4(uri, options) {
159800
160643
  if (typeof uri === "string") uri = serialize2(parse6(uri, options), options);
159801
160644
  else if (typeof uri === "object") uri = parse6(serialize2(uri, options), options);
159802
160645
  return uri;
@@ -159974,7 +160817,7 @@ var require_fast_uri3 = /* @__PURE__ */ __commonJSMin2(((exports, module) => {
159974
160817
  }
159975
160818
  const fastUri = {
159976
160819
  SCHEMES,
159977
- normalize: normalize3,
160820
+ normalize: normalize4,
159978
160821
  resolve: resolve3,
159979
160822
  resolveComponent,
159980
160823
  equal,
@@ -163697,8 +164540,8 @@ var addFormats2 = import_dist2.default;
163697
164540
  var Ajv3 = import_ajv3.Ajv;
163698
164541
 
163699
164542
  // node_modules/.pnpm/pkce-challenge@5.0.1/node_modules/pkce-challenge/dist/index.node.js
163700
- var crypto3;
163701
- crypto3 = globalThis.crypto?.webcrypto ?? // Node.js [18-16] REPL
164543
+ var crypto4;
164544
+ crypto4 = globalThis.crypto?.webcrypto ?? // Node.js [18-16] REPL
163702
164545
  globalThis.crypto ?? // Node.js >18
163703
164546
  import("node:crypto").then((m) => m.webcrypto);
163704
164547
 
@@ -163885,7 +164728,7 @@ var __toESM4 = (mod, isNodeMode, target) => (target = mod != null ? __create4(__
163885
164728
  value: mod,
163886
164729
  enumerable: true
163887
164730
  }) : target, mod));
163888
- var __require2 = /* @__PURE__ */ createRequire(import.meta.url);
164731
+ var __require2 = /* @__PURE__ */ createRequire2(import.meta.url);
163889
164732
  var getProtectedResourceMetadataUrl = (resource) => {
163890
164733
  let metadataUrl;
163891
164734
  try {
@@ -169672,13 +170515,13 @@ var newRequest = (incoming, defaultHostname) => {
169672
170515
  };
169673
170516
  var responseCache = Symbol("responseCache");
169674
170517
  var getResponseCache = Symbol("getResponseCache");
169675
- var cacheKey = Symbol("cache");
170518
+ var cacheKey2 = Symbol("cache");
169676
170519
  var GlobalResponse = global.Response;
169677
170520
  var Response2 = class _Response {
169678
170521
  #body;
169679
170522
  #init;
169680
170523
  [getResponseCache]() {
169681
- delete this[cacheKey];
170524
+ delete this[cacheKey2];
169682
170525
  return this[responseCache] ||= new GlobalResponse(this.#body, this.#init);
169683
170526
  }
169684
170527
  constructor(body, init) {
@@ -169695,14 +170538,14 @@ var Response2 = class _Response {
169695
170538
  headers = new Headers(init.#init.headers);
169696
170539
  }
169697
170540
  } else this.#init = init;
169698
- if (typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) this[cacheKey] = [
170541
+ if (typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) this[cacheKey2] = [
169699
170542
  init?.status || 200,
169700
170543
  body,
169701
170544
  headers || init?.headers
169702
170545
  ];
169703
170546
  }
169704
170547
  get headers() {
169705
- const cache = this[cacheKey];
170548
+ const cache = this[cacheKey2];
169706
170549
  if (cache) {
169707
170550
  if (!(cache[2] instanceof Headers)) cache[2] = new Headers(cache[2] || { "content-type": "text/plain; charset=UTF-8" });
169708
170551
  return cache[2];
@@ -169710,7 +170553,7 @@ var Response2 = class _Response {
169710
170553
  return this[getResponseCache]().headers;
169711
170554
  }
169712
170555
  get status() {
169713
- return this[cacheKey]?.[0] ?? this[getResponseCache]().status;
170556
+ return this[cacheKey2]?.[0] ?? this[getResponseCache]().status;
169714
170557
  }
169715
170558
  get ok() {
169716
170559
  const status$1 = this.status;
@@ -169791,7 +170634,7 @@ var buildOutgoingHttpHeaders = (headers) => {
169791
170634
  return res;
169792
170635
  };
169793
170636
  var X_ALREADY_SENT = "x-hono-already-sent";
169794
- if (typeof global.crypto === "undefined") global.crypto = crypto4;
170637
+ if (typeof global.crypto === "undefined") global.crypto = crypto5;
169795
170638
  var outgoingEnded = Symbol("outgoingEnded");
169796
170639
  var handleRequestError = () => new Response(null, { status: 400 });
169797
170640
  var handleFetchError = (e) => new Response(null, { status: e instanceof Error && (e.name === "TimeoutError" || e.constructor.name === "TimeoutError") ? 504 : 500 });
@@ -169809,7 +170652,7 @@ var flushHeaders = (outgoing) => {
169809
170652
  if ("flushHeaders" in outgoing && outgoing.writable) outgoing.flushHeaders();
169810
170653
  };
169811
170654
  var responseViaCache = async (res, outgoing) => {
169812
- let [status$1, body, header] = res[cacheKey];
170655
+ let [status$1, body, header] = res[cacheKey2];
169813
170656
  let hasContentLength = false;
169814
170657
  if (!header) header = { "content-type": "text/plain; charset=UTF-8" };
169815
170658
  else if (header instanceof Headers) {
@@ -169847,7 +170690,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
169847
170690
  res = errRes;
169848
170691
  }
169849
170692
  else res = await res.catch(handleFetchError);
169850
- if (cacheKey in res) return responseViaCache(res, outgoing);
170693
+ if (cacheKey2 in res) return responseViaCache(res, outgoing);
169851
170694
  const resHeaderRecord = buildOutgoingHttpHeaders(res.headers);
169852
170695
  if (res.body) {
169853
170696
  const reader = res.body.getReader();
@@ -169935,7 +170778,7 @@ var getRequestListener = (fetchCallback, options = {}) => {
169935
170778
  incoming,
169936
170779
  outgoing
169937
170780
  });
169938
- if (cacheKey in res) return responseViaCache(res, outgoing);
170781
+ if (cacheKey2 in res) return responseViaCache(res, outgoing);
169939
170782
  } catch (e) {
169940
170783
  if (!res) if (options.errorHandler) {
169941
170784
  res = await options.errorHandler(req ? e : toRequestError(e));
@@ -183522,8 +184365,8 @@ function closeBrowserDaemon(toolState) {
183522
184365
  }
183523
184366
 
183524
184367
  // mcp/checkout.ts
183525
- import { createHash as createHash3 } from "node:crypto";
183526
- import { statSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync11 } from "node:fs";
184368
+ import { createHash as createHash4 } from "node:crypto";
184369
+ import { statSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync12 } from "node:fs";
183527
184370
  import { join as join17 } from "node:path";
183528
184371
 
183529
184372
  // node_modules/.pnpm/@ark+schema@0.56.0/node_modules/@ark/schema/out/shared/errors.js
@@ -190852,740 +191695,6 @@ var schema = ark.schema;
190852
191695
  var define2 = ark.define;
190853
191696
  var declare = ark.declare;
190854
191697
 
190855
- // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/cache/adapter.js
190856
- var AdapterError = class extends Error {
190857
- /** the adapter method that failed */
190858
- method;
190859
- /** the full store key, or the op's prefix when the call covered many keys. never the raw input. */
190860
- key;
190861
- constructor(method, key, cause) {
190862
- super(`cache ${method} failed for ${key}: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
190863
- this.name = "AdapterError";
190864
- this.method = method;
190865
- this.key = key;
190866
- }
190867
- };
190868
-
190869
- // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/cache/memory.js
190870
- function memory({ maxItems = 1e3 } = {}) {
190871
- const store = /* @__PURE__ */ new Map();
190872
- const peek = (key) => {
190873
- const slot = store.get(key);
190874
- if (slot === void 0)
190875
- return;
190876
- if (slot.until > Date.now())
190877
- return slot;
190878
- store.delete(key);
190879
- };
190880
- const evict = () => {
190881
- for (const [key, slot] of store) {
190882
- store.delete(key);
190883
- if (!slot.used)
190884
- return;
190885
- slot.used = false;
190886
- store.set(key, slot);
190887
- }
190888
- };
190889
- return {
190890
- get: (key) => {
190891
- const slot = peek(key);
190892
- if (slot === void 0)
190893
- return;
190894
- slot.used = true;
190895
- return slot.entry;
190896
- },
190897
- peek: (key) => peek(key)?.entry,
190898
- // the TTL rides on each entry, so ops with different lifetimes can share one store
190899
- // evicted before the new slot goes in, so the entry being written is never the one dropped: after it, a full store
190900
- // whose every slot was read would pass each over and drop the new, unread one
190901
- set: (key, entry, ttlMs) => {
190902
- store.delete(key);
190903
- if (store.size >= maxItems)
190904
- evict();
190905
- store.set(key, { entry, until: Date.now() + ttlMs, used: false });
190906
- },
190907
- delete: (keys) => {
190908
- for (const key of keys)
190909
- store.delete(key);
190910
- },
190911
- // a snapshot, so deleting while iterating is safe
190912
- list: (prefix) => {
190913
- const now = Date.now();
190914
- const listed = [];
190915
- for (const [key, slot] of store)
190916
- if (slot.until > now && key.startsWith(prefix))
190917
- listed.push([key, slot.entry]);
190918
- return listed;
190919
- }
190920
- };
190921
- }
190922
-
190923
- // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/issues.js
190924
- function issueJSON(issue4) {
190925
- const segments = issue4.path ?? [];
190926
- const path4 = [];
190927
- for (let i2 = 0; i2 < segments.length; i2++) {
190928
- const segment = segments[i2];
190929
- const wrapped = typeof segment === "object" && segment !== null;
190930
- const key = wrapped ? segment.key : segment;
190931
- if (typeof key === "string" || typeof key === "number" && Number.isFinite(key))
190932
- path4.push(key);
190933
- else if (typeof key === "symbol")
190934
- path4.push(String(key));
190935
- else if (!(wrapped && key === null && segment.type === "set"))
190936
- break;
190937
- }
190938
- const { keyword } = issue4;
190939
- return typeof keyword === "string" ? { message: issue4.message, path: path4, keyword } : { message: issue4.message, path: path4 };
190940
- }
190941
- function issuesJSON(issues) {
190942
- const out = [];
190943
- for (let i2 = 0; i2 < issues.length; i2++)
190944
- if (issues[i2])
190945
- out.push(issueJSON(issues[i2]));
190946
- return out;
190947
- }
190948
- var identifier = /^[A-Za-z_$][\w$]*$/;
190949
- var longestKey = 40;
190950
- function renderPath(path4) {
190951
- let out = "";
190952
- for (const key of path4) {
190953
- if (typeof key === "number")
190954
- out += `[${key}]`;
190955
- else if (key.length <= longestKey && identifier.test(key))
190956
- out += out ? `.${key}` : key;
190957
- else
190958
- out += `[${JSON.stringify(key.length <= longestKey ? key : `${key.slice(0, longestKey)}\u2026`)}]`;
190959
- }
190960
- return out;
190961
- }
190962
- var shown = 10;
190963
- function summary2(issues, truncated2) {
190964
- const lines = [];
190965
- let i2 = 0;
190966
- for (; i2 < issues.length && lines.length < shown; i2++) {
190967
- const issue4 = issues[i2];
190968
- if (!issue4)
190969
- continue;
190970
- const { message: message2, path: path4 } = issueJSON(issue4);
190971
- lines.push(path4.length ? `${renderPath(path4)}: ${message2}` : message2);
190972
- }
190973
- let more = 0;
190974
- for (; i2 < issues.length; i2++)
190975
- if (issues[i2])
190976
- more++;
190977
- if (more > 0)
190978
- lines.push(truncated2 ? `and over ${more} more` : `and ${more} more`);
190979
- else if (truncated2)
190980
- lines.push("and more");
190981
- return `validation failed: ${lines.join("; ")}`;
190982
- }
190983
- var ValidationError = class extends Error {
190984
- name = "ValidationError";
190985
- constructor(result) {
190986
- super(message(result));
190987
- Object.defineProperty(this, "result", { value: result });
190988
- Object.assign(this, { issues: result.issues });
190989
- }
190990
- /**
190991
- * The error as plain data, each issue projected to its message, path and keyword, so what else a validator keeps on
190992
- * one (Valibot's and Zod's `input`) is left out. The messages are the validator's own, and some quote the value.
190993
- */
190994
- toJSON() {
190995
- const json4 = { name: "ValidationError", message: this.message, issues: issuesJSON(this.issues) };
190996
- return truncated(this.result) ? { ...json4, truncated: true } : json4;
190997
- }
190998
- };
190999
- function message(result) {
191000
- try {
191001
- return ownSummary(result) ?? summary2(result.issues, truncated(result));
191002
- } catch {
191003
- return "validation failed";
191004
- }
191005
- }
191006
- function ownSummary(result) {
191007
- const own2 = result;
191008
- return typeof own2.message === "string" ? own2.message : typeof own2.summary === "string" ? own2.summary : void 0;
191009
- }
191010
- var truncated = (result) => result.truncated === true;
191011
-
191012
- // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/env.js
191013
- var debugging = () => debug2 ??= read();
191014
- var read = () => {
191015
- try {
191016
- return globalThis.process?.env?.LOG_LEVEL === "debug";
191017
- } catch {
191018
- return false;
191019
- }
191020
- };
191021
- var debug2;
191022
-
191023
- // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/hash-node.js
191024
- import { createRequire as createRequire2 } from "node:module";
191025
- var sha1 = (text) => {
191026
- crypto5 ??= load();
191027
- return crypto5.hash("sha1", text);
191028
- };
191029
- var crypto5;
191030
- var load = () => globalThis.process?.getBuiltinModule?.("node:crypto") ?? createRequire2("/")("node:crypto");
191031
-
191032
- // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/key.js
191033
- function cacheKey2(value2) {
191034
- if (value2 === null)
191035
- throw new Error("null cannot be part of a cache key");
191036
- if (value2 === void 0)
191037
- return "~void";
191038
- const json4 = canonical(value2);
191039
- return json4.length > longKey ? `#${sha1(json4)}` : json4;
191040
- }
191041
- var longKey = 4096;
191042
- function hashKey(key) {
191043
- if (key === "~void")
191044
- return key;
191045
- return key[0] === "#" ? key.slice(1) : sha1(key);
191046
- }
191047
- function canonical(value2) {
191048
- return serialize(value2, 0);
191049
- }
191050
- function serialize(value2, depth) {
191051
- switch (typeof value2) {
191052
- case "number":
191053
- if (Number.isFinite(value2))
191054
- return String(value2);
191055
- throw new Error(`${value2} cannot be part of a cache key`);
191056
- case "string":
191057
- case "boolean":
191058
- return JSON.stringify(value2);
191059
- case "undefined":
191060
- throw new Error("undefined cannot be part of a cache key, except as an object property");
191061
- case "object":
191062
- break;
191063
- default:
191064
- throw new Error(`a ${typeof value2} cannot be part of a cache key`);
191065
- }
191066
- if (value2 === null)
191067
- return "null";
191068
- if (depth++ === 64)
191069
- throw new Error("an input nested more than 64 levels deep, or circular");
191070
- if (Array.isArray(value2)) {
191071
- let out2 = "[";
191072
- for (let i2 = 0; i2 < value2.length; i2++)
191073
- out2 += `${i2 ? "," : ""}${serialize(value2[i2], depth)}`;
191074
- return `${out2}]`;
191075
- }
191076
- const proto = Object.getPrototypeOf(value2);
191077
- if (proto !== Object.prototype && proto !== null) {
191078
- const name = proto.constructor?.name || "class instance";
191079
- throw new Error(`a ${name} cannot be part of a cache key: only JSON data can`);
191080
- }
191081
- let out = "";
191082
- for (const key of Object.keys(value2).sort()) {
191083
- const v = value2[key];
191084
- if (v !== void 0)
191085
- out += `${out ? "," : ""}${JSON.stringify(key)}:${serialize(v, depth)}`;
191086
- }
191087
- return `{${out}}`;
191088
- }
191089
-
191090
- // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/plain.js
191091
- var isPlain = (value2) => {
191092
- if (typeof value2 !== "object" || value2 === null)
191093
- return false;
191094
- const proto = Object.getPrototypeOf(value2);
191095
- return proto === Object.prototype || proto === null;
191096
- };
191097
-
191098
- // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/sleep.js
191099
- function sleep2(ms, signal) {
191100
- return new Promise((resolve3) => {
191101
- if (signal?.aborted)
191102
- return resolve3();
191103
- const done = () => {
191104
- clearTimeout(timer);
191105
- signal?.removeEventListener("abort", done);
191106
- resolve3();
191107
- };
191108
- const timer = setTimeout(done, ms);
191109
- signal?.addEventListener("abort", done, { once: true });
191110
- });
191111
- }
191112
-
191113
- // node_modules/.pnpm/yes@0.2.7_typescript@5.9.3/node_modules/yes/dist/ops/api.js
191114
- function backoff(schedule, attempt) {
191115
- const d = schedule[attempt - 1];
191116
- return d === void 0 ? -1 : Math.round(d / 2 + Math.random() * d / 2);
191117
- }
191118
- async function assertSchema(schema2, value2) {
191119
- const result = await schema2["~standard"].validate(value2);
191120
- if (result.issues)
191121
- throw new ValidationError(result);
191122
- return result.value;
191123
- }
191124
- var TimeoutError = class extends Error {
191125
- name = "TimeoutError";
191126
- /** the op's `timeout`, in ms */
191127
- timeout;
191128
- constructor(timeout) {
191129
- super(`attempt timed out after ${timeout}ms`);
191130
- this.timeout = timeout;
191131
- }
191132
- };
191133
- var gates = /* @__PURE__ */ new WeakMap();
191134
- function semaphore(size) {
191135
- let free = size;
191136
- const line = [];
191137
- return {
191138
- acquire: (signal) => free > 0 ? void free-- : wait(line, signal),
191139
- release: () => {
191140
- const next2 = line.shift();
191141
- if (next2)
191142
- next2();
191143
- else
191144
- free++;
191145
- }
191146
- };
191147
- }
191148
- function wait(line, signal, left) {
191149
- return new Promise((resolve3, reject) => {
191150
- const abort = () => {
191151
- line.splice(line.indexOf(next2), 1);
191152
- left?.();
191153
- reject(signal.reason);
191154
- };
191155
- const next2 = () => {
191156
- signal?.removeEventListener("abort", abort);
191157
- resolve3();
191158
- };
191159
- signal?.addEventListener("abort", abort, { once: true });
191160
- line.push(next2);
191161
- });
191162
- }
191163
- function op(options) {
191164
- return build3(options, true);
191165
- }
191166
- function build3(options, cacheMethods) {
191167
- const { name, input: inputSchema, output: outputSchema, run: run4, dedupe, ttl, cache: adapter, timeout } = options;
191168
- const { retry, concurrency } = options;
191169
- const delayFor = Array.isArray(retry) ? (_, attempt) => backoff(retry, attempt) : retry;
191170
- if (ttl !== void 0 && typeof ttl !== "function" && !isLifetime(ttl)) {
191171
- throw new TypeError(`yes.op: ttl must be a positive number of milliseconds, got ${ttl}`);
191172
- }
191173
- if (timeout !== void 0 && !(isLifetime(timeout) && timeout <= maxDelay)) {
191174
- throw new TypeError(`yes.op: timeout must be a positive number of milliseconds up to ${maxDelay}, got ${timeout}`);
191175
- }
191176
- if (concurrency !== void 0 && !(Number.isInteger(concurrency) && concurrency > 0)) {
191177
- throw new TypeError(`yes.op: concurrency must be a positive integer, got ${concurrency}`);
191178
- }
191179
- const lifetime = typeof ttl === "function" ? ttl : (result) => result == null || result instanceof Error ? 0 : ttl;
191180
- if (adapter && (!name || name.includes(":"))) {
191181
- throw new TypeError(`yes.op: an op with a cache adapter needs a name without ":", got ${JSON.stringify(name)}`);
191182
- }
191183
- if (adapter && ttl === void 0)
191184
- throw new TypeError(`yes.op: a cache adapter does nothing without a ttl`);
191185
- const store = ttl === void 0 ? void 0 : adapter ?? memory({ maxItems: options.maxItems });
191186
- const keepsErrors = !!store && "peek" in store;
191187
- const prefix = adapter ? `yes:${name}:` : "";
191188
- const storeKey = adapter ? (key) => prefix + hashedKey(key) : (key) => key.local;
191189
- const reported = adapter ? void 0 : hashKey;
191190
- const label = name ? `[${name}] ` : "";
191191
- const slots = concurrency === void 0 ? void 0 : semaphore(concurrency);
191192
- const gate = options.rateLimit === void 0 ? void 0 : gates.get(options.rateLimit);
191193
- if (options.rateLimit !== void 0 && !gate)
191194
- throw new TypeError(`yes.op: rateLimit takes a yes.rateLimiter`);
191195
- const take = gate?.take;
191196
- const admit = slots || take ? async (signal, limitKey) => {
191197
- await slots?.acquire(signal);
191198
- try {
191199
- await take?.(signal, limitKey);
191200
- } catch (error63) {
191201
- slots?.release();
191202
- throw error63;
191203
- }
191204
- } : void 0;
191205
- const keyOf = (input2) => {
191206
- try {
191207
- return { local: cacheKey2(input2), hashed: void 0 };
191208
- } catch (error63) {
191209
- throw new Error(`${label}${error63.message}. dedupe and ttl key the input, and a query always dedupes; a write is yes.mutation, which never keys.`, { cause: error63 });
191210
- }
191211
- };
191212
- const report = (attempt, message2, error63, key) => {
191213
- console.log(`${label}attempt ${attempt} ${message2}`);
191214
- const data = key === void 0 ? { error: error63, attempt } : { key, error: error63, attempt };
191215
- console.log(...label ? [label, data] : [data]);
191216
- };
191217
- const on = options.on ?? {};
191218
- const onHit = on.hit ?? void 0;
191219
- const onRun = on.run ?? void 0;
191220
- const onAttempt = on.attempt ?? void 0;
191221
- const onRetry = hookOr(on.retry, delayFor && ((event) => report(event.attempt, `failed, retrying in ${event.wait}ms`, event.error, event.key)));
191222
- const onSuccess = on.success ?? void 0;
191223
- const onFailure = hookOr(on.failure, delayFor && ((event) => report(event.attempts, "failed, not retrying", event.error, event.key)));
191224
- const failureLine = on.failure === void 0;
191225
- const runOnce = (input2, ctx, signal) => {
191226
- if (timeout === void 0)
191227
- return run4(input2, ctx);
191228
- const controller = timeout !== void 0 && ownsSignal(ctx) ? new AbortController() : void 0;
191229
- const follow = controller && signal && (() => controller.abort(signal.reason));
191230
- return new Promise((resolve3, reject) => {
191231
- let settled = false;
191232
- let pending;
191233
- const settle2 = (done) => (value2) => {
191234
- if (settled)
191235
- return;
191236
- settled = true;
191237
- clearTimeout(pending);
191238
- if (follow)
191239
- signal.removeEventListener("abort", follow);
191240
- done(value2);
191241
- };
191242
- if (timeout !== void 0) {
191243
- pending = setTimeout(() => {
191244
- const error63 = new TimeoutError(timeout);
191245
- settle2(reject)(error63);
191246
- controller?.abort(error63);
191247
- }, timeout);
191248
- }
191249
- if (follow) {
191250
- if (signal.aborted)
191251
- follow();
191252
- else
191253
- signal.addEventListener("abort", follow, { once: true });
191254
- }
191255
- try {
191256
- const own2 = controller ? { ...ctx, signal: controller.signal } : ctx;
191257
- Promise.resolve(run4(input2, own2)).then(settle2(resolve3), settle2(reject));
191258
- } catch (error63) {
191259
- settle2(reject)(error63);
191260
- }
191261
- });
191262
- };
191263
- const attempts = async (input2, ctx, key, trace, signal, tally) => {
191264
- const limitKey = gate?.by?.(input2, ctx);
191265
- const own2 = inject(ctx);
191266
- for (let attempt = 1; ; attempt++) {
191267
- signal?.throwIfAborted();
191268
- if (admit)
191269
- await admit(signal, limitKey);
191270
- if (tally)
191271
- tally.started = attempt;
191272
- try {
191273
- let returned;
191274
- try {
191275
- if (onAttempt) {
191276
- const awaited = onAttempt({ name, input: input2, ctx, key: hashedKey(key), attempt });
191277
- if (isThenable(awaited))
191278
- await awaited;
191279
- }
191280
- returned = await runOnce(input2, own2, signal);
191281
- } finally {
191282
- slots?.release();
191283
- }
191284
- const result = outputSchema ? await assertSchema(outputSchema, returned) : returned;
191285
- trace?.(`run resolved on attempt ${attempt}`);
191286
- return result;
191287
- } catch (thrown) {
191288
- let error63 = thrown;
191289
- let wait2 = -1;
191290
- let stopped = false;
191291
- if (gate && !(error63 instanceof ValidationError)) {
191292
- try {
191293
- const paused = gate.failed(error63, limitKey);
191294
- if (paused)
191295
- trace?.(`rate limit paused for ${paused}ms`);
191296
- } catch (stop2) {
191297
- error63 = stop2;
191298
- stopped = true;
191299
- }
191300
- }
191301
- if (delayFor && !stopped && !(error63 instanceof ValidationError) && !signal?.aborted) {
191302
- try {
191303
- wait2 = delayFor(error63, attempt);
191304
- } catch (stop2) {
191305
- error63 = stop2;
191306
- }
191307
- if (typeof wait2 !== "number") {
191308
- error63 = new TypeError(`yes.op: a retry waits a number of ms, got ${typeof wait2}`, { cause: error63 });
191309
- wait2 = -1;
191310
- } else if (wait2 > maxDelay) {
191311
- error63 = new RangeError(`yes.op: a retry waits at most ${maxDelay}ms, got ${wait2}`, { cause: error63 });
191312
- wait2 = -1;
191313
- }
191314
- }
191315
- if (wait2 >= 0 && onRetry) {
191316
- try {
191317
- const returned = onRetry({ name, input: input2, ctx, key: hashedKey(key), error: error63, attempt, wait: wait2 });
191318
- if (isThenable(returned))
191319
- await returned;
191320
- } catch (stop2) {
191321
- error63 = stop2;
191322
- wait2 = -1;
191323
- }
191324
- }
191325
- if (wait2 >= 0) {
191326
- await sleep2(wait2, signal);
191327
- continue;
191328
- }
191329
- trace?.(`run failed on attempt ${attempt}`, { error: error63 });
191330
- throw error63;
191331
- }
191332
- }
191333
- };
191334
- const execution = onRun || onSuccess || onFailure ? async (input2, ctx, key, trace, signal, write2) => {
191335
- const tally = { started: 0 };
191336
- let result;
191337
- try {
191338
- if (onRun) {
191339
- const awaited = onRun({ name, input: input2, ctx, key: hashedKey(key) });
191340
- if (isThenable(awaited))
191341
- await awaited;
191342
- }
191343
- result = await attempts(input2, ctx, key, trace, signal, tally);
191344
- if (write2)
191345
- result = await write2(result);
191346
- } catch (error63) {
191347
- if (onFailure && !signal?.aborted && !(failureLine && tally.started <= 1)) {
191348
- const awaited = onFailure({ name, input: input2, ctx, key: hashedKey(key), error: error63, attempts: tally.started });
191349
- if (isThenable(awaited))
191350
- await awaited;
191351
- }
191352
- throw error63;
191353
- }
191354
- if (onSuccess) {
191355
- const awaited = onSuccess({ name, input: input2, ctx, key: hashedKey(key), result, attempts: tally.started });
191356
- if (isThenable(awaited))
191357
- await awaited;
191358
- }
191359
- return result;
191360
- } : (input2, ctx, key, trace, signal, write2) => {
191361
- const running = attempts(input2, ctx, key, trace, signal);
191362
- return write2 ? running.then(write2) : running;
191363
- };
191364
- const hit = (input2, ctx, key, trace, from, value2) => {
191365
- trace?.(`cache hit (${from})`);
191366
- const awaited = onHit?.({ name, input: input2, ctx, key: hashedKey(key), from });
191367
- if (!isThenable(awaited))
191368
- return value2;
191369
- if (isThenable(value2))
191370
- value2.then(void 0, () => {
191371
- });
191372
- return awaited.then(() => value2);
191373
- };
191374
- const inFlight = /* @__PURE__ */ new Map();
191375
- const writers = /* @__PURE__ */ new Map();
191376
- let executions = 0;
191377
- const execute2 = async (rawInput, ctx, refresh) => {
191378
- const input2 = inputSchema ? await assertSchema(inputSchema, rawInput) : rawInput;
191379
- const signal = signalOf(ctx);
191380
- if (!dedupe && !store)
191381
- return execution(input2, ctx, void 0, debugTrace(label), signal);
191382
- const key = keyOf(input2);
191383
- const trace = debugTrace(label, key);
191384
- const shared = inFlight.get(key.local);
191385
- if (shared && !refresh) {
191386
- const [execution2, leader] = shared;
191387
- return hit(input2, ctx, key, trace, "in-flight", leader ? execution2.catch((error63) => {
191388
- if (!leader.aborted)
191389
- throw error63;
191390
- signal?.throwIfAborted();
191391
- return execute2(rawInput, ctx, false);
191392
- }) : execution2);
191393
- }
191394
- const fullKey = storeKey(key);
191395
- const read3 = store && !refresh ? callAdapter("get", fullKey, () => store.get(fullKey), reported) : void 0;
191396
- const entry = freshEntry(read3);
191397
- if (entry)
191398
- return hit(input2, ctx, key, trace, "store", entry.value);
191399
- const number6 = ++executions;
191400
- let writer;
191401
- if (store) {
191402
- writer = writers.get(key.local);
191403
- if (!writer) {
191404
- writer = { running: 0, refreshed: 0 };
191405
- writers.set(key.local, writer);
191406
- }
191407
- writer.running++;
191408
- if (refresh)
191409
- writer.refreshed = number6;
191410
- }
191411
- const write2 = store && (async (result) => {
191412
- const ms = lifetime(result);
191413
- if (!(isLifetime(ms) && writer.refreshed <= number6 && (keepsErrors || !(result instanceof Error)))) {
191414
- return result;
191415
- }
191416
- const created = Date.now();
191417
- try {
191418
- await store.set(fullKey, { value: result, created, expires: created + ms, input: input2 }, ms);
191419
- } catch (error63) {
191420
- console.error(`${label}cache write failed, returning the result uncached`, new AdapterError("set", reported ? reported(fullKey) : fullKey, error63));
191421
- }
191422
- return result;
191423
- });
191424
- const promise2 = (async () => {
191425
- const stored = isThenable(read3) ? freshEntry(await read3) : void 0;
191426
- if (stored)
191427
- return hit(input2, ctx, key, trace, "store", stored.value);
191428
- trace?.(refresh ? "refreshing, running" : "cache miss, running");
191429
- return execution(input2, ctx, key, trace, signal, write2);
191430
- })();
191431
- const settled = writer ? promise2.finally(() => --writer.running || writers.delete(key.local)) : promise2;
191432
- if (!dedupe)
191433
- return settled;
191434
- const flight = [settled, signal];
191435
- inFlight.set(key.local, flight);
191436
- return settled.finally(() => inFlight.get(key.local) === flight && inFlight.delete(key.local));
191437
- };
191438
- const call = (rawInput, ctx) => execute2(rawInput, ctx, false);
191439
- const jsonSchema2 = inputSchema?.["~standard"].jsonSchema;
191440
- if (jsonSchema2) {
191441
- call["~standard"] = {
191442
- version: 1,
191443
- vendor: "yes",
191444
- name: name ?? "",
191445
- description: options.description ?? "",
191446
- jsonSchema: {
191447
- input: (params) => jsonSchema2.input(params),
191448
- // what the op returns is what its output schema returns; without one that can say so, any value
191449
- output: (params) => outputSchema?.["~standard"].jsonSchema?.output(params) ?? {}
191450
- },
191451
- ...run4.length < 2 && {
191452
- execute: (input2, options2) => call(input2, options2?.signal ? { signal: options2.signal } : void 0)
191453
- }
191454
- };
191455
- }
191456
- if (!cacheMethods)
191457
- return call;
191458
- const withKey = (input2, use) => {
191459
- const toKey = (result2) => use(storeKey(keyOf(result2 && !result2.issues ? result2.value : input2)));
191460
- const result = inputSchema?.["~standard"].validate(input2);
191461
- return result instanceof Promise ? result.then(toKey) : toKey(result);
191462
- };
191463
- return Object.assign(call, {
191464
- clear: async (input2) => {
191465
- if (!store)
191466
- return;
191467
- if (input2 === void 0)
191468
- await sweep(store, prefix, () => true);
191469
- else
191470
- await withKey(input2, (key) => callAdapter("delete", key, () => store.delete([key]), reported));
191471
- },
191472
- // the memory store peeks, so asking whether a key is cached does not change which key is evicted next
191473
- has: async (input2) => !!store && !!freshEntry(await withKey(input2, (key) => callAdapter("get", key, () => "peek" in store ? store.peek(key) : store.get(key), reported))),
191474
- // not `async`: on the memory store a predicate that throws throws here, not in a promise nobody awaits
191475
- invalidate: (match3) => {
191476
- const accepts = typeof match3 === "function" ? match3 : fieldsMatch(match3);
191477
- return Promise.resolve(store ? sweep(store, prefix, accepts) : 0);
191478
- },
191479
- refresh: (rawInput, ctx) => execute2(rawInput, ctx, true)
191480
- });
191481
- }
191482
- function query(options) {
191483
- return op({ ...options, dedupe: true });
191484
- }
191485
- function mutation({ dedupe: _dedupe, ttl: _ttl, cache: _cache, ...options }) {
191486
- return build3(options, false);
191487
- }
191488
- var hookOr = (given, line) => given === void 0 ? line || void 0 : given ?? void 0;
191489
- var ownsSignal = (ctx) => {
191490
- if (ctx === void 0)
191491
- return true;
191492
- if (!isPlain(ctx))
191493
- return false;
191494
- const signal = ctx.signal;
191495
- return signal === void 0 || isSignal(signal);
191496
- };
191497
- var inject = (ctx) => {
191498
- if (ctx === void 0)
191499
- return { signal: idleSignal() };
191500
- return isPlain(ctx) && ctx.signal === void 0 ? { ...ctx, signal: idleSignal() } : ctx;
191501
- };
191502
- var idle;
191503
- var idleSignal = () => {
191504
- if (idle === void 0 && typeof AbortController === "function")
191505
- idle = new AbortController().signal;
191506
- return idle;
191507
- };
191508
- var signalOf = (ctx) => {
191509
- const signal = ctx?.signal;
191510
- return isSignal(signal) ? signal : void 0;
191511
- };
191512
- var isSignal = (value2) => typeof AbortSignal === "function" && value2 instanceof AbortSignal;
191513
- function debugTrace(label, callKey) {
191514
- if (!debugging())
191515
- return;
191516
- const prefix = `${label}[${(/* @__PURE__ */ new Date()).toISOString()}]`;
191517
- const start = performance.now();
191518
- const key = hashedKey(callKey);
191519
- return (message2, data) => console.log(`${prefix} ${message2} +${Math.round(performance.now() - start)}ms`, { ...key && { key }, ...data });
191520
- }
191521
- function hashedKey(key) {
191522
- if (key)
191523
- key.hashed ??= hashKey(key.local);
191524
- return key?.hashed;
191525
- }
191526
- var maxDelay = 2 ** 31 - 1;
191527
- var isLifetime = (ms) => typeof ms === "number" && ms > 0 && Number.isFinite(ms);
191528
- function fieldsMatch(partial3) {
191529
- const fields = Object.entries(partial3).map(([field, value2]) => [
191530
- field,
191531
- value2 === void 0 ? void 0 : canonical(value2)
191532
- ]);
191533
- return (input2) => typeof input2 === "object" && input2 !== null && fields.every(([field, value2]) => {
191534
- const actual = input2[field];
191535
- return actual === void 0 ? value2 === void 0 : value2 !== void 0 && canonical(actual) === value2;
191536
- });
191537
- }
191538
- var isThenable = (value2) => typeof value2?.then === "function";
191539
- function freshEntry(value2) {
191540
- return typeof value2?.expires === "number" && value2.expires > Date.now() && "value" in value2 ? value2 : void 0;
191541
- }
191542
- function callAdapter(method, key, run4, reported) {
191543
- try {
191544
- const result = run4();
191545
- if (!isThenable(result))
191546
- return result;
191547
- return result.then(void 0, (error63) => {
191548
- throw new AdapterError(method, reported ? reported(key) : key, error63);
191549
- });
191550
- } catch (error63) {
191551
- throw new AdapterError(method, reported ? reported(key) : key, error63);
191552
- }
191553
- }
191554
- function sweep(store, prefix, match3) {
191555
- const purge = (listed2) => {
191556
- const now = Date.now();
191557
- const keys = [];
191558
- let count = 0;
191559
- for (const [key, { input: input2, expires }] of listed2) {
191560
- if (!(expires > now))
191561
- keys.push(key);
191562
- else if (match3(input2)) {
191563
- keys.push(key);
191564
- count++;
191565
- }
191566
- }
191567
- const remove = (from) => {
191568
- if (from >= keys.length)
191569
- return count;
191570
- const deleted = callAdapter("delete", prefix, () => store.delete(keys.slice(from, from + 1e3)));
191571
- return isThenable(deleted) ? Promise.resolve(deleted).then(() => remove(from + 1e3)) : remove(from + 1e3);
191572
- };
191573
- return remove(0);
191574
- };
191575
- const listed = callAdapter("list", prefix, () => {
191576
- const listed2 = store.list(prefix);
191577
- if (Array.isArray(listed2))
191578
- return listed2;
191579
- return (async () => {
191580
- const items = [];
191581
- for await (const item of await listed2)
191582
- items.push(item);
191583
- return items;
191584
- })();
191585
- });
191586
- return Array.isArray(listed) ? purge(listed) : listed.then(purge);
191587
- }
191588
-
191589
191698
  // utils/progressComment.ts
191590
191699
  function parseProgressComment(raw2) {
191591
191700
  if (!raw2?.id) return void 0;
@@ -191730,7 +191839,7 @@ function ensureRepoState(toolState, init) {
191730
191839
 
191731
191840
  // utils/changeImpact.ts
191732
191841
  import { spawn as spawn4 } from "node:child_process";
191733
- import { writeFileSync as writeFileSync8 } from "node:fs";
191842
+ import { writeFileSync as writeFileSync9 } from "node:fs";
191734
191843
  import { join as join10 } from "node:path";
191735
191844
  var MAX_CANDIDATES = 24;
191736
191845
  var MAX_ATOM_LENGTH = 128;
@@ -192083,7 +192192,7 @@ async function createChangeImpactArtifact(ctx, params) {
192083
192192
  lookupError: lookup2.error
192084
192193
  });
192085
192194
  const path4 = join10(ctx.tmpdir, `pr-${params.pullNumber}-${params.headSha.slice(0, 7)}-impact.md`);
192086
- writeFileSync8(path4, artifact.content);
192195
+ writeFileSync9(path4, artifact.content);
192087
192196
  return {
192088
192197
  path: path4,
192089
192198
  candidateCount: candidates.selected.length,
@@ -192352,7 +192461,7 @@ var GENERATED = /(^|\/)(package-lock\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb
192352
192461
 
192353
192462
  // utils/gitAuth.ts
192354
192463
  import { execSync } from "node:child_process";
192355
- import { createHash as createHash2 } from "node:crypto";
192464
+ import { createHash as createHash3 } from "node:crypto";
192356
192465
  import { readFileSync as readFileSync6, realpathSync, unlinkSync } from "node:fs";
192357
192466
  import { join as join11 } from "node:path";
192358
192467
 
@@ -192415,7 +192524,7 @@ var TRANSIENT_AUTH_PATTERNS = [
192415
192524
  ];
192416
192525
  var gitBinary;
192417
192526
  function hashFile(path4) {
192418
- return createHash2("sha256").update(readFileSync6(path4)).digest("hex");
192527
+ return createHash3("sha256").update(readFileSync6(path4)).digest("hex");
192419
192528
  }
192420
192529
  function resolveGit() {
192421
192530
  const whichPath = execSync("which git", { encoding: "utf-8" }).trim();
@@ -192560,7 +192669,7 @@ import { spawnSync as spawnSync8 } from "node:child_process";
192560
192669
  import { spawn as spawn5, spawnSync as spawnSync7 } from "node:child_process";
192561
192670
  import { randomUUID as randomUUID4 } from "node:crypto";
192562
192671
  import { once } from "node:events";
192563
- import { closeSync, existsSync as existsSync10, openSync, writeFileSync as writeFileSync9 } from "node:fs";
192672
+ import { closeSync, existsSync as existsSync10, openSync, writeFileSync as writeFileSync10 } from "node:fs";
192564
192673
  import { userInfo as userInfo2 } from "node:os";
192565
192674
  import { join as join12 } from "node:path";
192566
192675
  import { setTimeout as sleep3 } from "node:timers/promises";
@@ -193447,7 +193556,7 @@ ${spawnError}` : spawnError;
193447
193556
  function capOutput(output2) {
193448
193557
  if (output2.length <= MAX_OUTPUT_CHARS) return output2;
193449
193558
  const fullPath = join12(getTempDir(), `shell-${randomUUID4().slice(0, 8)}.log`);
193450
- writeFileSync9(fullPath, output2);
193559
+ writeFileSync10(fullPath, output2);
193451
193560
  const elided = output2.length - MAX_OUTPUT_CHARS;
193452
193561
  return `... [${elided} chars truncated; output saved to ${fullPath}] ...
193453
193562
  ${output2.slice(-MAX_OUTPUT_CHARS)}`;
@@ -193523,7 +193632,7 @@ Do NOT use this tool for git commands \u2014 use the dedicated git tools instead
193523
193632
  throw new Error(`failed to start background process: ${error63.message}`);
193524
193633
  }
193525
193634
  proc.unref();
193526
- writeFileSync9(pidPath, `${proc.pid}
193635
+ writeFileSync10(pidPath, `${proc.pid}
193527
193636
  `);
193528
193637
  ctx.toolState.backgroundProcesses.set(handle, { pid: proc.pid, outputPath, pidPath });
193529
193638
  return {
@@ -193695,14 +193804,15 @@ function computeIncrementalDiff(params) {
193695
193804
  const tips = [`origin/${params.baseBranch}`, ...params.formerBaseTips];
193696
193805
  const oldBase = versionBase({ sha: params.beforeSha, tips });
193697
193806
  const newBase = versionBase({ sha: params.headSha, tips });
193807
+ const replayed = oldBase === newBase ? null : replay({ sha: params.beforeSha, from: oldBase, onto: newBase });
193698
193808
  const raw2 = $(
193699
193809
  "sh",
193700
193810
  [
193701
193811
  "-c",
193702
193812
  'git range-diff --no-color --creation-factor=1000 "$1..$(git commit-tree "$2^{tree}" -p "$1" -m x)" "$3..$(git commit-tree "$4^{tree}" -p "$3" -m x)"',
193703
193813
  "--",
193704
- oldBase,
193705
- params.beforeSha,
193814
+ replayed ? newBase : oldBase,
193815
+ replayed ?? params.beforeSha,
193706
193816
  newBase,
193707
193817
  params.headSha
193708
193818
  ],
@@ -193737,6 +193847,22 @@ function versionBase(params) {
193737
193847
  }
193738
193848
  return best.sha;
193739
193849
  }
193850
+ function replay(params) {
193851
+ try {
193852
+ return git([
193853
+ "merge-tree",
193854
+ "--write-tree",
193855
+ `--merge-base=${params.from}`,
193856
+ params.onto,
193857
+ params.sha
193858
+ ]);
193859
+ } catch {
193860
+ log2.info(
193861
+ `\xBB incremental diff: ${params.sha.slice(0, 7)} does not replay onto the new base; comparing each on its own`
193862
+ );
193863
+ return null;
193864
+ }
193865
+ }
193740
193866
  function isDiffPrefix(ch) {
193741
193867
  return ch === " " || ch === "+" || ch === "-";
193742
193868
  }
@@ -193851,7 +193977,7 @@ function postProcessRangeDiff(raw2, contextLines = 3) {
193851
193977
 
193852
193978
  // mcp/git.ts
193853
193979
  import { randomUUID as randomUUID5 } from "node:crypto";
193854
- import { writeFileSync as writeFileSync10 } from "node:fs";
193980
+ import { writeFileSync as writeFileSync11 } from "node:fs";
193855
193981
  import { join as join15 } from "node:path";
193856
193982
 
193857
193983
  // utils/apiCommit.ts
@@ -199304,7 +199430,7 @@ function spillGitOutput(params) {
199304
199430
  const tempDir = process.env.PULLFROG_TEMP_DIR;
199305
199431
  if (!tempDir) throw new Error("PULLFROG_TEMP_DIR not set");
199306
199432
  const outputPath = join15(tempDir, `git-${params.command}-${randomUUID5().slice(0, 8)}.txt`);
199307
- writeFileSync10(outputPath, params.output);
199433
+ writeFileSync11(outputPath, params.output);
199308
199434
  const previewByLines = params.output.split("\n").slice(0, OVERFLOW_PREVIEW_LINES).join("\n");
199309
199435
  const preview = previewByLines.length <= OVERFLOW_PREVIEW_MAX_CHARS ? previewByLines : `${previewByLines.slice(0, OVERFLOW_PREVIEW_MAX_CHARS)}\u2026`;
199310
199436
  log2.info(
@@ -199649,9 +199775,21 @@ function fixDoubleEscapedString(str) {
199649
199775
  }
199650
199776
 
199651
199777
  // utils/isPullfrog.ts
199778
+ var BUILT_IN = /* @__PURE__ */ new Set(["pullfrog", "pullfrogdev"]);
199779
+ var runBotLogin = "pullfrog";
199780
+ function setBotLogin(login) {
199781
+ runBotLogin = normalize3(login);
199782
+ }
199652
199783
  function isPullfrog(actor) {
199653
- actor = actor?.toLowerCase().replace("[bot]", "");
199654
- return !!actor && (actor === "pullfrog" || actor === "pullfrogdev");
199784
+ if (!actor) return false;
199785
+ const login = normalize3(actor);
199786
+ return login === runBotLogin || BUILT_IN.has(login);
199787
+ }
199788
+ function mentionHandles() {
199789
+ return [.../* @__PURE__ */ new Set(["@pullfrog", `@${runBotLogin}`])];
199790
+ }
199791
+ function normalize3(login) {
199792
+ return login.toLowerCase().replace("[bot]", "");
199655
199793
  }
199656
199794
 
199657
199795
  // utils/outstandingThreads.ts
@@ -199671,6 +199809,7 @@ query ($owner: String!, $name: String!, $prNumber: Int!, $cursor: String) {
199671
199809
  }
199672
199810
  `;
199673
199811
  async function countOutstandingPullfrogThreads(ctx, pullNumber) {
199812
+ const isOwn = ctx.isPullfrog ?? isPullfrog;
199674
199813
  let count = 0;
199675
199814
  let cursor3 = null;
199676
199815
  for (let page = 0; page < 50; page += 1) {
@@ -199682,7 +199821,7 @@ async function countOutstandingPullfrogThreads(ctx, pullNumber) {
199682
199821
  for (const thread of conn?.nodes ?? []) {
199683
199822
  if (!thread || thread.isResolved) continue;
199684
199823
  const root = thread.comments?.nodes?.find((c2) => c2 != null);
199685
- if (root && isPullfrog(root.author?.login)) count += 1;
199824
+ if (root && isOwn(root.author?.login)) count += 1;
199686
199825
  }
199687
199826
  if (!conn?.pageInfo.hasNextPage) break;
199688
199827
  cursor3 = conn.pageInfo.endCursor;
@@ -199723,6 +199862,8 @@ var defaultSettings = {
199723
199862
  codexAgent: false,
199724
199863
  signedCommits: false,
199725
199864
  repoIntelligence: false,
199865
+ botLogin: "pullfrog[bot]",
199866
+ botUserId: "226033991",
199726
199867
  progressComments: true,
199727
199868
  statusChecks: true,
199728
199869
  approvalCheck: false,
@@ -199803,7 +199944,8 @@ async function fetchRunContext(params) {
199803
199944
  secretsUnavailable: data.secretsUnavailable,
199804
199945
  routerUnfunded: data.routerUnfunded,
199805
199946
  trialFallback: data.trialFallback,
199806
- trialCreditsLeftUsd: data.trialCreditsLeftUsd
199947
+ trialCreditsLeftUsd: data.trialCreditsLeftUsd,
199948
+ modelRegistry: data.modelRegistry
199807
199949
  };
199808
199950
  } catch {
199809
199951
  clearTimeout(timeoutId);
@@ -200996,11 +201138,25 @@ import { execFileSync as execFileSync7, execSync as execSync2 } from "node:child
200996
201138
  import { mkdtempSync as mkdtempSync3, readdirSync, realpathSync as realpathSync2, rmSync as rmSync4, unlinkSync as unlinkSync2 } from "node:fs";
200997
201139
  import { tmpdir as tmpdir3 } from "node:os";
200998
201140
  import { join as join16 } from "node:path";
201141
+ var TEMP_DIR_STATE = "temp_dir";
200999
201142
  function createTempDirectory() {
201000
201143
  const path4 = mkdtempSync3(join16(tmpdir3(), "pullfrog-"));
201001
201144
  process.env.PULLFROG_TEMP_DIR = path4;
201002
201145
  log2.info(`\xBB created temp dir at ${path4}`);
201003
- return { path: path4, [Symbol.dispose]: () => removeTempDirectory(path4) };
201146
+ const tracked = process.env.RUNNER_ENVIRONMENT !== "github-hosted";
201147
+ if (tracked) saveSecretState(TEMP_DIR_STATE, path4);
201148
+ return {
201149
+ path: path4,
201150
+ [Symbol.dispose]: () => {
201151
+ if (removeTempDirectory(path4) && tracked) saveSecretState(TEMP_DIR_STATE, "");
201152
+ }
201153
+ };
201154
+ }
201155
+ function removeAbandonedTempDirectory() {
201156
+ const path4 = getState(TEMP_DIR_STATE);
201157
+ if (!path4) return;
201158
+ log2.info(`\xBB removing temp dir left by an interrupted run at ${path4}`);
201159
+ removeTempDirectory(path4);
201004
201160
  }
201005
201161
  function removeTempDirectory(path4) {
201006
201162
  try {
@@ -201011,10 +201167,12 @@ function removeTempDirectory(path4) {
201011
201167
  rmSync4(path4, { recursive: true, force: true });
201012
201168
  }
201013
201169
  log2.debug(`\xBB removed temp dir at ${path4}`);
201170
+ return true;
201014
201171
  } catch (err) {
201015
201172
  log2.warning(
201016
201173
  `\xBB could not remove temp dir at ${path4}: ${err instanceof Error ? err.message : String(err)}`
201017
201174
  );
201175
+ return false;
201018
201176
  }
201019
201177
  }
201020
201178
  function wipeRunnerLeakSurface() {
@@ -201136,11 +201294,12 @@ async function configureRepoGit(params) {
201136
201294
  }
201137
201295
  const shouldSetDefaults = !currentEmail || currentEmail === "github-actions[bot]@users.noreply.github.com";
201138
201296
  if (shouldSetDefaults) {
201139
- execSync2('git config --local user.email "226033991+pullfrog[bot]@users.noreply.github.com"', {
201297
+ const email5 = `${params.botUserId}+${params.botLogin}@users.noreply.github.com`;
201298
+ execFileSync7("git", ["config", "--local", "user.email", email5], {
201140
201299
  cwd: repoDir,
201141
201300
  stdio: "pipe"
201142
201301
  });
201143
- execSync2('git config --local user.name "pullfrog[bot]"', {
201302
+ execFileSync7("git", ["config", "--local", "user.name", params.botLogin], {
201144
201303
  cwd: repoDir,
201145
201304
  stdio: "pipe"
201146
201305
  });
@@ -201257,7 +201416,7 @@ function formatFilesWithLineNumbers(files) {
201257
201416
  }
201258
201417
  const tocLines = [`## Files (${files.length})`];
201259
201418
  for (const entry of tocEntries) {
201260
- const anchor2 = createHash3("sha256").update(entry.filename).digest("hex");
201419
+ const anchor2 = createHash4("sha256").update(entry.filename).digest("hex");
201261
201420
  const generated = GENERATED.test(entry.filename) ? " \xB7 generated" : "";
201262
201421
  tocLines.push(
201263
201422
  `- ${entry.filename} \u2192 lines ${entry.startLine}-${entry.endLine} \xB7 diff-${anchor2}${generated}`
@@ -201640,6 +201799,8 @@ function CheckoutPrTool(ctx) {
201640
201799
  toolState: ctx.toolState,
201641
201800
  shell: ctx.payload.shell,
201642
201801
  postCheckoutScript: ctx.postCheckoutScript,
201802
+ botLogin: ctx.botLogin,
201803
+ botUserId: ctx.botUserId,
201643
201804
  beforeSha: primary.beforeSha,
201644
201805
  signal
201645
201806
  });
@@ -201670,7 +201831,7 @@ function CheckoutPrTool(ctx) {
201670
201831
  tempDir,
201671
201832
  `pr-${pull_number}-${beforeShort}-${headShort}-incremental.diff`
201672
201833
  );
201673
- writeFileSync11(incrementalDiffPath, incremental.diff);
201834
+ writeFileSync12(incrementalDiffPath, incremental.diff);
201674
201835
  incrementalDiff = incremental.diff;
201675
201836
  log2.info(
201676
201837
  `\xBB incremental diff computed (${incremental.diff.length} bytes) \u2192 ${incrementalDiffPath}`
@@ -201687,7 +201848,7 @@ function CheckoutPrTool(ctx) {
201687
201848
  log2.debug(`formatted diff preview (first 100 lines):
201688
201849
  ${diffPreview}`);
201689
201850
  const diffPath = join17(tempDir, `pr-${pull_number}-${headShort}.diff`);
201690
- writeFileSync11(diffPath, formatResult.content);
201851
+ writeFileSync12(diffPath, formatResult.content);
201691
201852
  log2.debug(`wrote diff to ${diffPath} (${formatResult.content.length} bytes)`);
201692
201853
  const coverageEntries = incrementalDiff ? parseIncrementalDiffEntries({ content: incrementalDiff }) : parseDiffTocEntries({ toc: formatResult.toc });
201693
201854
  primary.diffCoverage = incrementalEmpty ? void 0 : createDiffCoverageState({
@@ -201850,7 +202011,7 @@ ${dirty}`
201850
202011
  }
201851
202012
 
201852
202013
  // mcp/checkSuite.ts
201853
- import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync12 } from "node:fs";
202014
+ import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync13 } from "node:fs";
201854
202015
  import { join as join18 } from "node:path";
201855
202016
  var GetCheckSuiteLogs = type({
201856
202017
  check_suite_id: type.number.describe("the id from check_suite.id")
@@ -201948,7 +202109,7 @@ function GetCheckSuiteLogsTool(ctx) {
201948
202109
  throw new Error("PULLFROG_TEMP_DIR not set");
201949
202110
  }
201950
202111
  const logsDir = join18(tempDir, "ci-logs");
201951
- mkdirSync8(logsDir, { recursive: true });
202112
+ mkdirSync9(logsDir, { recursive: true });
201952
202113
  const jobResults = [];
201953
202114
  for (const run4 of failedRuns) {
201954
202115
  const jobs = await ctx.octokit.paginate(ctx.octokit.rest.actions.listJobsForWorkflowRun, {
@@ -201975,7 +202136,7 @@ function GetCheckSuiteLogsTool(ctx) {
201975
202136
  }
201976
202137
  const logsText = await logsResult.text();
201977
202138
  const logPath = join18(logsDir, `job-${job.id}.log`);
201978
- writeFileSync12(logPath, logsText);
202139
+ writeFileSync13(logPath, logsText);
201979
202140
  const analysis = analyzeLog(logsText, 80);
201980
202141
  const failedSteps = job.steps?.filter((s) => s.conclusion === "failure").map((s) => `Step ${s.number}: ${s.name}`) ?? [];
201981
202142
  jobResults.push({
@@ -202023,7 +202184,7 @@ function GetCheckSuiteLogsTool(ctx) {
202023
202184
  }
202024
202185
 
202025
202186
  // mcp/commitInfo.ts
202026
- import { writeFileSync as writeFileSync13 } from "node:fs";
202187
+ import { writeFileSync as writeFileSync14 } from "node:fs";
202027
202188
  import { join as join19 } from "node:path";
202028
202189
  var CommitInfo = type({
202029
202190
  sha: type.string.describe("the commit SHA (full or abbreviated) to fetch")
@@ -202049,7 +202210,7 @@ function CommitInfoTool(ctx) {
202049
202210
  );
202050
202211
  }
202051
202212
  const diffFile = join19(tempDir, `commit-${sha.slice(0, 7)}.diff`);
202052
- writeFileSync13(diffFile, formatResult.content);
202213
+ writeFileSync14(diffFile, formatResult.content);
202053
202214
  log2.debug(`wrote commit diff to ${diffFile} (${formatResult.content.length} bytes)`);
202054
202215
  return {
202055
202216
  sha: data.sha,
@@ -202808,7 +202969,7 @@ function AwaitDependencyInstallationTool(ctx) {
202808
202969
  }
202809
202970
 
202810
202971
  // mcp/gh.ts
202811
- import { mkdirSync as mkdirSync9 } from "node:fs";
202972
+ import { mkdirSync as mkdirSync10 } from "node:fs";
202812
202973
  import { join as join23 } from "node:path";
202813
202974
  var GH_TIMEOUT_MS = 12e4;
202814
202975
  var GhParams = type({
@@ -202832,7 +202993,7 @@ function GhTool(ctx) {
202832
202993
  parameters: GhParams,
202833
202994
  execute: execute(async (params) => {
202834
202995
  const configDir = join23(ctx.tmpdir, "gh-config");
202835
- mkdirSync9(configDir, { recursive: true });
202996
+ mkdirSync10(configDir, { recursive: true });
202836
202997
  const command = ["gh", ...params.args.map(shellQuote)].join(" ");
202837
202998
  const result = await runSandboxed({
202838
202999
  command,
@@ -203556,7 +203717,7 @@ function PullRequestInfoTool(ctx) {
203556
203717
  }
203557
203718
 
203558
203719
  // mcp/reviewComments.ts
203559
- import { writeFileSync as writeFileSync14 } from "node:fs";
203720
+ import { writeFileSync as writeFileSync15 } from "node:fs";
203560
203721
  import { join as join24 } from "node:path";
203561
203722
 
203562
203723
  // utils/payload.ts
@@ -204244,7 +204405,8 @@ function concurrentThreads(allThreads, threadsForReview, input2) {
204244
204405
  }
204245
204406
  function mentionsPullfrog(body) {
204246
204407
  if (!body) return false;
204247
- return body.split(/\r?\n/).filter((line) => !line.trim().startsWith(">")).join("\n").toLowerCase().includes("@pullfrog");
204408
+ const text = body.split(/\r?\n/).filter((line) => !line.trim().startsWith(">")).join("\n").toLowerCase();
204409
+ return mentionHandles().some((handle) => text.includes(handle));
204248
204410
  }
204249
204411
  function formatReviewData(input2) {
204250
204412
  const rawReviewBody = input2.review.body;
@@ -204374,7 +204536,7 @@ function GetReviewCommentsTool(ctx) {
204374
204536
  }
204375
204537
  const filename = `review-${params.review_id}-threads.md`;
204376
204538
  const commentsPath = join24(tempDir, filename);
204377
- writeFileSync14(commentsPath, formatted.content);
204539
+ writeFileSync15(commentsPath, formatted.content);
204378
204540
  log2.debug(`wrote ${threadBlocks.length} threads to ${commentsPath}`);
204379
204541
  return {
204380
204542
  review_id: params.review_id,
@@ -204778,7 +204940,7 @@ function UploadFileTool(ctx) {
204778
204940
  }
204779
204941
 
204780
204942
  // mcp/xrepo.ts
204781
- import { mkdirSync as mkdirSync10, rmSync as rmSync5 } from "node:fs";
204943
+ import { mkdirSync as mkdirSync11, rmSync as rmSync5 } from "node:fs";
204782
204944
  import { join as join25 } from "node:path";
204783
204945
  function assertValidRepoName(name) {
204784
204946
  if (!/^[A-Za-z0-9._-]+$/.test(name) || name.startsWith("-") || name.includes("..")) {
@@ -204860,7 +205022,7 @@ function CheckoutRepoTool(ctx) {
204860
205022
  }
204861
205023
  const access2 = accessFor(ctx, repo);
204862
205024
  const dir = join25(ctx.tmpdir, "xrepo", repo);
204863
- mkdirSync10(dir, { recursive: true });
205025
+ mkdirSync11(dir, { recursive: true });
204864
205026
  const state = ensureRepoState(ctx.toolState, { owner, name: repo, dir, access: access2 });
204865
205027
  const rc = resolveRepoCtx(ctx, repo);
204866
205028
  try {
@@ -204884,7 +205046,9 @@ function CheckoutRepoTool(ctx) {
204884
205046
  octokit: rc.octokit,
204885
205047
  toolState: ctx.toolState,
204886
205048
  shell: ctx.payload.shell,
204887
- postCheckoutScript: null
205049
+ postCheckoutScript: null,
205050
+ botLogin: ctx.botLogin,
205051
+ botUserId: ctx.botUserId
204888
205052
  });
204889
205053
  log2.info(`\xBB checked out secondary repo ${owner}/${repo} (${access2}) \u2192 ${dir}`);
204890
205054
  return { path: dir, access: access2, defaultBranch };
@@ -206457,7 +206621,7 @@ function activate(input2) {
206457
206621
 
206458
206622
  // utils/gitAuthServer.ts
206459
206623
  import { randomUUID as randomUUID7 } from "node:crypto";
206460
- import { writeFileSync as writeFileSync15 } from "node:fs";
206624
+ import { writeFileSync as writeFileSync16 } from "node:fs";
206461
206625
  import { createServer as createServer4 } from "node:http";
206462
206626
  import { join as join26 } from "node:path";
206463
206627
  var REVOKED_TRAP_MS = 6e4;
@@ -206544,7 +206708,7 @@ async function startGitAuthServer(tmpdir5) {
206544
206708
  `r.on("end",function(){process.stdout.write(d+"\\n")})`,
206545
206709
  `}).on("error",function(){process.exit(1)})}`
206546
206710
  ].join("\n");
206547
- writeFileSync15(scriptPath, content, { mode: 448 });
206711
+ writeFileSync16(scriptPath, content, { mode: 448 });
206548
206712
  return scriptPath;
206549
206713
  }
206550
206714
  async function close() {
@@ -207788,6 +207952,22 @@ ${collapsible}` : output2;
207788
207952
  }
207789
207953
 
207790
207954
  // utils/runContextData.ts
207955
+ function installServedRegistry(served) {
207956
+ const pins = getHarnessPins();
207957
+ const moved = Object.keys(pins).filter((name) => served.harnessPins[name] !== pins[name]);
207958
+ if (moved.length > 0) {
207959
+ const theirs = moved.map((name) => `${name}@${served.harnessPins[name]}`).join(", ");
207960
+ log2.info(`\xBB kept the bundled model registry: the server's is written for ${theirs}`);
207961
+ return;
207962
+ }
207963
+ try {
207964
+ installProviders(served.providers);
207965
+ } catch (error63) {
207966
+ log2.warning(
207967
+ `\xBB kept the bundled model registry: the server's ${error63 instanceof Error ? error63.message : error63}`
207968
+ );
207969
+ }
207970
+ }
207791
207971
  async function resolveRunContextData(params) {
207792
207972
  const actionRef = process.env.GITHUB_ACTION_REF;
207793
207973
  log2.info(
@@ -207819,6 +207999,7 @@ async function resolveRunContextData(params) {
207819
207999
  })
207820
208000
  ]);
207821
208001
  if (runContext.apiToken) maskSecret(runContext.apiToken);
208002
+ if (runContext.modelRegistry) installServedRegistry(runContext.modelRegistry);
207822
208003
  return {
207823
208004
  repo: {
207824
208005
  owner: repoContext.owner,
@@ -208039,6 +208220,19 @@ function formatProviderModelNotFound(ctx) {
208039
208220
  const model = /Model not found: (\S+?)\.?(?:\s|$)/.exec(ctx.errorMessage)?.[1];
208040
208221
  const suggestions = /Did you mean: ([^?\n]+)\?/.exec(ctx.errorMessage)?.[1]?.split(",").map((id) => `\`${id.trim()}\``);
208041
208222
  const suggested = suggestions?.length ? ` OpenCode suggests ${suggestions.slice(0, -1).join(", ")}${suggestions.length > 1 ? " or " : ""}${suggestions.at(-1)}.` : "";
208223
+ if (ctx.modelsCatalogFailure) {
208224
+ return renderFailure({
208225
+ headline: model ? `OpenCode couldn't download its model list, so it didn't recognize \`${model}\`.` : "OpenCode couldn't download its model list, so it didn't recognize this repo's model.",
208226
+ detail: `It fell back to the copy built into it, which lacks models released since that build. Re-run once the runner can reach OpenCode's model catalog, or pick an older model.${suggested}`,
208227
+ details: {
208228
+ summary: "Why the download failed",
208229
+ text: `${ctx.modelsCatalogFailure}
208230
+
208231
+ ${ctx.errorMessage}`
208232
+ },
208233
+ links: [pickModelLink(ctx.repo)]
208234
+ });
208235
+ }
208042
208236
  return renderFailure({
208043
208237
  headline: model ? `\`${model}\` isn't in OpenCode's catalog.` : "This repo's model isn't in OpenCode's catalog.",
208044
208238
  detail: `Pick another model wherever this repo sets it: the Pullfrog console, the workflow's \`model\` input or the \`PULLFROG_MODEL\` variable.${suggested}`,
@@ -208920,6 +209114,7 @@ async function main() {
208920
209114
  routedTier: typeof resolvedPromptInput === "string" ? void 0 : resolvedPromptInput.routing?.tier
208921
209115
  });
208922
209116
  timer.checkpoint("runContextData");
209117
+ setBotLogin(runContext.repoSettings.botLogin);
208923
209118
  const payload = resolvePayload(resolvedPromptInput, runContext.repoSettings);
208924
209119
  const toolState = initToolState({
208925
209120
  progressComment: typeof resolvedPromptInput !== "string" ? resolvedPromptInput.progressComment : void 0,
@@ -208971,6 +209166,7 @@ async function main() {
208971
209166
  const repoDir = payload.cwd;
208972
209167
  const preIntrospectionDirty = repoDir ? await dirtyTrackedPaths({ cwd: repoDir }) : null;
208973
209168
  const opencodeCliPath = await agents.opencode.install();
209169
+ await seedModelsCatalog(tmpdir5);
208974
209170
  captureBaselineModels({ cliPath: opencodeCliPath, tmpdir: tmpdir5 });
208975
209171
  const injected = [];
208976
209172
  if (runContext.dbSecrets) {
@@ -209166,7 +209362,9 @@ async function main() {
209166
209362
  octokit,
209167
209363
  toolState,
209168
209364
  shell: payload.shell,
209169
- postCheckoutScript: runContext.repoSettings.postCheckoutScript
209365
+ postCheckoutScript: runContext.repoSettings.postCheckoutScript,
209366
+ botLogin: runContext.repoSettings.botLogin,
209367
+ botUserId: runContext.repoSettings.botUserId
209170
209368
  });
209171
209369
  timer.checkpoint("git");
209172
209370
  const pmSpec = await resolvePackageManagerSpec(process.cwd());
@@ -209193,7 +209391,11 @@ async function main() {
209193
209391
  timer.checkpoint("lifecycleHooks::setup");
209194
209392
  const agentId = agent2.name;
209195
209393
  const modes2 = [
209196
- ...computeModes(agentId, runContext.repoSettings.signedCommits),
209394
+ ...computeModes({
209395
+ agentId,
209396
+ signedCommits: runContext.repoSettings.signedCommits,
209397
+ botLogin: runContext.repoSettings.botLogin
209398
+ }),
209197
209399
  ...runContext.repoSettings.modes
209198
209400
  ];
209199
209401
  const outputSchema = resolveOutputSchema();
@@ -209219,6 +209421,8 @@ async function main() {
209219
209421
  apiToken: runContext.apiToken,
209220
209422
  modes: modes2,
209221
209423
  postCheckoutScript: runContext.repoSettings.postCheckoutScript,
209424
+ botLogin: runContext.repoSettings.botLogin,
209425
+ botUserId: runContext.repoSettings.botUserId,
209222
209426
  prepushScript: runContext.repoSettings.prepushScript,
209223
209427
  prApproveEnabled: runContext.repoSettings.prApproveEnabled,
209224
209428
  reviewDrafts: runContext.repoSettings.reviewDrafts,
@@ -209484,7 +209688,8 @@ ${instructions.user}` : null,
209484
209688
  routerActive: !!payload.proxyModel,
209485
209689
  model: toolState.model,
209486
209690
  credential: toolState.credential,
209487
- trial: toolState.modelClamped?.reason === "trial"
209691
+ trial: toolState.modelClamped?.reason === "trial",
209692
+ modelsCatalogFailure: getModelsCatalogFailure()
209488
209693
  });
209489
209694
  await writeRunErrorOutputs({ rendered, toolState });
209490
209695
  if (toolContext) {
@@ -209665,6 +209870,7 @@ async function runCli5(params) {
209665
209870
  async function run(args2) {
209666
209871
  if (args2.includes("--post") && !args2.includes("token")) {
209667
209872
  await runOAuthWriteback().catch((error63) => warning(`oauth post-hook: ${error63}`));
209873
+ removeAbandonedTempDirectory();
209668
209874
  return;
209669
209875
  }
209670
209876
  try {
@@ -209943,7 +210149,7 @@ async function run2() {
209943
210149
  }
209944
210150
 
209945
210151
  // commands/_prEvents.ts
209946
- import { mkdirSync as mkdirSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync16 } from "node:fs";
210152
+ import { mkdirSync as mkdirSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync17 } from "node:fs";
209947
210153
  import { homedir as homedir3 } from "node:os";
209948
210154
  import { join as join30 } from "node:path";
209949
210155
  var REQUEST_TIMEOUT_MS = 35e3;
@@ -210011,8 +210217,8 @@ function readCursor(target) {
210011
210217
  function writeCursor(target, cursor3) {
210012
210218
  try {
210013
210219
  const path4 = cursorPath(target);
210014
- mkdirSync11(join30(stateDir(), "watch"), { recursive: true });
210015
- writeFileSync16(path4, cursor3, "utf-8");
210220
+ mkdirSync12(join30(stateDir(), "watch"), { recursive: true });
210221
+ writeFileSync17(path4, cursor3, "utf-8");
210016
210222
  } catch {
210017
210223
  }
210018
210224
  }
@@ -210066,7 +210272,7 @@ function resolveTarget2(repo) {
210066
210272
  return { owner: match3[1], repo: match3[2] };
210067
210273
  }
210068
210274
  function cliVersion() {
210069
- const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.105");
210275
+ const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.107");
210070
210276
  if (!parts) return "0.0.0";
210071
210277
  return `${Number(parts[1])}.${Number(parts[2])}.${Number(parts[3])}`;
210072
210278
  }
@@ -210263,7 +210469,7 @@ async function runCli9(input2) {
210263
210469
  }
210264
210470
 
210265
210471
  // cli.ts
210266
- var VERSION10 = "0.1.105";
210472
+ var VERSION10 = "0.1.107";
210267
210473
  var bin = basename2(process.argv[1] || "");
210268
210474
  var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
210269
210475
  var rawArgs = process.argv.slice(2);