pullfrog 0.1.50 → 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/index.js CHANGED
@@ -3598,9 +3598,9 @@ var require_constants2 = __commonJS({
3598
3598
  }
3599
3599
  })();
3600
3600
  var channel;
3601
- var structuredClone = globalThis.structuredClone ?? // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js
3601
+ var structuredClone2 = globalThis.structuredClone ?? // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js
3602
3602
  // structuredClone was added in v17.0.0, but fetch supports v16.8
3603
- function structuredClone2(value2, options = void 0) {
3603
+ function structuredClone3(value2, options = void 0) {
3604
3604
  if (arguments.length === 0) {
3605
3605
  throw new TypeError("missing argument");
3606
3606
  }
@@ -3614,7 +3614,7 @@ var require_constants2 = __commonJS({
3614
3614
  };
3615
3615
  module.exports = {
3616
3616
  DOMException: DOMException2,
3617
- structuredClone,
3617
+ structuredClone: structuredClone2,
3618
3618
  subresource,
3619
3619
  forbiddenMethods,
3620
3620
  requestBodyHeader,
@@ -5319,7 +5319,7 @@ var require_body = __commonJS({
5319
5319
  var { FormData: FormData2 } = require_formdata();
5320
5320
  var { kState } = require_symbols2();
5321
5321
  var { webidl } = require_webidl();
5322
- var { DOMException: DOMException2, structuredClone } = require_constants2();
5322
+ var { DOMException: DOMException2, structuredClone: structuredClone2 } = require_constants2();
5323
5323
  var { Blob: Blob2, File: NativeFile } = __require("buffer");
5324
5324
  var { kBodyUsed } = require_symbols();
5325
5325
  var assert3 = __require("assert");
@@ -5483,7 +5483,7 @@ Content-Type: ${value2.type || "application/octet-stream"}\r
5483
5483
  }
5484
5484
  function cloneBody(body) {
5485
5485
  const [out1, out2] = body.stream.tee();
5486
- const out2Clone = structuredClone(out2, { transfer: [out2] });
5486
+ const out2Clone = structuredClone2(out2, { transfer: [out2] });
5487
5487
  const [, finalClone] = out2Clone.tee();
5488
5488
  body.stream = out1;
5489
5489
  return {
@@ -19793,10 +19793,10 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
19793
19793
  (0, command_1.issueCommand)("error", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
19794
19794
  }
19795
19795
  exports.error = error49;
19796
- function warning2(message, properties = {}) {
19796
+ function warning3(message, properties = {}) {
19797
19797
  (0, command_1.issueCommand)("warning", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
19798
19798
  }
19799
- exports.warning = warning2;
19799
+ exports.warning = warning3;
19800
19800
  function notice(message, properties = {}) {
19801
19801
  (0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
19802
19802
  }
@@ -66407,7 +66407,7 @@ function initializeContext(params) {
66407
66407
  external: params?.external ?? void 0
66408
66408
  };
66409
66409
  }
66410
- function process2(schema2, ctx, _params = { path: [], schemaPath: [] }) {
66410
+ function process3(schema2, ctx, _params = { path: [], schemaPath: [] }) {
66411
66411
  var _a2;
66412
66412
  const def = schema2._zod.def;
66413
66413
  const seen = ctx.seen.get(schema2);
@@ -66444,7 +66444,7 @@ function process2(schema2, ctx, _params = { path: [], schemaPath: [] }) {
66444
66444
  if (parent) {
66445
66445
  if (!result.ref)
66446
66446
  result.ref = parent;
66447
- process2(parent, ctx, params);
66447
+ process3(parent, ctx, params);
66448
66448
  ctx.seen.get(parent).isParent = true;
66449
66449
  }
66450
66450
  }
@@ -66729,14 +66729,14 @@ var init_to_json_schema = __esm({
66729
66729
  init_registries();
66730
66730
  createToJSONSchemaMethod = (schema2, processors = {}) => (params) => {
66731
66731
  const ctx = initializeContext({ ...params, processors });
66732
- process2(schema2, ctx);
66732
+ process3(schema2, ctx);
66733
66733
  extractDefs(ctx, schema2);
66734
66734
  return finalize(ctx, schema2);
66735
66735
  };
66736
66736
  createStandardJSONSchemaMethod = (schema2, io, processors = {}) => (params) => {
66737
66737
  const { libraryOptions, target } = params ?? {};
66738
66738
  const ctx = initializeContext({ ...libraryOptions ?? {}, target, io, processors });
66739
- process2(schema2, ctx);
66739
+ process3(schema2, ctx);
66740
66740
  extractDefs(ctx, schema2);
66741
66741
  return finalize(ctx, schema2);
66742
66742
  };
@@ -66751,7 +66751,7 @@ function toJSONSchema(input, params) {
66751
66751
  const defs = {};
66752
66752
  for (const entry of registry4._idmap.entries()) {
66753
66753
  const [_, schema2] = entry;
66754
- process2(schema2, ctx2);
66754
+ process3(schema2, ctx2);
66755
66755
  }
66756
66756
  const schemas = {};
66757
66757
  const external = {
@@ -66774,7 +66774,7 @@ function toJSONSchema(input, params) {
66774
66774
  return { schemas };
66775
66775
  }
66776
66776
  const ctx = initializeContext({ ...params, processors: allProcessors });
66777
- process2(input, ctx);
66777
+ process3(input, ctx);
66778
66778
  extractDefs(ctx, input);
66779
66779
  return finalize(ctx, input);
66780
66780
  }
@@ -67034,7 +67034,7 @@ var init_json_schema_processors = __esm({
67034
67034
  if (typeof maximum === "number")
67035
67035
  json4.maxItems = maximum;
67036
67036
  json4.type = "array";
67037
- json4.items = process2(def.element, ctx, { ...params, path: [...params.path, "items"] });
67037
+ json4.items = process3(def.element, ctx, { ...params, path: [...params.path, "items"] });
67038
67038
  };
67039
67039
  objectProcessor = (schema2, ctx, _json, params) => {
67040
67040
  const json4 = _json;
@@ -67043,7 +67043,7 @@ var init_json_schema_processors = __esm({
67043
67043
  json4.properties = {};
67044
67044
  const shape = def.shape;
67045
67045
  for (const key in shape) {
67046
- json4.properties[key] = process2(shape[key], ctx, {
67046
+ json4.properties[key] = process3(shape[key], ctx, {
67047
67047
  ...params,
67048
67048
  path: [...params.path, "properties", key]
67049
67049
  });
@@ -67066,7 +67066,7 @@ var init_json_schema_processors = __esm({
67066
67066
  if (ctx.io === "output")
67067
67067
  json4.additionalProperties = false;
67068
67068
  } else if (def.catchall) {
67069
- json4.additionalProperties = process2(def.catchall, ctx, {
67069
+ json4.additionalProperties = process3(def.catchall, ctx, {
67070
67070
  ...params,
67071
67071
  path: [...params.path, "additionalProperties"]
67072
67072
  });
@@ -67075,7 +67075,7 @@ var init_json_schema_processors = __esm({
67075
67075
  unionProcessor = (schema2, ctx, json4, params) => {
67076
67076
  const def = schema2._zod.def;
67077
67077
  const isExclusive = def.inclusive === false;
67078
- const options = def.options.map((x, i) => process2(x, ctx, {
67078
+ const options = def.options.map((x, i) => process3(x, ctx, {
67079
67079
  ...params,
67080
67080
  path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
67081
67081
  }));
@@ -67087,11 +67087,11 @@ var init_json_schema_processors = __esm({
67087
67087
  };
67088
67088
  intersectionProcessor = (schema2, ctx, json4, params) => {
67089
67089
  const def = schema2._zod.def;
67090
- const a = process2(def.left, ctx, {
67090
+ const a = process3(def.left, ctx, {
67091
67091
  ...params,
67092
67092
  path: [...params.path, "allOf", 0]
67093
67093
  });
67094
- const b = process2(def.right, ctx, {
67094
+ const b = process3(def.right, ctx, {
67095
67095
  ...params,
67096
67096
  path: [...params.path, "allOf", 1]
67097
67097
  });
@@ -67108,11 +67108,11 @@ var init_json_schema_processors = __esm({
67108
67108
  json4.type = "array";
67109
67109
  const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
67110
67110
  const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
67111
- const prefixItems = def.items.map((x, i) => process2(x, ctx, {
67111
+ const prefixItems = def.items.map((x, i) => process3(x, ctx, {
67112
67112
  ...params,
67113
67113
  path: [...params.path, prefixPath, i]
67114
67114
  }));
67115
- const rest = def.rest ? process2(def.rest, ctx, {
67115
+ const rest = def.rest ? process3(def.rest, ctx, {
67116
67116
  ...params,
67117
67117
  path: [...params.path, restPath, ...ctx.target === "openapi-3.0" ? [def.items.length] : []]
67118
67118
  }) : null;
@@ -67152,7 +67152,7 @@ var init_json_schema_processors = __esm({
67152
67152
  const keyBag = keyType._zod.bag;
67153
67153
  const patterns = keyBag?.patterns;
67154
67154
  if (def.mode === "loose" && patterns && patterns.size > 0) {
67155
- const valueSchema = process2(def.valueType, ctx, {
67155
+ const valueSchema = process3(def.valueType, ctx, {
67156
67156
  ...params,
67157
67157
  path: [...params.path, "patternProperties", "*"]
67158
67158
  });
@@ -67162,12 +67162,12 @@ var init_json_schema_processors = __esm({
67162
67162
  }
67163
67163
  } else {
67164
67164
  if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
67165
- json4.propertyNames = process2(def.keyType, ctx, {
67165
+ json4.propertyNames = process3(def.keyType, ctx, {
67166
67166
  ...params,
67167
67167
  path: [...params.path, "propertyNames"]
67168
67168
  });
67169
67169
  }
67170
- json4.additionalProperties = process2(def.valueType, ctx, {
67170
+ json4.additionalProperties = process3(def.valueType, ctx, {
67171
67171
  ...params,
67172
67172
  path: [...params.path, "additionalProperties"]
67173
67173
  });
@@ -67182,7 +67182,7 @@ var init_json_schema_processors = __esm({
67182
67182
  };
67183
67183
  nullableProcessor = (schema2, ctx, json4, params) => {
67184
67184
  const def = schema2._zod.def;
67185
- const inner = process2(def.innerType, ctx, params);
67185
+ const inner = process3(def.innerType, ctx, params);
67186
67186
  const seen = ctx.seen.get(schema2);
67187
67187
  if (ctx.target === "openapi-3.0") {
67188
67188
  seen.ref = def.innerType;
@@ -67193,20 +67193,20 @@ var init_json_schema_processors = __esm({
67193
67193
  };
67194
67194
  nonoptionalProcessor = (schema2, ctx, _json, params) => {
67195
67195
  const def = schema2._zod.def;
67196
- process2(def.innerType, ctx, params);
67196
+ process3(def.innerType, ctx, params);
67197
67197
  const seen = ctx.seen.get(schema2);
67198
67198
  seen.ref = def.innerType;
67199
67199
  };
67200
67200
  defaultProcessor = (schema2, ctx, json4, params) => {
67201
67201
  const def = schema2._zod.def;
67202
- process2(def.innerType, ctx, params);
67202
+ process3(def.innerType, ctx, params);
67203
67203
  const seen = ctx.seen.get(schema2);
67204
67204
  seen.ref = def.innerType;
67205
67205
  json4.default = JSON.parse(JSON.stringify(def.defaultValue));
67206
67206
  };
67207
67207
  prefaultProcessor = (schema2, ctx, json4, params) => {
67208
67208
  const def = schema2._zod.def;
67209
- process2(def.innerType, ctx, params);
67209
+ process3(def.innerType, ctx, params);
67210
67210
  const seen = ctx.seen.get(schema2);
67211
67211
  seen.ref = def.innerType;
67212
67212
  if (ctx.io === "input")
@@ -67214,7 +67214,7 @@ var init_json_schema_processors = __esm({
67214
67214
  };
67215
67215
  catchProcessor = (schema2, ctx, json4, params) => {
67216
67216
  const def = schema2._zod.def;
67217
- process2(def.innerType, ctx, params);
67217
+ process3(def.innerType, ctx, params);
67218
67218
  const seen = ctx.seen.get(schema2);
67219
67219
  seen.ref = def.innerType;
67220
67220
  let catchValue;
@@ -67228,32 +67228,32 @@ var init_json_schema_processors = __esm({
67228
67228
  pipeProcessor = (schema2, ctx, _json, params) => {
67229
67229
  const def = schema2._zod.def;
67230
67230
  const innerType = ctx.io === "input" ? def.in._zod.def.type === "transform" ? def.out : def.in : def.out;
67231
- process2(innerType, ctx, params);
67231
+ process3(innerType, ctx, params);
67232
67232
  const seen = ctx.seen.get(schema2);
67233
67233
  seen.ref = innerType;
67234
67234
  };
67235
67235
  readonlyProcessor = (schema2, ctx, json4, params) => {
67236
67236
  const def = schema2._zod.def;
67237
- process2(def.innerType, ctx, params);
67237
+ process3(def.innerType, ctx, params);
67238
67238
  const seen = ctx.seen.get(schema2);
67239
67239
  seen.ref = def.innerType;
67240
67240
  json4.readOnly = true;
67241
67241
  };
67242
67242
  promiseProcessor = (schema2, ctx, _json, params) => {
67243
67243
  const def = schema2._zod.def;
67244
- process2(def.innerType, ctx, params);
67244
+ process3(def.innerType, ctx, params);
67245
67245
  const seen = ctx.seen.get(schema2);
67246
67246
  seen.ref = def.innerType;
67247
67247
  };
67248
67248
  optionalProcessor = (schema2, ctx, _json, params) => {
67249
67249
  const def = schema2._zod.def;
67250
- process2(def.innerType, ctx, params);
67250
+ process3(def.innerType, ctx, params);
67251
67251
  const seen = ctx.seen.get(schema2);
67252
67252
  seen.ref = def.innerType;
67253
67253
  };
67254
67254
  lazyProcessor = (schema2, ctx, _json, params) => {
67255
67255
  const innerType = schema2._zod.innerType;
67256
- process2(innerType, ctx, params);
67256
+ process3(innerType, ctx, params);
67257
67257
  const seen = ctx.seen.get(schema2);
67258
67258
  seen.ref = innerType;
67259
67259
  };
@@ -67359,7 +67359,7 @@ var init_json_schema_generator = __esm({
67359
67359
  * This must be called before emit().
67360
67360
  */
67361
67361
  process(schema2, _params = { path: [], schemaPath: [] }) {
67362
- return process2(schema2, this.ctx, _params);
67362
+ return process3(schema2, this.ctx, _params);
67363
67363
  }
67364
67364
  /**
67365
67365
  * Emit the final JSON Schema after processing.
@@ -67652,7 +67652,7 @@ __export(core_exports2, {
67652
67652
  parse: () => parse,
67653
67653
  parseAsync: () => parseAsync,
67654
67654
  prettifyError: () => prettifyError,
67655
- process: () => process2,
67655
+ process: () => process3,
67656
67656
  regexes: () => regexes_exports,
67657
67657
  registry: () => registry2,
67658
67658
  safeDecode: () => safeDecode,
@@ -99803,6 +99803,299 @@ import { existsSync as existsSync8, readdirSync as readdirSync2 } from "node:fs"
99803
99803
  import { readFile as readFile5 } from "node:fs/promises";
99804
99804
  import { join as join25 } from "node:path";
99805
99805
 
99806
+ // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/commands.mjs
99807
+ function dashDashArg(agent2, agentCommand) {
99808
+ return (args2) => {
99809
+ if (args2.length > 1) {
99810
+ return [agent2, agentCommand, args2[0], "--", ...args2.slice(1)];
99811
+ } else {
99812
+ return [agent2, agentCommand, args2[0]];
99813
+ }
99814
+ };
99815
+ }
99816
+ function denoExecute() {
99817
+ return (args2) => {
99818
+ return ["deno", "run", `npm:${args2[0]}`, ...args2.slice(1)];
99819
+ };
99820
+ }
99821
+ var npm = {
99822
+ "agent": ["npm", 0],
99823
+ "run": dashDashArg("npm", "run"),
99824
+ "install": ["npm", "i", 0],
99825
+ "frozen": ["npm", "ci", 0],
99826
+ "global": ["npm", "i", "-g", 0],
99827
+ "add": ["npm", "i", 0],
99828
+ "upgrade": ["npm", "update", 0],
99829
+ "upgrade-interactive": null,
99830
+ "dedupe": ["npm", "dedupe", 0],
99831
+ "execute": ["npx", 0],
99832
+ "execute-local": ["npx", 0],
99833
+ "uninstall": ["npm", "uninstall", 0],
99834
+ "global_uninstall": ["npm", "uninstall", "-g", 0]
99835
+ };
99836
+ var yarn = {
99837
+ "agent": ["yarn", 0],
99838
+ "run": ["yarn", "run", 0],
99839
+ "install": ["yarn", "install", 0],
99840
+ "frozen": ["yarn", "install", "--frozen-lockfile", 0],
99841
+ "global": ["yarn", "global", "add", 0],
99842
+ "add": ["yarn", "add", 0],
99843
+ "upgrade": ["yarn", "upgrade", 0],
99844
+ "upgrade-interactive": ["yarn", "upgrade-interactive", 0],
99845
+ "dedupe": null,
99846
+ "execute": ["npx", 0],
99847
+ "execute-local": dashDashArg("yarn", "exec"),
99848
+ "uninstall": ["yarn", "remove", 0],
99849
+ "global_uninstall": ["yarn", "global", "remove", 0]
99850
+ };
99851
+ var yarnBerry = {
99852
+ ...yarn,
99853
+ "frozen": ["yarn", "install", "--immutable", 0],
99854
+ "upgrade": ["yarn", "up", 0],
99855
+ "upgrade-interactive": ["yarn", "up", "-i", 0],
99856
+ "dedupe": ["yarn", "dedupe", 0],
99857
+ "execute": ["yarn", "dlx", 0],
99858
+ "execute-local": ["yarn", "exec", 0],
99859
+ // Yarn 2+ removed 'global', see https://github.com/yarnpkg/berry/issues/821
99860
+ "global": ["npm", "i", "-g", 0],
99861
+ "global_uninstall": ["npm", "uninstall", "-g", 0]
99862
+ };
99863
+ var pnpm = {
99864
+ "agent": ["pnpm", 0],
99865
+ "run": ["pnpm", "run", 0],
99866
+ "install": ["pnpm", "i", 0],
99867
+ "frozen": ["pnpm", "i", "--frozen-lockfile", 0],
99868
+ "global": ["pnpm", "add", "-g", 0],
99869
+ "add": ["pnpm", "add", 0],
99870
+ "upgrade": ["pnpm", "update", 0],
99871
+ "upgrade-interactive": ["pnpm", "update", "-i", 0],
99872
+ "dedupe": ["pnpm", "dedupe", 0],
99873
+ "execute": ["pnpm", "dlx", 0],
99874
+ "execute-local": ["pnpm", "exec", 0],
99875
+ "uninstall": ["pnpm", "remove", 0],
99876
+ "global_uninstall": ["pnpm", "remove", "--global", 0]
99877
+ };
99878
+ var bun = {
99879
+ "agent": ["bun", 0],
99880
+ "run": ["bun", "run", 0],
99881
+ "install": ["bun", "install", 0],
99882
+ "frozen": ["bun", "install", "--frozen-lockfile", 0],
99883
+ "global": ["bun", "add", "-g", 0],
99884
+ "add": ["bun", "add", 0],
99885
+ "upgrade": ["bun", "update", 0],
99886
+ "upgrade-interactive": ["bun", "update", "-i", 0],
99887
+ "dedupe": null,
99888
+ "execute": ["bun", "x", 0],
99889
+ "execute-local": ["bun", "x", 0],
99890
+ "uninstall": ["bun", "remove", 0],
99891
+ "global_uninstall": ["bun", "remove", "-g", 0]
99892
+ };
99893
+ var deno = {
99894
+ "agent": ["deno", 0],
99895
+ "run": ["deno", "task", 0],
99896
+ "install": ["deno", "install", 0],
99897
+ "frozen": ["deno", "install", "--frozen", 0],
99898
+ "global": ["deno", "install", "-g", 0],
99899
+ "add": ["deno", "add", 0],
99900
+ "upgrade": ["deno", "outdated", "--update", 0],
99901
+ "upgrade-interactive": ["deno", "outdated", "--update", 0],
99902
+ "dedupe": null,
99903
+ "execute": denoExecute(),
99904
+ "execute-local": ["deno", "task", "--eval", 0],
99905
+ "uninstall": ["deno", "remove", 0],
99906
+ "global_uninstall": ["deno", "uninstall", "-g", 0]
99907
+ };
99908
+ var COMMANDS = {
99909
+ "npm": npm,
99910
+ "yarn": yarn,
99911
+ "yarn@berry": yarnBerry,
99912
+ "pnpm": pnpm,
99913
+ // pnpm v6.x or below
99914
+ "pnpm@6": {
99915
+ ...pnpm,
99916
+ run: dashDashArg("pnpm", "run")
99917
+ },
99918
+ "bun": bun,
99919
+ "deno": deno
99920
+ };
99921
+ function resolveCommand(agent2, command, args2) {
99922
+ const value2 = COMMANDS[agent2][command];
99923
+ return constructCommand(value2, args2);
99924
+ }
99925
+ function constructCommand(value2, args2) {
99926
+ if (value2 == null)
99927
+ return null;
99928
+ const list = typeof value2 === "function" ? value2(args2) : value2.flatMap((v) => {
99929
+ if (typeof v === "number")
99930
+ return args2;
99931
+ return [v];
99932
+ });
99933
+ return {
99934
+ command: list[0],
99935
+ args: list.slice(1)
99936
+ };
99937
+ }
99938
+
99939
+ // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/constants.mjs
99940
+ var AGENTS = [
99941
+ "npm",
99942
+ "yarn",
99943
+ "yarn@berry",
99944
+ "pnpm",
99945
+ "pnpm@6",
99946
+ "bun",
99947
+ "deno"
99948
+ ];
99949
+ var LOCKS = {
99950
+ "bun.lock": "bun",
99951
+ "bun.lockb": "bun",
99952
+ "deno.lock": "deno",
99953
+ "pnpm-lock.yaml": "pnpm",
99954
+ "pnpm-workspace.yaml": "pnpm",
99955
+ "yarn.lock": "yarn",
99956
+ "package-lock.json": "npm",
99957
+ "npm-shrinkwrap.json": "npm"
99958
+ };
99959
+ var INSTALL_METADATA = {
99960
+ "node_modules/.deno/": "deno",
99961
+ "node_modules/.pnpm/": "pnpm",
99962
+ "node_modules/.yarn-state.yml": "yarn",
99963
+ // yarn v2+ (node-modules)
99964
+ "node_modules/.yarn_integrity": "yarn",
99965
+ // yarn v1
99966
+ "node_modules/.package-lock.json": "npm",
99967
+ ".pnp.cjs": "yarn",
99968
+ // yarn v3+ (pnp)
99969
+ ".pnp.js": "yarn",
99970
+ // yarn v2 (pnp)
99971
+ "bun.lock": "bun",
99972
+ "bun.lockb": "bun"
99973
+ };
99974
+
99975
+ // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/detect.mjs
99976
+ import fs from "node:fs/promises";
99977
+ import path from "node:path";
99978
+ import process2 from "node:process";
99979
+ async function pathExists(path22, type2) {
99980
+ try {
99981
+ const stat = await fs.stat(path22);
99982
+ return type2 === "file" ? stat.isFile() : stat.isDirectory();
99983
+ } catch {
99984
+ return false;
99985
+ }
99986
+ }
99987
+ function* lookup(cwd = process2.cwd()) {
99988
+ let directory = path.resolve(cwd);
99989
+ const { root } = path.parse(directory);
99990
+ while (directory && directory !== root) {
99991
+ yield directory;
99992
+ directory = path.dirname(directory);
99993
+ }
99994
+ }
99995
+ async function parsePackageJson(filepath, options) {
99996
+ if (!filepath || !await pathExists(filepath, "file"))
99997
+ return null;
99998
+ return await handlePackageManager(filepath, options);
99999
+ }
100000
+ async function detect(options = {}) {
100001
+ const {
100002
+ cwd,
100003
+ strategies = ["lockfile", "packageManager-field", "devEngines-field"]
100004
+ } = options;
100005
+ let stopDir;
100006
+ if (typeof options.stopDir === "string") {
100007
+ const resolved = path.resolve(options.stopDir);
100008
+ stopDir = (dir) => dir === resolved;
100009
+ } else {
100010
+ stopDir = options.stopDir;
100011
+ }
100012
+ for (const directory of lookup(cwd)) {
100013
+ for (const strategy of strategies) {
100014
+ switch (strategy) {
100015
+ case "lockfile": {
100016
+ for (const lock of Object.keys(LOCKS)) {
100017
+ if (await pathExists(path.join(directory, lock), "file")) {
100018
+ const name = LOCKS[lock];
100019
+ const result = await parsePackageJson(path.join(directory, "package.json"), options);
100020
+ if (result)
100021
+ return result;
100022
+ else
100023
+ return { name, agent: name };
100024
+ }
100025
+ }
100026
+ break;
100027
+ }
100028
+ case "packageManager-field":
100029
+ case "devEngines-field": {
100030
+ const result = await parsePackageJson(path.join(directory, "package.json"), options);
100031
+ if (result)
100032
+ return result;
100033
+ break;
100034
+ }
100035
+ case "install-metadata": {
100036
+ for (const metadata of Object.keys(INSTALL_METADATA)) {
100037
+ const fileOrDir = metadata.endsWith("/") ? "dir" : "file";
100038
+ if (await pathExists(path.join(directory, metadata), fileOrDir)) {
100039
+ const name = INSTALL_METADATA[metadata];
100040
+ const agent2 = name === "yarn" ? isMetadataYarnClassic(metadata) ? "yarn" : "yarn@berry" : name;
100041
+ return { name, agent: agent2 };
100042
+ }
100043
+ }
100044
+ break;
100045
+ }
100046
+ }
100047
+ }
100048
+ if (stopDir?.(directory))
100049
+ break;
100050
+ }
100051
+ return null;
100052
+ }
100053
+ function getNameAndVer(pkg) {
100054
+ const handelVer = (version3) => version3?.match(/\d+(\.\d+){0,2}/)?.[0] ?? version3;
100055
+ if (typeof pkg.packageManager === "string") {
100056
+ const [name, ver] = pkg.packageManager.replace(/^\^/, "").split("@");
100057
+ return { name, ver: handelVer(ver) };
100058
+ }
100059
+ if (typeof pkg.devEngines?.packageManager?.name === "string") {
100060
+ return {
100061
+ name: pkg.devEngines.packageManager.name,
100062
+ ver: handelVer(pkg.devEngines.packageManager.version)
100063
+ };
100064
+ }
100065
+ return void 0;
100066
+ }
100067
+ async function handlePackageManager(filepath, options) {
100068
+ try {
100069
+ const content = await fs.readFile(filepath, "utf8");
100070
+ const pkg = options.packageJsonParser ? await options.packageJsonParser(content, filepath) : JSON.parse(content);
100071
+ let agent2;
100072
+ const nameAndVer = getNameAndVer(pkg);
100073
+ if (nameAndVer) {
100074
+ const name = nameAndVer.name;
100075
+ const ver = nameAndVer.ver;
100076
+ let version3 = ver;
100077
+ if (name === "yarn" && ver && Number.parseInt(ver) > 1) {
100078
+ agent2 = "yarn@berry";
100079
+ version3 = "berry";
100080
+ return { name, agent: agent2, version: version3 };
100081
+ } else if (name === "pnpm" && ver && Number.parseInt(ver) < 7) {
100082
+ agent2 = "pnpm@6";
100083
+ return { name, agent: agent2, version: version3 };
100084
+ } else if (AGENTS.includes(name)) {
100085
+ agent2 = name;
100086
+ return { name, agent: agent2, version: version3 };
100087
+ } else {
100088
+ return options.onUnknown?.(pkg.packageManager) ?? null;
100089
+ }
100090
+ }
100091
+ } catch {
100092
+ }
100093
+ return null;
100094
+ }
100095
+ function isMetadataYarnClassic(metadataPath) {
100096
+ return metadataPath.endsWith(".yarn_integrity");
100097
+ }
100098
+
99806
100099
  // agents/claude.ts
99807
100100
  import { execFileSync as execFileSync2 } from "node:child_process";
99808
100101
  import { chmodSync as chmodSync2, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "node:fs";
@@ -99838,6 +100131,12 @@ function resolveRung(params) {
99838
100131
  const clamped = Math.min(1, Math.max(0, params.position));
99839
100132
  return rungs[Math.floor(clamped * (rungs.length - 1))];
99840
100133
  }
100134
+ function rungPosition(params) {
100135
+ const rungs = offeredRungs(params.published);
100136
+ const index = rungs.indexOf(params.rung);
100137
+ if (index === -1) return void 0;
100138
+ return rungs.length > 1 ? index / (rungs.length - 1) : 0;
100139
+ }
99841
100140
 
99842
100141
  // models.ts
99843
100142
  function provider(config3) {
@@ -99891,7 +100190,11 @@ var providers = {
99891
100190
  envVars: ["OPENAI_API_KEY"],
99892
100191
  managedCredentials: ["CODEX_AUTH_JSON"],
99893
100192
  models: {
99894
- gpt: {
100193
+ // Sol/Terra/Luna are OpenAI's durable capability tiers, so they ARE the
100194
+ // brand-tier names the slug convention asks for — the pre-5.6 `gpt` /
100195
+ // `gpt-pro` / `gpt-mini` slugs are holdovers from the retired GPT / GPT Pro
100196
+ // / GPT Mini tiering and are carried below as deprecated aliases.
100197
+ "gpt-sol": {
99895
100198
  displayName: "GPT Sol",
99896
100199
  resolve: "openai/gpt-5.6-sol",
99897
100200
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
@@ -99902,24 +100205,23 @@ var providers = {
99902
100205
  // Sol served at reasoning.mode=pro — same $/token as Sol, just more tokens
99903
100206
  // burned; not a pricier premium tier. models.dev has no -pro id, so direct-key
99904
100207
  // (BYOK) resolves to plain Sol; only the Router/OpenRouter path gets sol-pro.
99905
- "gpt-pro": {
100208
+ "gpt-sol-pro": {
99906
100209
  displayName: "GPT Sol Pro",
99907
100210
  description: "Maximum reasoning effort",
99908
100211
  resolve: "openai/gpt-5.6-sol",
99909
100212
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
99910
100213
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
99911
- subagentModel: "gpt"
100214
+ subagentModel: "gpt-sol"
99912
100215
  },
99913
- // gpt-5.6's balanced mid-tier (Sol/Terra/Luna are durable capability tiers,
99914
- // not version bumps). selectable on its own and doubles as `gpt`'s cheaper
99915
- // lens-fanout subagent — replaces the old hidden gpt-5.4 subagent target.
100216
+ // gpt-5.6's balanced mid-tier. selectable on its own and doubles as Sol's
100217
+ // cheaper lens-fanout subagent replaces the old hidden gpt-5.4 target.
99916
100218
  "gpt-terra": {
99917
100219
  displayName: "GPT Terra",
99918
100220
  resolve: "openai/gpt-5.6-terra",
99919
100221
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
99920
100222
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
99921
100223
  },
99922
- "gpt-mini": {
100224
+ "gpt-luna": {
99923
100225
  displayName: "GPT Luna",
99924
100226
  resolve: "openai/gpt-5.6-luna",
99925
100227
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
@@ -99934,20 +100236,40 @@ var providers = {
99934
100236
  displayName: "GPT Codex",
99935
100237
  resolve: "openai/gpt-5.3-codex",
99936
100238
  openRouterResolve: "openrouter/openai/gpt-5.3-codex",
99937
- fallback: "openai/gpt"
100239
+ fallback: "openai/gpt-sol"
99938
100240
  },
99939
100241
  "gpt-codex-mini": {
99940
100242
  displayName: "GPT Codex Mini",
99941
100243
  resolve: "openai/gpt-5.1-codex-mini",
99942
100244
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
99943
- fallback: "openai/gpt-mini"
100245
+ fallback: "openai/gpt-luna"
99944
100246
  },
99945
- // dropped hidden subagent tier folds stored pins forward to gpt (Sol).
100247
+ // pre-5.6 tier slugs. the tiers themselves were renamed Sol/Sol Pro/Luna,
100248
+ // so these fold forward rather than describing anything that still runs.
100249
+ gpt: {
100250
+ displayName: "GPT",
100251
+ resolve: "openai/gpt-5.6-sol",
100252
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100253
+ fallback: "openai/gpt-sol"
100254
+ },
100255
+ "gpt-pro": {
100256
+ displayName: "GPT Pro",
100257
+ resolve: "openai/gpt-5.6-sol",
100258
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100259
+ fallback: "openai/gpt-sol-pro"
100260
+ },
100261
+ "gpt-mini": {
100262
+ displayName: "GPT Mini",
100263
+ resolve: "openai/gpt-5.6-luna",
100264
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna",
100265
+ fallback: "openai/gpt-luna"
100266
+ },
100267
+ // dropped hidden subagent tier — folds stored pins forward to Sol.
99946
100268
  "gpt-5.4": {
99947
100269
  displayName: "GPT 5.4",
99948
100270
  resolve: "openai/gpt-5.4",
99949
100271
  openRouterResolve: "openrouter/openai/gpt-5.4",
99950
- fallback: "openai/gpt"
100272
+ fallback: "openai/gpt-sol"
99951
100273
  },
99952
100274
  o3: {
99953
100275
  displayName: "O3",
@@ -100023,12 +100345,20 @@ var providers = {
100023
100345
  openRouterResolve: "openrouter/deepseek/deepseek-v4-pro",
100024
100346
  preferred: true
100025
100347
  },
100348
+ // DeepSeek upgraded the `deepseek-v4-flash` API model in place to the
100349
+ // 0731 release, but OpenRouter forked it into a separate `-0731` id and
100350
+ // left the April preview live at a HIGHER price — so the direct
100351
+ // `resolve` needs no version and the OpenRouter route must be pinned.
100352
+ // 0731 publishes a DIFFERENT OpenRouter ladder to both the April preview
100353
+ // and Pro (`high, xhigh`) — it gained a `low` rung and renamed the top to
100354
+ // `max`. that makes `low`, not `high`, position 0 on this route, which is
100355
+ // why the OSS effort floor in `main.ts` pins the `high` rung by name.
100026
100356
  "deepseek-flash": {
100027
100357
  displayName: "DeepSeek Flash",
100028
100358
  resolve: "deepseek/deepseek-v4-flash",
100029
100359
  effort: ["high", "max"],
100030
- openRouterEffort: ["high", "xhigh"],
100031
- openRouterResolve: "openrouter/deepseek/deepseek-v4-flash"
100360
+ openRouterEffort: ["low", "high", "max"],
100361
+ openRouterResolve: "openrouter/deepseek/deepseek-v4-flash-0731"
100032
100362
  },
100033
100363
  // legacy aliases — deepseek retires these on 2026-07-24; transparently
100034
100364
  // upgrade existing users to the v4 family via the fallback chain.
@@ -100097,30 +100427,30 @@ var providers = {
100097
100427
  resolve: "opencode/claude-haiku-4-5",
100098
100428
  openRouterResolve: "openrouter/anthropic/claude-haiku-4.5"
100099
100429
  },
100100
- gpt: {
100430
+ "gpt-sol": {
100101
100431
  displayName: "GPT Sol",
100102
100432
  resolve: "opencode/gpt-5.6-sol",
100103
100433
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100104
100434
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100105
100435
  subagentModel: "gpt-terra"
100106
100436
  },
100107
- // see openai/gpt-pro — Zen has no -pro id, so direct resolves to plain Sol.
100108
- "gpt-pro": {
100437
+ // see openai/gpt-sol-pro — Zen has no -pro id, so direct resolves to plain Sol.
100438
+ "gpt-sol-pro": {
100109
100439
  displayName: "GPT Sol Pro",
100110
100440
  description: "Maximum reasoning effort",
100111
100441
  resolve: "opencode/gpt-5.6-sol",
100112
100442
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100113
100443
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100114
- subagentModel: "gpt"
100444
+ subagentModel: "gpt-sol"
100115
100445
  },
100116
- // gpt-5.6 balanced mid-tier — selectable + `gpt`'s subagent. see openai above.
100446
+ // gpt-5.6 balanced mid-tier — selectable + Sol's subagent. see openai above.
100117
100447
  "gpt-terra": {
100118
100448
  displayName: "GPT Terra",
100119
100449
  resolve: "opencode/gpt-5.6-terra",
100120
100450
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100121
100451
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
100122
100452
  },
100123
- "gpt-mini": {
100453
+ "gpt-luna": {
100124
100454
  displayName: "GPT Luna",
100125
100455
  resolve: "opencode/gpt-5.6-luna",
100126
100456
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
@@ -100131,20 +100461,39 @@ var providers = {
100131
100461
  displayName: "GPT Codex",
100132
100462
  resolve: "opencode/gpt-5.3-codex",
100133
100463
  openRouterResolve: "openrouter/openai/gpt-5.3-codex",
100134
- fallback: "opencode/gpt"
100464
+ fallback: "opencode/gpt-sol"
100135
100465
  },
100136
100466
  "gpt-codex-mini": {
100137
100467
  displayName: "GPT Codex Mini",
100138
100468
  resolve: "opencode/gpt-5.1-codex-mini",
100139
100469
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
100140
- fallback: "opencode/gpt-mini"
100470
+ fallback: "opencode/gpt-luna"
100471
+ },
100472
+ // pre-5.6 tier slugs — see openai provider above.
100473
+ gpt: {
100474
+ displayName: "GPT",
100475
+ resolve: "opencode/gpt-5.6-sol",
100476
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100477
+ fallback: "opencode/gpt-sol"
100141
100478
  },
100142
- // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
100479
+ "gpt-pro": {
100480
+ displayName: "GPT Pro",
100481
+ resolve: "opencode/gpt-5.6-sol",
100482
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100483
+ fallback: "opencode/gpt-sol-pro"
100484
+ },
100485
+ "gpt-mini": {
100486
+ displayName: "GPT Mini",
100487
+ resolve: "opencode/gpt-5.6-luna",
100488
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna",
100489
+ fallback: "opencode/gpt-luna"
100490
+ },
100491
+ // dropped hidden subagent tier — folds stored pins forward to Sol.
100143
100492
  "gpt-5.4": {
100144
100493
  displayName: "GPT 5.4",
100145
100494
  resolve: "opencode/gpt-5.4",
100146
100495
  openRouterResolve: "openrouter/openai/gpt-5.4",
100147
- fallback: "opencode/gpt"
100496
+ fallback: "opencode/gpt-sol"
100148
100497
  },
100149
100498
  "gemini-pro": {
100150
100499
  displayName: "Gemini Pro",
@@ -100300,30 +100649,30 @@ var providers = {
100300
100649
  // alias): after the Sol/Terra/Luna rename, ~gpt-mini-latest no longer maps
100301
100650
  // to Luna, so rolling aliases would silently diverge `gpt`/`gpt-mini` from
100302
100651
  // the chosen tiers across funding paths.
100303
- gpt: {
100652
+ "gpt-sol": {
100304
100653
  displayName: "GPT Sol",
100305
100654
  resolve: "openrouter/openai/gpt-5.6-sol",
100306
100655
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100307
100656
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100308
100657
  subagentModel: "gpt-terra"
100309
100658
  },
100310
- // see openai/gpt-pro. openrouter serves sol-pro directly on both routes.
100311
- "gpt-pro": {
100659
+ // see openai/gpt-sol-pro. openrouter serves sol-pro directly on both routes.
100660
+ "gpt-sol-pro": {
100312
100661
  displayName: "GPT Sol Pro",
100313
100662
  description: "Maximum reasoning effort",
100314
100663
  resolve: "openrouter/openai/gpt-5.6-sol-pro",
100315
100664
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100316
100665
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100317
- subagentModel: "gpt"
100666
+ subagentModel: "gpt-sol"
100318
100667
  },
100319
- // gpt-5.6 balanced mid-tier — selectable + `gpt`'s subagent. see openai above.
100668
+ // gpt-5.6 balanced mid-tier — selectable + Sol's subagent. see openai above.
100320
100669
  "gpt-terra": {
100321
100670
  displayName: "GPT Terra",
100322
100671
  resolve: "openrouter/openai/gpt-5.6-terra",
100323
100672
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100324
100673
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
100325
100674
  },
100326
- "gpt-mini": {
100675
+ "gpt-luna": {
100327
100676
  displayName: "GPT Luna",
100328
100677
  resolve: "openrouter/openai/gpt-5.6-luna",
100329
100678
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
@@ -100334,20 +100683,39 @@ var providers = {
100334
100683
  displayName: "GPT Codex",
100335
100684
  resolve: "openrouter/openai/gpt-5.3-codex",
100336
100685
  openRouterResolve: "openrouter/openai/gpt-5.3-codex",
100337
- fallback: "openrouter/gpt"
100686
+ fallback: "openrouter/gpt-sol"
100338
100687
  },
100339
100688
  "gpt-codex-mini": {
100340
100689
  displayName: "GPT Codex Mini",
100341
100690
  resolve: "openrouter/openai/gpt-5.1-codex-mini",
100342
100691
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
100343
- fallback: "openrouter/gpt-mini"
100692
+ fallback: "openrouter/gpt-luna"
100693
+ },
100694
+ // pre-5.6 tier slugs — see openai provider above.
100695
+ gpt: {
100696
+ displayName: "GPT",
100697
+ resolve: "openrouter/openai/gpt-5.6-sol",
100698
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100699
+ fallback: "openrouter/gpt-sol"
100700
+ },
100701
+ "gpt-pro": {
100702
+ displayName: "GPT Pro",
100703
+ resolve: "openrouter/openai/gpt-5.6-sol-pro",
100704
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100705
+ fallback: "openrouter/gpt-sol-pro"
100344
100706
  },
100345
- // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
100707
+ "gpt-mini": {
100708
+ displayName: "GPT Mini",
100709
+ resolve: "openrouter/openai/gpt-5.6-luna",
100710
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna",
100711
+ fallback: "openrouter/gpt-luna"
100712
+ },
100713
+ // dropped hidden subagent tier — folds stored pins forward to Sol.
100346
100714
  "gpt-5.4": {
100347
100715
  displayName: "GPT 5.4",
100348
100716
  resolve: "openrouter/openai/gpt-5.4",
100349
100717
  openRouterResolve: "openrouter/openai/gpt-5.4",
100350
- fallback: "openrouter/gpt"
100718
+ fallback: "openrouter/gpt-sol"
100351
100719
  },
100352
100720
  "o4-mini": {
100353
100721
  displayName: "O4 Mini",
@@ -100382,9 +100750,9 @@ var providers = {
100382
100750
  },
100383
100751
  "deepseek-flash": {
100384
100752
  displayName: "DeepSeek Flash",
100385
- resolve: "openrouter/deepseek/deepseek-v4-flash",
100386
- effort: ["high", "xhigh"],
100387
- openRouterResolve: "openrouter/deepseek/deepseek-v4-flash"
100753
+ resolve: "openrouter/deepseek/deepseek-v4-flash-0731",
100754
+ effort: ["low", "high", "max"],
100755
+ openRouterResolve: "openrouter/deepseek/deepseek-v4-flash-0731"
100388
100756
  },
100389
100757
  // legacy alias — deepseek retires this on 2026-07-24; transparently
100390
100758
  // upgrade existing users to the v4 family via the fallback chain.
@@ -100465,7 +100833,7 @@ var modelAliases = Object.entries(providers).flatMap(
100465
100833
  var AUTO_EFFICIENT = "auto/efficient";
100466
100834
  var AUTO_INTELLIGENT = "auto/intelligent";
100467
100835
  var AUTO_TIER_TARGET = {
100468
- [AUTO_EFFICIENT]: "deepseek/deepseek-pro",
100836
+ [AUTO_EFFICIENT]: "deepseek/deepseek-flash",
100469
100837
  [AUTO_INTELLIGENT]: "anthropic/claude-opus"
100470
100838
  };
100471
100839
  function isAutoTier(slug2) {
@@ -100514,6 +100882,26 @@ if (!defaultProxyAlias?.openRouterResolve) {
100514
100882
  }
100515
100883
  var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
100516
100884
  var defaultProxyDisplayName = defaultProxyAlias.displayName;
100885
+ var OSS_MODEL_ALLOWLIST = [
100886
+ "deepseek/deepseek-flash",
100887
+ "deepseek/deepseek-pro",
100888
+ "openai/gpt-luna",
100889
+ "openrouter/minimax-m2.5",
100890
+ "moonshotai/kimi-k2"
100891
+ ];
100892
+ var OSS_RECOMMENDED_MODEL = AUTO_TIER_TARGET[AUTO_EFFICIENT];
100893
+ var ossAllowedTargets = new Set(
100894
+ OSS_MODEL_ALLOWLIST.map((slug2) => {
100895
+ const target = resolveOpenRouterModel(slug2);
100896
+ if (!target) throw new Error(`OSS_MODEL_ALLOWLIST: ${slug2} has no openRouterResolve`);
100897
+ return target;
100898
+ })
100899
+ );
100900
+ function isOssAllowedModel(slug2) {
100901
+ if (!slug2) return false;
100902
+ const target = resolveOpenRouterModel(slug2);
100903
+ return target !== void 0 && ossAllowedTargets.has(target);
100904
+ }
100517
100905
  var BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
100518
100906
  var VERTEX_MODEL_ID_ENV = "VERTEX_MODEL_ID";
100519
100907
  var OPENAI_COMPATIBLE_PROVIDER = "openai-compatible";
@@ -100547,7 +100935,7 @@ function hasSimilarIssues(params) {
100547
100935
 
100548
100936
  // utils/activity.ts
100549
100937
  import { performance as performance2 } from "node:perf_hooks";
100550
- function isMonitorDebugEnabled() {
100938
+ function isDebugEnabled() {
100551
100939
  return process.env.ACTIONS_STEP_DEBUG === "true" || process.env.RUNNER_DEBUG === "1" || process.env.LOG_LEVEL === "debug";
100552
100940
  }
100553
100941
  var DEFAULT_ACTIVITY_TIMEOUT_MS = 3e5;
@@ -100596,7 +100984,7 @@ function startProcessOutputMonitor(ctx) {
100596
100984
  process.stdout.write = wrapWrite(originalStdoutWrite, markActivity);
100597
100985
  process.stderr.write = wrapWrite(originalStderrWrite, markActivity);
100598
100986
  const debugBypass = (msg) => {
100599
- if (!isMonitorDebugEnabled()) return;
100987
+ if (!isDebugEnabled()) return;
100600
100988
  originalStdoutWrite(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] ${msg}
100601
100989
  `);
100602
100990
  };
@@ -100805,7 +101193,6 @@ function prefixPlain(name) {
100805
101193
  }
100806
101194
  var isRunnerDebugEnabled = () => core.isDebug();
100807
101195
  var isLocalDebugEnabled = () => process.env.LOG_LEVEL === "debug" || process.env.ACTIONS_STEP_DEBUG === "true";
100808
- var isDebugEnabled = () => isLocalDebugEnabled() || isRunnerDebugEnabled();
100809
101196
  function ts() {
100810
101197
  return isDebugEnabled() ? `[${(/* @__PURE__ */ new Date()).toISOString()}] ` : "";
100811
101198
  }
@@ -101120,7 +101507,21 @@ var PROVIDER_ERROR_PATTERNS = [
101120
101507
  { regex: /\bFreeUsageLimitError\b/, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101121
101508
  { regex: /Insufficient balance/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101122
101509
  { regex: /credit balance is too low/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101123
- { regex: /spending cap/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101510
+ // "spending cap" (Gemini) and "spending limit" (xAI, #1076) are the same
101511
+ // condition in two house styles — a configured ceiling was reached.
101512
+ { regex: /spending (?:cap|limit)/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101513
+ // xAI exhausts credits and the monthly ceiling in one 403 whose status code
101514
+ // sits nowhere near a `status:` key, so no status pattern below fires (#1076).
101515
+ { regex: /used all available credits/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101516
+ // the OpenRouter shapes `isRouterKeylimitExhaustedError` matches. on a Router
101517
+ // run those mean the PULLFROG wallet is empty and `renderRunError` returns a
101518
+ // `BillingError` before ever reaching this list; on a BYOK run the very same
101519
+ // wire text means the user's OWN OpenRouter wallet is empty, and this entry is
101520
+ // what gives them the right dashboard instead of ours. see #1135.
101521
+ {
101522
+ regex: /requires more credits|Key limit exceeded \(total limit\)/i,
101523
+ label: PROVIDER_BILLING_EXHAUSTED_LABEL
101524
+ },
101124
101525
  // auth patterns must come BEFORE rate-limit patterns. OpenRouter 401 error
101125
101526
  // payloads carry `x-ratelimit-*` response headers in the dump, and the
101126
101527
  // free-form rate-limit regex below would otherwise win on word-boundary
@@ -101216,6 +101617,12 @@ function resolveRunAlias(ctx) {
101216
101617
  if (!model) return void 0;
101217
101618
  return modelAliases.find((a) => !a.fallback && a.resolve === model) ?? matchHostedAnthropicAlias(model);
101218
101619
  }
101620
+ function ossEffortFloor(ctx) {
101621
+ const alias = resolveRunAlias(ctx);
101622
+ const published = alias?.openRouterEffort ?? alias?.effort;
101623
+ if (!published) return 0;
101624
+ return rungPosition({ rung: "high", published }) ?? 0;
101625
+ }
101219
101626
  function resolveRunEffort(ctx) {
101220
101627
  const configured = ctx.payload.effort !== void 0;
101221
101628
  const position = ctx.payload.effort ?? DEFAULT_EFFORT_POSITION;
@@ -101246,7 +101653,7 @@ var import_semver = __toESM(require_semver2(), 1);
101246
101653
  // package.json
101247
101654
  var package_default = {
101248
101655
  name: "pullfrog",
101249
- version: "0.1.50",
101656
+ version: "0.1.52",
101250
101657
  type: "module",
101251
101658
  bin: {
101252
101659
  pullfrog: "dist/cli.mjs",
@@ -108903,6 +109310,41 @@ function bootstrapPullfrogDataDir() {
108903
109310
  }
108904
109311
  }
108905
109312
 
109313
+ // utils/worktree.ts
109314
+ async function dirtyTrackedPaths() {
109315
+ const result = await spawn({
109316
+ cmd: "git",
109317
+ args: ["diff", "--name-only", "HEAD"],
109318
+ env: process.env,
109319
+ activityTimeout: 0
109320
+ });
109321
+ if (result.exitCode !== 0) {
109322
+ throw new Error(
109323
+ `git diff --name-only HEAD failed (exit ${result.exitCode}): ${result.stderr.trim() || "(no stderr)"}`
109324
+ );
109325
+ }
109326
+ return new Set(result.stdout.split("\n").filter(Boolean));
109327
+ }
109328
+ async function restoreDirtiedSince(params) {
109329
+ const dirtied = [...await dirtyTrackedPaths()].filter((path4) => !params.before.has(path4));
109330
+ if (dirtied.length === 0) return;
109331
+ const result = await spawn({
109332
+ cmd: "git",
109333
+ args: ["restore", "--staged", "--worktree", "--", ...dirtied],
109334
+ env: process.env,
109335
+ activityTimeout: 0
109336
+ });
109337
+ if (result.exitCode !== 0) {
109338
+ log.warning(
109339
+ `\xBB failed to restore ${dirtied.length} tracked file(s) modified by ${params.actor}: ${result.stderr.trim() || "(no stderr)"}`
109340
+ );
109341
+ return;
109342
+ }
109343
+ log.info(
109344
+ `\xBB restored ${dirtied.length} tracked file(s) modified by ${params.actor}: ${dirtied.join(", ")}`
109345
+ );
109346
+ }
109347
+
108906
109348
  // agents/opencodePlugin.ts
108907
109349
  var PULLFROG_BUS_EVENT_TYPE = "pullfrog_bus_event";
108908
109350
  var PULLFROG_OPENCODE_GATE_PLUGIN_FILENAME = "pullfrog-subagent-gate.ts";
@@ -109234,9 +109676,11 @@ function parseModel2(value2) {
109234
109676
  return { providerID: value2.slice(0, slash), modelID: value2.slice(slash + 1) };
109235
109677
  }
109236
109678
  function bootOpencodeServer(params) {
109679
+ const logLevel = isDebugEnabled() ? "INFO" : "ERROR";
109680
+ if (logLevel !== "ERROR") log.info(`\xBB opencode log level: ${logLevel} (debug run)`);
109237
109681
  const proc = nodeSpawn2(
109238
109682
  params.cliPath,
109239
- ["serve", "--port", "0", "--hostname", "127.0.0.1", "--print-logs", "--log-level", "ERROR"],
109683
+ ["serve", "--port", "0", "--hostname", "127.0.0.1", "--print-logs", "--log-level", logLevel],
109240
109684
  {
109241
109685
  cwd: params.cwd,
109242
109686
  env: params.env,
@@ -109786,6 +110230,7 @@ var opencode = agent({
109786
110230
  }
109787
110231
  log.debug(`\xBB starting Pullfrog (OpenCode, in-process SDK): ${cliPath}`);
109788
110232
  log.debug(`\xBB working directory: ${repoDir}`);
110233
+ const preBootDirty = await dirtyTrackedPaths();
109789
110234
  const server = await bootOpencodeServer({ cliPath, env: env2, cwd: repoDir });
109790
110235
  const dispatcher = new import_undici.Agent({ headersTimeout: 0, bodyTimeout: 0, connectTimeout: 0 });
109791
110236
  const fetchWithoutTimeout = (input, init) => {
@@ -109806,6 +110251,7 @@ var opencode = agent({
109806
110251
  fetch: fetchWithoutTimeout
109807
110252
  });
109808
110253
  const sessionResp = await client2.session.create({ title: "Pullfrog" });
110254
+ await restoreDirtiedSince({ before: preBootDirty, actor: "agent startup" });
109809
110255
  if (sessionResp.error || !sessionResp.data) {
109810
110256
  const msg = sessionResp.error ? formatPromptError(sessionResp.error) : "session.create returned no data";
109811
110257
  return {
@@ -116534,7 +116980,7 @@ var Server = class extends Protocol {
116534
116980
  };
116535
116981
 
116536
116982
  // node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
116537
- import process3 from "node:process";
116983
+ import process4 from "node:process";
116538
116984
 
116539
116985
  // node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
116540
116986
  var ReadBuffer = class {
@@ -116566,7 +117012,7 @@ function serializeMessage(message) {
116566
117012
 
116567
117013
  // node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
116568
117014
  var StdioServerTransport = class {
116569
- constructor(_stdin = process3.stdin, _stdout = process3.stdout) {
117015
+ constructor(_stdin = process4.stdin, _stdout = process4.stdout) {
116570
117016
  this._stdin = _stdin;
116571
117017
  this._stdout = _stdout;
116572
117018
  this._readBuffer = new ReadBuffer();
@@ -120001,7 +120447,7 @@ var Hono2 = class extends Hono {
120001
120447
  import { createRequire } from "node:module";
120002
120448
  import { randomUUID as randomUUID2 } from "node:crypto";
120003
120449
  import { URL as URL$1 } from "node:url";
120004
- import fs from "fs";
120450
+ import fs2 from "fs";
120005
120451
  import http from "http";
120006
120452
  import https from "https";
120007
120453
  var __create2 = Object.create;
@@ -134569,17 +135015,17 @@ var startHTTPServer = async ({ apiKey, authenticate, cors, createServer: createS
134569
135015
  if (sslCa || sslCert || sslKey) {
134570
135016
  const options = {};
134571
135017
  if (sslCa) try {
134572
- options.ca = fs.readFileSync(sslCa);
135018
+ options.ca = fs2.readFileSync(sslCa);
134573
135019
  } catch (error$1) {
134574
135020
  throw new Error(`Failed to read CA file '${sslCa}': ${error$1.message}`);
134575
135021
  }
134576
135022
  if (sslCert) try {
134577
- options.cert = fs.readFileSync(sslCert);
135023
+ options.cert = fs2.readFileSync(sslCert);
134578
135024
  } catch (error$1) {
134579
135025
  throw new Error(`Failed to read certificate file '${sslCert}': ${error$1.message}`);
134580
135026
  }
134581
135027
  if (sslKey) try {
134582
- options.key = fs.readFileSync(sslKey);
135028
+ options.key = fs2.readFileSync(sslKey);
134583
135029
  } catch (error$1) {
134584
135030
  throw new Error(`Failed to read key file '${sslKey}': ${error$1.message}`);
134585
135031
  }
@@ -143006,6 +143452,24 @@ function isSafeEnvVar(key) {
143006
143452
  if (SAFE_ENV_NAMES.has(key)) return true;
143007
143453
  return SAFE_ENV_PREFIXES.some((p) => key.startsWith(p));
143008
143454
  }
143455
+ var WORKFLOW_COMMAND_ENV_NAMES = [
143456
+ "GITHUB_ENV",
143457
+ "GITHUB_PATH",
143458
+ "GITHUB_OUTPUT",
143459
+ "GITHUB_STATE",
143460
+ "GITHUB_STEP_SUMMARY",
143461
+ // dropping the five paths above but keeping RUNNER_TEMP would be theatre:
143462
+ // the file-command files live in `$RUNNER_TEMP/_runner_file_commands/`, so the
143463
+ // directory is one `ls` away. nothing in the install path reads it (only our
143464
+ // own leak-surface wipe in `setup.ts`, which runs in the parent), and package
143465
+ // managers use TMPDIR.
143466
+ "RUNNER_TEMP"
143467
+ ];
143468
+ function filterEnvForUntrustedCode() {
143469
+ const env2 = filterEnv();
143470
+ for (const name of WORKFLOW_COMMAND_ENV_NAMES) delete env2[name];
143471
+ return env2;
143472
+ }
143009
143473
  function filterEnv() {
143010
143474
  const filtered = {};
143011
143475
  for (const [key, value2] of Object.entries(process.env)) {
@@ -151199,6 +151663,8 @@ import { join as join8 } from "node:path";
151199
151663
 
151200
151664
  // utils/shell.ts
151201
151665
  import { spawnSync as spawnSync5 } from "node:child_process";
151666
+ var MAX_BUFFER_BYTES = 32 * 1024 * 1024;
151667
+ var MAX_ERROR_DETAIL_CHARS = 2e4;
151202
151668
  function $(cmd, args2, options) {
151203
151669
  const encoding = options?.encoding ?? "utf-8";
151204
151670
  const env2 = resolveEnv(options?.env);
@@ -151206,7 +151672,8 @@ function $(cmd, args2, options) {
151206
151672
  stdio: ["ignore", "pipe", "pipe"],
151207
151673
  encoding,
151208
151674
  cwd: options?.cwd,
151209
- env: env2
151675
+ env: env2,
151676
+ maxBuffer: MAX_BUFFER_BYTES
151210
151677
  });
151211
151678
  const stdout = result.stdout ?? "";
151212
151679
  const stderr = result.stderr ?? "";
@@ -151224,6 +151691,11 @@ function $(cmd, args2, options) {
151224
151691
  }
151225
151692
  }
151226
151693
  if (result.status !== 0) {
151694
+ if (result.error && "code" in result.error && result.error.code === "ENOBUFS") {
151695
+ throw new Error(
151696
+ `Command produced more than ${MAX_BUFFER_BYTES / 1024 / 1024}MB of output and was terminated: ${cmd} ${args2.join(" ")}`
151697
+ );
151698
+ }
151227
151699
  const errorResult = {
151228
151700
  status: result.status ?? -1,
151229
151701
  stdout,
@@ -151233,7 +151705,7 @@ function $(cmd, args2, options) {
151233
151705
  options.onError(errorResult);
151234
151706
  return stdout.trim();
151235
151707
  }
151236
- const detail = [stderr, stdout].map((s) => s.trim()).filter(Boolean).join("\n");
151708
+ const detail = [stderr, stdout].map((s) => s.trim()).filter(Boolean).join("\n").slice(0, MAX_ERROR_DETAIL_CHARS);
151237
151709
  throw new Error(
151238
151710
  `Command failed with exit code ${errorResult.status}: ${detail || "Unknown error"}`
151239
151711
  );
@@ -151242,6 +151714,10 @@ function $(cmd, args2, options) {
151242
151714
  }
151243
151715
 
151244
151716
  // utils/gitAuth.ts
151717
+ var TRANSIENT_AUTH_PATTERNS = [
151718
+ /Invalid username or token/,
151719
+ /Authentication failed for 'https:\/\/github\.com\//
151720
+ ];
151245
151721
  var gitBinary;
151246
151722
  function hashFile(path4) {
151247
151723
  return createHash("sha256").update(readFileSync2(path4)).digest("hex");
@@ -151358,6 +151834,17 @@ async function $gitFetchWithDeepen(args2, options, label) {
151358
151834
  return await $git("fetch", args2, options);
151359
151835
  } catch (err) {
151360
151836
  const msg = err instanceof Error ? err.message : String(err);
151837
+ if (TRANSIENT_AUTH_PATTERNS.some((p) => p.test(msg)) && options.refreshGitToken) {
151838
+ log.info(
151839
+ `\xBB ${label ?? "git fetch"} hit an auth error, re-minting the git token and retrying`
151840
+ );
151841
+ const fresh = await options.refreshGitToken(options.token);
151842
+ return await $gitFetchWithDeepen(
151843
+ args2,
151844
+ { ...options, token: fresh, refreshGitToken: void 0 },
151845
+ label
151846
+ );
151847
+ }
151361
151848
  const isShallowUnreachable = SHALLOW_UNREACHABLE_PATTERNS.some((p) => p.test(msg));
151362
151849
  if (!isShallowUnreachable) throw err;
151363
151850
  const isShallow = $("git", ["rev-parse", "--is-shallow-repository"], { log: false }).trim() === "true";
@@ -151477,10 +151964,12 @@ function computeIncrementalDiff(params) {
151477
151964
  ],
151478
151965
  { log: false }
151479
151966
  );
151480
- return postProcessRangeDiff(raw2);
151967
+ const processed = postProcessRangeDiff(raw2);
151968
+ return processed === null ? { status: "empty" } : { status: "ok", diff: processed };
151481
151969
  } catch (e) {
151482
- log.debug(`\xBB range-diff failed: ${e instanceof Error ? e.message : String(e)}`);
151483
- return null;
151970
+ const reason = e instanceof Error ? e.message : String(e);
151971
+ log.warning(`\xBB incremental diff unavailable: range-diff failed: ${reason}`);
151972
+ return { status: "unavailable", reason };
151484
151973
  }
151485
151974
  }
151486
151975
  function isDiffPrefix(ch) {
@@ -152912,7 +153401,7 @@ throttling.VERSION = VERSION;
152912
153401
  throttling.triggersNotification = triggersNotification;
152913
153402
 
152914
153403
  // node_modules/.pnpm/universal-user-agent@7.0.3/node_modules/universal-user-agent/index.js
152915
- function getUserAgent() {
153404
+ function getUserAgent2() {
152916
153405
  if (typeof navigator === "object" && "userAgent" in navigator) {
152917
153406
  return navigator.userAgent;
152918
153407
  }
@@ -153030,7 +153519,7 @@ var before_after_hook_default = { Singular, Collection };
153030
153519
 
153031
153520
  // node_modules/.pnpm/@octokit+endpoint@11.0.1/node_modules/@octokit/endpoint/dist-bundle/index.js
153032
153521
  var VERSION2 = "0.0.0-development";
153033
- var userAgent = `octokit-endpoint.js/${VERSION2} ${getUserAgent()}`;
153522
+ var userAgent = `octokit-endpoint.js/${VERSION2} ${getUserAgent2()}`;
153034
153523
  var DEFAULTS = {
153035
153524
  method: "GET",
153036
153525
  baseUrl: "https://api.github.com",
@@ -153387,7 +153876,7 @@ var RequestError = class extends Error {
153387
153876
  var VERSION3 = "10.0.5";
153388
153877
  var defaults_default = {
153389
153878
  headers: {
153390
- "user-agent": `octokit-request.js/${VERSION3} ${getUserAgent()}`
153879
+ "user-agent": `octokit-request.js/${VERSION3} ${getUserAgent2()}`
153391
153880
  }
153392
153881
  };
153393
153882
  function isPlainObject4(value2) {
@@ -153652,7 +154141,7 @@ function withDefaults3(request2, newDefaults) {
153652
154141
  }
153653
154142
  var graphql2 = withDefaults3(request, {
153654
154143
  headers: {
153655
- "user-agent": `octokit-graphql.js/${VERSION4} ${getUserAgent()}`
154144
+ "user-agent": `octokit-graphql.js/${VERSION4} ${getUserAgent2()}`
153656
154145
  },
153657
154146
  method: "POST",
153658
154147
  url: "/graphql"
@@ -153732,7 +154221,7 @@ function createLogger(logger = {}) {
153732
154221
  }
153733
154222
  return logger;
153734
154223
  }
153735
- var userAgentTrail = `octokit-core.js/${VERSION5} ${getUserAgent()}`;
154224
+ var userAgentTrail = `octokit-core.js/${VERSION5} ${getUserAgent2()}`;
153736
154225
  var Octokit = class {
153737
154226
  static VERSION = VERSION5;
153738
154227
  static defaults(defaults) {
@@ -156700,8 +157189,13 @@ function createOctokit(token, refreshAuth) {
156700
157189
  var readOctokitByToken = /* @__PURE__ */ new Map();
156701
157190
  function resolveRepoCtx(ctx, repo) {
156702
157191
  const owner = ctx.repo.owner;
156703
- const name = repo ?? ctx.repo.name;
156704
- const state = requireRepoState(ctx.toolState, owner, name);
157192
+ const name = repo?.trim() || ctx.repo.name;
157193
+ const state = ctx.toolState.repos.get(repoKey(owner, name));
157194
+ if (!state) {
157195
+ throw new Error(
157196
+ 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}`
157197
+ );
157198
+ }
156705
157199
  if (state.access !== "read") {
156706
157200
  return {
156707
157201
  owner,
@@ -157418,10 +157912,6 @@ var TRANSIENT_PATTERNS = [
157418
157912
  /HTTP 429/,
157419
157913
  /returned error: 429/i
157420
157914
  ];
157421
- var TRANSIENT_AUTH_PATTERNS = [
157422
- /Invalid username or token/,
157423
- /Authentication failed for 'https:\/\/github\.com\//
157424
- ];
157425
157915
  function classifyPushError(msg) {
157426
157916
  if (CONCURRENT_PUSH_PATTERNS.some((p) => msg.includes(p))) return "concurrent-push";
157427
157917
  if (TRANSIENT_AUTH_PATTERNS.some((p) => p.test(msg))) return "transient-auth";
@@ -157920,7 +158410,11 @@ function GitFetchTool(ctx) {
157920
158410
  if (params.depth !== void 0) {
157921
158411
  fetchArgs.push(`--depth=${params.depth}`);
157922
158412
  }
157923
- await $gitFetchWithDeepen(fetchArgs, { token: rc.gitToken, cwd: rc.dir }, "git_fetch");
158413
+ await $gitFetchWithDeepen(
158414
+ fetchArgs,
158415
+ { token: rc.gitToken, cwd: rc.dir, refreshGitToken: rc.refreshGitToken },
158416
+ "git_fetch"
158417
+ );
157924
158418
  return { success: true, ref: params.ref };
157925
158419
  })
157926
158420
  });
@@ -158009,7 +158503,7 @@ function formatModelLabel(params) {
158009
158503
  const ossBase = `\`${displayName}\` (free via [Pullfrog for OSS](https://pullfrog.com/for-oss))`;
158010
158504
  if (params.clamped?.reason !== "oss") return ossBase;
158011
158505
  const configured = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
158012
- return `${ossBase} (${configured} not used \u2014 the program covers this model; add its [provider key](https://docs.pullfrog.com/models) to run your pick)`;
158506
+ 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)`;
158013
158507
  }
158014
158508
  const base = alias?.isFree ? `\`${displayName}\` (free)` : `\`${displayName}\``;
158015
158509
  if (params.fallbackFrom) {
@@ -159557,7 +160051,7 @@ async function ensureBeforeShaReachable(params) {
159557
160051
  }), true);
159558
160052
  await $gitFetchWithDeepen(
159559
160053
  ["--no-tags", ...params.isShallow ? ["--depth=1"] : [], "origin", tempBranch],
159560
- { token: params.gitToken },
160054
+ { token: params.gitToken, refreshGitToken: params.refreshGitToken },
159561
160055
  `before_sha temp branch ${tempBranch}`
159562
160056
  );
159563
160057
  log.debug(`\xBB fetched before_sha via temp branch ${tempBranch}`);
@@ -159573,6 +160067,14 @@ async function ensureBeforeShaReachable(params) {
159573
160067
  return false;
159574
160068
  }
159575
160069
  }
160070
+ function hasLocalCommit(sha) {
160071
+ if (!sha) return false;
160072
+ try {
160073
+ return $("git", ["cat-file", "-t", sha], { log: false }).trim() === "commit";
160074
+ } catch {
160075
+ return false;
160076
+ }
160077
+ }
159576
160078
  var STALE_LOCK_AGE_MS = 3e4;
159577
160079
  var PULL_REF_RETRY_DELAYS_MS = [2e3, 5e3, 1e4];
159578
160080
  var PULL_REF_MISSING_PATTERN = /couldn't find remote ref pull\/\d+\/head/i;
@@ -159623,7 +160125,7 @@ async function abortIfPullRequestMoved(args2) {
159623
160125
  );
159624
160126
  }
159625
160127
  async function checkoutPrBranch(pr, params) {
159626
- const { octokit, owner, name, gitToken, toolState, beforeSha } = params;
160128
+ const { octokit, owner, name, gitToken, refreshGitToken, toolState, beforeSha } = params;
159627
160129
  rejectIfLeadingDash(pr.baseRef, "PR base ref");
159628
160130
  rejectIfLeadingDash(pr.headRef, "PR head ref");
159629
160131
  const repoState = requireRepoState(toolState, owner, name);
@@ -159637,7 +160139,7 @@ async function checkoutPrBranch(pr, params) {
159637
160139
  log.debug(`\xBB fetching base branch (${pr.baseRef})...`);
159638
160140
  await $gitFetchWithDeepen(
159639
160141
  ["--no-tags", "origin", pr.baseRef],
159640
- { token: gitToken },
160142
+ { token: gitToken, refreshGitToken },
159641
160143
  `base branch ${pr.baseRef}`
159642
160144
  );
159643
160145
  if (!alreadyOnBranch) {
@@ -159648,7 +160150,7 @@ async function checkoutPrBranch(pr, params) {
159648
160150
  try {
159649
160151
  await $gitFetchWithDeepen(
159650
160152
  ["--no-tags", "origin", `+pull/${pr.number}/head:${localBranch}`],
159651
- { token: gitToken },
160153
+ { token: gitToken, refreshGitToken },
159652
160154
  `PR #${pr.number}`
159653
160155
  );
159654
160156
  } catch (e) {
@@ -159675,6 +160177,7 @@ async function checkoutPrBranch(pr, params) {
159675
160177
  owner,
159676
160178
  repo: name,
159677
160179
  gitToken,
160180
+ refreshGitToken,
159678
160181
  isShallow
159679
160182
  }) : false;
159680
160183
  if (isShallow) {
@@ -159788,6 +160291,7 @@ function CheckoutPrTool(ctx) {
159788
160291
  owner: ctx.repo.owner,
159789
160292
  name: ctx.repo.name,
159790
160293
  gitToken: ctx.gitToken,
160294
+ refreshGitToken: ctx.refreshGitToken,
159791
160295
  toolState: ctx.toolState,
159792
160296
  shell: ctx.payload.shell,
159793
160297
  postCheckoutScript: ctx.postCheckoutScript,
@@ -159803,6 +160307,8 @@ function CheckoutPrTool(ctx) {
159803
160307
  if (!checkoutSha) throw new Error("checkout completed without a resolved HEAD SHA");
159804
160308
  const headShort = checkoutSha.slice(0, 7);
159805
160309
  let incrementalDiffPath;
160310
+ let incrementalUnavailable = false;
160311
+ let incrementalUnavailableReason;
159806
160312
  if (primary.beforeSha) {
159807
160313
  const beforeShort = primary.beforeSha.slice(0, 7);
159808
160314
  const incremental = computeIncrementalDiff({
@@ -159810,15 +160316,18 @@ function CheckoutPrTool(ctx) {
159810
160316
  beforeSha: primary.beforeSha,
159811
160317
  headSha: checkoutSha
159812
160318
  });
159813
- if (incremental) {
160319
+ if (incremental.status === "ok") {
159814
160320
  incrementalDiffPath = join13(
159815
160321
  tempDir,
159816
160322
  `pr-${pull_number}-${beforeShort}-${headShort}-incremental.diff`
159817
160323
  );
159818
- writeFileSync8(incrementalDiffPath, incremental);
160324
+ writeFileSync8(incrementalDiffPath, incremental.diff);
159819
160325
  log.info(
159820
- `\xBB incremental diff computed (${incremental.length} bytes) \u2192 ${incrementalDiffPath}`
160326
+ `\xBB incremental diff computed (${incremental.diff.length} bytes) \u2192 ${incrementalDiffPath}`
159821
160327
  );
160328
+ } else if (incremental.status === "unavailable") {
160329
+ incrementalUnavailable = true;
160330
+ incrementalUnavailableReason = incremental.reason;
159822
160331
  }
159823
160332
  }
159824
160333
  const formatResult = await fetchAndFormatPrDiff(ctx, pull_number);
@@ -159885,7 +160394,13 @@ ${diffPreview}`);
159885
160394
  primary.commentableLinesByFile = cached4;
159886
160395
  primary.commentableLinesPullNumber = pull_number;
159887
160396
  primary.commentableLinesCheckoutSha = checkoutSha;
159888
- 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. ` : "";
160397
+ 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 ? (
160398
+ // say it FAILED rather than leaving the agent to infer "nothing changed"
160399
+ // from an absent field. only suggest diff-tree when the previous
160400
+ // revision is actually PRESENT locally — if the fetch never landed it,
160401
+ // diff-tree needs that object too and would fail identically. see #1139.
160402
+ `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. `)
160403
+ ) : "";
159889
160404
  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.` : "";
159890
160405
  const COMMIT_LOG_MAX = 200;
159891
160406
  const baseRange = `origin/${pr.baseRef}..HEAD`;
@@ -160205,299 +160720,6 @@ import { performance as performance8 } from "node:perf_hooks";
160205
160720
  import { existsSync as existsSync6 } from "node:fs";
160206
160721
  import { join as join17 } from "node:path";
160207
160722
 
160208
- // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/commands.mjs
160209
- function dashDashArg(agent2, agentCommand) {
160210
- return (args2) => {
160211
- if (args2.length > 1) {
160212
- return [agent2, agentCommand, args2[0], "--", ...args2.slice(1)];
160213
- } else {
160214
- return [agent2, agentCommand, args2[0]];
160215
- }
160216
- };
160217
- }
160218
- function denoExecute() {
160219
- return (args2) => {
160220
- return ["deno", "run", `npm:${args2[0]}`, ...args2.slice(1)];
160221
- };
160222
- }
160223
- var npm = {
160224
- "agent": ["npm", 0],
160225
- "run": dashDashArg("npm", "run"),
160226
- "install": ["npm", "i", 0],
160227
- "frozen": ["npm", "ci", 0],
160228
- "global": ["npm", "i", "-g", 0],
160229
- "add": ["npm", "i", 0],
160230
- "upgrade": ["npm", "update", 0],
160231
- "upgrade-interactive": null,
160232
- "dedupe": ["npm", "dedupe", 0],
160233
- "execute": ["npx", 0],
160234
- "execute-local": ["npx", 0],
160235
- "uninstall": ["npm", "uninstall", 0],
160236
- "global_uninstall": ["npm", "uninstall", "-g", 0]
160237
- };
160238
- var yarn = {
160239
- "agent": ["yarn", 0],
160240
- "run": ["yarn", "run", 0],
160241
- "install": ["yarn", "install", 0],
160242
- "frozen": ["yarn", "install", "--frozen-lockfile", 0],
160243
- "global": ["yarn", "global", "add", 0],
160244
- "add": ["yarn", "add", 0],
160245
- "upgrade": ["yarn", "upgrade", 0],
160246
- "upgrade-interactive": ["yarn", "upgrade-interactive", 0],
160247
- "dedupe": null,
160248
- "execute": ["npx", 0],
160249
- "execute-local": dashDashArg("yarn", "exec"),
160250
- "uninstall": ["yarn", "remove", 0],
160251
- "global_uninstall": ["yarn", "global", "remove", 0]
160252
- };
160253
- var yarnBerry = {
160254
- ...yarn,
160255
- "frozen": ["yarn", "install", "--immutable", 0],
160256
- "upgrade": ["yarn", "up", 0],
160257
- "upgrade-interactive": ["yarn", "up", "-i", 0],
160258
- "dedupe": ["yarn", "dedupe", 0],
160259
- "execute": ["yarn", "dlx", 0],
160260
- "execute-local": ["yarn", "exec", 0],
160261
- // Yarn 2+ removed 'global', see https://github.com/yarnpkg/berry/issues/821
160262
- "global": ["npm", "i", "-g", 0],
160263
- "global_uninstall": ["npm", "uninstall", "-g", 0]
160264
- };
160265
- var pnpm = {
160266
- "agent": ["pnpm", 0],
160267
- "run": ["pnpm", "run", 0],
160268
- "install": ["pnpm", "i", 0],
160269
- "frozen": ["pnpm", "i", "--frozen-lockfile", 0],
160270
- "global": ["pnpm", "add", "-g", 0],
160271
- "add": ["pnpm", "add", 0],
160272
- "upgrade": ["pnpm", "update", 0],
160273
- "upgrade-interactive": ["pnpm", "update", "-i", 0],
160274
- "dedupe": ["pnpm", "dedupe", 0],
160275
- "execute": ["pnpm", "dlx", 0],
160276
- "execute-local": ["pnpm", "exec", 0],
160277
- "uninstall": ["pnpm", "remove", 0],
160278
- "global_uninstall": ["pnpm", "remove", "--global", 0]
160279
- };
160280
- var bun = {
160281
- "agent": ["bun", 0],
160282
- "run": ["bun", "run", 0],
160283
- "install": ["bun", "install", 0],
160284
- "frozen": ["bun", "install", "--frozen-lockfile", 0],
160285
- "global": ["bun", "add", "-g", 0],
160286
- "add": ["bun", "add", 0],
160287
- "upgrade": ["bun", "update", 0],
160288
- "upgrade-interactive": ["bun", "update", "-i", 0],
160289
- "dedupe": null,
160290
- "execute": ["bun", "x", 0],
160291
- "execute-local": ["bun", "x", 0],
160292
- "uninstall": ["bun", "remove", 0],
160293
- "global_uninstall": ["bun", "remove", "-g", 0]
160294
- };
160295
- var deno = {
160296
- "agent": ["deno", 0],
160297
- "run": ["deno", "task", 0],
160298
- "install": ["deno", "install", 0],
160299
- "frozen": ["deno", "install", "--frozen", 0],
160300
- "global": ["deno", "install", "-g", 0],
160301
- "add": ["deno", "add", 0],
160302
- "upgrade": ["deno", "outdated", "--update", 0],
160303
- "upgrade-interactive": ["deno", "outdated", "--update", 0],
160304
- "dedupe": null,
160305
- "execute": denoExecute(),
160306
- "execute-local": ["deno", "task", "--eval", 0],
160307
- "uninstall": ["deno", "remove", 0],
160308
- "global_uninstall": ["deno", "uninstall", "-g", 0]
160309
- };
160310
- var COMMANDS = {
160311
- "npm": npm,
160312
- "yarn": yarn,
160313
- "yarn@berry": yarnBerry,
160314
- "pnpm": pnpm,
160315
- // pnpm v6.x or below
160316
- "pnpm@6": {
160317
- ...pnpm,
160318
- run: dashDashArg("pnpm", "run")
160319
- },
160320
- "bun": bun,
160321
- "deno": deno
160322
- };
160323
- function resolveCommand(agent2, command, args2) {
160324
- const value2 = COMMANDS[agent2][command];
160325
- return constructCommand(value2, args2);
160326
- }
160327
- function constructCommand(value2, args2) {
160328
- if (value2 == null)
160329
- return null;
160330
- const list = typeof value2 === "function" ? value2(args2) : value2.flatMap((v) => {
160331
- if (typeof v === "number")
160332
- return args2;
160333
- return [v];
160334
- });
160335
- return {
160336
- command: list[0],
160337
- args: list.slice(1)
160338
- };
160339
- }
160340
-
160341
- // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/constants.mjs
160342
- var AGENTS = [
160343
- "npm",
160344
- "yarn",
160345
- "yarn@berry",
160346
- "pnpm",
160347
- "pnpm@6",
160348
- "bun",
160349
- "deno"
160350
- ];
160351
- var LOCKS = {
160352
- "bun.lock": "bun",
160353
- "bun.lockb": "bun",
160354
- "deno.lock": "deno",
160355
- "pnpm-lock.yaml": "pnpm",
160356
- "pnpm-workspace.yaml": "pnpm",
160357
- "yarn.lock": "yarn",
160358
- "package-lock.json": "npm",
160359
- "npm-shrinkwrap.json": "npm"
160360
- };
160361
- var INSTALL_METADATA = {
160362
- "node_modules/.deno/": "deno",
160363
- "node_modules/.pnpm/": "pnpm",
160364
- "node_modules/.yarn-state.yml": "yarn",
160365
- // yarn v2+ (node-modules)
160366
- "node_modules/.yarn_integrity": "yarn",
160367
- // yarn v1
160368
- "node_modules/.package-lock.json": "npm",
160369
- ".pnp.cjs": "yarn",
160370
- // yarn v3+ (pnp)
160371
- ".pnp.js": "yarn",
160372
- // yarn v2 (pnp)
160373
- "bun.lock": "bun",
160374
- "bun.lockb": "bun"
160375
- };
160376
-
160377
- // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/detect.mjs
160378
- import fs2 from "node:fs/promises";
160379
- import path from "node:path";
160380
- import process4 from "node:process";
160381
- async function pathExists(path22, type2) {
160382
- try {
160383
- const stat = await fs2.stat(path22);
160384
- return type2 === "file" ? stat.isFile() : stat.isDirectory();
160385
- } catch {
160386
- return false;
160387
- }
160388
- }
160389
- function* lookup(cwd = process4.cwd()) {
160390
- let directory = path.resolve(cwd);
160391
- const { root } = path.parse(directory);
160392
- while (directory && directory !== root) {
160393
- yield directory;
160394
- directory = path.dirname(directory);
160395
- }
160396
- }
160397
- async function parsePackageJson(filepath, options) {
160398
- if (!filepath || !await pathExists(filepath, "file"))
160399
- return null;
160400
- return await handlePackageManager(filepath, options);
160401
- }
160402
- async function detect(options = {}) {
160403
- const {
160404
- cwd,
160405
- strategies = ["lockfile", "packageManager-field", "devEngines-field"]
160406
- } = options;
160407
- let stopDir;
160408
- if (typeof options.stopDir === "string") {
160409
- const resolved = path.resolve(options.stopDir);
160410
- stopDir = (dir) => dir === resolved;
160411
- } else {
160412
- stopDir = options.stopDir;
160413
- }
160414
- for (const directory of lookup(cwd)) {
160415
- for (const strategy of strategies) {
160416
- switch (strategy) {
160417
- case "lockfile": {
160418
- for (const lock of Object.keys(LOCKS)) {
160419
- if (await pathExists(path.join(directory, lock), "file")) {
160420
- const name = LOCKS[lock];
160421
- const result = await parsePackageJson(path.join(directory, "package.json"), options);
160422
- if (result)
160423
- return result;
160424
- else
160425
- return { name, agent: name };
160426
- }
160427
- }
160428
- break;
160429
- }
160430
- case "packageManager-field":
160431
- case "devEngines-field": {
160432
- const result = await parsePackageJson(path.join(directory, "package.json"), options);
160433
- if (result)
160434
- return result;
160435
- break;
160436
- }
160437
- case "install-metadata": {
160438
- for (const metadata of Object.keys(INSTALL_METADATA)) {
160439
- const fileOrDir = metadata.endsWith("/") ? "dir" : "file";
160440
- if (await pathExists(path.join(directory, metadata), fileOrDir)) {
160441
- const name = INSTALL_METADATA[metadata];
160442
- const agent2 = name === "yarn" ? isMetadataYarnClassic(metadata) ? "yarn" : "yarn@berry" : name;
160443
- return { name, agent: agent2 };
160444
- }
160445
- }
160446
- break;
160447
- }
160448
- }
160449
- }
160450
- if (stopDir?.(directory))
160451
- break;
160452
- }
160453
- return null;
160454
- }
160455
- function getNameAndVer(pkg) {
160456
- const handelVer = (version3) => version3?.match(/\d+(\.\d+){0,2}/)?.[0] ?? version3;
160457
- if (typeof pkg.packageManager === "string") {
160458
- const [name, ver] = pkg.packageManager.replace(/^\^/, "").split("@");
160459
- return { name, ver: handelVer(ver) };
160460
- }
160461
- if (typeof pkg.devEngines?.packageManager?.name === "string") {
160462
- return {
160463
- name: pkg.devEngines.packageManager.name,
160464
- ver: handelVer(pkg.devEngines.packageManager.version)
160465
- };
160466
- }
160467
- return void 0;
160468
- }
160469
- async function handlePackageManager(filepath, options) {
160470
- try {
160471
- const content = await fs2.readFile(filepath, "utf8");
160472
- const pkg = options.packageJsonParser ? await options.packageJsonParser(content, filepath) : JSON.parse(content);
160473
- let agent2;
160474
- const nameAndVer = getNameAndVer(pkg);
160475
- if (nameAndVer) {
160476
- const name = nameAndVer.name;
160477
- const ver = nameAndVer.ver;
160478
- let version3 = ver;
160479
- if (name === "yarn" && ver && Number.parseInt(ver) > 1) {
160480
- agent2 = "yarn@berry";
160481
- version3 = "berry";
160482
- return { name, agent: agent2, version: version3 };
160483
- } else if (name === "pnpm" && ver && Number.parseInt(ver) < 7) {
160484
- agent2 = "pnpm@6";
160485
- return { name, agent: agent2, version: version3 };
160486
- } else if (AGENTS.includes(name)) {
160487
- agent2 = name;
160488
- return { name, agent: agent2, version: version3 };
160489
- } else {
160490
- return options.onUnknown?.(pkg.packageManager) ?? null;
160491
- }
160492
- }
160493
- } catch {
160494
- }
160495
- return null;
160496
- }
160497
- function isMetadataYarnClassic(metadataPath) {
160498
- return metadataPath.endsWith(".yarn_integrity");
160499
- }
160500
-
160501
160723
  // utils/packageManager.ts
160502
160724
  var import_semver2 = __toESM(require_semver2(), 1);
160503
160725
  import { existsSync as existsSync5 } from "node:fs";
@@ -160583,11 +160805,7 @@ async function runCorepack(args2) {
160583
160805
  const result = await spawn({
160584
160806
  cmd: "corepack",
160585
160807
  args: args2,
160586
- env: {
160587
- PATH: process.env.PATH || "",
160588
- HOME: process.env.HOME || "",
160589
- COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
160590
- },
160808
+ env: { ...filterEnvForUntrustedCode(), COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" },
160591
160809
  onStdout: (chunk) => process.stdout.write(chunk),
160592
160810
  onStderr: (chunk) => process.stderr.write(chunk)
160593
160811
  });
@@ -160597,7 +160815,7 @@ async function currentVersion(name) {
160597
160815
  const result = await spawn({
160598
160816
  cmd: name,
160599
160817
  args: ["--version"],
160600
- env: { PATH: process.env.PATH || "" }
160818
+ env: filterEnvForUntrustedCode()
160601
160819
  });
160602
160820
  if (result.exitCode !== 0) return null;
160603
160821
  return result.stdout.trim();
@@ -160649,14 +160867,8 @@ async function ensurePackageManager(params) {
160649
160867
  }
160650
160868
  return true;
160651
160869
  }
160652
-
160653
- // prep/installNodeDependencies.ts
160654
160870
  async function isCommandAvailable(command) {
160655
- const result = await spawn({
160656
- cmd: "which",
160657
- args: [command],
160658
- env: { PATH: process.env.PATH || "" }
160659
- });
160871
+ const result = await spawn({ cmd: "which", args: [command], env: filterEnvForUntrustedCode() });
160660
160872
  return result.exitCode === 0;
160661
160873
  }
160662
160874
  async function installFallback(name, installSpec) {
@@ -160667,19 +160879,41 @@ async function installFallback(name, installSpec) {
160667
160879
  const result = await spawn({
160668
160880
  cmd,
160669
160881
  args: args2,
160670
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
160882
+ env: filterEnvForUntrustedCode(),
160671
160883
  onStderr: (chunk) => process.stderr.write(chunk)
160672
160884
  });
160673
- if (result.exitCode !== 0) {
160674
- return result.stderr || `failed to install ${name}`;
160675
- }
160885
+ if (result.exitCode !== 0) return result.stderr || `failed to install ${name}`;
160676
160886
  if (name === "deno") {
160677
- const denoPath = join17(process.env.HOME || "", ".deno", "bin");
160887
+ const denoPath = join16(process.env.HOME || "", ".deno", "bin");
160678
160888
  process.env.PATH = `${denoPath}:${process.env.PATH}`;
160679
160889
  }
160680
160890
  log.info(`\xBB installed ${name}`);
160681
160891
  return null;
160682
160892
  }
160893
+ async function provisionPackageManager(params) {
160894
+ if (await isCommandAvailable(params.name)) {
160895
+ if (params.declared) {
160896
+ await ensurePackageManager({ spec: params.declared, binDir: params.binDir });
160897
+ }
160898
+ return null;
160899
+ }
160900
+ if (params.declared) {
160901
+ const activated = await ensurePackageManager({ spec: params.declared, binDir: params.binDir });
160902
+ if (activated) return null;
160903
+ }
160904
+ const spec = params.declared ? `${params.declared.name}@${params.declared.version}` : params.name;
160905
+ return installFallback(params.name, spec);
160906
+ }
160907
+
160908
+ // prep/installNodeDependencies.ts
160909
+ async function isCommandAvailable2(command) {
160910
+ const result = await spawn({
160911
+ cmd: "which",
160912
+ args: [command],
160913
+ env: filterEnvForUntrustedCode()
160914
+ });
160915
+ return result.exitCode === 0;
160916
+ }
160683
160917
  var installNodeDependencies = {
160684
160918
  name: "installNodeDependencies",
160685
160919
  shouldRun: () => {
@@ -160700,8 +160934,8 @@ var installNodeDependencies = {
160700
160934
  } else {
160701
160935
  log.info(`\xBB no package manager declared, defaulting to npm`);
160702
160936
  }
160703
- if (!await isCommandAvailable(packageManager)) {
160704
- if (options.ignoreScripts) {
160937
+ if (options.ignoreScripts) {
160938
+ if (!await isCommandAvailable2(packageManager)) {
160705
160939
  return {
160706
160940
  language: "node",
160707
160941
  packageManager,
@@ -160711,23 +160945,20 @@ var installNodeDependencies = {
160711
160945
  ]
160712
160946
  };
160713
160947
  }
160714
- let provisioned = false;
160715
- if (declared)
160716
- provisioned = await ensurePackageManager({ spec: declared, binDir: options.binDir });
160717
- if (!provisioned) {
160718
- const fallbackSpec = declared ? `${declared.name}@${declared.version}` : packageManager;
160719
- const installError = await installFallback(packageManager, fallbackSpec);
160720
- if (installError) {
160721
- return {
160722
- language: "node",
160723
- packageManager,
160724
- dependenciesInstalled: false,
160725
- issues: [installError]
160726
- };
160727
- }
160948
+ } else {
160949
+ const installError = await provisionPackageManager({
160950
+ name: packageManager,
160951
+ declared,
160952
+ binDir: options.binDir
160953
+ });
160954
+ if (installError) {
160955
+ return {
160956
+ language: "node",
160957
+ packageManager,
160958
+ dependenciesInstalled: false,
160959
+ issues: [installError]
160960
+ };
160728
160961
  }
160729
- } else if (declared) {
160730
- await ensurePackageManager({ spec: declared, binDir: options.binDir });
160731
160962
  }
160732
160963
  if (!detected) {
160733
160964
  log.info(
@@ -160753,7 +160984,7 @@ var installNodeDependencies = {
160753
160984
  const result = await spawn({
160754
160985
  cmd: resolved.command,
160755
160986
  args: resolved.args,
160756
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" }
160987
+ env: filterEnvForUntrustedCode()
160757
160988
  });
160758
160989
  const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
160759
160990
  if (output) {
@@ -160827,11 +161058,11 @@ var TOOL_INSTALL_COMMANDS = {
160827
161058
  pipenv: ["pip", "install", "pipenv"],
160828
161059
  poetry: ["pip", "install", "poetry"]
160829
161060
  };
160830
- async function isCommandAvailable2(command) {
161061
+ async function isCommandAvailable3(command) {
160831
161062
  const result = await spawn({
160832
161063
  cmd: "which",
160833
161064
  args: [command],
160834
- env: { PATH: process.env.PATH || "" }
161065
+ env: filterEnvForUntrustedCode()
160835
161066
  });
160836
161067
  return result.exitCode === 0;
160837
161068
  }
@@ -160845,7 +161076,7 @@ async function installTool(name) {
160845
161076
  const result = await spawn({
160846
161077
  cmd,
160847
161078
  args: args2,
160848
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
161079
+ env: filterEnvForUntrustedCode(),
160849
161080
  onStderr: (chunk) => process.stderr.write(chunk)
160850
161081
  });
160851
161082
  if (result.exitCode !== 0) {
@@ -160857,7 +161088,7 @@ async function installTool(name) {
160857
161088
  var installPythonDependencies = {
160858
161089
  name: "installPythonDependencies",
160859
161090
  shouldRun: async () => {
160860
- const hasPython = await isCommandAvailable2("python3") || await isCommandAvailable2("python");
161091
+ const hasPython = await isCommandAvailable3("python3") || await isCommandAvailable3("python");
160861
161092
  if (!hasPython) {
160862
161093
  return false;
160863
161094
  }
@@ -160891,7 +161122,7 @@ var installPythonDependencies = {
160891
161122
  ]
160892
161123
  };
160893
161124
  }
160894
- const isAvailable = await isCommandAvailable2(config3.tool);
161125
+ const isAvailable = await isCommandAvailable3(config3.tool);
160895
161126
  if (!isAvailable) {
160896
161127
  log.info(`\xBB ${config3.tool} not found, attempting to install...`);
160897
161128
  const installError = await installTool(config3.tool);
@@ -160911,7 +161142,7 @@ var installPythonDependencies = {
160911
161142
  const result = await spawn({
160912
161143
  cmd,
160913
161144
  args: args2,
160914
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" }
161145
+ env: filterEnvForUntrustedCode()
160915
161146
  });
160916
161147
  const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
160917
161148
  if (output) {
@@ -160940,37 +161171,6 @@ var installPythonDependencies = {
160940
161171
 
160941
161172
  // prep/index.ts
160942
161173
  var prepSteps = [installNodeDependencies, installPythonDependencies];
160943
- async function dirtyTrackedPaths() {
160944
- const result = await spawn({
160945
- cmd: "git",
160946
- args: ["diff", "--name-only", "HEAD"],
160947
- env: process.env,
160948
- activityTimeout: 0
160949
- });
160950
- if (result.exitCode !== 0) {
160951
- throw new Error(
160952
- `git diff --name-only HEAD failed (exit ${result.exitCode}): ${result.stderr.trim() || "(no stderr)"}`
160953
- );
160954
- }
160955
- return new Set(result.stdout.split("\n").filter(Boolean));
160956
- }
160957
- async function restorePrepDirtiedFiles(preDirty) {
160958
- const dirtied = [...await dirtyTrackedPaths()].filter((path4) => !preDirty.has(path4));
160959
- if (dirtied.length === 0) return;
160960
- const result = await spawn({
160961
- cmd: "git",
160962
- args: ["restore", "--staged", "--worktree", "--", ...dirtied],
160963
- env: process.env,
160964
- activityTimeout: 0
160965
- });
160966
- if (result.exitCode !== 0) {
160967
- log.warning(
160968
- `\xBB failed to restore ${dirtied.length} tracked file(s) modified by prep: ${result.stderr.trim() || "(no stderr)"}`
160969
- );
160970
- return;
160971
- }
160972
- log.info(`\xBB restored ${dirtied.length} tracked file(s) modified by prep: ${dirtied.join(", ")}`);
160973
- }
160974
161174
  async function runPrepPhase(options) {
160975
161175
  log.debug("\xBB starting prep phase...");
160976
161176
  const startTime = performance8.now();
@@ -160993,7 +161193,7 @@ async function runPrepPhase(options) {
160993
161193
  }
160994
161194
  }
160995
161195
  } finally {
160996
- await restorePrepDirtiedFiles(preDirty);
161196
+ await restoreDirtiedSince({ before: preDirty, actor: "prep" });
160997
161197
  }
160998
161198
  const totalDurationMs = performance8.now() - startTime;
160999
161199
  log.debug(`\xBB prep phase completed (${Math.round(totalDurationMs)}ms)`);
@@ -162209,13 +162409,38 @@ function buildThreadBlocks(threads, filePatchMap, reviewId) {
162209
162409
  }
162210
162410
  return threadBlocks;
162211
162411
  }
162412
+ var fetchAllReviewThreads = op(
162413
+ async (key, ctx) => {
162414
+ const response = await ctx.octokit.graphql(REVIEW_THREADS_QUERY, {
162415
+ owner: key.owner,
162416
+ name: key.name,
162417
+ prNumber: key.pullNumber
162418
+ });
162419
+ return response.repository?.pullRequest?.reviewThreads?.nodes ?? [];
162420
+ },
162421
+ { ttl: 6e4, name: "reviewThreads" }
162422
+ );
162423
+ var fetchPrFiles = op(
162424
+ async (key, ctx) => ctx.octokit.paginate(ctx.octokit.rest.pulls.listFiles, {
162425
+ owner: key.owner,
162426
+ repo: key.name,
162427
+ pull_number: key.pullNumber,
162428
+ per_page: 100
162429
+ }),
162430
+ { ttl: 6e4, name: "prFiles" }
162431
+ );
162432
+ function invalidateReviewThreadCache(repo) {
162433
+ fetchAllReviewThreads.invalidate(
162434
+ (cached4) => cached4.owner === repo.owner && cached4.name === repo.name
162435
+ );
162436
+ }
162212
162437
  async function getReviewThreads(input) {
162213
- const response = await input.octokit.graphql(REVIEW_THREADS_QUERY, {
162214
- owner: input.owner,
162215
- name: input.name,
162216
- prNumber: input.pullNumber
162217
- });
162218
- const allThreads = response.repository?.pullRequest?.reviewThreads?.nodes ?? [];
162438
+ const allThreads = structuredClone(
162439
+ await fetchAllReviewThreads(
162440
+ { owner: input.owner, name: input.name, pullNumber: input.pullNumber },
162441
+ { octokit: input.octokit }
162442
+ )
162443
+ );
162219
162444
  if (allThreads.length >= 100) {
162220
162445
  log.warning(
162221
162446
  `PR ${input.owner}/${input.name}#${input.pullNumber}: reviewThreads returned 100 results (limit reached, some threads may be missing)`
@@ -162272,12 +162497,10 @@ async function getReviewData(input) {
162272
162497
  }),
162273
162498
  getReviewThreads(input)
162274
162499
  ]);
162275
- const prFiles = threads.length > 0 ? await input.octokit.paginate(input.octokit.rest.pulls.listFiles, {
162276
- owner: input.owner,
162277
- repo: input.name,
162278
- pull_number: input.pullNumber,
162279
- per_page: 100
162280
- }) : [];
162500
+ const prFiles = threads.length > 0 ? await fetchPrFiles(
162501
+ { owner: input.owner, name: input.name, pullNumber: input.pullNumber },
162502
+ { octokit: input.octokit }
162503
+ ) : [];
162281
162504
  if (review.data.body) {
162282
162505
  review.data.body = await resolveBodyAssets({
162283
162506
  body: review.data.body,
@@ -162421,6 +162644,7 @@ function ResolveReviewThreadTool(ctx) {
162421
162644
  });
162422
162645
  const thread = response.resolveReviewThread.thread;
162423
162646
  log.info(`\xBB resolved review thread ${thread.id}`);
162647
+ invalidateReviewThreadCache({ owner: ctx.repo.owner, name: ctx.repo.name });
162424
162648
  return {
162425
162649
  thread_id: thread.id,
162426
162650
  is_resolved: thread.isResolved,
@@ -162595,7 +162819,10 @@ import { join as join20 } from "node:path";
162595
162819
  import { setTimeout as sleep2 } from "node:timers/promises";
162596
162820
  var ShellParams = type({
162597
162821
  command: "string",
162598
- description: "string",
162822
+ // advisory and unread — no code path consumes it. kept in the schema only
162823
+ // because it nudges the model to state intent before running a command;
162824
+ // REQUIRING it cost a full rejected turn every time one was omitted. #1140.
162825
+ "description?": "string",
162599
162826
  "timeout?": type.number.describe(
162600
162827
  "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."
162601
162828
  ),
@@ -162865,6 +163092,8 @@ Do NOT use this tool for git commands \u2014 use the dedicated git tools instead
162865
163092
  proc.on("exit", done);
162866
163093
  proc.on("error", () => done(null));
162867
163094
  });
163095
+ proc.stdout?.destroy();
163096
+ proc.stderr?.destroy();
162868
163097
  let output = stderr ? stdout ? `${stdout}
162869
163098
  ${stderr}` : stderr : stdout;
162870
163099
  if (timedOut)
@@ -163108,6 +163337,7 @@ function CheckoutRepoTool(ctx) {
163108
163337
  owner,
163109
163338
  name: repo,
163110
163339
  gitToken: rc.gitToken,
163340
+ refreshGitToken: rc.refreshGitToken,
163111
163341
  octokit: rc.octokit,
163112
163342
  toolState: ctx.toolState,
163113
163343
  shell: ctx.payload.shell,
@@ -163604,14 +163834,22 @@ function validateAgentApiKey(params) {
163604
163834
  }
163605
163835
  function isApiKeyAuthError(text) {
163606
163836
  if (!text) return false;
163607
- 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);
163837
+ 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);
163608
163838
  }
163609
163839
  function isOAuthCredentialExpiredError(text) {
163610
- return /authentication token has (expired|been invalidated)/i.test(text) || /OAuth access token has expired/i.test(text) || /Token refresh failed/i.test(text);
163840
+ return /(?:authentication|OAuth access) token has (?:expired|been (?:invalidated|revoked))/i.test(
163841
+ text
163842
+ ) || // the provider no longer recognises the token at all (#1086) — same dead
163843
+ // credential, phrased as a lookup miss rather than a state transition.
163844
+ /Could not find the appropriate key in your authentication token/i.test(text) || /Token refresh failed/i.test(text);
163611
163845
  }
163612
163846
  function isClaudeSubscriptionDisabledError(text) {
163613
163847
  return /disabled Claude subscription access/i.test(text);
163614
163848
  }
163849
+ var CLAUDE_SESSION_LIMIT_PATTERN = /hit your (?:session|weekly|five-hour|Opus|Sonnet|Haiku)\s+limit(?:\s*·\s*resets\s+([^"\n]+))?/i;
163850
+ function isClaudeSessionLimitError(text) {
163851
+ return CLAUDE_SESSION_LIMIT_PATTERN.test(text);
163852
+ }
163615
163853
  function formatApiKeyErrorSummary(params) {
163616
163854
  if (params.raw.includes(MISSING_KEY_MARKER)) {
163617
163855
  if (params.raw.startsWith(`**${MISSING_KEY_MARKER}**`)) return params.raw;
@@ -163619,6 +163857,15 @@ function formatApiKeyErrorSummary(params) {
163619
163857
  }
163620
163858
  const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
163621
163859
  const settingsUrl = `${getApiUrl()}/console/${params.owner}/${params.name}`;
163860
+ if (isClaudeSessionLimitError(params.raw)) {
163861
+ const reset = CLAUDE_SESSION_LIMIT_PATTERN.exec(params.raw)?.[1]?.trim();
163862
+ const resets = reset ? ` It resets at **${reset}**.` : "";
163863
+ return [
163864
+ `**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.`,
163865
+ "",
163866
+ `[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)`
163867
+ ].join("\n");
163868
+ }
163622
163869
  if (isClaudeSubscriptionDisabledError(params.raw)) {
163623
163870
  return [
163624
163871
  `**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.`,
@@ -164428,7 +164675,9 @@ function decideModelAccess(input) {
164428
164675
  if (input.proxyActive) {
164429
164676
  const target = resolveOpenRouterModel(input.model);
164430
164677
  if (input.oss) {
164431
- if (target && target === input.subsidyTarget) return { kind: "proxy", target };
164678
+ if (target && (target === input.subsidyTarget || isOssAllowedModel(input.model))) {
164679
+ return { kind: "proxy", target };
164680
+ }
164432
164681
  if (byokAuthorized) return { kind: "byok" };
164433
164682
  return { kind: "error", reason: "oss" };
164434
164683
  }
@@ -164440,6 +164689,11 @@ function decideModelAccess(input) {
164440
164689
  return { kind: "error", reason: "byok_no_key" };
164441
164690
  }
164442
164691
  var MODEL_ACCESS_MARKER = "requested model is not available";
164692
+ function ossAllowedLabels() {
164693
+ return OSS_MODEL_ALLOWLIST.map(
164694
+ (slug2) => `\`${resolveDisplayAlias(slug2)?.displayName ?? slug2}\``
164695
+ ).join(", ");
164696
+ }
164443
164697
  function buildModelAccessError(input) {
164444
164698
  const settingsUrl = `${getApiUrl()}/console/${input.owner}/${input.name}`;
164445
164699
  const secretsUrl = `https://github.com/${input.owner}/${input.name}/settings/secrets/actions`;
@@ -164447,8 +164701,8 @@ function buildModelAccessError(input) {
164447
164701
  const headline = `**The ${MODEL_ACCESS_MARKER}: \`${input.model}\`.**`;
164448
164702
  const branch = {
164449
164703
  oss: {
164450
- 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.",
164451
- cta: `[Add a provider key \u2192](${secretsUrl}) \xB7 [Setup docs \u2192](${docsUrl})`
164704
+ 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.`,
164705
+ cta: `[Configure model \u2192](${settingsUrl}) \xB7 [Add a provider key \u2192](${secretsUrl}) \xB7 [Setup docs \u2192](${docsUrl})`
164452
164706
  },
164453
164707
  byok_no_key: {
164454
164708
  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.`,
@@ -164695,6 +164949,14 @@ function resolvePromptFile(input) {
164695
164949
  }
164696
164950
  return content;
164697
164951
  }
164952
+ function warnIfDeprecatedStatusChecks(value2) {
164953
+ if (value2 !== void 0) {
164954
+ core6.warning(
164955
+ "`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."
164956
+ );
164957
+ }
164958
+ return value2;
164959
+ }
164698
164960
  function resolveNonPromptInputs() {
164699
164961
  return Inputs.omit("prompt", "prompt_file").assert({
164700
164962
  model: core6.getInput("model") || void 0,
@@ -164703,7 +164965,7 @@ function resolveNonPromptInputs() {
164703
164965
  cwd: core6.getInput("cwd") || void 0,
164704
164966
  push: core6.getInput("push") || void 0,
164705
164967
  shell: core6.getInput("shell") || void 0,
164706
- status_checks: core6.getInput("status_checks") || void 0,
164968
+ status_checks: warnIfDeprecatedStatusChecks(core6.getInput("status_checks") || void 0),
164707
164969
  progress_comments: core6.getInput("progress_comments") || void 0
164708
164970
  });
164709
164971
  }
@@ -164756,9 +165018,11 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
164756
165018
  // input is the source of truth when set (mirrors `push`); otherwise the repo
164757
165019
  // setting decides.
164758
165020
  runStatusCheck: inputs.status_checks === void 0 ? repoSettings.statusChecks : inputs.status_checks === "enabled",
164759
- // the `pullfrog-approval` verdict check stays opt-in and workflow-only. it exists to
164760
- // be *required* by branch protection, so it must never turn itself on.
164761
- approvalCheck: inputs.status_checks === "enabled",
165021
+ // the `pullfrog-approval` verdict check. `Repo.approvalCheck` is authoritative; the
165022
+ // `status_checks` input is DEPRECATED but still honoured, for the dormant installs the
165023
+ // backfill could not read (see `warnIfDeprecatedStatusChecks`). OR rather than override:
165024
+ // this can only ever turn the check ON, never off, so no existing user loses it.
165025
+ approvalCheck: repoSettings.approvalCheck || inputs.status_checks === "enabled",
164762
165026
  // temporary progress chrome. the workflow input is the source of truth when
164763
165027
  // set (mirrors `push`); otherwise the repo setting decides. defaults to true.
164764
165028
  progressComments: inputs.progress_comments === void 0 ? repoSettings.progressComments : inputs.progress_comments === "enabled",
@@ -165130,7 +165394,7 @@ async function resolveProxyModel(ctx) {
165130
165394
  if (ctx.oss) {
165131
165395
  ctx.toolState.modelClamped = { from: ctx.payload.model, reason: "oss" };
165132
165396
  log.info(
165133
- `\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.`
165397
+ `\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.`
165134
165398
  );
165135
165399
  } else if (isCardGatedModel(ctx.payload.model)) {
165136
165400
  ctx.toolState.modelClamped = { from: ctx.payload.model, reason: "card" };
@@ -165332,6 +165596,7 @@ var defaultSettings = {
165332
165596
  repoIntelligence: false,
165333
165597
  progressComments: true,
165334
165598
  statusChecks: true,
165599
+ approvalCheck: false,
165335
165600
  modeInstructions: {},
165336
165601
  learnings: null,
165337
165602
  learningsHeadings: [],
@@ -165559,6 +165824,40 @@ function formatBillingExhaustedBody(diagnostic) {
165559
165824
  function isProviderModelNotFoundError(message) {
165560
165825
  return message.includes("ProviderModelNotFoundError");
165561
165826
  }
165827
+ function isContextOverflowError(message) {
165828
+ 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);
165829
+ }
165830
+ function isNoProviderAvailableError(message) {
165831
+ return /\bNo provider available\b/i.test(message);
165832
+ }
165833
+ function formatNoProviderAvailableSummary(input) {
165834
+ const settingsUrl = `${getApiUrl()}/console/${input.owner}/${input.name}`;
165835
+ return [
165836
+ "**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.",
165837
+ "",
165838
+ "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.",
165839
+ "",
165840
+ `[Model settings \u2192](${settingsUrl}) \xB7 [Setup docs \u2192](https://docs.pullfrog.com/keys) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`,
165841
+ "",
165842
+ `\`\`\`
165843
+ ${input.raw}
165844
+ \`\`\``
165845
+ ].join("\n");
165846
+ }
165847
+ function formatContextOverflowSummary(input) {
165848
+ const settingsUrl = `${getApiUrl()}/console/${input.owner}/${input.name}`;
165849
+ return [
165850
+ "**This run exceeded the model's context window.** Pullfrog read more than the model could hold, so it stopped before finishing.",
165851
+ "",
165852
+ `Pick a model with a larger context window, or split this PR into smaller ones and re-trigger.`,
165853
+ "",
165854
+ `[Model settings \u2192](${settingsUrl}) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`,
165855
+ "",
165856
+ `\`\`\`
165857
+ ${input.raw}
165858
+ \`\`\``
165859
+ ].join("\n");
165860
+ }
165562
165861
  function formatGenericFailure(errorMessage) {
165563
165862
  return [
165564
165863
  "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.",
@@ -165580,12 +165879,18 @@ var PROVIDER_BILLING_URLS = {
165580
165879
  anthropic: "https://console.anthropic.com/settings/billing",
165581
165880
  openai: "https://platform.openai.com/account/billing",
165582
165881
  google: "https://aistudio.google.com/usage",
165583
- opencode: "https://opencode.ai/zen"
165882
+ opencode: "https://opencode.ai/zen",
165883
+ xai: "https://console.x.ai/team/default/billing",
165884
+ openrouter: "https://openrouter.ai/settings/credits"
165584
165885
  };
165585
165886
  function detectProviderId(message) {
165586
165887
  const harnessId = extractProviderId(message);
165587
165888
  if (harnessId) return harnessId;
165588
165889
  if (/credit balance is too low/i.test(message)) return "anthropic";
165890
+ if (/used all available credits/i.test(message)) return "xai";
165891
+ if (/requires more credits|Key limit exceeded \(total limit\)|openrouter\.ai/i.test(message)) {
165892
+ return "openrouter";
165893
+ }
165589
165894
  return null;
165590
165895
  }
165591
165896
  function formatProviderBillingExhausted(input) {
@@ -165613,7 +165918,7 @@ ${input.raw}
165613
165918
  \`\`\``;
165614
165919
  }
165615
165920
  function renderRunError(input) {
165616
- const billingError = isRouterKeylimitExhaustedError(input.errorMessage) ? new BillingError(input.errorMessage, { code: "router_keylimit_exhausted" }) : null;
165921
+ const billingError = input.routerActive && isRouterKeylimitExhaustedError(input.errorMessage) ? new BillingError(input.errorMessage, { code: "router_keylimit_exhausted" }) : null;
165617
165922
  if (billingError) {
165618
165923
  const body = formatBillingErrorSummary(billingError, input.repo.owner);
165619
165924
  return { summary: body, comment: body };
@@ -165653,6 +165958,26 @@ ${body}`, comment: body };
165653
165958
  });
165654
165959
  return { summary: body, comment: body };
165655
165960
  }
165961
+ if (isNoProviderAvailableError(input.errorMessage)) {
165962
+ const body = formatNoProviderAvailableSummary({
165963
+ owner: input.repo.owner,
165964
+ name: input.repo.name,
165965
+ raw: input.errorMessage
165966
+ });
165967
+ return { summary: `### \u274C Pullfrog failed
165968
+
165969
+ ${body}`, comment: body };
165970
+ }
165971
+ if (isContextOverflowError(input.errorMessage)) {
165972
+ const body = formatContextOverflowSummary({
165973
+ owner: input.repo.owner,
165974
+ name: input.repo.name,
165975
+ raw: input.errorMessage
165976
+ });
165977
+ return { summary: `### \u274C Pullfrog failed
165978
+
165979
+ ${body}`, comment: body };
165980
+ }
165656
165981
  if (hangBody) {
165657
165982
  const isBillingExhausted = input.agentDiagnostic?.lastProviderError === "provider billing exhausted";
165658
165983
  return {
@@ -166033,7 +166358,8 @@ async function finalizeSuccessRun(input) {
166033
166358
  const rendered = !input.result.success ? renderRunError({
166034
166359
  errorMessage: input.result.error || "agent run failed",
166035
166360
  repo: input.repo,
166036
- agentDiagnostic: input.toolState.agentDiagnostic
166361
+ agentDiagnostic: input.toolState.agentDiagnostic,
166362
+ routerActive: !!input.toolContext.payload.proxyModel
166037
166363
  }) : null;
166038
166364
  if (rendered) {
166039
166365
  await reportErrorToComment({
@@ -166481,7 +166807,9 @@ async function main() {
166481
166807
  }
166482
166808
  if (access.kind === "proxy") payload.proxyModel = access.target;
166483
166809
  if (access.kind === "byok") payload.proxyModel = void 0;
166484
- if (runContext.oss && payload.proxyModel) payload.effort = 0;
166810
+ if (runContext.oss && payload.proxyModel) {
166811
+ payload.effort = ossEffortFloor({ payload });
166812
+ }
166485
166813
  const resolvedModel = payload.proxyModel ? void 0 : resolveModel({ slug: payload.model });
166486
166814
  vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
166487
166815
  const agent2 = resolveAgent({ model: resolvedModel });
@@ -166508,8 +166836,15 @@ async function main() {
166508
166836
  });
166509
166837
  timer.checkpoint("git");
166510
166838
  const pmSpec = await resolvePackageManagerSpec(process.cwd());
166511
- if (pmSpec) {
166512
- await ensurePackageManager({ spec: pmSpec, binDir: packageManagerBinDir(tmpdir3) });
166839
+ const pmDetected = await detect({ cwd: process.cwd(), strategies: ["lockfile"] });
166840
+ const pmName = pmSpec?.name ?? pmDetected?.name ?? "npm";
166841
+ if (payload.shell !== "disabled") {
166842
+ const pmError = await provisionPackageManager({
166843
+ name: pmName,
166844
+ declared: pmSpec,
166845
+ binDir: packageManagerBinDir(tmpdir3)
166846
+ });
166847
+ if (pmError) log.warning(`\xBB could not provision ${pmName}: ${pmError}`);
166513
166848
  }
166514
166849
  timer.checkpoint("packageManager");
166515
166850
  const setupHook = await executeLifecycleHook({
@@ -166789,7 +167124,8 @@ ${instructions.user}` : null,
166789
167124
  const rendered = renderRunError({
166790
167125
  errorMessage,
166791
167126
  repo: runContext.repo,
166792
- agentDiagnostic: toolState.agentDiagnostic
167127
+ agentDiagnostic: toolState.agentDiagnostic,
167128
+ routerActive: !!payload.proxyModel
166793
167129
  });
166794
167130
  await writeRunErrorOutputs({ rendered, toolState });
166795
167131
  if (toolContext) {