pullfrog 0.1.51 → 0.1.52

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
@@ -3871,9 +3871,9 @@ var require_constants2 = __commonJS({
3871
3871
  }
3872
3872
  })();
3873
3873
  var channel;
3874
- var structuredClone = globalThis.structuredClone ?? // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js
3874
+ var structuredClone2 = globalThis.structuredClone ?? // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js
3875
3875
  // structuredClone was added in v17.0.0, but fetch supports v16.8
3876
- function structuredClone2(value2, options = void 0) {
3876
+ function structuredClone3(value2, options = void 0) {
3877
3877
  if (arguments.length === 0) {
3878
3878
  throw new TypeError("missing argument");
3879
3879
  }
@@ -3887,7 +3887,7 @@ var require_constants2 = __commonJS({
3887
3887
  };
3888
3888
  module.exports = {
3889
3889
  DOMException: DOMException2,
3890
- structuredClone,
3890
+ structuredClone: structuredClone2,
3891
3891
  subresource,
3892
3892
  forbiddenMethods,
3893
3893
  requestBodyHeader,
@@ -5592,7 +5592,7 @@ var require_body = __commonJS({
5592
5592
  var { FormData: FormData2 } = require_formdata();
5593
5593
  var { kState } = require_symbols2();
5594
5594
  var { webidl } = require_webidl();
5595
- var { DOMException: DOMException2, structuredClone } = require_constants2();
5595
+ var { DOMException: DOMException2, structuredClone: structuredClone2 } = require_constants2();
5596
5596
  var { Blob: Blob2, File: NativeFile } = __require("buffer");
5597
5597
  var { kBodyUsed } = require_symbols();
5598
5598
  var assert3 = __require("assert");
@@ -5756,7 +5756,7 @@ Content-Type: ${value2.type || "application/octet-stream"}\r
5756
5756
  }
5757
5757
  function cloneBody(body) {
5758
5758
  const [out1, out2] = body.stream.tee();
5759
- const out2Clone = structuredClone(out2, { transfer: [out2] });
5759
+ const out2Clone = structuredClone2(out2, { transfer: [out2] });
5760
5760
  const [, finalClone] = out2Clone.tee();
5761
5761
  body.stream = out1;
5762
5762
  return {
@@ -20066,10 +20066,10 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
20066
20066
  (0, command_1.issueCommand)("error", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
20067
20067
  }
20068
20068
  exports.error = error49;
20069
- function warning2(message, properties = {}) {
20069
+ function warning3(message, properties = {}) {
20070
20070
  (0, command_1.issueCommand)("warning", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
20071
20071
  }
20072
- exports.warning = warning2;
20072
+ exports.warning = warning3;
20073
20073
  function notice(message, properties = {}) {
20074
20074
  (0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
20075
20075
  }
@@ -66680,7 +66680,7 @@ function initializeContext(params) {
66680
66680
  external: params?.external ?? void 0
66681
66681
  };
66682
66682
  }
66683
- function process2(schema2, ctx, _params = { path: [], schemaPath: [] }) {
66683
+ function process3(schema2, ctx, _params = { path: [], schemaPath: [] }) {
66684
66684
  var _a2;
66685
66685
  const def = schema2._zod.def;
66686
66686
  const seen = ctx.seen.get(schema2);
@@ -66717,7 +66717,7 @@ function process2(schema2, ctx, _params = { path: [], schemaPath: [] }) {
66717
66717
  if (parent) {
66718
66718
  if (!result.ref)
66719
66719
  result.ref = parent;
66720
- process2(parent, ctx, params);
66720
+ process3(parent, ctx, params);
66721
66721
  ctx.seen.get(parent).isParent = true;
66722
66722
  }
66723
66723
  }
@@ -67002,14 +67002,14 @@ var init_to_json_schema = __esm({
67002
67002
  init_registries();
67003
67003
  createToJSONSchemaMethod = (schema2, processors = {}) => (params) => {
67004
67004
  const ctx = initializeContext({ ...params, processors });
67005
- process2(schema2, ctx);
67005
+ process3(schema2, ctx);
67006
67006
  extractDefs(ctx, schema2);
67007
67007
  return finalize(ctx, schema2);
67008
67008
  };
67009
67009
  createStandardJSONSchemaMethod = (schema2, io, processors = {}) => (params) => {
67010
67010
  const { libraryOptions, target } = params ?? {};
67011
67011
  const ctx = initializeContext({ ...libraryOptions ?? {}, target, io, processors });
67012
- process2(schema2, ctx);
67012
+ process3(schema2, ctx);
67013
67013
  extractDefs(ctx, schema2);
67014
67014
  return finalize(ctx, schema2);
67015
67015
  };
@@ -67024,7 +67024,7 @@ function toJSONSchema(input, params) {
67024
67024
  const defs = {};
67025
67025
  for (const entry of registry4._idmap.entries()) {
67026
67026
  const [_2, schema2] = entry;
67027
- process2(schema2, ctx2);
67027
+ process3(schema2, ctx2);
67028
67028
  }
67029
67029
  const schemas = {};
67030
67030
  const external = {
@@ -67047,7 +67047,7 @@ function toJSONSchema(input, params) {
67047
67047
  return { schemas };
67048
67048
  }
67049
67049
  const ctx = initializeContext({ ...params, processors: allProcessors });
67050
- process2(input, ctx);
67050
+ process3(input, ctx);
67051
67051
  extractDefs(ctx, input);
67052
67052
  return finalize(ctx, input);
67053
67053
  }
@@ -67307,7 +67307,7 @@ var init_json_schema_processors = __esm({
67307
67307
  if (typeof maximum === "number")
67308
67308
  json4.maxItems = maximum;
67309
67309
  json4.type = "array";
67310
- json4.items = process2(def.element, ctx, { ...params, path: [...params.path, "items"] });
67310
+ json4.items = process3(def.element, ctx, { ...params, path: [...params.path, "items"] });
67311
67311
  };
67312
67312
  objectProcessor = (schema2, ctx, _json, params) => {
67313
67313
  const json4 = _json;
@@ -67316,7 +67316,7 @@ var init_json_schema_processors = __esm({
67316
67316
  json4.properties = {};
67317
67317
  const shape = def.shape;
67318
67318
  for (const key in shape) {
67319
- json4.properties[key] = process2(shape[key], ctx, {
67319
+ json4.properties[key] = process3(shape[key], ctx, {
67320
67320
  ...params,
67321
67321
  path: [...params.path, "properties", key]
67322
67322
  });
@@ -67339,7 +67339,7 @@ var init_json_schema_processors = __esm({
67339
67339
  if (ctx.io === "output")
67340
67340
  json4.additionalProperties = false;
67341
67341
  } else if (def.catchall) {
67342
- json4.additionalProperties = process2(def.catchall, ctx, {
67342
+ json4.additionalProperties = process3(def.catchall, ctx, {
67343
67343
  ...params,
67344
67344
  path: [...params.path, "additionalProperties"]
67345
67345
  });
@@ -67348,7 +67348,7 @@ var init_json_schema_processors = __esm({
67348
67348
  unionProcessor = (schema2, ctx, json4, params) => {
67349
67349
  const def = schema2._zod.def;
67350
67350
  const isExclusive = def.inclusive === false;
67351
- const options = def.options.map((x, i) => process2(x, ctx, {
67351
+ const options = def.options.map((x, i) => process3(x, ctx, {
67352
67352
  ...params,
67353
67353
  path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
67354
67354
  }));
@@ -67360,11 +67360,11 @@ var init_json_schema_processors = __esm({
67360
67360
  };
67361
67361
  intersectionProcessor = (schema2, ctx, json4, params) => {
67362
67362
  const def = schema2._zod.def;
67363
- const a = process2(def.left, ctx, {
67363
+ const a = process3(def.left, ctx, {
67364
67364
  ...params,
67365
67365
  path: [...params.path, "allOf", 0]
67366
67366
  });
67367
- const b = process2(def.right, ctx, {
67367
+ const b = process3(def.right, ctx, {
67368
67368
  ...params,
67369
67369
  path: [...params.path, "allOf", 1]
67370
67370
  });
@@ -67381,11 +67381,11 @@ var init_json_schema_processors = __esm({
67381
67381
  json4.type = "array";
67382
67382
  const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
67383
67383
  const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
67384
- const prefixItems = def.items.map((x, i) => process2(x, ctx, {
67384
+ const prefixItems = def.items.map((x, i) => process3(x, ctx, {
67385
67385
  ...params,
67386
67386
  path: [...params.path, prefixPath, i]
67387
67387
  }));
67388
- const rest = def.rest ? process2(def.rest, ctx, {
67388
+ const rest = def.rest ? process3(def.rest, ctx, {
67389
67389
  ...params,
67390
67390
  path: [...params.path, restPath, ...ctx.target === "openapi-3.0" ? [def.items.length] : []]
67391
67391
  }) : null;
@@ -67425,7 +67425,7 @@ var init_json_schema_processors = __esm({
67425
67425
  const keyBag = keyType._zod.bag;
67426
67426
  const patterns = keyBag?.patterns;
67427
67427
  if (def.mode === "loose" && patterns && patterns.size > 0) {
67428
- const valueSchema = process2(def.valueType, ctx, {
67428
+ const valueSchema = process3(def.valueType, ctx, {
67429
67429
  ...params,
67430
67430
  path: [...params.path, "patternProperties", "*"]
67431
67431
  });
@@ -67435,12 +67435,12 @@ var init_json_schema_processors = __esm({
67435
67435
  }
67436
67436
  } else {
67437
67437
  if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
67438
- json4.propertyNames = process2(def.keyType, ctx, {
67438
+ json4.propertyNames = process3(def.keyType, ctx, {
67439
67439
  ...params,
67440
67440
  path: [...params.path, "propertyNames"]
67441
67441
  });
67442
67442
  }
67443
- json4.additionalProperties = process2(def.valueType, ctx, {
67443
+ json4.additionalProperties = process3(def.valueType, ctx, {
67444
67444
  ...params,
67445
67445
  path: [...params.path, "additionalProperties"]
67446
67446
  });
@@ -67455,7 +67455,7 @@ var init_json_schema_processors = __esm({
67455
67455
  };
67456
67456
  nullableProcessor = (schema2, ctx, json4, params) => {
67457
67457
  const def = schema2._zod.def;
67458
- const inner = process2(def.innerType, ctx, params);
67458
+ const inner = process3(def.innerType, ctx, params);
67459
67459
  const seen = ctx.seen.get(schema2);
67460
67460
  if (ctx.target === "openapi-3.0") {
67461
67461
  seen.ref = def.innerType;
@@ -67466,20 +67466,20 @@ var init_json_schema_processors = __esm({
67466
67466
  };
67467
67467
  nonoptionalProcessor = (schema2, ctx, _json, params) => {
67468
67468
  const def = schema2._zod.def;
67469
- process2(def.innerType, ctx, params);
67469
+ process3(def.innerType, ctx, params);
67470
67470
  const seen = ctx.seen.get(schema2);
67471
67471
  seen.ref = def.innerType;
67472
67472
  };
67473
67473
  defaultProcessor = (schema2, ctx, json4, params) => {
67474
67474
  const def = schema2._zod.def;
67475
- process2(def.innerType, ctx, params);
67475
+ process3(def.innerType, ctx, params);
67476
67476
  const seen = ctx.seen.get(schema2);
67477
67477
  seen.ref = def.innerType;
67478
67478
  json4.default = JSON.parse(JSON.stringify(def.defaultValue));
67479
67479
  };
67480
67480
  prefaultProcessor = (schema2, ctx, json4, params) => {
67481
67481
  const def = schema2._zod.def;
67482
- process2(def.innerType, ctx, params);
67482
+ process3(def.innerType, ctx, params);
67483
67483
  const seen = ctx.seen.get(schema2);
67484
67484
  seen.ref = def.innerType;
67485
67485
  if (ctx.io === "input")
@@ -67487,7 +67487,7 @@ var init_json_schema_processors = __esm({
67487
67487
  };
67488
67488
  catchProcessor = (schema2, ctx, json4, params) => {
67489
67489
  const def = schema2._zod.def;
67490
- process2(def.innerType, ctx, params);
67490
+ process3(def.innerType, ctx, params);
67491
67491
  const seen = ctx.seen.get(schema2);
67492
67492
  seen.ref = def.innerType;
67493
67493
  let catchValue;
@@ -67501,32 +67501,32 @@ var init_json_schema_processors = __esm({
67501
67501
  pipeProcessor = (schema2, ctx, _json, params) => {
67502
67502
  const def = schema2._zod.def;
67503
67503
  const innerType = ctx.io === "input" ? def.in._zod.def.type === "transform" ? def.out : def.in : def.out;
67504
- process2(innerType, ctx, params);
67504
+ process3(innerType, ctx, params);
67505
67505
  const seen = ctx.seen.get(schema2);
67506
67506
  seen.ref = innerType;
67507
67507
  };
67508
67508
  readonlyProcessor = (schema2, ctx, json4, params) => {
67509
67509
  const def = schema2._zod.def;
67510
- process2(def.innerType, ctx, params);
67510
+ process3(def.innerType, ctx, params);
67511
67511
  const seen = ctx.seen.get(schema2);
67512
67512
  seen.ref = def.innerType;
67513
67513
  json4.readOnly = true;
67514
67514
  };
67515
67515
  promiseProcessor = (schema2, ctx, _json, params) => {
67516
67516
  const def = schema2._zod.def;
67517
- process2(def.innerType, ctx, params);
67517
+ process3(def.innerType, ctx, params);
67518
67518
  const seen = ctx.seen.get(schema2);
67519
67519
  seen.ref = def.innerType;
67520
67520
  };
67521
67521
  optionalProcessor = (schema2, ctx, _json, params) => {
67522
67522
  const def = schema2._zod.def;
67523
- process2(def.innerType, ctx, params);
67523
+ process3(def.innerType, ctx, params);
67524
67524
  const seen = ctx.seen.get(schema2);
67525
67525
  seen.ref = def.innerType;
67526
67526
  };
67527
67527
  lazyProcessor = (schema2, ctx, _json, params) => {
67528
67528
  const innerType = schema2._zod.innerType;
67529
- process2(innerType, ctx, params);
67529
+ process3(innerType, ctx, params);
67530
67530
  const seen = ctx.seen.get(schema2);
67531
67531
  seen.ref = innerType;
67532
67532
  };
@@ -67632,7 +67632,7 @@ var init_json_schema_generator = __esm({
67632
67632
  * This must be called before emit().
67633
67633
  */
67634
67634
  process(schema2, _params = { path: [], schemaPath: [] }) {
67635
- return process2(schema2, this.ctx, _params);
67635
+ return process3(schema2, this.ctx, _params);
67636
67636
  }
67637
67637
  /**
67638
67638
  * Emit the final JSON Schema after processing.
@@ -67925,7 +67925,7 @@ __export(core_exports2, {
67925
67925
  parse: () => parse,
67926
67926
  parseAsync: () => parseAsync,
67927
67927
  prettifyError: () => prettifyError,
67928
- process: () => process2,
67928
+ process: () => process3,
67929
67929
  regexes: () => regexes_exports,
67930
67930
  registry: () => registry2,
67931
67931
  safeDecode: () => safeDecode,
@@ -101738,6 +101738,299 @@ import { existsSync as existsSync8, readdirSync as readdirSync2 } from "node:fs"
101738
101738
  import { readFile as readFile5 } from "node:fs/promises";
101739
101739
  import { join as join26 } from "node:path";
101740
101740
 
101741
+ // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/commands.mjs
101742
+ function dashDashArg(agent2, agentCommand) {
101743
+ return (args2) => {
101744
+ if (args2.length > 1) {
101745
+ return [agent2, agentCommand, args2[0], "--", ...args2.slice(1)];
101746
+ } else {
101747
+ return [agent2, agentCommand, args2[0]];
101748
+ }
101749
+ };
101750
+ }
101751
+ function denoExecute() {
101752
+ return (args2) => {
101753
+ return ["deno", "run", `npm:${args2[0]}`, ...args2.slice(1)];
101754
+ };
101755
+ }
101756
+ var npm = {
101757
+ "agent": ["npm", 0],
101758
+ "run": dashDashArg("npm", "run"),
101759
+ "install": ["npm", "i", 0],
101760
+ "frozen": ["npm", "ci", 0],
101761
+ "global": ["npm", "i", "-g", 0],
101762
+ "add": ["npm", "i", 0],
101763
+ "upgrade": ["npm", "update", 0],
101764
+ "upgrade-interactive": null,
101765
+ "dedupe": ["npm", "dedupe", 0],
101766
+ "execute": ["npx", 0],
101767
+ "execute-local": ["npx", 0],
101768
+ "uninstall": ["npm", "uninstall", 0],
101769
+ "global_uninstall": ["npm", "uninstall", "-g", 0]
101770
+ };
101771
+ var yarn = {
101772
+ "agent": ["yarn", 0],
101773
+ "run": ["yarn", "run", 0],
101774
+ "install": ["yarn", "install", 0],
101775
+ "frozen": ["yarn", "install", "--frozen-lockfile", 0],
101776
+ "global": ["yarn", "global", "add", 0],
101777
+ "add": ["yarn", "add", 0],
101778
+ "upgrade": ["yarn", "upgrade", 0],
101779
+ "upgrade-interactive": ["yarn", "upgrade-interactive", 0],
101780
+ "dedupe": null,
101781
+ "execute": ["npx", 0],
101782
+ "execute-local": dashDashArg("yarn", "exec"),
101783
+ "uninstall": ["yarn", "remove", 0],
101784
+ "global_uninstall": ["yarn", "global", "remove", 0]
101785
+ };
101786
+ var yarnBerry = {
101787
+ ...yarn,
101788
+ "frozen": ["yarn", "install", "--immutable", 0],
101789
+ "upgrade": ["yarn", "up", 0],
101790
+ "upgrade-interactive": ["yarn", "up", "-i", 0],
101791
+ "dedupe": ["yarn", "dedupe", 0],
101792
+ "execute": ["yarn", "dlx", 0],
101793
+ "execute-local": ["yarn", "exec", 0],
101794
+ // Yarn 2+ removed 'global', see https://github.com/yarnpkg/berry/issues/821
101795
+ "global": ["npm", "i", "-g", 0],
101796
+ "global_uninstall": ["npm", "uninstall", "-g", 0]
101797
+ };
101798
+ var pnpm = {
101799
+ "agent": ["pnpm", 0],
101800
+ "run": ["pnpm", "run", 0],
101801
+ "install": ["pnpm", "i", 0],
101802
+ "frozen": ["pnpm", "i", "--frozen-lockfile", 0],
101803
+ "global": ["pnpm", "add", "-g", 0],
101804
+ "add": ["pnpm", "add", 0],
101805
+ "upgrade": ["pnpm", "update", 0],
101806
+ "upgrade-interactive": ["pnpm", "update", "-i", 0],
101807
+ "dedupe": ["pnpm", "dedupe", 0],
101808
+ "execute": ["pnpm", "dlx", 0],
101809
+ "execute-local": ["pnpm", "exec", 0],
101810
+ "uninstall": ["pnpm", "remove", 0],
101811
+ "global_uninstall": ["pnpm", "remove", "--global", 0]
101812
+ };
101813
+ var bun = {
101814
+ "agent": ["bun", 0],
101815
+ "run": ["bun", "run", 0],
101816
+ "install": ["bun", "install", 0],
101817
+ "frozen": ["bun", "install", "--frozen-lockfile", 0],
101818
+ "global": ["bun", "add", "-g", 0],
101819
+ "add": ["bun", "add", 0],
101820
+ "upgrade": ["bun", "update", 0],
101821
+ "upgrade-interactive": ["bun", "update", "-i", 0],
101822
+ "dedupe": null,
101823
+ "execute": ["bun", "x", 0],
101824
+ "execute-local": ["bun", "x", 0],
101825
+ "uninstall": ["bun", "remove", 0],
101826
+ "global_uninstall": ["bun", "remove", "-g", 0]
101827
+ };
101828
+ var deno = {
101829
+ "agent": ["deno", 0],
101830
+ "run": ["deno", "task", 0],
101831
+ "install": ["deno", "install", 0],
101832
+ "frozen": ["deno", "install", "--frozen", 0],
101833
+ "global": ["deno", "install", "-g", 0],
101834
+ "add": ["deno", "add", 0],
101835
+ "upgrade": ["deno", "outdated", "--update", 0],
101836
+ "upgrade-interactive": ["deno", "outdated", "--update", 0],
101837
+ "dedupe": null,
101838
+ "execute": denoExecute(),
101839
+ "execute-local": ["deno", "task", "--eval", 0],
101840
+ "uninstall": ["deno", "remove", 0],
101841
+ "global_uninstall": ["deno", "uninstall", "-g", 0]
101842
+ };
101843
+ var COMMANDS = {
101844
+ "npm": npm,
101845
+ "yarn": yarn,
101846
+ "yarn@berry": yarnBerry,
101847
+ "pnpm": pnpm,
101848
+ // pnpm v6.x or below
101849
+ "pnpm@6": {
101850
+ ...pnpm,
101851
+ run: dashDashArg("pnpm", "run")
101852
+ },
101853
+ "bun": bun,
101854
+ "deno": deno
101855
+ };
101856
+ function resolveCommand(agent2, command, args2) {
101857
+ const value2 = COMMANDS[agent2][command];
101858
+ return constructCommand(value2, args2);
101859
+ }
101860
+ function constructCommand(value2, args2) {
101861
+ if (value2 == null)
101862
+ return null;
101863
+ const list = typeof value2 === "function" ? value2(args2) : value2.flatMap((v) => {
101864
+ if (typeof v === "number")
101865
+ return args2;
101866
+ return [v];
101867
+ });
101868
+ return {
101869
+ command: list[0],
101870
+ args: list.slice(1)
101871
+ };
101872
+ }
101873
+
101874
+ // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/constants.mjs
101875
+ var AGENTS = [
101876
+ "npm",
101877
+ "yarn",
101878
+ "yarn@berry",
101879
+ "pnpm",
101880
+ "pnpm@6",
101881
+ "bun",
101882
+ "deno"
101883
+ ];
101884
+ var LOCKS = {
101885
+ "bun.lock": "bun",
101886
+ "bun.lockb": "bun",
101887
+ "deno.lock": "deno",
101888
+ "pnpm-lock.yaml": "pnpm",
101889
+ "pnpm-workspace.yaml": "pnpm",
101890
+ "yarn.lock": "yarn",
101891
+ "package-lock.json": "npm",
101892
+ "npm-shrinkwrap.json": "npm"
101893
+ };
101894
+ var INSTALL_METADATA = {
101895
+ "node_modules/.deno/": "deno",
101896
+ "node_modules/.pnpm/": "pnpm",
101897
+ "node_modules/.yarn-state.yml": "yarn",
101898
+ // yarn v2+ (node-modules)
101899
+ "node_modules/.yarn_integrity": "yarn",
101900
+ // yarn v1
101901
+ "node_modules/.package-lock.json": "npm",
101902
+ ".pnp.cjs": "yarn",
101903
+ // yarn v3+ (pnp)
101904
+ ".pnp.js": "yarn",
101905
+ // yarn v2 (pnp)
101906
+ "bun.lock": "bun",
101907
+ "bun.lockb": "bun"
101908
+ };
101909
+
101910
+ // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/detect.mjs
101911
+ import fs from "node:fs/promises";
101912
+ import path from "node:path";
101913
+ import process2 from "node:process";
101914
+ async function pathExists(path22, type2) {
101915
+ try {
101916
+ const stat = await fs.stat(path22);
101917
+ return type2 === "file" ? stat.isFile() : stat.isDirectory();
101918
+ } catch {
101919
+ return false;
101920
+ }
101921
+ }
101922
+ function* lookup(cwd = process2.cwd()) {
101923
+ let directory = path.resolve(cwd);
101924
+ const { root } = path.parse(directory);
101925
+ while (directory && directory !== root) {
101926
+ yield directory;
101927
+ directory = path.dirname(directory);
101928
+ }
101929
+ }
101930
+ async function parsePackageJson(filepath, options) {
101931
+ if (!filepath || !await pathExists(filepath, "file"))
101932
+ return null;
101933
+ return await handlePackageManager(filepath, options);
101934
+ }
101935
+ async function detect(options = {}) {
101936
+ const {
101937
+ cwd,
101938
+ strategies = ["lockfile", "packageManager-field", "devEngines-field"]
101939
+ } = options;
101940
+ let stopDir;
101941
+ if (typeof options.stopDir === "string") {
101942
+ const resolved = path.resolve(options.stopDir);
101943
+ stopDir = (dir) => dir === resolved;
101944
+ } else {
101945
+ stopDir = options.stopDir;
101946
+ }
101947
+ for (const directory of lookup(cwd)) {
101948
+ for (const strategy of strategies) {
101949
+ switch (strategy) {
101950
+ case "lockfile": {
101951
+ for (const lock of Object.keys(LOCKS)) {
101952
+ if (await pathExists(path.join(directory, lock), "file")) {
101953
+ const name = LOCKS[lock];
101954
+ const result = await parsePackageJson(path.join(directory, "package.json"), options);
101955
+ if (result)
101956
+ return result;
101957
+ else
101958
+ return { name, agent: name };
101959
+ }
101960
+ }
101961
+ break;
101962
+ }
101963
+ case "packageManager-field":
101964
+ case "devEngines-field": {
101965
+ const result = await parsePackageJson(path.join(directory, "package.json"), options);
101966
+ if (result)
101967
+ return result;
101968
+ break;
101969
+ }
101970
+ case "install-metadata": {
101971
+ for (const metadata of Object.keys(INSTALL_METADATA)) {
101972
+ const fileOrDir = metadata.endsWith("/") ? "dir" : "file";
101973
+ if (await pathExists(path.join(directory, metadata), fileOrDir)) {
101974
+ const name = INSTALL_METADATA[metadata];
101975
+ const agent2 = name === "yarn" ? isMetadataYarnClassic(metadata) ? "yarn" : "yarn@berry" : name;
101976
+ return { name, agent: agent2 };
101977
+ }
101978
+ }
101979
+ break;
101980
+ }
101981
+ }
101982
+ }
101983
+ if (stopDir?.(directory))
101984
+ break;
101985
+ }
101986
+ return null;
101987
+ }
101988
+ function getNameAndVer(pkg) {
101989
+ const handelVer = (version3) => version3?.match(/\d+(\.\d+){0,2}/)?.[0] ?? version3;
101990
+ if (typeof pkg.packageManager === "string") {
101991
+ const [name, ver] = pkg.packageManager.replace(/^\^/, "").split("@");
101992
+ return { name, ver: handelVer(ver) };
101993
+ }
101994
+ if (typeof pkg.devEngines?.packageManager?.name === "string") {
101995
+ return {
101996
+ name: pkg.devEngines.packageManager.name,
101997
+ ver: handelVer(pkg.devEngines.packageManager.version)
101998
+ };
101999
+ }
102000
+ return void 0;
102001
+ }
102002
+ async function handlePackageManager(filepath, options) {
102003
+ try {
102004
+ const content = await fs.readFile(filepath, "utf8");
102005
+ const pkg = options.packageJsonParser ? await options.packageJsonParser(content, filepath) : JSON.parse(content);
102006
+ let agent2;
102007
+ const nameAndVer = getNameAndVer(pkg);
102008
+ if (nameAndVer) {
102009
+ const name = nameAndVer.name;
102010
+ const ver = nameAndVer.ver;
102011
+ let version3 = ver;
102012
+ if (name === "yarn" && ver && Number.parseInt(ver) > 1) {
102013
+ agent2 = "yarn@berry";
102014
+ version3 = "berry";
102015
+ return { name, agent: agent2, version: version3 };
102016
+ } else if (name === "pnpm" && ver && Number.parseInt(ver) < 7) {
102017
+ agent2 = "pnpm@6";
102018
+ return { name, agent: agent2, version: version3 };
102019
+ } else if (AGENTS.includes(name)) {
102020
+ agent2 = name;
102021
+ return { name, agent: agent2, version: version3 };
102022
+ } else {
102023
+ return options.onUnknown?.(pkg.packageManager) ?? null;
102024
+ }
102025
+ }
102026
+ } catch {
102027
+ }
102028
+ return null;
102029
+ }
102030
+ function isMetadataYarnClassic(metadataPath) {
102031
+ return metadataPath.endsWith(".yarn_integrity");
102032
+ }
102033
+
101741
102034
  // agents/claude.ts
101742
102035
  import { execFileSync as execFileSync3 } from "node:child_process";
101743
102036
  import { chmodSync as chmodSync2, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
@@ -101773,6 +102066,12 @@ function resolveRung(params) {
101773
102066
  const clamped = Math.min(1, Math.max(0, params.position));
101774
102067
  return rungs[Math.floor(clamped * (rungs.length - 1))];
101775
102068
  }
102069
+ function rungPosition(params) {
102070
+ const rungs = offeredRungs(params.published);
102071
+ const index = rungs.indexOf(params.rung);
102072
+ if (index === -1) return void 0;
102073
+ return rungs.length > 1 ? index / (rungs.length - 1) : 0;
102074
+ }
101776
102075
 
101777
102076
  // models.ts
101778
102077
  function provider(config3) {
@@ -101826,7 +102125,11 @@ var providers = {
101826
102125
  envVars: ["OPENAI_API_KEY"],
101827
102126
  managedCredentials: ["CODEX_AUTH_JSON"],
101828
102127
  models: {
101829
- gpt: {
102128
+ // Sol/Terra/Luna are OpenAI's durable capability tiers, so they ARE the
102129
+ // brand-tier names the slug convention asks for — the pre-5.6 `gpt` /
102130
+ // `gpt-pro` / `gpt-mini` slugs are holdovers from the retired GPT / GPT Pro
102131
+ // / GPT Mini tiering and are carried below as deprecated aliases.
102132
+ "gpt-sol": {
101830
102133
  displayName: "GPT Sol",
101831
102134
  resolve: "openai/gpt-5.6-sol",
101832
102135
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
@@ -101837,24 +102140,23 @@ var providers = {
101837
102140
  // Sol served at reasoning.mode=pro — same $/token as Sol, just more tokens
101838
102141
  // burned; not a pricier premium tier. models.dev has no -pro id, so direct-key
101839
102142
  // (BYOK) resolves to plain Sol; only the Router/OpenRouter path gets sol-pro.
101840
- "gpt-pro": {
102143
+ "gpt-sol-pro": {
101841
102144
  displayName: "GPT Sol Pro",
101842
102145
  description: "Maximum reasoning effort",
101843
102146
  resolve: "openai/gpt-5.6-sol",
101844
102147
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
101845
102148
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
101846
- subagentModel: "gpt"
102149
+ subagentModel: "gpt-sol"
101847
102150
  },
101848
- // gpt-5.6's balanced mid-tier (Sol/Terra/Luna are durable capability tiers,
101849
- // not version bumps). selectable on its own and doubles as `gpt`'s cheaper
101850
- // lens-fanout subagent — replaces the old hidden gpt-5.4 subagent target.
102151
+ // gpt-5.6's balanced mid-tier. selectable on its own and doubles as Sol's
102152
+ // cheaper lens-fanout subagent replaces the old hidden gpt-5.4 target.
101851
102153
  "gpt-terra": {
101852
102154
  displayName: "GPT Terra",
101853
102155
  resolve: "openai/gpt-5.6-terra",
101854
102156
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
101855
102157
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
101856
102158
  },
101857
- "gpt-mini": {
102159
+ "gpt-luna": {
101858
102160
  displayName: "GPT Luna",
101859
102161
  resolve: "openai/gpt-5.6-luna",
101860
102162
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
@@ -101869,20 +102171,40 @@ var providers = {
101869
102171
  displayName: "GPT Codex",
101870
102172
  resolve: "openai/gpt-5.3-codex",
101871
102173
  openRouterResolve: "openrouter/openai/gpt-5.3-codex",
101872
- fallback: "openai/gpt"
102174
+ fallback: "openai/gpt-sol"
101873
102175
  },
101874
102176
  "gpt-codex-mini": {
101875
102177
  displayName: "GPT Codex Mini",
101876
102178
  resolve: "openai/gpt-5.1-codex-mini",
101877
102179
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
101878
- fallback: "openai/gpt-mini"
102180
+ fallback: "openai/gpt-luna"
101879
102181
  },
101880
- // dropped hidden subagent tier folds stored pins forward to gpt (Sol).
102182
+ // pre-5.6 tier slugs. the tiers themselves were renamed Sol/Sol Pro/Luna,
102183
+ // so these fold forward rather than describing anything that still runs.
102184
+ gpt: {
102185
+ displayName: "GPT",
102186
+ resolve: "openai/gpt-5.6-sol",
102187
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
102188
+ fallback: "openai/gpt-sol"
102189
+ },
102190
+ "gpt-pro": {
102191
+ displayName: "GPT Pro",
102192
+ resolve: "openai/gpt-5.6-sol",
102193
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
102194
+ fallback: "openai/gpt-sol-pro"
102195
+ },
102196
+ "gpt-mini": {
102197
+ displayName: "GPT Mini",
102198
+ resolve: "openai/gpt-5.6-luna",
102199
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna",
102200
+ fallback: "openai/gpt-luna"
102201
+ },
102202
+ // dropped hidden subagent tier — folds stored pins forward to Sol.
101881
102203
  "gpt-5.4": {
101882
102204
  displayName: "GPT 5.4",
101883
102205
  resolve: "openai/gpt-5.4",
101884
102206
  openRouterResolve: "openrouter/openai/gpt-5.4",
101885
- fallback: "openai/gpt"
102207
+ fallback: "openai/gpt-sol"
101886
102208
  },
101887
102209
  o3: {
101888
102210
  displayName: "O3",
@@ -101958,12 +102280,20 @@ var providers = {
101958
102280
  openRouterResolve: "openrouter/deepseek/deepseek-v4-pro",
101959
102281
  preferred: true
101960
102282
  },
102283
+ // DeepSeek upgraded the `deepseek-v4-flash` API model in place to the
102284
+ // 0731 release, but OpenRouter forked it into a separate `-0731` id and
102285
+ // left the April preview live at a HIGHER price — so the direct
102286
+ // `resolve` needs no version and the OpenRouter route must be pinned.
102287
+ // 0731 publishes a DIFFERENT OpenRouter ladder to both the April preview
102288
+ // and Pro (`high, xhigh`) — it gained a `low` rung and renamed the top to
102289
+ // `max`. that makes `low`, not `high`, position 0 on this route, which is
102290
+ // why the OSS effort floor in `main.ts` pins the `high` rung by name.
101961
102291
  "deepseek-flash": {
101962
102292
  displayName: "DeepSeek Flash",
101963
102293
  resolve: "deepseek/deepseek-v4-flash",
101964
102294
  effort: ["high", "max"],
101965
- openRouterEffort: ["high", "xhigh"],
101966
- openRouterResolve: "openrouter/deepseek/deepseek-v4-flash"
102295
+ openRouterEffort: ["low", "high", "max"],
102296
+ openRouterResolve: "openrouter/deepseek/deepseek-v4-flash-0731"
101967
102297
  },
101968
102298
  // legacy aliases — deepseek retires these on 2026-07-24; transparently
101969
102299
  // upgrade existing users to the v4 family via the fallback chain.
@@ -102032,30 +102362,30 @@ var providers = {
102032
102362
  resolve: "opencode/claude-haiku-4-5",
102033
102363
  openRouterResolve: "openrouter/anthropic/claude-haiku-4.5"
102034
102364
  },
102035
- gpt: {
102365
+ "gpt-sol": {
102036
102366
  displayName: "GPT Sol",
102037
102367
  resolve: "opencode/gpt-5.6-sol",
102038
102368
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
102039
102369
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
102040
102370
  subagentModel: "gpt-terra"
102041
102371
  },
102042
- // see openai/gpt-pro — Zen has no -pro id, so direct resolves to plain Sol.
102043
- "gpt-pro": {
102372
+ // see openai/gpt-sol-pro — Zen has no -pro id, so direct resolves to plain Sol.
102373
+ "gpt-sol-pro": {
102044
102374
  displayName: "GPT Sol Pro",
102045
102375
  description: "Maximum reasoning effort",
102046
102376
  resolve: "opencode/gpt-5.6-sol",
102047
102377
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
102048
102378
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
102049
- subagentModel: "gpt"
102379
+ subagentModel: "gpt-sol"
102050
102380
  },
102051
- // gpt-5.6 balanced mid-tier — selectable + `gpt`'s subagent. see openai above.
102381
+ // gpt-5.6 balanced mid-tier — selectable + Sol's subagent. see openai above.
102052
102382
  "gpt-terra": {
102053
102383
  displayName: "GPT Terra",
102054
102384
  resolve: "opencode/gpt-5.6-terra",
102055
102385
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
102056
102386
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
102057
102387
  },
102058
- "gpt-mini": {
102388
+ "gpt-luna": {
102059
102389
  displayName: "GPT Luna",
102060
102390
  resolve: "opencode/gpt-5.6-luna",
102061
102391
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
@@ -102066,20 +102396,39 @@ var providers = {
102066
102396
  displayName: "GPT Codex",
102067
102397
  resolve: "opencode/gpt-5.3-codex",
102068
102398
  openRouterResolve: "openrouter/openai/gpt-5.3-codex",
102069
- fallback: "opencode/gpt"
102399
+ fallback: "opencode/gpt-sol"
102070
102400
  },
102071
102401
  "gpt-codex-mini": {
102072
102402
  displayName: "GPT Codex Mini",
102073
102403
  resolve: "opencode/gpt-5.1-codex-mini",
102074
102404
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
102075
- fallback: "opencode/gpt-mini"
102405
+ fallback: "opencode/gpt-luna"
102406
+ },
102407
+ // pre-5.6 tier slugs — see openai provider above.
102408
+ gpt: {
102409
+ displayName: "GPT",
102410
+ resolve: "opencode/gpt-5.6-sol",
102411
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
102412
+ fallback: "opencode/gpt-sol"
102076
102413
  },
102077
- // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
102414
+ "gpt-pro": {
102415
+ displayName: "GPT Pro",
102416
+ resolve: "opencode/gpt-5.6-sol",
102417
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
102418
+ fallback: "opencode/gpt-sol-pro"
102419
+ },
102420
+ "gpt-mini": {
102421
+ displayName: "GPT Mini",
102422
+ resolve: "opencode/gpt-5.6-luna",
102423
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna",
102424
+ fallback: "opencode/gpt-luna"
102425
+ },
102426
+ // dropped hidden subagent tier — folds stored pins forward to Sol.
102078
102427
  "gpt-5.4": {
102079
102428
  displayName: "GPT 5.4",
102080
102429
  resolve: "opencode/gpt-5.4",
102081
102430
  openRouterResolve: "openrouter/openai/gpt-5.4",
102082
- fallback: "opencode/gpt"
102431
+ fallback: "opencode/gpt-sol"
102083
102432
  },
102084
102433
  "gemini-pro": {
102085
102434
  displayName: "Gemini Pro",
@@ -102235,30 +102584,30 @@ var providers = {
102235
102584
  // alias): after the Sol/Terra/Luna rename, ~gpt-mini-latest no longer maps
102236
102585
  // to Luna, so rolling aliases would silently diverge `gpt`/`gpt-mini` from
102237
102586
  // the chosen tiers across funding paths.
102238
- gpt: {
102587
+ "gpt-sol": {
102239
102588
  displayName: "GPT Sol",
102240
102589
  resolve: "openrouter/openai/gpt-5.6-sol",
102241
102590
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
102242
102591
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
102243
102592
  subagentModel: "gpt-terra"
102244
102593
  },
102245
- // see openai/gpt-pro. openrouter serves sol-pro directly on both routes.
102246
- "gpt-pro": {
102594
+ // see openai/gpt-sol-pro. openrouter serves sol-pro directly on both routes.
102595
+ "gpt-sol-pro": {
102247
102596
  displayName: "GPT Sol Pro",
102248
102597
  description: "Maximum reasoning effort",
102249
102598
  resolve: "openrouter/openai/gpt-5.6-sol-pro",
102250
102599
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
102251
102600
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
102252
- subagentModel: "gpt"
102601
+ subagentModel: "gpt-sol"
102253
102602
  },
102254
- // gpt-5.6 balanced mid-tier — selectable + `gpt`'s subagent. see openai above.
102603
+ // gpt-5.6 balanced mid-tier — selectable + Sol's subagent. see openai above.
102255
102604
  "gpt-terra": {
102256
102605
  displayName: "GPT Terra",
102257
102606
  resolve: "openrouter/openai/gpt-5.6-terra",
102258
102607
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
102259
102608
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
102260
102609
  },
102261
- "gpt-mini": {
102610
+ "gpt-luna": {
102262
102611
  displayName: "GPT Luna",
102263
102612
  resolve: "openrouter/openai/gpt-5.6-luna",
102264
102613
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
@@ -102269,20 +102618,39 @@ var providers = {
102269
102618
  displayName: "GPT Codex",
102270
102619
  resolve: "openrouter/openai/gpt-5.3-codex",
102271
102620
  openRouterResolve: "openrouter/openai/gpt-5.3-codex",
102272
- fallback: "openrouter/gpt"
102621
+ fallback: "openrouter/gpt-sol"
102273
102622
  },
102274
102623
  "gpt-codex-mini": {
102275
102624
  displayName: "GPT Codex Mini",
102276
102625
  resolve: "openrouter/openai/gpt-5.1-codex-mini",
102277
102626
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
102278
- fallback: "openrouter/gpt-mini"
102627
+ fallback: "openrouter/gpt-luna"
102628
+ },
102629
+ // pre-5.6 tier slugs — see openai provider above.
102630
+ gpt: {
102631
+ displayName: "GPT",
102632
+ resolve: "openrouter/openai/gpt-5.6-sol",
102633
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
102634
+ fallback: "openrouter/gpt-sol"
102635
+ },
102636
+ "gpt-pro": {
102637
+ displayName: "GPT Pro",
102638
+ resolve: "openrouter/openai/gpt-5.6-sol-pro",
102639
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
102640
+ fallback: "openrouter/gpt-sol-pro"
102279
102641
  },
102280
- // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
102642
+ "gpt-mini": {
102643
+ displayName: "GPT Mini",
102644
+ resolve: "openrouter/openai/gpt-5.6-luna",
102645
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna",
102646
+ fallback: "openrouter/gpt-luna"
102647
+ },
102648
+ // dropped hidden subagent tier — folds stored pins forward to Sol.
102281
102649
  "gpt-5.4": {
102282
102650
  displayName: "GPT 5.4",
102283
102651
  resolve: "openrouter/openai/gpt-5.4",
102284
102652
  openRouterResolve: "openrouter/openai/gpt-5.4",
102285
- fallback: "openrouter/gpt"
102653
+ fallback: "openrouter/gpt-sol"
102286
102654
  },
102287
102655
  "o4-mini": {
102288
102656
  displayName: "O4 Mini",
@@ -102317,9 +102685,9 @@ var providers = {
102317
102685
  },
102318
102686
  "deepseek-flash": {
102319
102687
  displayName: "DeepSeek Flash",
102320
- resolve: "openrouter/deepseek/deepseek-v4-flash",
102321
- effort: ["high", "xhigh"],
102322
- openRouterResolve: "openrouter/deepseek/deepseek-v4-flash"
102688
+ resolve: "openrouter/deepseek/deepseek-v4-flash-0731",
102689
+ effort: ["low", "high", "max"],
102690
+ openRouterResolve: "openrouter/deepseek/deepseek-v4-flash-0731"
102323
102691
  },
102324
102692
  // legacy alias — deepseek retires this on 2026-07-24; transparently
102325
102693
  // upgrade existing users to the v4 family via the fallback chain.
@@ -102400,7 +102768,7 @@ var modelAliases = Object.entries(providers).flatMap(
102400
102768
  var AUTO_EFFICIENT = "auto/efficient";
102401
102769
  var AUTO_INTELLIGENT = "auto/intelligent";
102402
102770
  var AUTO_TIER_TARGET = {
102403
- [AUTO_EFFICIENT]: "deepseek/deepseek-pro",
102771
+ [AUTO_EFFICIENT]: "deepseek/deepseek-flash",
102404
102772
  [AUTO_INTELLIGENT]: "anthropic/claude-opus"
102405
102773
  };
102406
102774
  function isAutoTier(slug2) {
@@ -102449,6 +102817,26 @@ if (!defaultProxyAlias?.openRouterResolve) {
102449
102817
  }
102450
102818
  var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
102451
102819
  var defaultProxyDisplayName = defaultProxyAlias.displayName;
102820
+ var OSS_MODEL_ALLOWLIST = [
102821
+ "deepseek/deepseek-flash",
102822
+ "deepseek/deepseek-pro",
102823
+ "openai/gpt-luna",
102824
+ "openrouter/minimax-m2.5",
102825
+ "moonshotai/kimi-k2"
102826
+ ];
102827
+ var OSS_RECOMMENDED_MODEL = AUTO_TIER_TARGET[AUTO_EFFICIENT];
102828
+ var ossAllowedTargets = new Set(
102829
+ OSS_MODEL_ALLOWLIST.map((slug2) => {
102830
+ const target = resolveOpenRouterModel(slug2);
102831
+ if (!target) throw new Error(`OSS_MODEL_ALLOWLIST: ${slug2} has no openRouterResolve`);
102832
+ return target;
102833
+ })
102834
+ );
102835
+ function isOssAllowedModel(slug2) {
102836
+ if (!slug2) return false;
102837
+ const target = resolveOpenRouterModel(slug2);
102838
+ return target !== void 0 && ossAllowedTargets.has(target);
102839
+ }
102452
102840
  var BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
102453
102841
  var VERTEX_MODEL_ID_ENV = "VERTEX_MODEL_ID";
102454
102842
  var OPENAI_COMPATIBLE_PROVIDER = "openai-compatible";
@@ -103054,7 +103442,21 @@ var PROVIDER_ERROR_PATTERNS = [
103054
103442
  { regex: /\bFreeUsageLimitError\b/, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
103055
103443
  { regex: /Insufficient balance/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
103056
103444
  { regex: /credit balance is too low/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
103057
- { regex: /spending cap/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
103445
+ // "spending cap" (Gemini) and "spending limit" (xAI, #1076) are the same
103446
+ // condition in two house styles — a configured ceiling was reached.
103447
+ { regex: /spending (?:cap|limit)/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
103448
+ // xAI exhausts credits and the monthly ceiling in one 403 whose status code
103449
+ // sits nowhere near a `status:` key, so no status pattern below fires (#1076).
103450
+ { regex: /used all available credits/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
103451
+ // the OpenRouter shapes `isRouterKeylimitExhaustedError` matches. on a Router
103452
+ // run those mean the PULLFROG wallet is empty and `renderRunError` returns a
103453
+ // `BillingError` before ever reaching this list; on a BYOK run the very same
103454
+ // wire text means the user's OWN OpenRouter wallet is empty, and this entry is
103455
+ // what gives them the right dashboard instead of ours. see #1135.
103456
+ {
103457
+ regex: /requires more credits|Key limit exceeded \(total limit\)/i,
103458
+ label: PROVIDER_BILLING_EXHAUSTED_LABEL
103459
+ },
103058
103460
  // auth patterns must come BEFORE rate-limit patterns. OpenRouter 401 error
103059
103461
  // payloads carry `x-ratelimit-*` response headers in the dump, and the
103060
103462
  // free-form rate-limit regex below would otherwise win on word-boundary
@@ -103150,6 +103552,12 @@ function resolveRunAlias(ctx) {
103150
103552
  if (!model) return void 0;
103151
103553
  return modelAliases.find((a) => !a.fallback && a.resolve === model) ?? matchHostedAnthropicAlias(model);
103152
103554
  }
103555
+ function ossEffortFloor(ctx) {
103556
+ const alias = resolveRunAlias(ctx);
103557
+ const published = alias?.openRouterEffort ?? alias?.effort;
103558
+ if (!published) return 0;
103559
+ return rungPosition({ rung: "high", published }) ?? 0;
103560
+ }
103153
103561
  function resolveRunEffort(ctx) {
103154
103562
  const configured = ctx.payload.effort !== void 0;
103155
103563
  const position = ctx.payload.effort ?? DEFAULT_EFFORT_POSITION;
@@ -103180,7 +103588,7 @@ var import_semver = __toESM(require_semver2(), 1);
103180
103588
  // package.json
103181
103589
  var package_default = {
103182
103590
  name: "pullfrog",
103183
- version: "0.1.51",
103591
+ version: "0.1.52",
103184
103592
  type: "module",
103185
103593
  bin: {
103186
103594
  pullfrog: "dist/cli.mjs",
@@ -110795,6 +111203,41 @@ function bootstrapPullfrogDataDir() {
110795
111203
  }
110796
111204
  }
110797
111205
 
111206
+ // utils/worktree.ts
111207
+ async function dirtyTrackedPaths() {
111208
+ const result = await spawn3({
111209
+ cmd: "git",
111210
+ args: ["diff", "--name-only", "HEAD"],
111211
+ env: process.env,
111212
+ activityTimeout: 0
111213
+ });
111214
+ if (result.exitCode !== 0) {
111215
+ throw new Error(
111216
+ `git diff --name-only HEAD failed (exit ${result.exitCode}): ${result.stderr.trim() || "(no stderr)"}`
111217
+ );
111218
+ }
111219
+ return new Set(result.stdout.split("\n").filter(Boolean));
111220
+ }
111221
+ async function restoreDirtiedSince(params) {
111222
+ const dirtied = [...await dirtyTrackedPaths()].filter((path4) => !params.before.has(path4));
111223
+ if (dirtied.length === 0) return;
111224
+ const result = await spawn3({
111225
+ cmd: "git",
111226
+ args: ["restore", "--staged", "--worktree", "--", ...dirtied],
111227
+ env: process.env,
111228
+ activityTimeout: 0
111229
+ });
111230
+ if (result.exitCode !== 0) {
111231
+ log.warning(
111232
+ `\xBB failed to restore ${dirtied.length} tracked file(s) modified by ${params.actor}: ${result.stderr.trim() || "(no stderr)"}`
111233
+ );
111234
+ return;
111235
+ }
111236
+ log.info(
111237
+ `\xBB restored ${dirtied.length} tracked file(s) modified by ${params.actor}: ${dirtied.join(", ")}`
111238
+ );
111239
+ }
111240
+
110798
111241
  // agents/opencodePlugin.ts
110799
111242
  var PULLFROG_BUS_EVENT_TYPE = "pullfrog_bus_event";
110800
111243
  var PULLFROG_OPENCODE_GATE_PLUGIN_FILENAME = "pullfrog-subagent-gate.ts";
@@ -111680,6 +112123,7 @@ var opencode = agent({
111680
112123
  }
111681
112124
  log.debug(`\xBB starting Pullfrog (OpenCode, in-process SDK): ${cliPath}`);
111682
112125
  log.debug(`\xBB working directory: ${repoDir}`);
112126
+ const preBootDirty = await dirtyTrackedPaths();
111683
112127
  const server = await bootOpencodeServer({ cliPath, env: env2, cwd: repoDir });
111684
112128
  const dispatcher = new import_undici.Agent({ headersTimeout: 0, bodyTimeout: 0, connectTimeout: 0 });
111685
112129
  const fetchWithoutTimeout = (input, init) => {
@@ -111700,6 +112144,7 @@ var opencode = agent({
111700
112144
  fetch: fetchWithoutTimeout
111701
112145
  });
111702
112146
  const sessionResp = await client2.session.create({ title: "Pullfrog" });
112147
+ await restoreDirtiedSince({ before: preBootDirty, actor: "agent startup" });
111703
112148
  if (sessionResp.error || !sessionResp.data) {
111704
112149
  const msg = sessionResp.error ? formatPromptError(sessionResp.error) : "session.create returned no data";
111705
112150
  return {
@@ -118428,7 +118873,7 @@ var Server = class extends Protocol {
118428
118873
  };
118429
118874
 
118430
118875
  // node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
118431
- import process3 from "node:process";
118876
+ import process4 from "node:process";
118432
118877
 
118433
118878
  // node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
118434
118879
  var ReadBuffer = class {
@@ -118460,7 +118905,7 @@ function serializeMessage(message) {
118460
118905
 
118461
118906
  // node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
118462
118907
  var StdioServerTransport = class {
118463
- constructor(_stdin = process3.stdin, _stdout = process3.stdout) {
118908
+ constructor(_stdin = process4.stdin, _stdout = process4.stdout) {
118464
118909
  this._stdin = _stdin;
118465
118910
  this._stdout = _stdout;
118466
118911
  this._readBuffer = new ReadBuffer();
@@ -121895,7 +122340,7 @@ var Hono2 = class extends Hono {
121895
122340
  import { createRequire } from "node:module";
121896
122341
  import { randomUUID as randomUUID2 } from "node:crypto";
121897
122342
  import { URL as URL$1 } from "node:url";
121898
- import fs from "fs";
122343
+ import fs2 from "fs";
121899
122344
  import http from "http";
121900
122345
  import https from "https";
121901
122346
  var __create2 = Object.create;
@@ -136463,17 +136908,17 @@ var startHTTPServer = async ({ apiKey, authenticate, cors, createServer: createS
136463
136908
  if (sslCa || sslCert || sslKey) {
136464
136909
  const options = {};
136465
136910
  if (sslCa) try {
136466
- options.ca = fs.readFileSync(sslCa);
136911
+ options.ca = fs2.readFileSync(sslCa);
136467
136912
  } catch (error$1) {
136468
136913
  throw new Error(`Failed to read CA file '${sslCa}': ${error$1.message}`);
136469
136914
  }
136470
136915
  if (sslCert) try {
136471
- options.cert = fs.readFileSync(sslCert);
136916
+ options.cert = fs2.readFileSync(sslCert);
136472
136917
  } catch (error$1) {
136473
136918
  throw new Error(`Failed to read certificate file '${sslCert}': ${error$1.message}`);
136474
136919
  }
136475
136920
  if (sslKey) try {
136476
- options.key = fs.readFileSync(sslKey);
136921
+ options.key = fs2.readFileSync(sslKey);
136477
136922
  } catch (error$1) {
136478
136923
  throw new Error(`Failed to read key file '${sslKey}': ${error$1.message}`);
136479
136924
  }
@@ -144900,6 +145345,24 @@ function isSafeEnvVar(key) {
144900
145345
  if (SAFE_ENV_NAMES.has(key)) return true;
144901
145346
  return SAFE_ENV_PREFIXES.some((p2) => key.startsWith(p2));
144902
145347
  }
145348
+ var WORKFLOW_COMMAND_ENV_NAMES = [
145349
+ "GITHUB_ENV",
145350
+ "GITHUB_PATH",
145351
+ "GITHUB_OUTPUT",
145352
+ "GITHUB_STATE",
145353
+ "GITHUB_STEP_SUMMARY",
145354
+ // dropping the five paths above but keeping RUNNER_TEMP would be theatre:
145355
+ // the file-command files live in `$RUNNER_TEMP/_runner_file_commands/`, so the
145356
+ // directory is one `ls` away. nothing in the install path reads it (only our
145357
+ // own leak-surface wipe in `setup.ts`, which runs in the parent), and package
145358
+ // managers use TMPDIR.
145359
+ "RUNNER_TEMP"
145360
+ ];
145361
+ function filterEnvForUntrustedCode() {
145362
+ const env2 = filterEnv();
145363
+ for (const name of WORKFLOW_COMMAND_ENV_NAMES) delete env2[name];
145364
+ return env2;
145365
+ }
144903
145366
  function filterEnv() {
144904
145367
  const filtered = {};
144905
145368
  for (const [key, value2] of Object.entries(process.env)) {
@@ -153093,6 +153556,8 @@ import { join as join9 } from "node:path";
153093
153556
 
153094
153557
  // utils/shell.ts
153095
153558
  import { spawnSync as spawnSync5 } from "node:child_process";
153559
+ var MAX_BUFFER_BYTES = 32 * 1024 * 1024;
153560
+ var MAX_ERROR_DETAIL_CHARS = 2e4;
153096
153561
  function $2(cmd, args2, options) {
153097
153562
  const encoding = options?.encoding ?? "utf-8";
153098
153563
  const env2 = resolveEnv(options?.env);
@@ -153100,7 +153565,8 @@ function $2(cmd, args2, options) {
153100
153565
  stdio: ["ignore", "pipe", "pipe"],
153101
153566
  encoding,
153102
153567
  cwd: options?.cwd,
153103
- env: env2
153568
+ env: env2,
153569
+ maxBuffer: MAX_BUFFER_BYTES
153104
153570
  });
153105
153571
  const stdout = result.stdout ?? "";
153106
153572
  const stderr = result.stderr ?? "";
@@ -153118,6 +153584,11 @@ function $2(cmd, args2, options) {
153118
153584
  }
153119
153585
  }
153120
153586
  if (result.status !== 0) {
153587
+ if (result.error && "code" in result.error && result.error.code === "ENOBUFS") {
153588
+ throw new Error(
153589
+ `Command produced more than ${MAX_BUFFER_BYTES / 1024 / 1024}MB of output and was terminated: ${cmd} ${args2.join(" ")}`
153590
+ );
153591
+ }
153121
153592
  const errorResult = {
153122
153593
  status: result.status ?? -1,
153123
153594
  stdout,
@@ -153127,7 +153598,7 @@ function $2(cmd, args2, options) {
153127
153598
  options.onError(errorResult);
153128
153599
  return stdout.trim();
153129
153600
  }
153130
- const detail = [stderr, stdout].map((s) => s.trim()).filter(Boolean).join("\n");
153601
+ const detail = [stderr, stdout].map((s) => s.trim()).filter(Boolean).join("\n").slice(0, MAX_ERROR_DETAIL_CHARS);
153131
153602
  throw new Error(
153132
153603
  `Command failed with exit code ${errorResult.status}: ${detail || "Unknown error"}`
153133
153604
  );
@@ -153136,6 +153607,10 @@ function $2(cmd, args2, options) {
153136
153607
  }
153137
153608
 
153138
153609
  // utils/gitAuth.ts
153610
+ var TRANSIENT_AUTH_PATTERNS = [
153611
+ /Invalid username or token/,
153612
+ /Authentication failed for 'https:\/\/github\.com\//
153613
+ ];
153139
153614
  var gitBinary;
153140
153615
  function hashFile(path4) {
153141
153616
  return createHash("sha256").update(readFileSync3(path4)).digest("hex");
@@ -153252,6 +153727,17 @@ async function $gitFetchWithDeepen(args2, options, label) {
153252
153727
  return await $git("fetch", args2, options);
153253
153728
  } catch (err) {
153254
153729
  const msg = err instanceof Error ? err.message : String(err);
153730
+ if (TRANSIENT_AUTH_PATTERNS.some((p2) => p2.test(msg)) && options.refreshGitToken) {
153731
+ log.info(
153732
+ `\xBB ${label ?? "git fetch"} hit an auth error, re-minting the git token and retrying`
153733
+ );
153734
+ const fresh = await options.refreshGitToken(options.token);
153735
+ return await $gitFetchWithDeepen(
153736
+ args2,
153737
+ { ...options, token: fresh, refreshGitToken: void 0 },
153738
+ label
153739
+ );
153740
+ }
153255
153741
  const isShallowUnreachable = SHALLOW_UNREACHABLE_PATTERNS.some((p2) => p2.test(msg));
153256
153742
  if (!isShallowUnreachable) throw err;
153257
153743
  const isShallow = $2("git", ["rev-parse", "--is-shallow-repository"], { log: false }).trim() === "true";
@@ -153371,10 +153857,12 @@ function computeIncrementalDiff(params) {
153371
153857
  ],
153372
153858
  { log: false }
153373
153859
  );
153374
- return postProcessRangeDiff(raw2);
153860
+ const processed = postProcessRangeDiff(raw2);
153861
+ return processed === null ? { status: "empty" } : { status: "ok", diff: processed };
153375
153862
  } catch (e) {
153376
- log.debug(`\xBB range-diff failed: ${e instanceof Error ? e.message : String(e)}`);
153377
- return null;
153863
+ const reason = e instanceof Error ? e.message : String(e);
153864
+ log.warning(`\xBB incremental diff unavailable: range-diff failed: ${reason}`);
153865
+ return { status: "unavailable", reason };
153378
153866
  }
153379
153867
  }
153380
153868
  function isDiffPrefix(ch) {
@@ -154806,7 +155294,7 @@ throttling.VERSION = VERSION;
154806
155294
  throttling.triggersNotification = triggersNotification;
154807
155295
 
154808
155296
  // node_modules/.pnpm/universal-user-agent@7.0.3/node_modules/universal-user-agent/index.js
154809
- function getUserAgent() {
155297
+ function getUserAgent2() {
154810
155298
  if (typeof navigator === "object" && "userAgent" in navigator) {
154811
155299
  return navigator.userAgent;
154812
155300
  }
@@ -154924,7 +155412,7 @@ var before_after_hook_default = { Singular, Collection };
154924
155412
 
154925
155413
  // node_modules/.pnpm/@octokit+endpoint@11.0.1/node_modules/@octokit/endpoint/dist-bundle/index.js
154926
155414
  var VERSION2 = "0.0.0-development";
154927
- var userAgent = `octokit-endpoint.js/${VERSION2} ${getUserAgent()}`;
155415
+ var userAgent = `octokit-endpoint.js/${VERSION2} ${getUserAgent2()}`;
154928
155416
  var DEFAULTS = {
154929
155417
  method: "GET",
154930
155418
  baseUrl: "https://api.github.com",
@@ -155281,7 +155769,7 @@ var RequestError = class extends Error {
155281
155769
  var VERSION3 = "10.0.5";
155282
155770
  var defaults_default = {
155283
155771
  headers: {
155284
- "user-agent": `octokit-request.js/${VERSION3} ${getUserAgent()}`
155772
+ "user-agent": `octokit-request.js/${VERSION3} ${getUserAgent2()}`
155285
155773
  }
155286
155774
  };
155287
155775
  function isPlainObject4(value2) {
@@ -155546,7 +156034,7 @@ function withDefaults3(request2, newDefaults) {
155546
156034
  }
155547
156035
  var graphql2 = withDefaults3(request, {
155548
156036
  headers: {
155549
- "user-agent": `octokit-graphql.js/${VERSION4} ${getUserAgent()}`
156037
+ "user-agent": `octokit-graphql.js/${VERSION4} ${getUserAgent2()}`
155550
156038
  },
155551
156039
  method: "POST",
155552
156040
  url: "/graphql"
@@ -155626,7 +156114,7 @@ function createLogger(logger = {}) {
155626
156114
  }
155627
156115
  return logger;
155628
156116
  }
155629
- var userAgentTrail = `octokit-core.js/${VERSION5} ${getUserAgent()}`;
156117
+ var userAgentTrail = `octokit-core.js/${VERSION5} ${getUserAgent2()}`;
155630
156118
  var Octokit = class {
155631
156119
  static VERSION = VERSION5;
155632
156120
  static defaults(defaults) {
@@ -158594,8 +159082,13 @@ function createOctokit(token, refreshAuth) {
158594
159082
  var readOctokitByToken = /* @__PURE__ */ new Map();
158595
159083
  function resolveRepoCtx(ctx, repo) {
158596
159084
  const owner = ctx.repo.owner;
158597
- const name = repo ?? ctx.repo.name;
158598
- const state = requireRepoState(ctx.toolState, owner, name);
159085
+ const name = repo?.trim() || ctx.repo.name;
159086
+ const state = ctx.toolState.repos.get(repoKey(owner, name));
159087
+ if (!state) {
159088
+ throw new Error(
159089
+ ctx.xrepo ? `repo ${repoKey(owner, name)} is not a registered checkout \u2014 use checkout_repo first` : `repo ${repoKey(owner, name)} is not a registered checkout \u2014 this run is single-repo, so omit \`repo\` to target ${owner}/${ctx.repo.name}`
159090
+ );
159091
+ }
158599
159092
  if (state.access !== "read") {
158600
159093
  return {
158601
159094
  owner,
@@ -159312,10 +159805,6 @@ var TRANSIENT_PATTERNS = [
159312
159805
  /HTTP 429/,
159313
159806
  /returned error: 429/i
159314
159807
  ];
159315
- var TRANSIENT_AUTH_PATTERNS = [
159316
- /Invalid username or token/,
159317
- /Authentication failed for 'https:\/\/github\.com\//
159318
- ];
159319
159808
  function classifyPushError(msg) {
159320
159809
  if (CONCURRENT_PUSH_PATTERNS.some((p2) => msg.includes(p2))) return "concurrent-push";
159321
159810
  if (TRANSIENT_AUTH_PATTERNS.some((p2) => p2.test(msg))) return "transient-auth";
@@ -159814,7 +160303,11 @@ function GitFetchTool(ctx) {
159814
160303
  if (params.depth !== void 0) {
159815
160304
  fetchArgs.push(`--depth=${params.depth}`);
159816
160305
  }
159817
- await $gitFetchWithDeepen(fetchArgs, { token: rc.gitToken, cwd: rc.dir }, "git_fetch");
160306
+ await $gitFetchWithDeepen(
160307
+ fetchArgs,
160308
+ { token: rc.gitToken, cwd: rc.dir, refreshGitToken: rc.refreshGitToken },
160309
+ "git_fetch"
160310
+ );
159818
160311
  return { success: true, ref: params.ref };
159819
160312
  })
159820
160313
  });
@@ -159903,7 +160396,7 @@ function formatModelLabel(params) {
159903
160396
  const ossBase = `\`${displayName}\` (free via [Pullfrog for OSS](https://pullfrog.com/for-oss))`;
159904
160397
  if (params.clamped?.reason !== "oss") return ossBase;
159905
160398
  const configured = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
159906
- return `${ossBase} (${configured} not used \u2014 the program covers this model; add its [provider key](https://docs.pullfrog.com/models) to run your pick)`;
160399
+ return `${ossBase} (${configured} not used \u2014 pick one of the [funded models](https://docs.pullfrog.com/models#pullfrog-for-oss) or add a [provider key](https://docs.pullfrog.com/keys) to run your own)`;
159907
160400
  }
159908
160401
  const base = alias?.isFree ? `\`${displayName}\` (free)` : `\`${displayName}\``;
159909
160402
  if (params.fallbackFrom) {
@@ -161451,7 +161944,7 @@ async function ensureBeforeShaReachable(params) {
161451
161944
  }), true);
161452
161945
  await $gitFetchWithDeepen(
161453
161946
  ["--no-tags", ...params.isShallow ? ["--depth=1"] : [], "origin", tempBranch],
161454
- { token: params.gitToken },
161947
+ { token: params.gitToken, refreshGitToken: params.refreshGitToken },
161455
161948
  `before_sha temp branch ${tempBranch}`
161456
161949
  );
161457
161950
  log.debug(`\xBB fetched before_sha via temp branch ${tempBranch}`);
@@ -161467,6 +161960,14 @@ async function ensureBeforeShaReachable(params) {
161467
161960
  return false;
161468
161961
  }
161469
161962
  }
161963
+ function hasLocalCommit(sha) {
161964
+ if (!sha) return false;
161965
+ try {
161966
+ return $2("git", ["cat-file", "-t", sha], { log: false }).trim() === "commit";
161967
+ } catch {
161968
+ return false;
161969
+ }
161970
+ }
161470
161971
  var STALE_LOCK_AGE_MS = 3e4;
161471
161972
  var PULL_REF_RETRY_DELAYS_MS = [2e3, 5e3, 1e4];
161472
161973
  var PULL_REF_MISSING_PATTERN = /couldn't find remote ref pull\/\d+\/head/i;
@@ -161517,7 +162018,7 @@ async function abortIfPullRequestMoved(args2) {
161517
162018
  );
161518
162019
  }
161519
162020
  async function checkoutPrBranch(pr, params) {
161520
- const { octokit, owner, name, gitToken, toolState, beforeSha } = params;
162021
+ const { octokit, owner, name, gitToken, refreshGitToken, toolState, beforeSha } = params;
161521
162022
  rejectIfLeadingDash(pr.baseRef, "PR base ref");
161522
162023
  rejectIfLeadingDash(pr.headRef, "PR head ref");
161523
162024
  const repoState = requireRepoState(toolState, owner, name);
@@ -161531,7 +162032,7 @@ async function checkoutPrBranch(pr, params) {
161531
162032
  log.debug(`\xBB fetching base branch (${pr.baseRef})...`);
161532
162033
  await $gitFetchWithDeepen(
161533
162034
  ["--no-tags", "origin", pr.baseRef],
161534
- { token: gitToken },
162035
+ { token: gitToken, refreshGitToken },
161535
162036
  `base branch ${pr.baseRef}`
161536
162037
  );
161537
162038
  if (!alreadyOnBranch) {
@@ -161542,7 +162043,7 @@ async function checkoutPrBranch(pr, params) {
161542
162043
  try {
161543
162044
  await $gitFetchWithDeepen(
161544
162045
  ["--no-tags", "origin", `+pull/${pr.number}/head:${localBranch}`],
161545
- { token: gitToken },
162046
+ { token: gitToken, refreshGitToken },
161546
162047
  `PR #${pr.number}`
161547
162048
  );
161548
162049
  } catch (e) {
@@ -161569,6 +162070,7 @@ async function checkoutPrBranch(pr, params) {
161569
162070
  owner,
161570
162071
  repo: name,
161571
162072
  gitToken,
162073
+ refreshGitToken,
161572
162074
  isShallow
161573
162075
  }) : false;
161574
162076
  if (isShallow) {
@@ -161682,6 +162184,7 @@ function CheckoutPrTool(ctx) {
161682
162184
  owner: ctx.repo.owner,
161683
162185
  name: ctx.repo.name,
161684
162186
  gitToken: ctx.gitToken,
162187
+ refreshGitToken: ctx.refreshGitToken,
161685
162188
  toolState: ctx.toolState,
161686
162189
  shell: ctx.payload.shell,
161687
162190
  postCheckoutScript: ctx.postCheckoutScript,
@@ -161697,6 +162200,8 @@ function CheckoutPrTool(ctx) {
161697
162200
  if (!checkoutSha) throw new Error("checkout completed without a resolved HEAD SHA");
161698
162201
  const headShort = checkoutSha.slice(0, 7);
161699
162202
  let incrementalDiffPath;
162203
+ let incrementalUnavailable = false;
162204
+ let incrementalUnavailableReason;
161700
162205
  if (primary.beforeSha) {
161701
162206
  const beforeShort = primary.beforeSha.slice(0, 7);
161702
162207
  const incremental = computeIncrementalDiff({
@@ -161704,15 +162209,18 @@ function CheckoutPrTool(ctx) {
161704
162209
  beforeSha: primary.beforeSha,
161705
162210
  headSha: checkoutSha
161706
162211
  });
161707
- if (incremental) {
162212
+ if (incremental.status === "ok") {
161708
162213
  incrementalDiffPath = join14(
161709
162214
  tempDir,
161710
162215
  `pr-${pull_number}-${beforeShort}-${headShort}-incremental.diff`
161711
162216
  );
161712
- writeFileSync9(incrementalDiffPath, incremental);
162217
+ writeFileSync9(incrementalDiffPath, incremental.diff);
161713
162218
  log.info(
161714
- `\xBB incremental diff computed (${incremental.length} bytes) \u2192 ${incrementalDiffPath}`
162219
+ `\xBB incremental diff computed (${incremental.diff.length} bytes) \u2192 ${incrementalDiffPath}`
161715
162220
  );
162221
+ } else if (incremental.status === "unavailable") {
162222
+ incrementalUnavailable = true;
162223
+ incrementalUnavailableReason = incremental.reason;
161716
162224
  }
161717
162225
  }
161718
162226
  const formatResult = await fetchAndFormatPrDiff(ctx, pull_number);
@@ -161779,7 +162287,13 @@ ${diffPreview}`);
161779
162287
  primary.commentableLinesByFile = cached4;
161780
162288
  primary.commentableLinesPullNumber = pull_number;
161781
162289
  primary.commentableLinesCheckoutSha = checkoutSha;
161782
- const incrementalInstructions = incrementalDiffPath ? `IMPORTANT: incrementalDiffPath contains ONLY the changes since the last reviewed version (computed via range-diff). you MUST read incrementalDiffPath FIRST to understand what changed, then use diffPath for full PR context. do NOT skip the incremental diff. ` : "";
162290
+ const incrementalInstructions = incrementalDiffPath ? `IMPORTANT: incrementalDiffPath contains ONLY the changes since the last reviewed version (computed via range-diff). you MUST read incrementalDiffPath FIRST to understand what changed, then use diffPath for full PR context. do NOT skip the incremental diff. ` : incrementalUnavailable ? (
162291
+ // say it FAILED rather than leaving the agent to infer "nothing changed"
162292
+ // from an absent field. only suggest diff-tree when the previous
162293
+ // revision is actually PRESENT locally — if the fetch never landed it,
162294
+ // diff-tree needs that object too and would fail identically. see #1139.
162295
+ `NOTE: an incremental diff was expected for this run but could not be computed` + (incrementalUnavailableReason ? ` (${incrementalUnavailableReason})` : "") + `. review the full diffPath instead. ` + (hasLocalCommit(primary.beforeSha) ? `if you need just the delta, \`git diff-tree -p ${primary.beforeSha} ${checkoutSha}\` works without a merge base. ` : `the previous revision was never fetched into this shallow checkout, so the full diff is the only option. `)
162296
+ ) : "";
161783
162297
  const impactInstructions = impactPath ? ` impactPath contains bounded, deterministic reference leads for semantic atoms changed by the PR. read the authoritative diff TOC and relevant raw diff lines FIRST; only then use impactPath as a supplemental, explicitly incomplete lead list. impactPath never establishes review coverage and an empty artifact is not evidence of no wider impact.` : "";
161784
162298
  const COMMIT_LOG_MAX = 200;
161785
162299
  const baseRange = `origin/${pr.baseRef}..HEAD`;
@@ -162099,299 +162613,6 @@ import { performance as performance8 } from "node:perf_hooks";
162099
162613
  import { existsSync as existsSync6 } from "node:fs";
162100
162614
  import { join as join18 } from "node:path";
162101
162615
 
162102
- // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/commands.mjs
162103
- function dashDashArg(agent2, agentCommand) {
162104
- return (args2) => {
162105
- if (args2.length > 1) {
162106
- return [agent2, agentCommand, args2[0], "--", ...args2.slice(1)];
162107
- } else {
162108
- return [agent2, agentCommand, args2[0]];
162109
- }
162110
- };
162111
- }
162112
- function denoExecute() {
162113
- return (args2) => {
162114
- return ["deno", "run", `npm:${args2[0]}`, ...args2.slice(1)];
162115
- };
162116
- }
162117
- var npm = {
162118
- "agent": ["npm", 0],
162119
- "run": dashDashArg("npm", "run"),
162120
- "install": ["npm", "i", 0],
162121
- "frozen": ["npm", "ci", 0],
162122
- "global": ["npm", "i", "-g", 0],
162123
- "add": ["npm", "i", 0],
162124
- "upgrade": ["npm", "update", 0],
162125
- "upgrade-interactive": null,
162126
- "dedupe": ["npm", "dedupe", 0],
162127
- "execute": ["npx", 0],
162128
- "execute-local": ["npx", 0],
162129
- "uninstall": ["npm", "uninstall", 0],
162130
- "global_uninstall": ["npm", "uninstall", "-g", 0]
162131
- };
162132
- var yarn = {
162133
- "agent": ["yarn", 0],
162134
- "run": ["yarn", "run", 0],
162135
- "install": ["yarn", "install", 0],
162136
- "frozen": ["yarn", "install", "--frozen-lockfile", 0],
162137
- "global": ["yarn", "global", "add", 0],
162138
- "add": ["yarn", "add", 0],
162139
- "upgrade": ["yarn", "upgrade", 0],
162140
- "upgrade-interactive": ["yarn", "upgrade-interactive", 0],
162141
- "dedupe": null,
162142
- "execute": ["npx", 0],
162143
- "execute-local": dashDashArg("yarn", "exec"),
162144
- "uninstall": ["yarn", "remove", 0],
162145
- "global_uninstall": ["yarn", "global", "remove", 0]
162146
- };
162147
- var yarnBerry = {
162148
- ...yarn,
162149
- "frozen": ["yarn", "install", "--immutable", 0],
162150
- "upgrade": ["yarn", "up", 0],
162151
- "upgrade-interactive": ["yarn", "up", "-i", 0],
162152
- "dedupe": ["yarn", "dedupe", 0],
162153
- "execute": ["yarn", "dlx", 0],
162154
- "execute-local": ["yarn", "exec", 0],
162155
- // Yarn 2+ removed 'global', see https://github.com/yarnpkg/berry/issues/821
162156
- "global": ["npm", "i", "-g", 0],
162157
- "global_uninstall": ["npm", "uninstall", "-g", 0]
162158
- };
162159
- var pnpm = {
162160
- "agent": ["pnpm", 0],
162161
- "run": ["pnpm", "run", 0],
162162
- "install": ["pnpm", "i", 0],
162163
- "frozen": ["pnpm", "i", "--frozen-lockfile", 0],
162164
- "global": ["pnpm", "add", "-g", 0],
162165
- "add": ["pnpm", "add", 0],
162166
- "upgrade": ["pnpm", "update", 0],
162167
- "upgrade-interactive": ["pnpm", "update", "-i", 0],
162168
- "dedupe": ["pnpm", "dedupe", 0],
162169
- "execute": ["pnpm", "dlx", 0],
162170
- "execute-local": ["pnpm", "exec", 0],
162171
- "uninstall": ["pnpm", "remove", 0],
162172
- "global_uninstall": ["pnpm", "remove", "--global", 0]
162173
- };
162174
- var bun = {
162175
- "agent": ["bun", 0],
162176
- "run": ["bun", "run", 0],
162177
- "install": ["bun", "install", 0],
162178
- "frozen": ["bun", "install", "--frozen-lockfile", 0],
162179
- "global": ["bun", "add", "-g", 0],
162180
- "add": ["bun", "add", 0],
162181
- "upgrade": ["bun", "update", 0],
162182
- "upgrade-interactive": ["bun", "update", "-i", 0],
162183
- "dedupe": null,
162184
- "execute": ["bun", "x", 0],
162185
- "execute-local": ["bun", "x", 0],
162186
- "uninstall": ["bun", "remove", 0],
162187
- "global_uninstall": ["bun", "remove", "-g", 0]
162188
- };
162189
- var deno = {
162190
- "agent": ["deno", 0],
162191
- "run": ["deno", "task", 0],
162192
- "install": ["deno", "install", 0],
162193
- "frozen": ["deno", "install", "--frozen", 0],
162194
- "global": ["deno", "install", "-g", 0],
162195
- "add": ["deno", "add", 0],
162196
- "upgrade": ["deno", "outdated", "--update", 0],
162197
- "upgrade-interactive": ["deno", "outdated", "--update", 0],
162198
- "dedupe": null,
162199
- "execute": denoExecute(),
162200
- "execute-local": ["deno", "task", "--eval", 0],
162201
- "uninstall": ["deno", "remove", 0],
162202
- "global_uninstall": ["deno", "uninstall", "-g", 0]
162203
- };
162204
- var COMMANDS = {
162205
- "npm": npm,
162206
- "yarn": yarn,
162207
- "yarn@berry": yarnBerry,
162208
- "pnpm": pnpm,
162209
- // pnpm v6.x or below
162210
- "pnpm@6": {
162211
- ...pnpm,
162212
- run: dashDashArg("pnpm", "run")
162213
- },
162214
- "bun": bun,
162215
- "deno": deno
162216
- };
162217
- function resolveCommand(agent2, command, args2) {
162218
- const value2 = COMMANDS[agent2][command];
162219
- return constructCommand(value2, args2);
162220
- }
162221
- function constructCommand(value2, args2) {
162222
- if (value2 == null)
162223
- return null;
162224
- const list = typeof value2 === "function" ? value2(args2) : value2.flatMap((v) => {
162225
- if (typeof v === "number")
162226
- return args2;
162227
- return [v];
162228
- });
162229
- return {
162230
- command: list[0],
162231
- args: list.slice(1)
162232
- };
162233
- }
162234
-
162235
- // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/constants.mjs
162236
- var AGENTS = [
162237
- "npm",
162238
- "yarn",
162239
- "yarn@berry",
162240
- "pnpm",
162241
- "pnpm@6",
162242
- "bun",
162243
- "deno"
162244
- ];
162245
- var LOCKS = {
162246
- "bun.lock": "bun",
162247
- "bun.lockb": "bun",
162248
- "deno.lock": "deno",
162249
- "pnpm-lock.yaml": "pnpm",
162250
- "pnpm-workspace.yaml": "pnpm",
162251
- "yarn.lock": "yarn",
162252
- "package-lock.json": "npm",
162253
- "npm-shrinkwrap.json": "npm"
162254
- };
162255
- var INSTALL_METADATA = {
162256
- "node_modules/.deno/": "deno",
162257
- "node_modules/.pnpm/": "pnpm",
162258
- "node_modules/.yarn-state.yml": "yarn",
162259
- // yarn v2+ (node-modules)
162260
- "node_modules/.yarn_integrity": "yarn",
162261
- // yarn v1
162262
- "node_modules/.package-lock.json": "npm",
162263
- ".pnp.cjs": "yarn",
162264
- // yarn v3+ (pnp)
162265
- ".pnp.js": "yarn",
162266
- // yarn v2 (pnp)
162267
- "bun.lock": "bun",
162268
- "bun.lockb": "bun"
162269
- };
162270
-
162271
- // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/detect.mjs
162272
- import fs2 from "node:fs/promises";
162273
- import path from "node:path";
162274
- import process4 from "node:process";
162275
- async function pathExists(path22, type2) {
162276
- try {
162277
- const stat = await fs2.stat(path22);
162278
- return type2 === "file" ? stat.isFile() : stat.isDirectory();
162279
- } catch {
162280
- return false;
162281
- }
162282
- }
162283
- function* lookup(cwd = process4.cwd()) {
162284
- let directory = path.resolve(cwd);
162285
- const { root } = path.parse(directory);
162286
- while (directory && directory !== root) {
162287
- yield directory;
162288
- directory = path.dirname(directory);
162289
- }
162290
- }
162291
- async function parsePackageJson(filepath, options) {
162292
- if (!filepath || !await pathExists(filepath, "file"))
162293
- return null;
162294
- return await handlePackageManager(filepath, options);
162295
- }
162296
- async function detect(options = {}) {
162297
- const {
162298
- cwd,
162299
- strategies = ["lockfile", "packageManager-field", "devEngines-field"]
162300
- } = options;
162301
- let stopDir;
162302
- if (typeof options.stopDir === "string") {
162303
- const resolved = path.resolve(options.stopDir);
162304
- stopDir = (dir) => dir === resolved;
162305
- } else {
162306
- stopDir = options.stopDir;
162307
- }
162308
- for (const directory of lookup(cwd)) {
162309
- for (const strategy of strategies) {
162310
- switch (strategy) {
162311
- case "lockfile": {
162312
- for (const lock of Object.keys(LOCKS)) {
162313
- if (await pathExists(path.join(directory, lock), "file")) {
162314
- const name = LOCKS[lock];
162315
- const result = await parsePackageJson(path.join(directory, "package.json"), options);
162316
- if (result)
162317
- return result;
162318
- else
162319
- return { name, agent: name };
162320
- }
162321
- }
162322
- break;
162323
- }
162324
- case "packageManager-field":
162325
- case "devEngines-field": {
162326
- const result = await parsePackageJson(path.join(directory, "package.json"), options);
162327
- if (result)
162328
- return result;
162329
- break;
162330
- }
162331
- case "install-metadata": {
162332
- for (const metadata of Object.keys(INSTALL_METADATA)) {
162333
- const fileOrDir = metadata.endsWith("/") ? "dir" : "file";
162334
- if (await pathExists(path.join(directory, metadata), fileOrDir)) {
162335
- const name = INSTALL_METADATA[metadata];
162336
- const agent2 = name === "yarn" ? isMetadataYarnClassic(metadata) ? "yarn" : "yarn@berry" : name;
162337
- return { name, agent: agent2 };
162338
- }
162339
- }
162340
- break;
162341
- }
162342
- }
162343
- }
162344
- if (stopDir?.(directory))
162345
- break;
162346
- }
162347
- return null;
162348
- }
162349
- function getNameAndVer(pkg) {
162350
- const handelVer = (version3) => version3?.match(/\d+(\.\d+){0,2}/)?.[0] ?? version3;
162351
- if (typeof pkg.packageManager === "string") {
162352
- const [name, ver] = pkg.packageManager.replace(/^\^/, "").split("@");
162353
- return { name, ver: handelVer(ver) };
162354
- }
162355
- if (typeof pkg.devEngines?.packageManager?.name === "string") {
162356
- return {
162357
- name: pkg.devEngines.packageManager.name,
162358
- ver: handelVer(pkg.devEngines.packageManager.version)
162359
- };
162360
- }
162361
- return void 0;
162362
- }
162363
- async function handlePackageManager(filepath, options) {
162364
- try {
162365
- const content = await fs2.readFile(filepath, "utf8");
162366
- const pkg = options.packageJsonParser ? await options.packageJsonParser(content, filepath) : JSON.parse(content);
162367
- let agent2;
162368
- const nameAndVer = getNameAndVer(pkg);
162369
- if (nameAndVer) {
162370
- const name = nameAndVer.name;
162371
- const ver = nameAndVer.ver;
162372
- let version3 = ver;
162373
- if (name === "yarn" && ver && Number.parseInt(ver) > 1) {
162374
- agent2 = "yarn@berry";
162375
- version3 = "berry";
162376
- return { name, agent: agent2, version: version3 };
162377
- } else if (name === "pnpm" && ver && Number.parseInt(ver) < 7) {
162378
- agent2 = "pnpm@6";
162379
- return { name, agent: agent2, version: version3 };
162380
- } else if (AGENTS.includes(name)) {
162381
- agent2 = name;
162382
- return { name, agent: agent2, version: version3 };
162383
- } else {
162384
- return options.onUnknown?.(pkg.packageManager) ?? null;
162385
- }
162386
- }
162387
- } catch {
162388
- }
162389
- return null;
162390
- }
162391
- function isMetadataYarnClassic(metadataPath) {
162392
- return metadataPath.endsWith(".yarn_integrity");
162393
- }
162394
-
162395
162616
  // utils/packageManager.ts
162396
162617
  var import_semver2 = __toESM(require_semver2(), 1);
162397
162618
  import { existsSync as existsSync5 } from "node:fs";
@@ -162477,11 +162698,7 @@ async function runCorepack(args2) {
162477
162698
  const result = await spawn3({
162478
162699
  cmd: "corepack",
162479
162700
  args: args2,
162480
- env: {
162481
- PATH: process.env.PATH || "",
162482
- HOME: process.env.HOME || "",
162483
- COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
162484
- },
162701
+ env: { ...filterEnvForUntrustedCode(), COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" },
162485
162702
  onStdout: (chunk) => process.stdout.write(chunk),
162486
162703
  onStderr: (chunk) => process.stderr.write(chunk)
162487
162704
  });
@@ -162491,7 +162708,7 @@ async function currentVersion(name) {
162491
162708
  const result = await spawn3({
162492
162709
  cmd: name,
162493
162710
  args: ["--version"],
162494
- env: { PATH: process.env.PATH || "" }
162711
+ env: filterEnvForUntrustedCode()
162495
162712
  });
162496
162713
  if (result.exitCode !== 0) return null;
162497
162714
  return result.stdout.trim();
@@ -162543,14 +162760,8 @@ async function ensurePackageManager(params) {
162543
162760
  }
162544
162761
  return true;
162545
162762
  }
162546
-
162547
- // prep/installNodeDependencies.ts
162548
162763
  async function isCommandAvailable(command) {
162549
- const result = await spawn3({
162550
- cmd: "which",
162551
- args: [command],
162552
- env: { PATH: process.env.PATH || "" }
162553
- });
162764
+ const result = await spawn3({ cmd: "which", args: [command], env: filterEnvForUntrustedCode() });
162554
162765
  return result.exitCode === 0;
162555
162766
  }
162556
162767
  async function installFallback(name, installSpec) {
@@ -162561,19 +162772,41 @@ async function installFallback(name, installSpec) {
162561
162772
  const result = await spawn3({
162562
162773
  cmd,
162563
162774
  args: args2,
162564
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
162775
+ env: filterEnvForUntrustedCode(),
162565
162776
  onStderr: (chunk) => process.stderr.write(chunk)
162566
162777
  });
162567
- if (result.exitCode !== 0) {
162568
- return result.stderr || `failed to install ${name}`;
162569
- }
162778
+ if (result.exitCode !== 0) return result.stderr || `failed to install ${name}`;
162570
162779
  if (name === "deno") {
162571
- const denoPath = join18(process.env.HOME || "", ".deno", "bin");
162780
+ const denoPath = join17(process.env.HOME || "", ".deno", "bin");
162572
162781
  process.env.PATH = `${denoPath}:${process.env.PATH}`;
162573
162782
  }
162574
162783
  log.info(`\xBB installed ${name}`);
162575
162784
  return null;
162576
162785
  }
162786
+ async function provisionPackageManager(params) {
162787
+ if (await isCommandAvailable(params.name)) {
162788
+ if (params.declared) {
162789
+ await ensurePackageManager({ spec: params.declared, binDir: params.binDir });
162790
+ }
162791
+ return null;
162792
+ }
162793
+ if (params.declared) {
162794
+ const activated = await ensurePackageManager({ spec: params.declared, binDir: params.binDir });
162795
+ if (activated) return null;
162796
+ }
162797
+ const spec = params.declared ? `${params.declared.name}@${params.declared.version}` : params.name;
162798
+ return installFallback(params.name, spec);
162799
+ }
162800
+
162801
+ // prep/installNodeDependencies.ts
162802
+ async function isCommandAvailable2(command) {
162803
+ const result = await spawn3({
162804
+ cmd: "which",
162805
+ args: [command],
162806
+ env: filterEnvForUntrustedCode()
162807
+ });
162808
+ return result.exitCode === 0;
162809
+ }
162577
162810
  var installNodeDependencies = {
162578
162811
  name: "installNodeDependencies",
162579
162812
  shouldRun: () => {
@@ -162594,8 +162827,8 @@ var installNodeDependencies = {
162594
162827
  } else {
162595
162828
  log.info(`\xBB no package manager declared, defaulting to npm`);
162596
162829
  }
162597
- if (!await isCommandAvailable(packageManager)) {
162598
- if (options.ignoreScripts) {
162830
+ if (options.ignoreScripts) {
162831
+ if (!await isCommandAvailable2(packageManager)) {
162599
162832
  return {
162600
162833
  language: "node",
162601
162834
  packageManager,
@@ -162605,23 +162838,20 @@ var installNodeDependencies = {
162605
162838
  ]
162606
162839
  };
162607
162840
  }
162608
- let provisioned = false;
162609
- if (declared)
162610
- provisioned = await ensurePackageManager({ spec: declared, binDir: options.binDir });
162611
- if (!provisioned) {
162612
- const fallbackSpec = declared ? `${declared.name}@${declared.version}` : packageManager;
162613
- const installError = await installFallback(packageManager, fallbackSpec);
162614
- if (installError) {
162615
- return {
162616
- language: "node",
162617
- packageManager,
162618
- dependenciesInstalled: false,
162619
- issues: [installError]
162620
- };
162621
- }
162841
+ } else {
162842
+ const installError = await provisionPackageManager({
162843
+ name: packageManager,
162844
+ declared,
162845
+ binDir: options.binDir
162846
+ });
162847
+ if (installError) {
162848
+ return {
162849
+ language: "node",
162850
+ packageManager,
162851
+ dependenciesInstalled: false,
162852
+ issues: [installError]
162853
+ };
162622
162854
  }
162623
- } else if (declared) {
162624
- await ensurePackageManager({ spec: declared, binDir: options.binDir });
162625
162855
  }
162626
162856
  if (!detected) {
162627
162857
  log.info(
@@ -162647,7 +162877,7 @@ var installNodeDependencies = {
162647
162877
  const result = await spawn3({
162648
162878
  cmd: resolved.command,
162649
162879
  args: resolved.args,
162650
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" }
162880
+ env: filterEnvForUntrustedCode()
162651
162881
  });
162652
162882
  const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
162653
162883
  if (output) {
@@ -162721,11 +162951,11 @@ var TOOL_INSTALL_COMMANDS = {
162721
162951
  pipenv: ["pip", "install", "pipenv"],
162722
162952
  poetry: ["pip", "install", "poetry"]
162723
162953
  };
162724
- async function isCommandAvailable2(command) {
162954
+ async function isCommandAvailable3(command) {
162725
162955
  const result = await spawn3({
162726
162956
  cmd: "which",
162727
162957
  args: [command],
162728
- env: { PATH: process.env.PATH || "" }
162958
+ env: filterEnvForUntrustedCode()
162729
162959
  });
162730
162960
  return result.exitCode === 0;
162731
162961
  }
@@ -162739,7 +162969,7 @@ async function installTool(name) {
162739
162969
  const result = await spawn3({
162740
162970
  cmd,
162741
162971
  args: args2,
162742
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
162972
+ env: filterEnvForUntrustedCode(),
162743
162973
  onStderr: (chunk) => process.stderr.write(chunk)
162744
162974
  });
162745
162975
  if (result.exitCode !== 0) {
@@ -162751,7 +162981,7 @@ async function installTool(name) {
162751
162981
  var installPythonDependencies = {
162752
162982
  name: "installPythonDependencies",
162753
162983
  shouldRun: async () => {
162754
- const hasPython = await isCommandAvailable2("python3") || await isCommandAvailable2("python");
162984
+ const hasPython = await isCommandAvailable3("python3") || await isCommandAvailable3("python");
162755
162985
  if (!hasPython) {
162756
162986
  return false;
162757
162987
  }
@@ -162785,7 +163015,7 @@ var installPythonDependencies = {
162785
163015
  ]
162786
163016
  };
162787
163017
  }
162788
- const isAvailable = await isCommandAvailable2(config3.tool);
163018
+ const isAvailable = await isCommandAvailable3(config3.tool);
162789
163019
  if (!isAvailable) {
162790
163020
  log.info(`\xBB ${config3.tool} not found, attempting to install...`);
162791
163021
  const installError = await installTool(config3.tool);
@@ -162805,7 +163035,7 @@ var installPythonDependencies = {
162805
163035
  const result = await spawn3({
162806
163036
  cmd,
162807
163037
  args: args2,
162808
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" }
163038
+ env: filterEnvForUntrustedCode()
162809
163039
  });
162810
163040
  const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
162811
163041
  if (output) {
@@ -162834,37 +163064,6 @@ var installPythonDependencies = {
162834
163064
 
162835
163065
  // prep/index.ts
162836
163066
  var prepSteps = [installNodeDependencies, installPythonDependencies];
162837
- async function dirtyTrackedPaths() {
162838
- const result = await spawn3({
162839
- cmd: "git",
162840
- args: ["diff", "--name-only", "HEAD"],
162841
- env: process.env,
162842
- activityTimeout: 0
162843
- });
162844
- if (result.exitCode !== 0) {
162845
- throw new Error(
162846
- `git diff --name-only HEAD failed (exit ${result.exitCode}): ${result.stderr.trim() || "(no stderr)"}`
162847
- );
162848
- }
162849
- return new Set(result.stdout.split("\n").filter(Boolean));
162850
- }
162851
- async function restorePrepDirtiedFiles(preDirty) {
162852
- const dirtied = [...await dirtyTrackedPaths()].filter((path4) => !preDirty.has(path4));
162853
- if (dirtied.length === 0) return;
162854
- const result = await spawn3({
162855
- cmd: "git",
162856
- args: ["restore", "--staged", "--worktree", "--", ...dirtied],
162857
- env: process.env,
162858
- activityTimeout: 0
162859
- });
162860
- if (result.exitCode !== 0) {
162861
- log.warning(
162862
- `\xBB failed to restore ${dirtied.length} tracked file(s) modified by prep: ${result.stderr.trim() || "(no stderr)"}`
162863
- );
162864
- return;
162865
- }
162866
- log.info(`\xBB restored ${dirtied.length} tracked file(s) modified by prep: ${dirtied.join(", ")}`);
162867
- }
162868
163067
  async function runPrepPhase(options) {
162869
163068
  log.debug("\xBB starting prep phase...");
162870
163069
  const startTime = performance8.now();
@@ -162887,7 +163086,7 @@ async function runPrepPhase(options) {
162887
163086
  }
162888
163087
  }
162889
163088
  } finally {
162890
- await restorePrepDirtiedFiles(preDirty);
163089
+ await restoreDirtiedSince({ before: preDirty, actor: "prep" });
162891
163090
  }
162892
163091
  const totalDurationMs = performance8.now() - startTime;
162893
163092
  log.debug(`\xBB prep phase completed (${Math.round(totalDurationMs)}ms)`);
@@ -164103,13 +164302,38 @@ function buildThreadBlocks(threads, filePatchMap, reviewId) {
164103
164302
  }
164104
164303
  return threadBlocks;
164105
164304
  }
164305
+ var fetchAllReviewThreads = op(
164306
+ async (key, ctx) => {
164307
+ const response = await ctx.octokit.graphql(REVIEW_THREADS_QUERY, {
164308
+ owner: key.owner,
164309
+ name: key.name,
164310
+ prNumber: key.pullNumber
164311
+ });
164312
+ return response.repository?.pullRequest?.reviewThreads?.nodes ?? [];
164313
+ },
164314
+ { ttl: 6e4, name: "reviewThreads" }
164315
+ );
164316
+ var fetchPrFiles = op(
164317
+ async (key, ctx) => ctx.octokit.paginate(ctx.octokit.rest.pulls.listFiles, {
164318
+ owner: key.owner,
164319
+ repo: key.name,
164320
+ pull_number: key.pullNumber,
164321
+ per_page: 100
164322
+ }),
164323
+ { ttl: 6e4, name: "prFiles" }
164324
+ );
164325
+ function invalidateReviewThreadCache(repo) {
164326
+ fetchAllReviewThreads.invalidate(
164327
+ (cached4) => cached4.owner === repo.owner && cached4.name === repo.name
164328
+ );
164329
+ }
164106
164330
  async function getReviewThreads(input) {
164107
- const response = await input.octokit.graphql(REVIEW_THREADS_QUERY, {
164108
- owner: input.owner,
164109
- name: input.name,
164110
- prNumber: input.pullNumber
164111
- });
164112
- const allThreads = response.repository?.pullRequest?.reviewThreads?.nodes ?? [];
164331
+ const allThreads = structuredClone(
164332
+ await fetchAllReviewThreads(
164333
+ { owner: input.owner, name: input.name, pullNumber: input.pullNumber },
164334
+ { octokit: input.octokit }
164335
+ )
164336
+ );
164113
164337
  if (allThreads.length >= 100) {
164114
164338
  log.warning(
164115
164339
  `PR ${input.owner}/${input.name}#${input.pullNumber}: reviewThreads returned 100 results (limit reached, some threads may be missing)`
@@ -164166,12 +164390,10 @@ async function getReviewData(input) {
164166
164390
  }),
164167
164391
  getReviewThreads(input)
164168
164392
  ]);
164169
- const prFiles = threads.length > 0 ? await input.octokit.paginate(input.octokit.rest.pulls.listFiles, {
164170
- owner: input.owner,
164171
- repo: input.name,
164172
- pull_number: input.pullNumber,
164173
- per_page: 100
164174
- }) : [];
164393
+ const prFiles = threads.length > 0 ? await fetchPrFiles(
164394
+ { owner: input.owner, name: input.name, pullNumber: input.pullNumber },
164395
+ { octokit: input.octokit }
164396
+ ) : [];
164175
164397
  if (review.data.body) {
164176
164398
  review.data.body = await resolveBodyAssets({
164177
164399
  body: review.data.body,
@@ -164315,6 +164537,7 @@ function ResolveReviewThreadTool(ctx) {
164315
164537
  });
164316
164538
  const thread = response.resolveReviewThread.thread;
164317
164539
  log.info(`\xBB resolved review thread ${thread.id}`);
164540
+ invalidateReviewThreadCache({ owner: ctx.repo.owner, name: ctx.repo.name });
164318
164541
  return {
164319
164542
  thread_id: thread.id,
164320
164543
  is_resolved: thread.isResolved,
@@ -164489,7 +164712,10 @@ import { join as join21 } from "node:path";
164489
164712
  import { setTimeout as sleep2 } from "node:timers/promises";
164490
164713
  var ShellParams = type({
164491
164714
  command: "string",
164492
- description: "string",
164715
+ // advisory and unread — no code path consumes it. kept in the schema only
164716
+ // because it nudges the model to state intent before running a command;
164717
+ // REQUIRING it cost a full rejected turn every time one was omitted. #1140.
164718
+ "description?": "string",
164493
164719
  "timeout?": type.number.describe(
164494
164720
  "Timeout in MILLISECONDS (not seconds). Default 30000 (30s), max 120000 (2m). e.g. timeout: 180000 for 3 minutes; timeout: 180 means 180ms and will kill the process almost immediately."
164495
164721
  ),
@@ -164759,6 +164985,8 @@ Do NOT use this tool for git commands \u2014 use the dedicated git tools instead
164759
164985
  proc.on("exit", done);
164760
164986
  proc.on("error", () => done(null));
164761
164987
  });
164988
+ proc.stdout?.destroy();
164989
+ proc.stderr?.destroy();
164762
164990
  let output = stderr ? stdout ? `${stdout}
164763
164991
  ${stderr}` : stderr : stdout;
164764
164992
  if (timedOut)
@@ -165002,6 +165230,7 @@ function CheckoutRepoTool(ctx) {
165002
165230
  owner,
165003
165231
  name: repo,
165004
165232
  gitToken: rc.gitToken,
165233
+ refreshGitToken: rc.refreshGitToken,
165005
165234
  octokit: rc.octokit,
165006
165235
  toolState: ctx.toolState,
165007
165236
  shell: ctx.payload.shell,
@@ -165498,14 +165727,22 @@ function validateAgentApiKey(params) {
165498
165727
  }
165499
165728
  function isApiKeyAuthError(text) {
165500
165729
  if (!text) return false;
165501
- return text.includes(MISSING_KEY_MARKER) || /Invalid API key/i.test(text) || /\bUser not found\b/i.test(text) || /\bInvalid authentication\b/i.test(text) || /authentication_error/i.test(text) || /Invalid bearer token/i.test(text) || /api_error_status\s*=\s*401/i.test(text) || /API Error:\s*401/i.test(text) || /Failed to authenticate\. API Error:/i.test(text) || /Your api key:.*is invalid/i.test(text) || isClaudeSubscriptionDisabledError(text) || isOAuthCredentialExpiredError(text);
165730
+ return text.includes(MISSING_KEY_MARKER) || /Invalid API key/i.test(text) || /\bUser not found\b/i.test(text) || /\bInvalid authentication\b/i.test(text) || /authentication_error/i.test(text) || /Invalid bearer token/i.test(text) || /api_error_status\s*=\s*401/i.test(text) || /API Error:\s*401/i.test(text) || /Failed to authenticate\. API Error:/i.test(text) || /Your api key:.*is invalid/i.test(text) || isClaudeSubscriptionDisabledError(text) || isClaudeSessionLimitError(text) || isOAuthCredentialExpiredError(text);
165502
165731
  }
165503
165732
  function isOAuthCredentialExpiredError(text) {
165504
- return /authentication token has (expired|been invalidated)/i.test(text) || /OAuth access token has expired/i.test(text) || /Token refresh failed/i.test(text);
165733
+ return /(?:authentication|OAuth access) token has (?:expired|been (?:invalidated|revoked))/i.test(
165734
+ text
165735
+ ) || // the provider no longer recognises the token at all (#1086) — same dead
165736
+ // credential, phrased as a lookup miss rather than a state transition.
165737
+ /Could not find the appropriate key in your authentication token/i.test(text) || /Token refresh failed/i.test(text);
165505
165738
  }
165506
165739
  function isClaudeSubscriptionDisabledError(text) {
165507
165740
  return /disabled Claude subscription access/i.test(text);
165508
165741
  }
165742
+ var CLAUDE_SESSION_LIMIT_PATTERN = /hit your (?:session|weekly|five-hour|Opus|Sonnet|Haiku)\s+limit(?:\s*·\s*resets\s+([^"\n]+))?/i;
165743
+ function isClaudeSessionLimitError(text) {
165744
+ return CLAUDE_SESSION_LIMIT_PATTERN.test(text);
165745
+ }
165509
165746
  function formatApiKeyErrorSummary(params) {
165510
165747
  if (params.raw.includes(MISSING_KEY_MARKER)) {
165511
165748
  if (params.raw.startsWith(`**${MISSING_KEY_MARKER}**`)) return params.raw;
@@ -165513,6 +165750,15 @@ function formatApiKeyErrorSummary(params) {
165513
165750
  }
165514
165751
  const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
165515
165752
  const settingsUrl = `${getApiUrl()}/console/${params.owner}/${params.name}`;
165753
+ if (isClaudeSessionLimitError(params.raw)) {
165754
+ const reset = CLAUDE_SESSION_LIMIT_PATTERN.exec(params.raw)?.[1]?.trim();
165755
+ const resets = reset ? ` It resets at **${reset}**.` : "";
165756
+ return [
165757
+ `**Your Claude subscription has hit its usage limit.**${resets} Re-trigger Pullfrog after the reset, or add an \`ANTHROPIC_API_KEY\` repo secret \u2014 Pullfrog routes around an exhausted subscription automatically when one is present.`,
165758
+ "",
165759
+ `[Add repo secret \u2192](${githubSecretsUrl}) \xB7 [Model settings \u2192](${settingsUrl}) \xB7 [Setup docs \u2192](https://docs.pullfrog.com/keys) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`
165760
+ ].join("\n");
165761
+ }
165516
165762
  if (isClaudeSubscriptionDisabledError(params.raw)) {
165517
165763
  return [
165518
165764
  `**Your organization has disabled Claude subscription access for Claude Code.** Ask your Claude organization's admin to re-enable it in the Claude Console, or set an \`ANTHROPIC_API_KEY\` for this repo instead, then re-trigger the run.`,
@@ -166322,7 +166568,9 @@ function decideModelAccess(input) {
166322
166568
  if (input.proxyActive) {
166323
166569
  const target = resolveOpenRouterModel(input.model);
166324
166570
  if (input.oss) {
166325
- if (target && target === input.subsidyTarget) return { kind: "proxy", target };
166571
+ if (target && (target === input.subsidyTarget || isOssAllowedModel(input.model))) {
166572
+ return { kind: "proxy", target };
166573
+ }
166326
166574
  if (byokAuthorized) return { kind: "byok" };
166327
166575
  return { kind: "error", reason: "oss" };
166328
166576
  }
@@ -166334,6 +166582,11 @@ function decideModelAccess(input) {
166334
166582
  return { kind: "error", reason: "byok_no_key" };
166335
166583
  }
166336
166584
  var MODEL_ACCESS_MARKER = "requested model is not available";
166585
+ function ossAllowedLabels() {
166586
+ return OSS_MODEL_ALLOWLIST.map(
166587
+ (slug2) => `\`${resolveDisplayAlias(slug2)?.displayName ?? slug2}\``
166588
+ ).join(", ");
166589
+ }
166337
166590
  function buildModelAccessError(input) {
166338
166591
  const settingsUrl = `${getApiUrl()}/console/${input.owner}/${input.name}`;
166339
166592
  const secretsUrl = `https://github.com/${input.owner}/${input.name}/settings/secrets/actions`;
@@ -166341,8 +166594,8 @@ function buildModelAccessError(input) {
166341
166594
  const headline = `**The ${MODEL_ACCESS_MARKER}: \`${input.model}\`.**`;
166342
166595
  const branch = {
166343
166596
  oss: {
166344
- why: "This repo runs on Pullfrog's OSS subsidy, which only funds the default model. Switch back to the funded model, or add your own provider key to run a different one.",
166345
- cta: `[Add a provider key \u2192](${secretsUrl}) \xB7 [Setup docs \u2192](${docsUrl})`
166597
+ why: `This repo runs on Pullfrog's OSS subsidy, which funds a set of pre-approved models: ${ossAllowedLabels()}. Pick one of those, or add your own provider key to run a different one.`,
166598
+ cta: `[Configure model \u2192](${settingsUrl}) \xB7 [Add a provider key \u2192](${secretsUrl}) \xB7 [Setup docs \u2192](${docsUrl})`
166346
166599
  },
166347
166600
  byok_no_key: {
166348
166601
  why: `No provider key for \`${input.model}\` is present in this run's environment. Add the matching provider key as a GitHub Actions secret, or pick a model you already have a key for.`,
@@ -166589,6 +166842,14 @@ function resolvePromptFile(input) {
166589
166842
  }
166590
166843
  return content;
166591
166844
  }
166845
+ function warnIfDeprecatedStatusChecks(value2) {
166846
+ if (value2 !== void 0) {
166847
+ core6.warning(
166848
+ "`status_checks` is deprecated. Both checks are now repository settings \u2014 open the Pullfrog console for this repo (Automations \u2192 Review PRs) and set them there, then remove `status_checks` from your workflow. It keeps working until you do."
166849
+ );
166850
+ }
166851
+ return value2;
166852
+ }
166592
166853
  function resolveNonPromptInputs() {
166593
166854
  return Inputs.omit("prompt", "prompt_file").assert({
166594
166855
  model: core6.getInput("model") || void 0,
@@ -166597,7 +166858,7 @@ function resolveNonPromptInputs() {
166597
166858
  cwd: core6.getInput("cwd") || void 0,
166598
166859
  push: core6.getInput("push") || void 0,
166599
166860
  shell: core6.getInput("shell") || void 0,
166600
- status_checks: core6.getInput("status_checks") || void 0,
166861
+ status_checks: warnIfDeprecatedStatusChecks(core6.getInput("status_checks") || void 0),
166601
166862
  progress_comments: core6.getInput("progress_comments") || void 0
166602
166863
  });
166603
166864
  }
@@ -166650,9 +166911,11 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
166650
166911
  // input is the source of truth when set (mirrors `push`); otherwise the repo
166651
166912
  // setting decides.
166652
166913
  runStatusCheck: inputs.status_checks === void 0 ? repoSettings.statusChecks : inputs.status_checks === "enabled",
166653
- // the `pullfrog-approval` verdict check stays opt-in and workflow-only. it exists to
166654
- // be *required* by branch protection, so it must never turn itself on.
166655
- approvalCheck: inputs.status_checks === "enabled",
166914
+ // the `pullfrog-approval` verdict check. `Repo.approvalCheck` is authoritative; the
166915
+ // `status_checks` input is DEPRECATED but still honoured, for the dormant installs the
166916
+ // backfill could not read (see `warnIfDeprecatedStatusChecks`). OR rather than override:
166917
+ // this can only ever turn the check ON, never off, so no existing user loses it.
166918
+ approvalCheck: repoSettings.approvalCheck || inputs.status_checks === "enabled",
166656
166919
  // temporary progress chrome. the workflow input is the source of truth when
166657
166920
  // set (mirrors `push`); otherwise the repo setting decides. defaults to true.
166658
166921
  progressComments: inputs.progress_comments === void 0 ? repoSettings.progressComments : inputs.progress_comments === "enabled",
@@ -167024,7 +167287,7 @@ async function resolveProxyModel(ctx) {
167024
167287
  if (ctx.oss) {
167025
167288
  ctx.toolState.modelClamped = { from: ctx.payload.model, reason: "oss" };
167026
167289
  log.info(
167027
- `\xBB ${ctx.payload.model} overridden \u2014 Pullfrog for OSS covers ${ctx.proxyModel}; add a provider key in your Pullfrog settings to run your configured model.`
167290
+ `\xBB ${ctx.payload.model} overridden \u2014 it is not one of the models Pullfrog for OSS funds, so this run uses ${ctx.proxyModel}; pick a funded model in your Pullfrog settings, or add a provider key to run your own.`
167028
167291
  );
167029
167292
  } else if (isCardGatedModel(ctx.payload.model)) {
167030
167293
  ctx.toolState.modelClamped = { from: ctx.payload.model, reason: "card" };
@@ -167226,6 +167489,7 @@ var defaultSettings = {
167226
167489
  repoIntelligence: false,
167227
167490
  progressComments: true,
167228
167491
  statusChecks: true,
167492
+ approvalCheck: false,
167229
167493
  modeInstructions: {},
167230
167494
  learnings: null,
167231
167495
  learningsHeadings: [],
@@ -167453,6 +167717,40 @@ function formatBillingExhaustedBody(diagnostic) {
167453
167717
  function isProviderModelNotFoundError(message) {
167454
167718
  return message.includes("ProviderModelNotFoundError");
167455
167719
  }
167720
+ function isContextOverflowError(message) {
167721
+ return /Prompt is too long/i.test(message) || /Input exceeds context window/i.test(message) || /maximum context length is \d+ tokens/i.test(message) || /Session too large to compact/i.test(message);
167722
+ }
167723
+ function isNoProviderAvailableError(message) {
167724
+ return /\bNo provider available\b/i.test(message);
167725
+ }
167726
+ function formatNoProviderAvailableSummary(input) {
167727
+ const settingsUrl = `${getApiUrl()}/console/${input.owner}/${input.name}`;
167728
+ return [
167729
+ "**The provider refused to serve this model.** It's listed in the catalog, but the account this run used has no access to it \u2014 so the request was accepted and then declined.",
167730
+ "",
167731
+ "This often happens when Pullfrog auto-selects a model your account can't reach. Pin an explicit model for this repo, or add credentials for the provider that was picked.",
167732
+ "",
167733
+ `[Model settings \u2192](${settingsUrl}) \xB7 [Setup docs \u2192](https://docs.pullfrog.com/keys) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`,
167734
+ "",
167735
+ `\`\`\`
167736
+ ${input.raw}
167737
+ \`\`\``
167738
+ ].join("\n");
167739
+ }
167740
+ function formatContextOverflowSummary(input) {
167741
+ const settingsUrl = `${getApiUrl()}/console/${input.owner}/${input.name}`;
167742
+ return [
167743
+ "**This run exceeded the model's context window.** Pullfrog read more than the model could hold, so it stopped before finishing.",
167744
+ "",
167745
+ `Pick a model with a larger context window, or split this PR into smaller ones and re-trigger.`,
167746
+ "",
167747
+ `[Model settings \u2192](${settingsUrl}) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`,
167748
+ "",
167749
+ `\`\`\`
167750
+ ${input.raw}
167751
+ \`\`\``
167752
+ ].join("\n");
167753
+ }
167456
167754
  function formatGenericFailure(errorMessage) {
167457
167755
  return [
167458
167756
  "Pullfrog ran into an unexpected error and couldn't finish this run. The underlying error is below \u2014 re-trigger Pullfrog to try again, and reach out to support if it keeps happening.",
@@ -167474,12 +167772,18 @@ var PROVIDER_BILLING_URLS = {
167474
167772
  anthropic: "https://console.anthropic.com/settings/billing",
167475
167773
  openai: "https://platform.openai.com/account/billing",
167476
167774
  google: "https://aistudio.google.com/usage",
167477
- opencode: "https://opencode.ai/zen"
167775
+ opencode: "https://opencode.ai/zen",
167776
+ xai: "https://console.x.ai/team/default/billing",
167777
+ openrouter: "https://openrouter.ai/settings/credits"
167478
167778
  };
167479
167779
  function detectProviderId(message) {
167480
167780
  const harnessId = extractProviderId(message);
167481
167781
  if (harnessId) return harnessId;
167482
167782
  if (/credit balance is too low/i.test(message)) return "anthropic";
167783
+ if (/used all available credits/i.test(message)) return "xai";
167784
+ if (/requires more credits|Key limit exceeded \(total limit\)|openrouter\.ai/i.test(message)) {
167785
+ return "openrouter";
167786
+ }
167483
167787
  return null;
167484
167788
  }
167485
167789
  function formatProviderBillingExhausted(input) {
@@ -167507,7 +167811,7 @@ ${input.raw}
167507
167811
  \`\`\``;
167508
167812
  }
167509
167813
  function renderRunError(input) {
167510
- const billingError = isRouterKeylimitExhaustedError(input.errorMessage) ? new BillingError(input.errorMessage, { code: "router_keylimit_exhausted" }) : null;
167814
+ const billingError = input.routerActive && isRouterKeylimitExhaustedError(input.errorMessage) ? new BillingError(input.errorMessage, { code: "router_keylimit_exhausted" }) : null;
167511
167815
  if (billingError) {
167512
167816
  const body = formatBillingErrorSummary(billingError, input.repo.owner);
167513
167817
  return { summary: body, comment: body };
@@ -167547,6 +167851,26 @@ ${body}`, comment: body };
167547
167851
  });
167548
167852
  return { summary: body, comment: body };
167549
167853
  }
167854
+ if (isNoProviderAvailableError(input.errorMessage)) {
167855
+ const body = formatNoProviderAvailableSummary({
167856
+ owner: input.repo.owner,
167857
+ name: input.repo.name,
167858
+ raw: input.errorMessage
167859
+ });
167860
+ return { summary: `### \u274C Pullfrog failed
167861
+
167862
+ ${body}`, comment: body };
167863
+ }
167864
+ if (isContextOverflowError(input.errorMessage)) {
167865
+ const body = formatContextOverflowSummary({
167866
+ owner: input.repo.owner,
167867
+ name: input.repo.name,
167868
+ raw: input.errorMessage
167869
+ });
167870
+ return { summary: `### \u274C Pullfrog failed
167871
+
167872
+ ${body}`, comment: body };
167873
+ }
167550
167874
  if (hangBody) {
167551
167875
  const isBillingExhausted = input.agentDiagnostic?.lastProviderError === "provider billing exhausted";
167552
167876
  return {
@@ -167927,7 +168251,8 @@ async function finalizeSuccessRun(input) {
167927
168251
  const rendered = !input.result.success ? renderRunError({
167928
168252
  errorMessage: input.result.error || "agent run failed",
167929
168253
  repo: input.repo,
167930
- agentDiagnostic: input.toolState.agentDiagnostic
168254
+ agentDiagnostic: input.toolState.agentDiagnostic,
168255
+ routerActive: !!input.toolContext.payload.proxyModel
167931
168256
  }) : null;
167932
168257
  if (rendered) {
167933
168258
  await reportErrorToComment({
@@ -168375,7 +168700,9 @@ async function main() {
168375
168700
  }
168376
168701
  if (access.kind === "proxy") payload.proxyModel = access.target;
168377
168702
  if (access.kind === "byok") payload.proxyModel = void 0;
168378
- if (runContext.oss && payload.proxyModel) payload.effort = 0;
168703
+ if (runContext.oss && payload.proxyModel) {
168704
+ payload.effort = ossEffortFloor({ payload });
168705
+ }
168379
168706
  const resolvedModel = payload.proxyModel ? void 0 : resolveModel({ slug: payload.model });
168380
168707
  vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
168381
168708
  const agent2 = resolveAgent({ model: resolvedModel });
@@ -168402,8 +168729,15 @@ async function main() {
168402
168729
  });
168403
168730
  timer.checkpoint("git");
168404
168731
  const pmSpec = await resolvePackageManagerSpec(process.cwd());
168405
- if (pmSpec) {
168406
- await ensurePackageManager({ spec: pmSpec, binDir: packageManagerBinDir(tmpdir4) });
168732
+ const pmDetected = await detect({ cwd: process.cwd(), strategies: ["lockfile"] });
168733
+ const pmName = pmSpec?.name ?? pmDetected?.name ?? "npm";
168734
+ if (payload.shell !== "disabled") {
168735
+ const pmError = await provisionPackageManager({
168736
+ name: pmName,
168737
+ declared: pmSpec,
168738
+ binDir: packageManagerBinDir(tmpdir4)
168739
+ });
168740
+ if (pmError) log.warning(`\xBB could not provision ${pmName}: ${pmError}`);
168407
168741
  }
168408
168742
  timer.checkpoint("packageManager");
168409
168743
  const setupHook = await executeLifecycleHook({
@@ -168683,7 +169017,8 @@ ${instructions.user}` : null,
168683
169017
  const rendered = renderRunError({
168684
169018
  errorMessage,
168685
169019
  repo: runContext.repo,
168686
- agentDiagnostic: toolState.agentDiagnostic
169020
+ agentDiagnostic: toolState.agentDiagnostic,
169021
+ routerActive: !!payload.proxyModel
168687
169022
  });
168688
169023
  await writeRunErrorOutputs({ rendered, toolState });
168689
169024
  if (toolContext) {
@@ -169718,7 +170053,7 @@ async function runCli4(input) {
169718
170053
  }
169719
170054
 
169720
170055
  // cli.ts
169721
- var VERSION10 = "0.1.51";
170056
+ var VERSION10 = "0.1.52";
169722
170057
  var bin = basename2(process.argv[1] || "");
169723
170058
  var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
169724
170059
  var rawArgs = process.argv.slice(2);
@@ -169821,6 +170156,7 @@ async function run3() {
169821
170156
  }
169822
170157
  try {
169823
170158
  await run3();
170159
+ process.exit(process.exitCode ?? 0);
169824
170160
  } catch (error49) {
169825
170161
  const message = error49 instanceof Error ? error49.message : String(error49);
169826
170162
  console.error(import_picocolors5.default.red(message));