pullfrog 0.1.51 → 0.1.53

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"
100246
+ },
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"
99944
100266
  },
99945
- // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
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",
@@ -99975,9 +100297,9 @@ var providers = {
99975
100297
  },
99976
100298
  "gemini-flash": {
99977
100299
  displayName: "Gemini Flash",
99978
- resolve: "google/gemini-3.5-flash",
100300
+ resolve: "google/gemini-3.6-flash",
99979
100301
  effort: ["minimal", "low", "medium", "high"],
99980
- openRouterResolve: "openrouter/google/gemini-3.5-flash"
100302
+ openRouterResolve: "openrouter/google/gemini-3.6-flash"
99981
100303
  }
99982
100304
  }
99983
100305
  }),
@@ -99987,26 +100309,26 @@ var providers = {
99987
100309
  models: {
99988
100310
  grok: {
99989
100311
  displayName: "Grok",
99990
- resolve: "xai/grok-4.3",
99991
- effort: ["none", "low", "medium", "high"],
99992
- openRouterResolve: "openrouter/x-ai/grok-4.3",
100312
+ resolve: "xai/grok-4.5",
100313
+ effort: ["low", "medium", "high"],
100314
+ openRouterResolve: "openrouter/x-ai/grok-4.5",
99993
100315
  preferred: true
99994
100316
  },
99995
100317
  // legacy aliases — xAI retired the entire fast/code-fast line on
99996
100318
  // 2026-05-15 (https://docs.x.ai/developers/migration/may-15-deprecation)
99997
100319
  // and now redirects every deprecated text-model slug to grok-4.3 at
99998
100320
  // standard pricing. fall back to the live `xai/grok` so the alias
99999
- // chain resolves to grok-4.3 for both direct-key and OpenRouter users.
100321
+ // chain resolves to grok-4.5 for both direct-key and OpenRouter users.
100000
100322
  "grok-fast": {
100001
100323
  displayName: "Grok Fast",
100002
100324
  resolve: "xai/grok-4-1-fast",
100003
- openRouterResolve: "openrouter/x-ai/grok-4.3",
100325
+ openRouterResolve: "openrouter/x-ai/grok-4.5",
100004
100326
  fallback: "xai/grok"
100005
100327
  },
100006
100328
  "grok-code-fast": {
100007
100329
  displayName: "Grok Code Fast",
100008
100330
  resolve: "xai/grok-code-fast-1",
100009
- openRouterResolve: "openrouter/x-ai/grok-4.3",
100331
+ openRouterResolve: "openrouter/x-ai/grok-4.5",
100010
100332
  fallback: "xai/grok"
100011
100333
  }
100012
100334
  }
@@ -100023,12 +100345,25 @@ var providers = {
100023
100345
  openRouterResolve: "openrouter/deepseek/deepseek-v4-pro",
100024
100346
  preferred: true
100025
100347
  },
100348
+ // DeepSeek upgrades the `deepseek-v4-flash` API model in place, so the
100349
+ // direct `resolve` needs no version. OpenRouter instead forked the 0731
100350
+ // release into its own id and left the April preview live under the
100351
+ // unversioned one at a HIGHER price ($0.14/$0.28 vs $0.09/$0.18) — so the
100352
+ // OpenRouter route can never use the bare id. it tracks the rolling
100353
+ // `~deepseek/*-latest` pointer (rule 4), which resolves to 0731 at the
100354
+ // same price today and follows the next in-place upgrade on its own,
100355
+ // rather than pinning a dated snapshot that goes stale every release.
100356
+ // 0731 gained a `low` rung and renamed the top to `max`, unlike Pro
100357
+ // (`high, max` direct / `high, xhigh` via OpenRouter). that ladder now
100358
+ // reads the same on BOTH routes — the in-place direct upgrade caught up
100359
+ // to the fork — so `low`, not `high`, is position 0 either way, which is
100360
+ // why the OSS effort floor in `main.ts` pins the `high` rung by name.
100026
100361
  "deepseek-flash": {
100027
100362
  displayName: "DeepSeek Flash",
100028
100363
  resolve: "deepseek/deepseek-v4-flash",
100029
- effort: ["high", "max"],
100030
- openRouterEffort: ["high", "xhigh"],
100031
- openRouterResolve: "openrouter/deepseek/deepseek-v4-flash"
100364
+ effort: ["low", "high", "max"],
100365
+ openRouterEffort: ["low", "high", "max"],
100366
+ openRouterResolve: "openrouter/~deepseek/deepseek-v4-flash-latest"
100032
100367
  },
100033
100368
  // legacy aliases — deepseek retires these on 2026-07-24; transparently
100034
100369
  // upgrade existing users to the v4 family via the fallback chain.
@@ -100097,30 +100432,30 @@ var providers = {
100097
100432
  resolve: "opencode/claude-haiku-4-5",
100098
100433
  openRouterResolve: "openrouter/anthropic/claude-haiku-4.5"
100099
100434
  },
100100
- gpt: {
100435
+ "gpt-sol": {
100101
100436
  displayName: "GPT Sol",
100102
100437
  resolve: "opencode/gpt-5.6-sol",
100103
100438
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100104
100439
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100105
100440
  subagentModel: "gpt-terra"
100106
100441
  },
100107
- // see openai/gpt-pro — Zen has no -pro id, so direct resolves to plain Sol.
100108
- "gpt-pro": {
100442
+ // see openai/gpt-sol-pro — Zen has no -pro id, so direct resolves to plain Sol.
100443
+ "gpt-sol-pro": {
100109
100444
  displayName: "GPT Sol Pro",
100110
100445
  description: "Maximum reasoning effort",
100111
100446
  resolve: "opencode/gpt-5.6-sol",
100112
100447
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100113
100448
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100114
- subagentModel: "gpt"
100449
+ subagentModel: "gpt-sol"
100115
100450
  },
100116
- // gpt-5.6 balanced mid-tier — selectable + `gpt`'s subagent. see openai above.
100451
+ // gpt-5.6 balanced mid-tier — selectable + Sol's subagent. see openai above.
100117
100452
  "gpt-terra": {
100118
100453
  displayName: "GPT Terra",
100119
100454
  resolve: "opencode/gpt-5.6-terra",
100120
100455
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100121
100456
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
100122
100457
  },
100123
- "gpt-mini": {
100458
+ "gpt-luna": {
100124
100459
  displayName: "GPT Luna",
100125
100460
  resolve: "opencode/gpt-5.6-luna",
100126
100461
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
@@ -100131,20 +100466,39 @@ var providers = {
100131
100466
  displayName: "GPT Codex",
100132
100467
  resolve: "opencode/gpt-5.3-codex",
100133
100468
  openRouterResolve: "openrouter/openai/gpt-5.3-codex",
100134
- fallback: "opencode/gpt"
100469
+ fallback: "opencode/gpt-sol"
100135
100470
  },
100136
100471
  "gpt-codex-mini": {
100137
100472
  displayName: "GPT Codex Mini",
100138
100473
  resolve: "opencode/gpt-5.1-codex-mini",
100139
100474
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
100140
- fallback: "opencode/gpt-mini"
100475
+ fallback: "opencode/gpt-luna"
100476
+ },
100477
+ // pre-5.6 tier slugs — see openai provider above.
100478
+ gpt: {
100479
+ displayName: "GPT",
100480
+ resolve: "opencode/gpt-5.6-sol",
100481
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100482
+ fallback: "opencode/gpt-sol"
100483
+ },
100484
+ "gpt-pro": {
100485
+ displayName: "GPT Pro",
100486
+ resolve: "opencode/gpt-5.6-sol",
100487
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100488
+ fallback: "opencode/gpt-sol-pro"
100141
100489
  },
100142
- // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
100490
+ "gpt-mini": {
100491
+ displayName: "GPT Mini",
100492
+ resolve: "opencode/gpt-5.6-luna",
100493
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna",
100494
+ fallback: "opencode/gpt-luna"
100495
+ },
100496
+ // dropped hidden subagent tier — folds stored pins forward to Sol.
100143
100497
  "gpt-5.4": {
100144
100498
  displayName: "GPT 5.4",
100145
100499
  resolve: "opencode/gpt-5.4",
100146
100500
  openRouterResolve: "openrouter/openai/gpt-5.4",
100147
- fallback: "opencode/gpt"
100501
+ fallback: "opencode/gpt-sol"
100148
100502
  },
100149
100503
  "gemini-pro": {
100150
100504
  displayName: "Gemini Pro",
@@ -100155,21 +100509,19 @@ var providers = {
100155
100509
  },
100156
100510
  "gemini-flash": {
100157
100511
  displayName: "Gemini Flash",
100158
- resolve: "opencode/gemini-3.5-flash",
100512
+ resolve: "opencode/gemini-3.6-flash",
100159
100513
  effort: ["minimal", "low", "medium", "high"],
100160
- openRouterResolve: "openrouter/google/gemini-3.5-flash"
100514
+ openRouterResolve: "openrouter/google/gemini-3.6-flash"
100161
100515
  },
100162
100516
  "kimi-k2": {
100163
100517
  displayName: "Kimi K2",
100164
- // opencode Zen serves only up to k2.6; the OpenRouter fallback (used for
100165
- // router/oss proxy runs) takes the newer k2.7-code.
100166
- resolve: "opencode/kimi-k2.6",
100518
+ resolve: "opencode/kimi-k2.7-code",
100167
100519
  openRouterResolve: "openrouter/moonshotai/kimi-k2.7-code"
100168
100520
  },
100169
- // Zen serves m2.5; the funded OpenRouter path tracks the current m2.7.
100521
+ // slug pins the m2 line for DB stability; resolve tracks the current m2.7.
100170
100522
  "minimax-m2.5": {
100171
100523
  displayName: "MiniMax M2",
100172
- resolve: "opencode/minimax-m2.5",
100524
+ resolve: "opencode/minimax-m2.7",
100173
100525
  openRouterResolve: "openrouter/minimax/minimax-m2.7"
100174
100526
  },
100175
100527
  "gpt-5-nano": {
@@ -100300,30 +100652,30 @@ var providers = {
100300
100652
  // alias): after the Sol/Terra/Luna rename, ~gpt-mini-latest no longer maps
100301
100653
  // to Luna, so rolling aliases would silently diverge `gpt`/`gpt-mini` from
100302
100654
  // the chosen tiers across funding paths.
100303
- gpt: {
100655
+ "gpt-sol": {
100304
100656
  displayName: "GPT Sol",
100305
100657
  resolve: "openrouter/openai/gpt-5.6-sol",
100306
100658
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100307
100659
  openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100308
100660
  subagentModel: "gpt-terra"
100309
100661
  },
100310
- // see openai/gpt-pro. openrouter serves sol-pro directly on both routes.
100311
- "gpt-pro": {
100662
+ // see openai/gpt-sol-pro. openrouter serves sol-pro directly on both routes.
100663
+ "gpt-sol-pro": {
100312
100664
  displayName: "GPT Sol Pro",
100313
100665
  description: "Maximum reasoning effort",
100314
100666
  resolve: "openrouter/openai/gpt-5.6-sol-pro",
100315
100667
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100316
100668
  openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100317
- subagentModel: "gpt"
100669
+ subagentModel: "gpt-sol"
100318
100670
  },
100319
- // gpt-5.6 balanced mid-tier — selectable + `gpt`'s subagent. see openai above.
100671
+ // gpt-5.6 balanced mid-tier — selectable + Sol's subagent. see openai above.
100320
100672
  "gpt-terra": {
100321
100673
  displayName: "GPT Terra",
100322
100674
  resolve: "openrouter/openai/gpt-5.6-terra",
100323
100675
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
100324
100676
  openRouterResolve: "openrouter/openai/gpt-5.6-terra"
100325
100677
  },
100326
- "gpt-mini": {
100678
+ "gpt-luna": {
100327
100679
  displayName: "GPT Luna",
100328
100680
  resolve: "openrouter/openai/gpt-5.6-luna",
100329
100681
  effort: ["none", "low", "medium", "high", "xhigh", "max"],
@@ -100334,20 +100686,39 @@ var providers = {
100334
100686
  displayName: "GPT Codex",
100335
100687
  resolve: "openrouter/openai/gpt-5.3-codex",
100336
100688
  openRouterResolve: "openrouter/openai/gpt-5.3-codex",
100337
- fallback: "openrouter/gpt"
100689
+ fallback: "openrouter/gpt-sol"
100338
100690
  },
100339
100691
  "gpt-codex-mini": {
100340
100692
  displayName: "GPT Codex Mini",
100341
100693
  resolve: "openrouter/openai/gpt-5.1-codex-mini",
100342
100694
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
100343
- fallback: "openrouter/gpt-mini"
100695
+ fallback: "openrouter/gpt-luna"
100696
+ },
100697
+ // pre-5.6 tier slugs — see openai provider above.
100698
+ gpt: {
100699
+ displayName: "GPT",
100700
+ resolve: "openrouter/openai/gpt-5.6-sol",
100701
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
100702
+ fallback: "openrouter/gpt-sol"
100344
100703
  },
100345
- // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
100704
+ "gpt-pro": {
100705
+ displayName: "GPT Pro",
100706
+ resolve: "openrouter/openai/gpt-5.6-sol-pro",
100707
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
100708
+ fallback: "openrouter/gpt-sol-pro"
100709
+ },
100710
+ "gpt-mini": {
100711
+ displayName: "GPT Mini",
100712
+ resolve: "openrouter/openai/gpt-5.6-luna",
100713
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna",
100714
+ fallback: "openrouter/gpt-luna"
100715
+ },
100716
+ // dropped hidden subagent tier — folds stored pins forward to Sol.
100346
100717
  "gpt-5.4": {
100347
100718
  displayName: "GPT 5.4",
100348
100719
  resolve: "openrouter/openai/gpt-5.4",
100349
100720
  openRouterResolve: "openrouter/openai/gpt-5.4",
100350
- fallback: "openrouter/gpt"
100721
+ fallback: "openrouter/gpt-sol"
100351
100722
  },
100352
100723
  "o4-mini": {
100353
100724
  displayName: "O4 Mini",
@@ -100370,9 +100741,9 @@ var providers = {
100370
100741
  },
100371
100742
  grok: {
100372
100743
  displayName: "Grok",
100373
- resolve: "openrouter/x-ai/grok-4.3",
100374
- effort: ["none", "low", "medium", "high"],
100375
- openRouterResolve: "openrouter/x-ai/grok-4.3"
100744
+ resolve: "openrouter/x-ai/grok-4.5",
100745
+ effort: ["low", "medium", "high"],
100746
+ openRouterResolve: "openrouter/x-ai/grok-4.5"
100376
100747
  },
100377
100748
  "deepseek-pro": {
100378
100749
  displayName: "DeepSeek Pro",
@@ -100380,11 +100751,13 @@ var providers = {
100380
100751
  effort: ["high", "xhigh"],
100381
100752
  openRouterResolve: "openrouter/deepseek/deepseek-v4-pro"
100382
100753
  },
100754
+ // rolling pointer, not the bare id — see `deepseek/deepseek-flash` for why
100755
+ // OpenRouter's unversioned `deepseek-v4-flash` is the stale April preview.
100383
100756
  "deepseek-flash": {
100384
100757
  displayName: "DeepSeek Flash",
100385
- resolve: "openrouter/deepseek/deepseek-v4-flash",
100386
- effort: ["high", "xhigh"],
100387
- openRouterResolve: "openrouter/deepseek/deepseek-v4-flash"
100758
+ resolve: "openrouter/~deepseek/deepseek-v4-flash-latest",
100759
+ effort: ["low", "high", "max"],
100760
+ openRouterResolve: "openrouter/~deepseek/deepseek-v4-flash-latest"
100388
100761
  },
100389
100762
  // legacy alias — deepseek retires this on 2026-07-24; transparently
100390
100763
  // upgrade existing users to the v4 family via the fallback chain.
@@ -100465,7 +100838,7 @@ var modelAliases = Object.entries(providers).flatMap(
100465
100838
  var AUTO_EFFICIENT = "auto/efficient";
100466
100839
  var AUTO_INTELLIGENT = "auto/intelligent";
100467
100840
  var AUTO_TIER_TARGET = {
100468
- [AUTO_EFFICIENT]: "deepseek/deepseek-pro",
100841
+ [AUTO_EFFICIENT]: "deepseek/deepseek-flash",
100469
100842
  [AUTO_INTELLIGENT]: "anthropic/claude-opus"
100470
100843
  };
100471
100844
  function isAutoTier(slug2) {
@@ -100514,6 +100887,26 @@ if (!defaultProxyAlias?.openRouterResolve) {
100514
100887
  }
100515
100888
  var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
100516
100889
  var defaultProxyDisplayName = defaultProxyAlias.displayName;
100890
+ var OSS_MODEL_ALLOWLIST = [
100891
+ "deepseek/deepseek-flash",
100892
+ "deepseek/deepseek-pro",
100893
+ "openai/gpt-luna",
100894
+ "openrouter/minimax-m2.5",
100895
+ "moonshotai/kimi-k2"
100896
+ ];
100897
+ var OSS_RECOMMENDED_MODEL = AUTO_TIER_TARGET[AUTO_EFFICIENT];
100898
+ var ossAllowedTargets = new Set(
100899
+ OSS_MODEL_ALLOWLIST.map((slug2) => {
100900
+ const target = resolveOpenRouterModel(slug2);
100901
+ if (!target) throw new Error(`OSS_MODEL_ALLOWLIST: ${slug2} has no openRouterResolve`);
100902
+ return target;
100903
+ })
100904
+ );
100905
+ function isOssAllowedModel(slug2) {
100906
+ if (!slug2) return false;
100907
+ const target = resolveOpenRouterModel(slug2);
100908
+ return target !== void 0 && ossAllowedTargets.has(target);
100909
+ }
100517
100910
  var BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
100518
100911
  var VERTEX_MODEL_ID_ENV = "VERTEX_MODEL_ID";
100519
100912
  var OPENAI_COMPATIBLE_PROVIDER = "openai-compatible";
@@ -101119,7 +101512,21 @@ var PROVIDER_ERROR_PATTERNS = [
101119
101512
  { regex: /\bFreeUsageLimitError\b/, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101120
101513
  { regex: /Insufficient balance/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101121
101514
  { regex: /credit balance is too low/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101122
- { regex: /spending cap/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101515
+ // "spending cap" (Gemini) and "spending limit" (xAI, #1076) are the same
101516
+ // condition in two house styles — a configured ceiling was reached.
101517
+ { regex: /spending (?:cap|limit)/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101518
+ // xAI exhausts credits and the monthly ceiling in one 403 whose status code
101519
+ // sits nowhere near a `status:` key, so no status pattern below fires (#1076).
101520
+ { regex: /used all available credits/i, label: PROVIDER_BILLING_EXHAUSTED_LABEL },
101521
+ // the OpenRouter shapes `isRouterKeylimitExhaustedError` matches. on a Router
101522
+ // run those mean the PULLFROG wallet is empty and `renderRunError` returns a
101523
+ // `BillingError` before ever reaching this list; on a BYOK run the very same
101524
+ // wire text means the user's OWN OpenRouter wallet is empty, and this entry is
101525
+ // what gives them the right dashboard instead of ours. see #1135.
101526
+ {
101527
+ regex: /requires more credits|Key limit exceeded \(total limit\)/i,
101528
+ label: PROVIDER_BILLING_EXHAUSTED_LABEL
101529
+ },
101123
101530
  // auth patterns must come BEFORE rate-limit patterns. OpenRouter 401 error
101124
101531
  // payloads carry `x-ratelimit-*` response headers in the dump, and the
101125
101532
  // free-form rate-limit regex below would otherwise win on word-boundary
@@ -101215,6 +101622,12 @@ function resolveRunAlias(ctx) {
101215
101622
  if (!model) return void 0;
101216
101623
  return modelAliases.find((a) => !a.fallback && a.resolve === model) ?? matchHostedAnthropicAlias(model);
101217
101624
  }
101625
+ function ossEffortFloor(ctx) {
101626
+ const alias = resolveRunAlias(ctx);
101627
+ const published = alias?.openRouterEffort ?? alias?.effort;
101628
+ if (!published) return 0;
101629
+ return rungPosition({ rung: "high", published }) ?? 0;
101630
+ }
101218
101631
  function resolveRunEffort(ctx) {
101219
101632
  const configured = ctx.payload.effort !== void 0;
101220
101633
  const position = ctx.payload.effort ?? DEFAULT_EFFORT_POSITION;
@@ -101245,7 +101658,7 @@ var import_semver = __toESM(require_semver2(), 1);
101245
101658
  // package.json
101246
101659
  var package_default = {
101247
101660
  name: "pullfrog",
101248
- version: "0.1.51",
101661
+ version: "0.1.53",
101249
101662
  type: "module",
101250
101663
  bin: {
101251
101664
  pullfrog: "dist/cli.mjs",
@@ -108902,6 +109315,41 @@ function bootstrapPullfrogDataDir() {
108902
109315
  }
108903
109316
  }
108904
109317
 
109318
+ // utils/worktree.ts
109319
+ async function dirtyTrackedPaths() {
109320
+ const result = await spawn({
109321
+ cmd: "git",
109322
+ args: ["diff", "--name-only", "HEAD"],
109323
+ env: process.env,
109324
+ activityTimeout: 0
109325
+ });
109326
+ if (result.exitCode !== 0) {
109327
+ throw new Error(
109328
+ `git diff --name-only HEAD failed (exit ${result.exitCode}): ${result.stderr.trim() || "(no stderr)"}`
109329
+ );
109330
+ }
109331
+ return new Set(result.stdout.split("\n").filter(Boolean));
109332
+ }
109333
+ async function restoreDirtiedSince(params) {
109334
+ const dirtied = [...await dirtyTrackedPaths()].filter((path4) => !params.before.has(path4));
109335
+ if (dirtied.length === 0) return;
109336
+ const result = await spawn({
109337
+ cmd: "git",
109338
+ args: ["restore", "--staged", "--worktree", "--", ...dirtied],
109339
+ env: process.env,
109340
+ activityTimeout: 0
109341
+ });
109342
+ if (result.exitCode !== 0) {
109343
+ log.warning(
109344
+ `\xBB failed to restore ${dirtied.length} tracked file(s) modified by ${params.actor}: ${result.stderr.trim() || "(no stderr)"}`
109345
+ );
109346
+ return;
109347
+ }
109348
+ log.info(
109349
+ `\xBB restored ${dirtied.length} tracked file(s) modified by ${params.actor}: ${dirtied.join(", ")}`
109350
+ );
109351
+ }
109352
+
108905
109353
  // agents/opencodePlugin.ts
108906
109354
  var PULLFROG_BUS_EVENT_TYPE = "pullfrog_bus_event";
108907
109355
  var PULLFROG_OPENCODE_GATE_PLUGIN_FILENAME = "pullfrog-subagent-gate.ts";
@@ -109787,6 +110235,7 @@ var opencode = agent({
109787
110235
  }
109788
110236
  log.debug(`\xBB starting Pullfrog (OpenCode, in-process SDK): ${cliPath}`);
109789
110237
  log.debug(`\xBB working directory: ${repoDir}`);
110238
+ const preBootDirty = await dirtyTrackedPaths();
109790
110239
  const server = await bootOpencodeServer({ cliPath, env: env2, cwd: repoDir });
109791
110240
  const dispatcher = new import_undici.Agent({ headersTimeout: 0, bodyTimeout: 0, connectTimeout: 0 });
109792
110241
  const fetchWithoutTimeout = (input, init) => {
@@ -109807,6 +110256,7 @@ var opencode = agent({
109807
110256
  fetch: fetchWithoutTimeout
109808
110257
  });
109809
110258
  const sessionResp = await client2.session.create({ title: "Pullfrog" });
110259
+ await restoreDirtiedSince({ before: preBootDirty, actor: "agent startup" });
109810
110260
  if (sessionResp.error || !sessionResp.data) {
109811
110261
  const msg = sessionResp.error ? formatPromptError(sessionResp.error) : "session.create returned no data";
109812
110262
  return {
@@ -116535,7 +116985,7 @@ var Server = class extends Protocol {
116535
116985
  };
116536
116986
 
116537
116987
  // node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
116538
- import process3 from "node:process";
116988
+ import process4 from "node:process";
116539
116989
 
116540
116990
  // node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
116541
116991
  var ReadBuffer = class {
@@ -116567,7 +117017,7 @@ function serializeMessage(message) {
116567
117017
 
116568
117018
  // node_modules/.pnpm/@modelcontextprotocol+sdk@1.27.1_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
116569
117019
  var StdioServerTransport = class {
116570
- constructor(_stdin = process3.stdin, _stdout = process3.stdout) {
117020
+ constructor(_stdin = process4.stdin, _stdout = process4.stdout) {
116571
117021
  this._stdin = _stdin;
116572
117022
  this._stdout = _stdout;
116573
117023
  this._readBuffer = new ReadBuffer();
@@ -120002,7 +120452,7 @@ var Hono2 = class extends Hono {
120002
120452
  import { createRequire } from "node:module";
120003
120453
  import { randomUUID as randomUUID2 } from "node:crypto";
120004
120454
  import { URL as URL$1 } from "node:url";
120005
- import fs from "fs";
120455
+ import fs2 from "fs";
120006
120456
  import http from "http";
120007
120457
  import https from "https";
120008
120458
  var __create2 = Object.create;
@@ -134570,17 +135020,17 @@ var startHTTPServer = async ({ apiKey, authenticate, cors, createServer: createS
134570
135020
  if (sslCa || sslCert || sslKey) {
134571
135021
  const options = {};
134572
135022
  if (sslCa) try {
134573
- options.ca = fs.readFileSync(sslCa);
135023
+ options.ca = fs2.readFileSync(sslCa);
134574
135024
  } catch (error$1) {
134575
135025
  throw new Error(`Failed to read CA file '${sslCa}': ${error$1.message}`);
134576
135026
  }
134577
135027
  if (sslCert) try {
134578
- options.cert = fs.readFileSync(sslCert);
135028
+ options.cert = fs2.readFileSync(sslCert);
134579
135029
  } catch (error$1) {
134580
135030
  throw new Error(`Failed to read certificate file '${sslCert}': ${error$1.message}`);
134581
135031
  }
134582
135032
  if (sslKey) try {
134583
- options.key = fs.readFileSync(sslKey);
135033
+ options.key = fs2.readFileSync(sslKey);
134584
135034
  } catch (error$1) {
134585
135035
  throw new Error(`Failed to read key file '${sslKey}': ${error$1.message}`);
134586
135036
  }
@@ -143007,6 +143457,24 @@ function isSafeEnvVar(key) {
143007
143457
  if (SAFE_ENV_NAMES.has(key)) return true;
143008
143458
  return SAFE_ENV_PREFIXES.some((p) => key.startsWith(p));
143009
143459
  }
143460
+ var WORKFLOW_COMMAND_ENV_NAMES = [
143461
+ "GITHUB_ENV",
143462
+ "GITHUB_PATH",
143463
+ "GITHUB_OUTPUT",
143464
+ "GITHUB_STATE",
143465
+ "GITHUB_STEP_SUMMARY",
143466
+ // dropping the five paths above but keeping RUNNER_TEMP would be theatre:
143467
+ // the file-command files live in `$RUNNER_TEMP/_runner_file_commands/`, so the
143468
+ // directory is one `ls` away. nothing in the install path reads it (only our
143469
+ // own leak-surface wipe in `setup.ts`, which runs in the parent), and package
143470
+ // managers use TMPDIR.
143471
+ "RUNNER_TEMP"
143472
+ ];
143473
+ function filterEnvForUntrustedCode() {
143474
+ const env2 = filterEnv();
143475
+ for (const name of WORKFLOW_COMMAND_ENV_NAMES) delete env2[name];
143476
+ return env2;
143477
+ }
143010
143478
  function filterEnv() {
143011
143479
  const filtered = {};
143012
143480
  for (const [key, value2] of Object.entries(process.env)) {
@@ -151200,6 +151668,8 @@ import { join as join8 } from "node:path";
151200
151668
 
151201
151669
  // utils/shell.ts
151202
151670
  import { spawnSync as spawnSync5 } from "node:child_process";
151671
+ var MAX_BUFFER_BYTES = 32 * 1024 * 1024;
151672
+ var MAX_ERROR_DETAIL_CHARS = 2e4;
151203
151673
  function $(cmd, args2, options) {
151204
151674
  const encoding = options?.encoding ?? "utf-8";
151205
151675
  const env2 = resolveEnv(options?.env);
@@ -151207,7 +151677,8 @@ function $(cmd, args2, options) {
151207
151677
  stdio: ["ignore", "pipe", "pipe"],
151208
151678
  encoding,
151209
151679
  cwd: options?.cwd,
151210
- env: env2
151680
+ env: env2,
151681
+ maxBuffer: MAX_BUFFER_BYTES
151211
151682
  });
151212
151683
  const stdout = result.stdout ?? "";
151213
151684
  const stderr = result.stderr ?? "";
@@ -151225,6 +151696,11 @@ function $(cmd, args2, options) {
151225
151696
  }
151226
151697
  }
151227
151698
  if (result.status !== 0) {
151699
+ if (result.error && "code" in result.error && result.error.code === "ENOBUFS") {
151700
+ throw new Error(
151701
+ `Command produced more than ${MAX_BUFFER_BYTES / 1024 / 1024}MB of output and was terminated: ${cmd} ${args2.join(" ")}`
151702
+ );
151703
+ }
151228
151704
  const errorResult = {
151229
151705
  status: result.status ?? -1,
151230
151706
  stdout,
@@ -151234,7 +151710,7 @@ function $(cmd, args2, options) {
151234
151710
  options.onError(errorResult);
151235
151711
  return stdout.trim();
151236
151712
  }
151237
- const detail = [stderr, stdout].map((s) => s.trim()).filter(Boolean).join("\n");
151713
+ const detail = [stderr, stdout].map((s) => s.trim()).filter(Boolean).join("\n").slice(0, MAX_ERROR_DETAIL_CHARS);
151238
151714
  throw new Error(
151239
151715
  `Command failed with exit code ${errorResult.status}: ${detail || "Unknown error"}`
151240
151716
  );
@@ -151243,6 +151719,10 @@ function $(cmd, args2, options) {
151243
151719
  }
151244
151720
 
151245
151721
  // utils/gitAuth.ts
151722
+ var TRANSIENT_AUTH_PATTERNS = [
151723
+ /Invalid username or token/,
151724
+ /Authentication failed for 'https:\/\/github\.com\//
151725
+ ];
151246
151726
  var gitBinary;
151247
151727
  function hashFile(path4) {
151248
151728
  return createHash("sha256").update(readFileSync2(path4)).digest("hex");
@@ -151359,6 +151839,17 @@ async function $gitFetchWithDeepen(args2, options, label) {
151359
151839
  return await $git("fetch", args2, options);
151360
151840
  } catch (err) {
151361
151841
  const msg = err instanceof Error ? err.message : String(err);
151842
+ if (TRANSIENT_AUTH_PATTERNS.some((p) => p.test(msg)) && options.refreshGitToken) {
151843
+ log.info(
151844
+ `\xBB ${label ?? "git fetch"} hit an auth error, re-minting the git token and retrying`
151845
+ );
151846
+ const fresh = await options.refreshGitToken(options.token);
151847
+ return await $gitFetchWithDeepen(
151848
+ args2,
151849
+ { ...options, token: fresh, refreshGitToken: void 0 },
151850
+ label
151851
+ );
151852
+ }
151362
151853
  const isShallowUnreachable = SHALLOW_UNREACHABLE_PATTERNS.some((p) => p.test(msg));
151363
151854
  if (!isShallowUnreachable) throw err;
151364
151855
  const isShallow = $("git", ["rev-parse", "--is-shallow-repository"], { log: false }).trim() === "true";
@@ -151478,10 +151969,12 @@ function computeIncrementalDiff(params) {
151478
151969
  ],
151479
151970
  { log: false }
151480
151971
  );
151481
- return postProcessRangeDiff(raw2);
151972
+ const processed = postProcessRangeDiff(raw2);
151973
+ return processed === null ? { status: "empty" } : { status: "ok", diff: processed };
151482
151974
  } catch (e) {
151483
- log.debug(`\xBB range-diff failed: ${e instanceof Error ? e.message : String(e)}`);
151484
- return null;
151975
+ const reason = e instanceof Error ? e.message : String(e);
151976
+ log.warning(`\xBB incremental diff unavailable: range-diff failed: ${reason}`);
151977
+ return { status: "unavailable", reason };
151485
151978
  }
151486
151979
  }
151487
151980
  function isDiffPrefix(ch) {
@@ -152913,7 +153406,7 @@ throttling.VERSION = VERSION;
152913
153406
  throttling.triggersNotification = triggersNotification;
152914
153407
 
152915
153408
  // node_modules/.pnpm/universal-user-agent@7.0.3/node_modules/universal-user-agent/index.js
152916
- function getUserAgent() {
153409
+ function getUserAgent2() {
152917
153410
  if (typeof navigator === "object" && "userAgent" in navigator) {
152918
153411
  return navigator.userAgent;
152919
153412
  }
@@ -153031,7 +153524,7 @@ var before_after_hook_default = { Singular, Collection };
153031
153524
 
153032
153525
  // node_modules/.pnpm/@octokit+endpoint@11.0.1/node_modules/@octokit/endpoint/dist-bundle/index.js
153033
153526
  var VERSION2 = "0.0.0-development";
153034
- var userAgent = `octokit-endpoint.js/${VERSION2} ${getUserAgent()}`;
153527
+ var userAgent = `octokit-endpoint.js/${VERSION2} ${getUserAgent2()}`;
153035
153528
  var DEFAULTS = {
153036
153529
  method: "GET",
153037
153530
  baseUrl: "https://api.github.com",
@@ -153388,7 +153881,7 @@ var RequestError = class extends Error {
153388
153881
  var VERSION3 = "10.0.5";
153389
153882
  var defaults_default = {
153390
153883
  headers: {
153391
- "user-agent": `octokit-request.js/${VERSION3} ${getUserAgent()}`
153884
+ "user-agent": `octokit-request.js/${VERSION3} ${getUserAgent2()}`
153392
153885
  }
153393
153886
  };
153394
153887
  function isPlainObject4(value2) {
@@ -153653,7 +154146,7 @@ function withDefaults3(request2, newDefaults) {
153653
154146
  }
153654
154147
  var graphql2 = withDefaults3(request, {
153655
154148
  headers: {
153656
- "user-agent": `octokit-graphql.js/${VERSION4} ${getUserAgent()}`
154149
+ "user-agent": `octokit-graphql.js/${VERSION4} ${getUserAgent2()}`
153657
154150
  },
153658
154151
  method: "POST",
153659
154152
  url: "/graphql"
@@ -153733,7 +154226,7 @@ function createLogger(logger = {}) {
153733
154226
  }
153734
154227
  return logger;
153735
154228
  }
153736
- var userAgentTrail = `octokit-core.js/${VERSION5} ${getUserAgent()}`;
154229
+ var userAgentTrail = `octokit-core.js/${VERSION5} ${getUserAgent2()}`;
153737
154230
  var Octokit = class {
153738
154231
  static VERSION = VERSION5;
153739
154232
  static defaults(defaults) {
@@ -156701,8 +157194,13 @@ function createOctokit(token, refreshAuth) {
156701
157194
  var readOctokitByToken = /* @__PURE__ */ new Map();
156702
157195
  function resolveRepoCtx(ctx, repo) {
156703
157196
  const owner = ctx.repo.owner;
156704
- const name = repo ?? ctx.repo.name;
156705
- const state = requireRepoState(ctx.toolState, owner, name);
157197
+ const name = repo?.trim() || ctx.repo.name;
157198
+ const state = ctx.toolState.repos.get(repoKey(owner, name));
157199
+ if (!state) {
157200
+ throw new Error(
157201
+ 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}`
157202
+ );
157203
+ }
156706
157204
  if (state.access !== "read") {
156707
157205
  return {
156708
157206
  owner,
@@ -157419,10 +157917,6 @@ var TRANSIENT_PATTERNS = [
157419
157917
  /HTTP 429/,
157420
157918
  /returned error: 429/i
157421
157919
  ];
157422
- var TRANSIENT_AUTH_PATTERNS = [
157423
- /Invalid username or token/,
157424
- /Authentication failed for 'https:\/\/github\.com\//
157425
- ];
157426
157920
  function classifyPushError(msg) {
157427
157921
  if (CONCURRENT_PUSH_PATTERNS.some((p) => msg.includes(p))) return "concurrent-push";
157428
157922
  if (TRANSIENT_AUTH_PATTERNS.some((p) => p.test(msg))) return "transient-auth";
@@ -157921,7 +158415,11 @@ function GitFetchTool(ctx) {
157921
158415
  if (params.depth !== void 0) {
157922
158416
  fetchArgs.push(`--depth=${params.depth}`);
157923
158417
  }
157924
- await $gitFetchWithDeepen(fetchArgs, { token: rc.gitToken, cwd: rc.dir }, "git_fetch");
158418
+ await $gitFetchWithDeepen(
158419
+ fetchArgs,
158420
+ { token: rc.gitToken, cwd: rc.dir, refreshGitToken: rc.refreshGitToken },
158421
+ "git_fetch"
158422
+ );
157925
158423
  return { success: true, ref: params.ref };
157926
158424
  })
157927
158425
  });
@@ -158010,7 +158508,7 @@ function formatModelLabel(params) {
158010
158508
  const ossBase = `\`${displayName}\` (free via [Pullfrog for OSS](https://pullfrog.com/for-oss))`;
158011
158509
  if (params.clamped?.reason !== "oss") return ossBase;
158012
158510
  const configured = isAutoTier(params.clamped.from) ? "the intelligent tier" : `\`${resolveDisplayAlias(params.clamped.from)?.displayName ?? params.clamped.from}\``;
158013
- return `${ossBase} (${configured} not used \u2014 the program covers this model; add its [provider key](https://docs.pullfrog.com/models) to run your pick)`;
158511
+ 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)`;
158014
158512
  }
158015
158513
  const base = alias?.isFree ? `\`${displayName}\` (free)` : `\`${displayName}\``;
158016
158514
  if (params.fallbackFrom) {
@@ -159558,7 +160056,7 @@ async function ensureBeforeShaReachable(params) {
159558
160056
  }), true);
159559
160057
  await $gitFetchWithDeepen(
159560
160058
  ["--no-tags", ...params.isShallow ? ["--depth=1"] : [], "origin", tempBranch],
159561
- { token: params.gitToken },
160059
+ { token: params.gitToken, refreshGitToken: params.refreshGitToken },
159562
160060
  `before_sha temp branch ${tempBranch}`
159563
160061
  );
159564
160062
  log.debug(`\xBB fetched before_sha via temp branch ${tempBranch}`);
@@ -159574,6 +160072,14 @@ async function ensureBeforeShaReachable(params) {
159574
160072
  return false;
159575
160073
  }
159576
160074
  }
160075
+ function hasLocalCommit(sha) {
160076
+ if (!sha) return false;
160077
+ try {
160078
+ return $("git", ["cat-file", "-t", sha], { log: false }).trim() === "commit";
160079
+ } catch {
160080
+ return false;
160081
+ }
160082
+ }
159577
160083
  var STALE_LOCK_AGE_MS = 3e4;
159578
160084
  var PULL_REF_RETRY_DELAYS_MS = [2e3, 5e3, 1e4];
159579
160085
  var PULL_REF_MISSING_PATTERN = /couldn't find remote ref pull\/\d+\/head/i;
@@ -159624,7 +160130,7 @@ async function abortIfPullRequestMoved(args2) {
159624
160130
  );
159625
160131
  }
159626
160132
  async function checkoutPrBranch(pr, params) {
159627
- const { octokit, owner, name, gitToken, toolState, beforeSha } = params;
160133
+ const { octokit, owner, name, gitToken, refreshGitToken, toolState, beforeSha } = params;
159628
160134
  rejectIfLeadingDash(pr.baseRef, "PR base ref");
159629
160135
  rejectIfLeadingDash(pr.headRef, "PR head ref");
159630
160136
  const repoState = requireRepoState(toolState, owner, name);
@@ -159638,7 +160144,7 @@ async function checkoutPrBranch(pr, params) {
159638
160144
  log.debug(`\xBB fetching base branch (${pr.baseRef})...`);
159639
160145
  await $gitFetchWithDeepen(
159640
160146
  ["--no-tags", "origin", pr.baseRef],
159641
- { token: gitToken },
160147
+ { token: gitToken, refreshGitToken },
159642
160148
  `base branch ${pr.baseRef}`
159643
160149
  );
159644
160150
  if (!alreadyOnBranch) {
@@ -159649,7 +160155,7 @@ async function checkoutPrBranch(pr, params) {
159649
160155
  try {
159650
160156
  await $gitFetchWithDeepen(
159651
160157
  ["--no-tags", "origin", `+pull/${pr.number}/head:${localBranch}`],
159652
- { token: gitToken },
160158
+ { token: gitToken, refreshGitToken },
159653
160159
  `PR #${pr.number}`
159654
160160
  );
159655
160161
  } catch (e) {
@@ -159676,6 +160182,7 @@ async function checkoutPrBranch(pr, params) {
159676
160182
  owner,
159677
160183
  repo: name,
159678
160184
  gitToken,
160185
+ refreshGitToken,
159679
160186
  isShallow
159680
160187
  }) : false;
159681
160188
  if (isShallow) {
@@ -159789,6 +160296,7 @@ function CheckoutPrTool(ctx) {
159789
160296
  owner: ctx.repo.owner,
159790
160297
  name: ctx.repo.name,
159791
160298
  gitToken: ctx.gitToken,
160299
+ refreshGitToken: ctx.refreshGitToken,
159792
160300
  toolState: ctx.toolState,
159793
160301
  shell: ctx.payload.shell,
159794
160302
  postCheckoutScript: ctx.postCheckoutScript,
@@ -159804,6 +160312,8 @@ function CheckoutPrTool(ctx) {
159804
160312
  if (!checkoutSha) throw new Error("checkout completed without a resolved HEAD SHA");
159805
160313
  const headShort = checkoutSha.slice(0, 7);
159806
160314
  let incrementalDiffPath;
160315
+ let incrementalUnavailable = false;
160316
+ let incrementalUnavailableReason;
159807
160317
  if (primary.beforeSha) {
159808
160318
  const beforeShort = primary.beforeSha.slice(0, 7);
159809
160319
  const incremental = computeIncrementalDiff({
@@ -159811,15 +160321,18 @@ function CheckoutPrTool(ctx) {
159811
160321
  beforeSha: primary.beforeSha,
159812
160322
  headSha: checkoutSha
159813
160323
  });
159814
- if (incremental) {
160324
+ if (incremental.status === "ok") {
159815
160325
  incrementalDiffPath = join13(
159816
160326
  tempDir,
159817
160327
  `pr-${pull_number}-${beforeShort}-${headShort}-incremental.diff`
159818
160328
  );
159819
- writeFileSync8(incrementalDiffPath, incremental);
160329
+ writeFileSync8(incrementalDiffPath, incremental.diff);
159820
160330
  log.info(
159821
- `\xBB incremental diff computed (${incremental.length} bytes) \u2192 ${incrementalDiffPath}`
160331
+ `\xBB incremental diff computed (${incremental.diff.length} bytes) \u2192 ${incrementalDiffPath}`
159822
160332
  );
160333
+ } else if (incremental.status === "unavailable") {
160334
+ incrementalUnavailable = true;
160335
+ incrementalUnavailableReason = incremental.reason;
159823
160336
  }
159824
160337
  }
159825
160338
  const formatResult = await fetchAndFormatPrDiff(ctx, pull_number);
@@ -159886,7 +160399,13 @@ ${diffPreview}`);
159886
160399
  primary.commentableLinesByFile = cached4;
159887
160400
  primary.commentableLinesPullNumber = pull_number;
159888
160401
  primary.commentableLinesCheckoutSha = checkoutSha;
159889
- 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. ` : "";
160402
+ 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 ? (
160403
+ // say it FAILED rather than leaving the agent to infer "nothing changed"
160404
+ // from an absent field. only suggest diff-tree when the previous
160405
+ // revision is actually PRESENT locally — if the fetch never landed it,
160406
+ // diff-tree needs that object too and would fail identically. see #1139.
160407
+ `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. `)
160408
+ ) : "";
159890
160409
  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.` : "";
159891
160410
  const COMMIT_LOG_MAX = 200;
159892
160411
  const baseRange = `origin/${pr.baseRef}..HEAD`;
@@ -160206,299 +160725,6 @@ import { performance as performance8 } from "node:perf_hooks";
160206
160725
  import { existsSync as existsSync6 } from "node:fs";
160207
160726
  import { join as join17 } from "node:path";
160208
160727
 
160209
- // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/commands.mjs
160210
- function dashDashArg(agent2, agentCommand) {
160211
- return (args2) => {
160212
- if (args2.length > 1) {
160213
- return [agent2, agentCommand, args2[0], "--", ...args2.slice(1)];
160214
- } else {
160215
- return [agent2, agentCommand, args2[0]];
160216
- }
160217
- };
160218
- }
160219
- function denoExecute() {
160220
- return (args2) => {
160221
- return ["deno", "run", `npm:${args2[0]}`, ...args2.slice(1)];
160222
- };
160223
- }
160224
- var npm = {
160225
- "agent": ["npm", 0],
160226
- "run": dashDashArg("npm", "run"),
160227
- "install": ["npm", "i", 0],
160228
- "frozen": ["npm", "ci", 0],
160229
- "global": ["npm", "i", "-g", 0],
160230
- "add": ["npm", "i", 0],
160231
- "upgrade": ["npm", "update", 0],
160232
- "upgrade-interactive": null,
160233
- "dedupe": ["npm", "dedupe", 0],
160234
- "execute": ["npx", 0],
160235
- "execute-local": ["npx", 0],
160236
- "uninstall": ["npm", "uninstall", 0],
160237
- "global_uninstall": ["npm", "uninstall", "-g", 0]
160238
- };
160239
- var yarn = {
160240
- "agent": ["yarn", 0],
160241
- "run": ["yarn", "run", 0],
160242
- "install": ["yarn", "install", 0],
160243
- "frozen": ["yarn", "install", "--frozen-lockfile", 0],
160244
- "global": ["yarn", "global", "add", 0],
160245
- "add": ["yarn", "add", 0],
160246
- "upgrade": ["yarn", "upgrade", 0],
160247
- "upgrade-interactive": ["yarn", "upgrade-interactive", 0],
160248
- "dedupe": null,
160249
- "execute": ["npx", 0],
160250
- "execute-local": dashDashArg("yarn", "exec"),
160251
- "uninstall": ["yarn", "remove", 0],
160252
- "global_uninstall": ["yarn", "global", "remove", 0]
160253
- };
160254
- var yarnBerry = {
160255
- ...yarn,
160256
- "frozen": ["yarn", "install", "--immutable", 0],
160257
- "upgrade": ["yarn", "up", 0],
160258
- "upgrade-interactive": ["yarn", "up", "-i", 0],
160259
- "dedupe": ["yarn", "dedupe", 0],
160260
- "execute": ["yarn", "dlx", 0],
160261
- "execute-local": ["yarn", "exec", 0],
160262
- // Yarn 2+ removed 'global', see https://github.com/yarnpkg/berry/issues/821
160263
- "global": ["npm", "i", "-g", 0],
160264
- "global_uninstall": ["npm", "uninstall", "-g", 0]
160265
- };
160266
- var pnpm = {
160267
- "agent": ["pnpm", 0],
160268
- "run": ["pnpm", "run", 0],
160269
- "install": ["pnpm", "i", 0],
160270
- "frozen": ["pnpm", "i", "--frozen-lockfile", 0],
160271
- "global": ["pnpm", "add", "-g", 0],
160272
- "add": ["pnpm", "add", 0],
160273
- "upgrade": ["pnpm", "update", 0],
160274
- "upgrade-interactive": ["pnpm", "update", "-i", 0],
160275
- "dedupe": ["pnpm", "dedupe", 0],
160276
- "execute": ["pnpm", "dlx", 0],
160277
- "execute-local": ["pnpm", "exec", 0],
160278
- "uninstall": ["pnpm", "remove", 0],
160279
- "global_uninstall": ["pnpm", "remove", "--global", 0]
160280
- };
160281
- var bun = {
160282
- "agent": ["bun", 0],
160283
- "run": ["bun", "run", 0],
160284
- "install": ["bun", "install", 0],
160285
- "frozen": ["bun", "install", "--frozen-lockfile", 0],
160286
- "global": ["bun", "add", "-g", 0],
160287
- "add": ["bun", "add", 0],
160288
- "upgrade": ["bun", "update", 0],
160289
- "upgrade-interactive": ["bun", "update", "-i", 0],
160290
- "dedupe": null,
160291
- "execute": ["bun", "x", 0],
160292
- "execute-local": ["bun", "x", 0],
160293
- "uninstall": ["bun", "remove", 0],
160294
- "global_uninstall": ["bun", "remove", "-g", 0]
160295
- };
160296
- var deno = {
160297
- "agent": ["deno", 0],
160298
- "run": ["deno", "task", 0],
160299
- "install": ["deno", "install", 0],
160300
- "frozen": ["deno", "install", "--frozen", 0],
160301
- "global": ["deno", "install", "-g", 0],
160302
- "add": ["deno", "add", 0],
160303
- "upgrade": ["deno", "outdated", "--update", 0],
160304
- "upgrade-interactive": ["deno", "outdated", "--update", 0],
160305
- "dedupe": null,
160306
- "execute": denoExecute(),
160307
- "execute-local": ["deno", "task", "--eval", 0],
160308
- "uninstall": ["deno", "remove", 0],
160309
- "global_uninstall": ["deno", "uninstall", "-g", 0]
160310
- };
160311
- var COMMANDS = {
160312
- "npm": npm,
160313
- "yarn": yarn,
160314
- "yarn@berry": yarnBerry,
160315
- "pnpm": pnpm,
160316
- // pnpm v6.x or below
160317
- "pnpm@6": {
160318
- ...pnpm,
160319
- run: dashDashArg("pnpm", "run")
160320
- },
160321
- "bun": bun,
160322
- "deno": deno
160323
- };
160324
- function resolveCommand(agent2, command, args2) {
160325
- const value2 = COMMANDS[agent2][command];
160326
- return constructCommand(value2, args2);
160327
- }
160328
- function constructCommand(value2, args2) {
160329
- if (value2 == null)
160330
- return null;
160331
- const list = typeof value2 === "function" ? value2(args2) : value2.flatMap((v) => {
160332
- if (typeof v === "number")
160333
- return args2;
160334
- return [v];
160335
- });
160336
- return {
160337
- command: list[0],
160338
- args: list.slice(1)
160339
- };
160340
- }
160341
-
160342
- // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/constants.mjs
160343
- var AGENTS = [
160344
- "npm",
160345
- "yarn",
160346
- "yarn@berry",
160347
- "pnpm",
160348
- "pnpm@6",
160349
- "bun",
160350
- "deno"
160351
- ];
160352
- var LOCKS = {
160353
- "bun.lock": "bun",
160354
- "bun.lockb": "bun",
160355
- "deno.lock": "deno",
160356
- "pnpm-lock.yaml": "pnpm",
160357
- "pnpm-workspace.yaml": "pnpm",
160358
- "yarn.lock": "yarn",
160359
- "package-lock.json": "npm",
160360
- "npm-shrinkwrap.json": "npm"
160361
- };
160362
- var INSTALL_METADATA = {
160363
- "node_modules/.deno/": "deno",
160364
- "node_modules/.pnpm/": "pnpm",
160365
- "node_modules/.yarn-state.yml": "yarn",
160366
- // yarn v2+ (node-modules)
160367
- "node_modules/.yarn_integrity": "yarn",
160368
- // yarn v1
160369
- "node_modules/.package-lock.json": "npm",
160370
- ".pnp.cjs": "yarn",
160371
- // yarn v3+ (pnp)
160372
- ".pnp.js": "yarn",
160373
- // yarn v2 (pnp)
160374
- "bun.lock": "bun",
160375
- "bun.lockb": "bun"
160376
- };
160377
-
160378
- // node_modules/.pnpm/package-manager-detector@1.6.0/node_modules/package-manager-detector/dist/detect.mjs
160379
- import fs2 from "node:fs/promises";
160380
- import path from "node:path";
160381
- import process4 from "node:process";
160382
- async function pathExists(path22, type2) {
160383
- try {
160384
- const stat = await fs2.stat(path22);
160385
- return type2 === "file" ? stat.isFile() : stat.isDirectory();
160386
- } catch {
160387
- return false;
160388
- }
160389
- }
160390
- function* lookup(cwd = process4.cwd()) {
160391
- let directory = path.resolve(cwd);
160392
- const { root } = path.parse(directory);
160393
- while (directory && directory !== root) {
160394
- yield directory;
160395
- directory = path.dirname(directory);
160396
- }
160397
- }
160398
- async function parsePackageJson(filepath, options) {
160399
- if (!filepath || !await pathExists(filepath, "file"))
160400
- return null;
160401
- return await handlePackageManager(filepath, options);
160402
- }
160403
- async function detect(options = {}) {
160404
- const {
160405
- cwd,
160406
- strategies = ["lockfile", "packageManager-field", "devEngines-field"]
160407
- } = options;
160408
- let stopDir;
160409
- if (typeof options.stopDir === "string") {
160410
- const resolved = path.resolve(options.stopDir);
160411
- stopDir = (dir) => dir === resolved;
160412
- } else {
160413
- stopDir = options.stopDir;
160414
- }
160415
- for (const directory of lookup(cwd)) {
160416
- for (const strategy of strategies) {
160417
- switch (strategy) {
160418
- case "lockfile": {
160419
- for (const lock of Object.keys(LOCKS)) {
160420
- if (await pathExists(path.join(directory, lock), "file")) {
160421
- const name = LOCKS[lock];
160422
- const result = await parsePackageJson(path.join(directory, "package.json"), options);
160423
- if (result)
160424
- return result;
160425
- else
160426
- return { name, agent: name };
160427
- }
160428
- }
160429
- break;
160430
- }
160431
- case "packageManager-field":
160432
- case "devEngines-field": {
160433
- const result = await parsePackageJson(path.join(directory, "package.json"), options);
160434
- if (result)
160435
- return result;
160436
- break;
160437
- }
160438
- case "install-metadata": {
160439
- for (const metadata of Object.keys(INSTALL_METADATA)) {
160440
- const fileOrDir = metadata.endsWith("/") ? "dir" : "file";
160441
- if (await pathExists(path.join(directory, metadata), fileOrDir)) {
160442
- const name = INSTALL_METADATA[metadata];
160443
- const agent2 = name === "yarn" ? isMetadataYarnClassic(metadata) ? "yarn" : "yarn@berry" : name;
160444
- return { name, agent: agent2 };
160445
- }
160446
- }
160447
- break;
160448
- }
160449
- }
160450
- }
160451
- if (stopDir?.(directory))
160452
- break;
160453
- }
160454
- return null;
160455
- }
160456
- function getNameAndVer(pkg) {
160457
- const handelVer = (version3) => version3?.match(/\d+(\.\d+){0,2}/)?.[0] ?? version3;
160458
- if (typeof pkg.packageManager === "string") {
160459
- const [name, ver] = pkg.packageManager.replace(/^\^/, "").split("@");
160460
- return { name, ver: handelVer(ver) };
160461
- }
160462
- if (typeof pkg.devEngines?.packageManager?.name === "string") {
160463
- return {
160464
- name: pkg.devEngines.packageManager.name,
160465
- ver: handelVer(pkg.devEngines.packageManager.version)
160466
- };
160467
- }
160468
- return void 0;
160469
- }
160470
- async function handlePackageManager(filepath, options) {
160471
- try {
160472
- const content = await fs2.readFile(filepath, "utf8");
160473
- const pkg = options.packageJsonParser ? await options.packageJsonParser(content, filepath) : JSON.parse(content);
160474
- let agent2;
160475
- const nameAndVer = getNameAndVer(pkg);
160476
- if (nameAndVer) {
160477
- const name = nameAndVer.name;
160478
- const ver = nameAndVer.ver;
160479
- let version3 = ver;
160480
- if (name === "yarn" && ver && Number.parseInt(ver) > 1) {
160481
- agent2 = "yarn@berry";
160482
- version3 = "berry";
160483
- return { name, agent: agent2, version: version3 };
160484
- } else if (name === "pnpm" && ver && Number.parseInt(ver) < 7) {
160485
- agent2 = "pnpm@6";
160486
- return { name, agent: agent2, version: version3 };
160487
- } else if (AGENTS.includes(name)) {
160488
- agent2 = name;
160489
- return { name, agent: agent2, version: version3 };
160490
- } else {
160491
- return options.onUnknown?.(pkg.packageManager) ?? null;
160492
- }
160493
- }
160494
- } catch {
160495
- }
160496
- return null;
160497
- }
160498
- function isMetadataYarnClassic(metadataPath) {
160499
- return metadataPath.endsWith(".yarn_integrity");
160500
- }
160501
-
160502
160728
  // utils/packageManager.ts
160503
160729
  var import_semver2 = __toESM(require_semver2(), 1);
160504
160730
  import { existsSync as existsSync5 } from "node:fs";
@@ -160584,11 +160810,7 @@ async function runCorepack(args2) {
160584
160810
  const result = await spawn({
160585
160811
  cmd: "corepack",
160586
160812
  args: args2,
160587
- env: {
160588
- PATH: process.env.PATH || "",
160589
- HOME: process.env.HOME || "",
160590
- COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
160591
- },
160813
+ env: { ...filterEnvForUntrustedCode(), COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" },
160592
160814
  onStdout: (chunk) => process.stdout.write(chunk),
160593
160815
  onStderr: (chunk) => process.stderr.write(chunk)
160594
160816
  });
@@ -160598,7 +160820,7 @@ async function currentVersion(name) {
160598
160820
  const result = await spawn({
160599
160821
  cmd: name,
160600
160822
  args: ["--version"],
160601
- env: { PATH: process.env.PATH || "" }
160823
+ env: filterEnvForUntrustedCode()
160602
160824
  });
160603
160825
  if (result.exitCode !== 0) return null;
160604
160826
  return result.stdout.trim();
@@ -160650,14 +160872,8 @@ async function ensurePackageManager(params) {
160650
160872
  }
160651
160873
  return true;
160652
160874
  }
160653
-
160654
- // prep/installNodeDependencies.ts
160655
160875
  async function isCommandAvailable(command) {
160656
- const result = await spawn({
160657
- cmd: "which",
160658
- args: [command],
160659
- env: { PATH: process.env.PATH || "" }
160660
- });
160876
+ const result = await spawn({ cmd: "which", args: [command], env: filterEnvForUntrustedCode() });
160661
160877
  return result.exitCode === 0;
160662
160878
  }
160663
160879
  async function installFallback(name, installSpec) {
@@ -160668,19 +160884,41 @@ async function installFallback(name, installSpec) {
160668
160884
  const result = await spawn({
160669
160885
  cmd,
160670
160886
  args: args2,
160671
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
160887
+ env: filterEnvForUntrustedCode(),
160672
160888
  onStderr: (chunk) => process.stderr.write(chunk)
160673
160889
  });
160674
- if (result.exitCode !== 0) {
160675
- return result.stderr || `failed to install ${name}`;
160676
- }
160890
+ if (result.exitCode !== 0) return result.stderr || `failed to install ${name}`;
160677
160891
  if (name === "deno") {
160678
- const denoPath = join17(process.env.HOME || "", ".deno", "bin");
160892
+ const denoPath = join16(process.env.HOME || "", ".deno", "bin");
160679
160893
  process.env.PATH = `${denoPath}:${process.env.PATH}`;
160680
160894
  }
160681
160895
  log.info(`\xBB installed ${name}`);
160682
160896
  return null;
160683
160897
  }
160898
+ async function provisionPackageManager(params) {
160899
+ if (await isCommandAvailable(params.name)) {
160900
+ if (params.declared) {
160901
+ await ensurePackageManager({ spec: params.declared, binDir: params.binDir });
160902
+ }
160903
+ return null;
160904
+ }
160905
+ if (params.declared) {
160906
+ const activated = await ensurePackageManager({ spec: params.declared, binDir: params.binDir });
160907
+ if (activated) return null;
160908
+ }
160909
+ const spec = params.declared ? `${params.declared.name}@${params.declared.version}` : params.name;
160910
+ return installFallback(params.name, spec);
160911
+ }
160912
+
160913
+ // prep/installNodeDependencies.ts
160914
+ async function isCommandAvailable2(command) {
160915
+ const result = await spawn({
160916
+ cmd: "which",
160917
+ args: [command],
160918
+ env: filterEnvForUntrustedCode()
160919
+ });
160920
+ return result.exitCode === 0;
160921
+ }
160684
160922
  var installNodeDependencies = {
160685
160923
  name: "installNodeDependencies",
160686
160924
  shouldRun: () => {
@@ -160701,8 +160939,8 @@ var installNodeDependencies = {
160701
160939
  } else {
160702
160940
  log.info(`\xBB no package manager declared, defaulting to npm`);
160703
160941
  }
160704
- if (!await isCommandAvailable(packageManager)) {
160705
- if (options.ignoreScripts) {
160942
+ if (options.ignoreScripts) {
160943
+ if (!await isCommandAvailable2(packageManager)) {
160706
160944
  return {
160707
160945
  language: "node",
160708
160946
  packageManager,
@@ -160712,23 +160950,20 @@ var installNodeDependencies = {
160712
160950
  ]
160713
160951
  };
160714
160952
  }
160715
- let provisioned = false;
160716
- if (declared)
160717
- provisioned = await ensurePackageManager({ spec: declared, binDir: options.binDir });
160718
- if (!provisioned) {
160719
- const fallbackSpec = declared ? `${declared.name}@${declared.version}` : packageManager;
160720
- const installError = await installFallback(packageManager, fallbackSpec);
160721
- if (installError) {
160722
- return {
160723
- language: "node",
160724
- packageManager,
160725
- dependenciesInstalled: false,
160726
- issues: [installError]
160727
- };
160728
- }
160953
+ } else {
160954
+ const installError = await provisionPackageManager({
160955
+ name: packageManager,
160956
+ declared,
160957
+ binDir: options.binDir
160958
+ });
160959
+ if (installError) {
160960
+ return {
160961
+ language: "node",
160962
+ packageManager,
160963
+ dependenciesInstalled: false,
160964
+ issues: [installError]
160965
+ };
160729
160966
  }
160730
- } else if (declared) {
160731
- await ensurePackageManager({ spec: declared, binDir: options.binDir });
160732
160967
  }
160733
160968
  if (!detected) {
160734
160969
  log.info(
@@ -160754,7 +160989,7 @@ var installNodeDependencies = {
160754
160989
  const result = await spawn({
160755
160990
  cmd: resolved.command,
160756
160991
  args: resolved.args,
160757
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" }
160992
+ env: filterEnvForUntrustedCode()
160758
160993
  });
160759
160994
  const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
160760
160995
  if (output) {
@@ -160828,11 +161063,11 @@ var TOOL_INSTALL_COMMANDS = {
160828
161063
  pipenv: ["pip", "install", "pipenv"],
160829
161064
  poetry: ["pip", "install", "poetry"]
160830
161065
  };
160831
- async function isCommandAvailable2(command) {
161066
+ async function isCommandAvailable3(command) {
160832
161067
  const result = await spawn({
160833
161068
  cmd: "which",
160834
161069
  args: [command],
160835
- env: { PATH: process.env.PATH || "" }
161070
+ env: filterEnvForUntrustedCode()
160836
161071
  });
160837
161072
  return result.exitCode === 0;
160838
161073
  }
@@ -160846,7 +161081,7 @@ async function installTool(name) {
160846
161081
  const result = await spawn({
160847
161082
  cmd,
160848
161083
  args: args2,
160849
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" },
161084
+ env: filterEnvForUntrustedCode(),
160850
161085
  onStderr: (chunk) => process.stderr.write(chunk)
160851
161086
  });
160852
161087
  if (result.exitCode !== 0) {
@@ -160858,7 +161093,7 @@ async function installTool(name) {
160858
161093
  var installPythonDependencies = {
160859
161094
  name: "installPythonDependencies",
160860
161095
  shouldRun: async () => {
160861
- const hasPython = await isCommandAvailable2("python3") || await isCommandAvailable2("python");
161096
+ const hasPython = await isCommandAvailable3("python3") || await isCommandAvailable3("python");
160862
161097
  if (!hasPython) {
160863
161098
  return false;
160864
161099
  }
@@ -160892,7 +161127,7 @@ var installPythonDependencies = {
160892
161127
  ]
160893
161128
  };
160894
161129
  }
160895
- const isAvailable = await isCommandAvailable2(config3.tool);
161130
+ const isAvailable = await isCommandAvailable3(config3.tool);
160896
161131
  if (!isAvailable) {
160897
161132
  log.info(`\xBB ${config3.tool} not found, attempting to install...`);
160898
161133
  const installError = await installTool(config3.tool);
@@ -160912,7 +161147,7 @@ var installPythonDependencies = {
160912
161147
  const result = await spawn({
160913
161148
  cmd,
160914
161149
  args: args2,
160915
- env: { PATH: process.env.PATH || "", HOME: process.env.HOME || "" }
161150
+ env: filterEnvForUntrustedCode()
160916
161151
  });
160917
161152
  const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
160918
161153
  if (output) {
@@ -160941,37 +161176,6 @@ var installPythonDependencies = {
160941
161176
 
160942
161177
  // prep/index.ts
160943
161178
  var prepSteps = [installNodeDependencies, installPythonDependencies];
160944
- async function dirtyTrackedPaths() {
160945
- const result = await spawn({
160946
- cmd: "git",
160947
- args: ["diff", "--name-only", "HEAD"],
160948
- env: process.env,
160949
- activityTimeout: 0
160950
- });
160951
- if (result.exitCode !== 0) {
160952
- throw new Error(
160953
- `git diff --name-only HEAD failed (exit ${result.exitCode}): ${result.stderr.trim() || "(no stderr)"}`
160954
- );
160955
- }
160956
- return new Set(result.stdout.split("\n").filter(Boolean));
160957
- }
160958
- async function restorePrepDirtiedFiles(preDirty) {
160959
- const dirtied = [...await dirtyTrackedPaths()].filter((path4) => !preDirty.has(path4));
160960
- if (dirtied.length === 0) return;
160961
- const result = await spawn({
160962
- cmd: "git",
160963
- args: ["restore", "--staged", "--worktree", "--", ...dirtied],
160964
- env: process.env,
160965
- activityTimeout: 0
160966
- });
160967
- if (result.exitCode !== 0) {
160968
- log.warning(
160969
- `\xBB failed to restore ${dirtied.length} tracked file(s) modified by prep: ${result.stderr.trim() || "(no stderr)"}`
160970
- );
160971
- return;
160972
- }
160973
- log.info(`\xBB restored ${dirtied.length} tracked file(s) modified by prep: ${dirtied.join(", ")}`);
160974
- }
160975
161179
  async function runPrepPhase(options) {
160976
161180
  log.debug("\xBB starting prep phase...");
160977
161181
  const startTime = performance8.now();
@@ -160994,7 +161198,7 @@ async function runPrepPhase(options) {
160994
161198
  }
160995
161199
  }
160996
161200
  } finally {
160997
- await restorePrepDirtiedFiles(preDirty);
161201
+ await restoreDirtiedSince({ before: preDirty, actor: "prep" });
160998
161202
  }
160999
161203
  const totalDurationMs = performance8.now() - startTime;
161000
161204
  log.debug(`\xBB prep phase completed (${Math.round(totalDurationMs)}ms)`);
@@ -162210,13 +162414,38 @@ function buildThreadBlocks(threads, filePatchMap, reviewId) {
162210
162414
  }
162211
162415
  return threadBlocks;
162212
162416
  }
162417
+ var fetchAllReviewThreads = op(
162418
+ async (key, ctx) => {
162419
+ const response = await ctx.octokit.graphql(REVIEW_THREADS_QUERY, {
162420
+ owner: key.owner,
162421
+ name: key.name,
162422
+ prNumber: key.pullNumber
162423
+ });
162424
+ return response.repository?.pullRequest?.reviewThreads?.nodes ?? [];
162425
+ },
162426
+ { ttl: 6e4, name: "reviewThreads" }
162427
+ );
162428
+ var fetchPrFiles = op(
162429
+ async (key, ctx) => ctx.octokit.paginate(ctx.octokit.rest.pulls.listFiles, {
162430
+ owner: key.owner,
162431
+ repo: key.name,
162432
+ pull_number: key.pullNumber,
162433
+ per_page: 100
162434
+ }),
162435
+ { ttl: 6e4, name: "prFiles" }
162436
+ );
162437
+ function invalidateReviewThreadCache(repo) {
162438
+ fetchAllReviewThreads.invalidate(
162439
+ (cached4) => cached4.owner === repo.owner && cached4.name === repo.name
162440
+ );
162441
+ }
162213
162442
  async function getReviewThreads(input) {
162214
- const response = await input.octokit.graphql(REVIEW_THREADS_QUERY, {
162215
- owner: input.owner,
162216
- name: input.name,
162217
- prNumber: input.pullNumber
162218
- });
162219
- const allThreads = response.repository?.pullRequest?.reviewThreads?.nodes ?? [];
162443
+ const allThreads = structuredClone(
162444
+ await fetchAllReviewThreads(
162445
+ { owner: input.owner, name: input.name, pullNumber: input.pullNumber },
162446
+ { octokit: input.octokit }
162447
+ )
162448
+ );
162220
162449
  if (allThreads.length >= 100) {
162221
162450
  log.warning(
162222
162451
  `PR ${input.owner}/${input.name}#${input.pullNumber}: reviewThreads returned 100 results (limit reached, some threads may be missing)`
@@ -162273,12 +162502,10 @@ async function getReviewData(input) {
162273
162502
  }),
162274
162503
  getReviewThreads(input)
162275
162504
  ]);
162276
- const prFiles = threads.length > 0 ? await input.octokit.paginate(input.octokit.rest.pulls.listFiles, {
162277
- owner: input.owner,
162278
- repo: input.name,
162279
- pull_number: input.pullNumber,
162280
- per_page: 100
162281
- }) : [];
162505
+ const prFiles = threads.length > 0 ? await fetchPrFiles(
162506
+ { owner: input.owner, name: input.name, pullNumber: input.pullNumber },
162507
+ { octokit: input.octokit }
162508
+ ) : [];
162282
162509
  if (review.data.body) {
162283
162510
  review.data.body = await resolveBodyAssets({
162284
162511
  body: review.data.body,
@@ -162422,6 +162649,7 @@ function ResolveReviewThreadTool(ctx) {
162422
162649
  });
162423
162650
  const thread = response.resolveReviewThread.thread;
162424
162651
  log.info(`\xBB resolved review thread ${thread.id}`);
162652
+ invalidateReviewThreadCache({ owner: ctx.repo.owner, name: ctx.repo.name });
162425
162653
  return {
162426
162654
  thread_id: thread.id,
162427
162655
  is_resolved: thread.isResolved,
@@ -162596,7 +162824,10 @@ import { join as join20 } from "node:path";
162596
162824
  import { setTimeout as sleep2 } from "node:timers/promises";
162597
162825
  var ShellParams = type({
162598
162826
  command: "string",
162599
- description: "string",
162827
+ // advisory and unread — no code path consumes it. kept in the schema only
162828
+ // because it nudges the model to state intent before running a command;
162829
+ // REQUIRING it cost a full rejected turn every time one was omitted. #1140.
162830
+ "description?": "string",
162600
162831
  "timeout?": type.number.describe(
162601
162832
  "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."
162602
162833
  ),
@@ -162604,6 +162835,7 @@ var ShellParams = type({
162604
162835
  "background?": "boolean"
162605
162836
  });
162606
162837
  var detectedSandboxMethod;
162838
+ var usernsProbeError;
162607
162839
  function detectSandboxMethod() {
162608
162840
  if (detectedSandboxMethod !== void 0) {
162609
162841
  return detectedSandboxMethod;
@@ -162637,6 +162869,35 @@ function detectSandboxMethod() {
162637
162869
  }
162638
162870
  } catch {
162639
162871
  }
162872
+ try {
162873
+ const result = spawnSync6(
162874
+ "unshare",
162875
+ [
162876
+ "--user",
162877
+ "--map-root-user",
162878
+ "--pid",
162879
+ "--fork",
162880
+ "--mount",
162881
+ "setpriv",
162882
+ "--no-new-privs",
162883
+ "--bounding-set",
162884
+ "-all",
162885
+ "--inh-caps",
162886
+ "-all",
162887
+ "--ambient-caps",
162888
+ "-all",
162889
+ "true"
162890
+ ],
162891
+ { timeout: 5e3, stdio: ["ignore", "ignore", "pipe"] }
162892
+ );
162893
+ if (result.status === 0) {
162894
+ detectedSandboxMethod = "userns-unshare";
162895
+ log.debug("PID namespace isolation enabled (unprivileged userns unshare)");
162896
+ return "userns-unshare";
162897
+ }
162898
+ usernsProbeError = result.stderr?.toString().trim() || result.error?.message;
162899
+ } catch {
162900
+ }
162640
162901
  detectedSandboxMethod = "none";
162641
162902
  log.info("PID namespace isolation not available");
162642
162903
  return "none";
@@ -162684,7 +162945,7 @@ function spawnShell(params) {
162684
162945
  const ci = process.env.CI === "true";
162685
162946
  if (ci && sandboxMethod === "none") {
162686
162947
  throw new Error(
162687
- "pid namespace isolation is required in CI but unavailable (both unshare and sudo unshare failed)"
162948
+ "PID-namespace isolation is required in CI but unavailable: unprivileged unshare, sudo unshare, and userns-nested unshare all failed. " + (usernsProbeError ? `userns probe said: ${usernsProbeError}. ` : "") + "on a containerized / Kubernetes self-hosted runner the cause is usually one of: the pod's seccomp profile blocks user-namespace creation (Pod Security Standards baseline/restricted); the pod runs as root without CAP_SETFCAP, which the kernel requires to map uid 0; or the node kernel disallows unprivileged user namespaces (Ubuntu >= 23.10, Bottlerocket, Talos). elsewhere, check that `unshare` and `setpriv` (util-linux >= 2.31, which is what added --ambient-caps) are on PATH. see https://docs.pullfrog.com/security#self-hosted-runners"
162688
162949
  );
162689
162950
  }
162690
162951
  const repoRoot = resolveRepoRoot();
@@ -162703,6 +162964,23 @@ function spawnShell(params) {
162703
162964
  spawnOpts
162704
162965
  );
162705
162966
  }
162967
+ if (sandboxMethod === "userns-unshare") {
162968
+ const escaped = params.command.replace(/'/g, "'\\''");
162969
+ return spawn3(
162970
+ "unshare",
162971
+ [
162972
+ "--user",
162973
+ "--map-root-user",
162974
+ "--pid",
162975
+ "--fork",
162976
+ "--mount",
162977
+ "bash",
162978
+ "-c",
162979
+ `${PROC_CLEANUP} ${SOCKET_CLEANUP} ${fsMounts} exec setpriv --no-new-privs --bounding-set -all --inh-caps -all --ambient-caps -all bash -c '${escaped}'`
162980
+ ],
162981
+ spawnOpts
162982
+ );
162983
+ }
162706
162984
  if (sandboxMethod === "sudo-unshare") {
162707
162985
  const envArgs = [];
162708
162986
  for (const [k, v] of Object.entries(params.env)) {
@@ -162866,6 +163144,8 @@ Do NOT use this tool for git commands \u2014 use the dedicated git tools instead
162866
163144
  proc.on("exit", done);
162867
163145
  proc.on("error", () => done(null));
162868
163146
  });
163147
+ proc.stdout?.destroy();
163148
+ proc.stderr?.destroy();
162869
163149
  let output = stderr ? stdout ? `${stdout}
162870
163150
  ${stderr}` : stderr : stdout;
162871
163151
  if (timedOut)
@@ -163109,6 +163389,7 @@ function CheckoutRepoTool(ctx) {
163109
163389
  owner,
163110
163390
  name: repo,
163111
163391
  gitToken: rc.gitToken,
163392
+ refreshGitToken: rc.refreshGitToken,
163112
163393
  octokit: rc.octokit,
163113
163394
  toolState: ctx.toolState,
163114
163395
  shell: ctx.payload.shell,
@@ -163605,14 +163886,22 @@ function validateAgentApiKey(params) {
163605
163886
  }
163606
163887
  function isApiKeyAuthError(text) {
163607
163888
  if (!text) return false;
163608
- 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);
163889
+ 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);
163609
163890
  }
163610
163891
  function isOAuthCredentialExpiredError(text) {
163611
- return /authentication token has (expired|been invalidated)/i.test(text) || /OAuth access token has expired/i.test(text) || /Token refresh failed/i.test(text);
163892
+ return /(?:authentication|OAuth access) token has (?:expired|been (?:invalidated|revoked))/i.test(
163893
+ text
163894
+ ) || // the provider no longer recognises the token at all (#1086) — same dead
163895
+ // credential, phrased as a lookup miss rather than a state transition.
163896
+ /Could not find the appropriate key in your authentication token/i.test(text) || /Token refresh failed/i.test(text);
163612
163897
  }
163613
163898
  function isClaudeSubscriptionDisabledError(text) {
163614
163899
  return /disabled Claude subscription access/i.test(text);
163615
163900
  }
163901
+ var CLAUDE_SESSION_LIMIT_PATTERN = /hit your (?:session|weekly|five-hour|Opus|Sonnet|Haiku)\s+limit(?:\s*·\s*resets\s+([^"\n]+))?/i;
163902
+ function isClaudeSessionLimitError(text) {
163903
+ return CLAUDE_SESSION_LIMIT_PATTERN.test(text);
163904
+ }
163616
163905
  function formatApiKeyErrorSummary(params) {
163617
163906
  if (params.raw.includes(MISSING_KEY_MARKER)) {
163618
163907
  if (params.raw.startsWith(`**${MISSING_KEY_MARKER}**`)) return params.raw;
@@ -163620,6 +163909,15 @@ function formatApiKeyErrorSummary(params) {
163620
163909
  }
163621
163910
  const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
163622
163911
  const settingsUrl = `${getApiUrl()}/console/${params.owner}/${params.name}`;
163912
+ if (isClaudeSessionLimitError(params.raw)) {
163913
+ const reset = CLAUDE_SESSION_LIMIT_PATTERN.exec(params.raw)?.[1]?.trim();
163914
+ const resets = reset ? ` It resets at **${reset}**.` : "";
163915
+ return [
163916
+ `**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.`,
163917
+ "",
163918
+ `[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)`
163919
+ ].join("\n");
163920
+ }
163623
163921
  if (isClaudeSubscriptionDisabledError(params.raw)) {
163624
163922
  return [
163625
163923
  `**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.`,
@@ -164429,7 +164727,9 @@ function decideModelAccess(input) {
164429
164727
  if (input.proxyActive) {
164430
164728
  const target = resolveOpenRouterModel(input.model);
164431
164729
  if (input.oss) {
164432
- if (target && target === input.subsidyTarget) return { kind: "proxy", target };
164730
+ if (target && (target === input.subsidyTarget || isOssAllowedModel(input.model))) {
164731
+ return { kind: "proxy", target };
164732
+ }
164433
164733
  if (byokAuthorized) return { kind: "byok" };
164434
164734
  return { kind: "error", reason: "oss" };
164435
164735
  }
@@ -164441,6 +164741,11 @@ function decideModelAccess(input) {
164441
164741
  return { kind: "error", reason: "byok_no_key" };
164442
164742
  }
164443
164743
  var MODEL_ACCESS_MARKER = "requested model is not available";
164744
+ function ossAllowedLabels() {
164745
+ return OSS_MODEL_ALLOWLIST.map(
164746
+ (slug2) => `\`${resolveDisplayAlias(slug2)?.displayName ?? slug2}\``
164747
+ ).join(", ");
164748
+ }
164444
164749
  function buildModelAccessError(input) {
164445
164750
  const settingsUrl = `${getApiUrl()}/console/${input.owner}/${input.name}`;
164446
164751
  const secretsUrl = `https://github.com/${input.owner}/${input.name}/settings/secrets/actions`;
@@ -164448,8 +164753,8 @@ function buildModelAccessError(input) {
164448
164753
  const headline = `**The ${MODEL_ACCESS_MARKER}: \`${input.model}\`.**`;
164449
164754
  const branch = {
164450
164755
  oss: {
164451
- 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.",
164452
- cta: `[Add a provider key \u2192](${secretsUrl}) \xB7 [Setup docs \u2192](${docsUrl})`
164756
+ 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.`,
164757
+ cta: `[Configure model \u2192](${settingsUrl}) \xB7 [Add a provider key \u2192](${secretsUrl}) \xB7 [Setup docs \u2192](${docsUrl})`
164453
164758
  },
164454
164759
  byok_no_key: {
164455
164760
  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.`,
@@ -164605,12 +164910,14 @@ var ShellPermissionInput = type.enumerated("disabled", "restricted", "enabled");
164605
164910
  var PushPermissionInput = type.enumerated("disabled", "restricted", "enabled");
164606
164911
  var StatusChecksInput = type.enumerated("disabled", "enabled");
164607
164912
  var ProgressCommentsInput = type.enumerated("disabled", "enabled");
164913
+ var DebugInput = type.enumerated("disabled", "enabled");
164608
164914
  var JsonPayload = type({
164609
164915
  "~pullfrog": "true",
164610
164916
  version: "string",
164611
164917
  "model?": "string | undefined",
164612
164918
  "modelExplicit?": "boolean | undefined",
164613
164919
  "effort?": "number | string | undefined",
164920
+ "debug?": "boolean | undefined",
164614
164921
  prompt: "string",
164615
164922
  "triggerer?": "string | undefined",
164616
164923
  "baseInstructions?": "string | undefined",
@@ -164645,6 +164952,7 @@ var Inputs = type({
164645
164952
  "prompt_file?": type.string.or("undefined"),
164646
164953
  "model?": type.string.or("undefined"),
164647
164954
  "effort?": type.string.or("undefined"),
164955
+ "debug?": DebugInput.or("undefined"),
164648
164956
  "timeout?": type.string.or("undefined"),
164649
164957
  "push?": PushPermissionInput.or("undefined"),
164650
164958
  "shell?": ShellPermissionInput.or("undefined"),
@@ -164696,15 +165004,24 @@ function resolvePromptFile(input) {
164696
165004
  }
164697
165005
  return content;
164698
165006
  }
165007
+ function warnIfDeprecatedStatusChecks(value2) {
165008
+ if (value2 !== void 0) {
165009
+ core6.warning(
165010
+ "`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."
165011
+ );
165012
+ }
165013
+ return value2;
165014
+ }
164699
165015
  function resolveNonPromptInputs() {
164700
165016
  return Inputs.omit("prompt", "prompt_file").assert({
164701
165017
  model: core6.getInput("model") || void 0,
164702
165018
  effort: core6.getInput("effort") || void 0,
165019
+ debug: core6.getInput("debug") || void 0,
164703
165020
  timeout: core6.getInput("timeout") || void 0,
164704
165021
  cwd: core6.getInput("cwd") || void 0,
164705
165022
  push: core6.getInput("push") || void 0,
164706
165023
  shell: core6.getInput("shell") || void 0,
164707
- status_checks: core6.getInput("status_checks") || void 0,
165024
+ status_checks: warnIfDeprecatedStatusChecks(core6.getInput("status_checks") || void 0),
164708
165025
  progress_comments: core6.getInput("progress_comments") || void 0
164709
165026
  });
164710
165027
  }
@@ -164716,6 +165033,8 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
164716
165033
  const model = jsonPayload?.model ?? inputs.model ?? repoSettings.model ?? void 0;
164717
165034
  const rawEffort = jsonPayload?.effort ?? inputs.effort ?? repoSettings.effort ?? void 0;
164718
165035
  const effort = rawEffort === void 0 ? void 0 : parseEffortPosition(String(rawEffort));
165036
+ const debug3 = jsonPayload?.debug ?? inputs.debug === "enabled";
165037
+ if (debug3) process.env.LOG_LEVEL = "debug";
164719
165038
  const isNonCollaborator = !isCollaborator(event);
164720
165039
  const repoShell = repoSettings.shell ?? "restricted";
164721
165040
  const inputShell = inputs.shell;
@@ -164736,6 +165055,7 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
164736
165055
  // the JSON payload). a GHA `model` input or the repo default is not explicit.
164737
165056
  modelExplicit: jsonPayload?.modelExplicit ?? false,
164738
165057
  effort,
165058
+ debug: debug3 || void 0,
164739
165059
  prompt,
164740
165060
  triggerer: jsonPayload?.triggerer ?? // it's not a common use case but GITHUB_ACTOR can be a user when the workflow is manually triggered by a user through GitHub Actions UI
164741
165061
  (!isPullfrog(process.env.GITHUB_ACTOR) ? process.env.GITHUB_ACTOR : void 0),
@@ -164757,9 +165077,11 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
164757
165077
  // input is the source of truth when set (mirrors `push`); otherwise the repo
164758
165078
  // setting decides.
164759
165079
  runStatusCheck: inputs.status_checks === void 0 ? repoSettings.statusChecks : inputs.status_checks === "enabled",
164760
- // the `pullfrog-approval` verdict check stays opt-in and workflow-only. it exists to
164761
- // be *required* by branch protection, so it must never turn itself on.
164762
- approvalCheck: inputs.status_checks === "enabled",
165080
+ // the `pullfrog-approval` verdict check. `Repo.approvalCheck` is authoritative; the
165081
+ // `status_checks` input is DEPRECATED but still honoured, for the dormant installs the
165082
+ // backfill could not read (see `warnIfDeprecatedStatusChecks`). OR rather than override:
165083
+ // this can only ever turn the check ON, never off, so no existing user loses it.
165084
+ approvalCheck: repoSettings.approvalCheck || inputs.status_checks === "enabled",
164763
165085
  // temporary progress chrome. the workflow input is the source of truth when
164764
165086
  // set (mirrors `push`); otherwise the repo setting decides. defaults to true.
164765
165087
  progressComments: inputs.progress_comments === void 0 ? repoSettings.progressComments : inputs.progress_comments === "enabled",
@@ -165131,7 +165453,7 @@ async function resolveProxyModel(ctx) {
165131
165453
  if (ctx.oss) {
165132
165454
  ctx.toolState.modelClamped = { from: ctx.payload.model, reason: "oss" };
165133
165455
  log.info(
165134
- `\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.`
165456
+ `\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.`
165135
165457
  );
165136
165458
  } else if (isCardGatedModel(ctx.payload.model)) {
165137
165459
  ctx.toolState.modelClamped = { from: ctx.payload.model, reason: "card" };
@@ -165333,6 +165655,7 @@ var defaultSettings = {
165333
165655
  repoIntelligence: false,
165334
165656
  progressComments: true,
165335
165657
  statusChecks: true,
165658
+ approvalCheck: false,
165336
165659
  modeInstructions: {},
165337
165660
  learnings: null,
165338
165661
  learningsHeadings: [],
@@ -165560,6 +165883,40 @@ function formatBillingExhaustedBody(diagnostic) {
165560
165883
  function isProviderModelNotFoundError(message) {
165561
165884
  return message.includes("ProviderModelNotFoundError");
165562
165885
  }
165886
+ function isContextOverflowError(message) {
165887
+ 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);
165888
+ }
165889
+ function isNoProviderAvailableError(message) {
165890
+ return /\bNo provider available\b/i.test(message);
165891
+ }
165892
+ function formatNoProviderAvailableSummary(input) {
165893
+ const settingsUrl = `${getApiUrl()}/console/${input.owner}/${input.name}`;
165894
+ return [
165895
+ "**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.",
165896
+ "",
165897
+ "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.",
165898
+ "",
165899
+ `[Model settings \u2192](${settingsUrl}) \xB7 [Setup docs \u2192](https://docs.pullfrog.com/keys) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`,
165900
+ "",
165901
+ `\`\`\`
165902
+ ${input.raw}
165903
+ \`\`\``
165904
+ ].join("\n");
165905
+ }
165906
+ function formatContextOverflowSummary(input) {
165907
+ const settingsUrl = `${getApiUrl()}/console/${input.owner}/${input.name}`;
165908
+ return [
165909
+ "**This run exceeded the model's context window.** Pullfrog read more than the model could hold, so it stopped before finishing.",
165910
+ "",
165911
+ `Pick a model with a larger context window, or split this PR into smaller ones and re-trigger.`,
165912
+ "",
165913
+ `[Model settings \u2192](${settingsUrl}) \xB7 [Ask in Discord \u2192](https://discord.gg/8y96raFg8e)`,
165914
+ "",
165915
+ `\`\`\`
165916
+ ${input.raw}
165917
+ \`\`\``
165918
+ ].join("\n");
165919
+ }
165563
165920
  function formatGenericFailure(errorMessage) {
165564
165921
  return [
165565
165922
  "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.",
@@ -165581,12 +165938,18 @@ var PROVIDER_BILLING_URLS = {
165581
165938
  anthropic: "https://console.anthropic.com/settings/billing",
165582
165939
  openai: "https://platform.openai.com/account/billing",
165583
165940
  google: "https://aistudio.google.com/usage",
165584
- opencode: "https://opencode.ai/zen"
165941
+ opencode: "https://opencode.ai/zen",
165942
+ xai: "https://console.x.ai/team/default/billing",
165943
+ openrouter: "https://openrouter.ai/settings/credits"
165585
165944
  };
165586
165945
  function detectProviderId(message) {
165587
165946
  const harnessId = extractProviderId(message);
165588
165947
  if (harnessId) return harnessId;
165589
165948
  if (/credit balance is too low/i.test(message)) return "anthropic";
165949
+ if (/used all available credits/i.test(message)) return "xai";
165950
+ if (/requires more credits|Key limit exceeded \(total limit\)|openrouter\.ai/i.test(message)) {
165951
+ return "openrouter";
165952
+ }
165590
165953
  return null;
165591
165954
  }
165592
165955
  function formatProviderBillingExhausted(input) {
@@ -165614,7 +165977,7 @@ ${input.raw}
165614
165977
  \`\`\``;
165615
165978
  }
165616
165979
  function renderRunError(input) {
165617
- const billingError = isRouterKeylimitExhaustedError(input.errorMessage) ? new BillingError(input.errorMessage, { code: "router_keylimit_exhausted" }) : null;
165980
+ const billingError = input.routerActive && isRouterKeylimitExhaustedError(input.errorMessage) ? new BillingError(input.errorMessage, { code: "router_keylimit_exhausted" }) : null;
165618
165981
  if (billingError) {
165619
165982
  const body = formatBillingErrorSummary(billingError, input.repo.owner);
165620
165983
  return { summary: body, comment: body };
@@ -165654,6 +166017,26 @@ ${body}`, comment: body };
165654
166017
  });
165655
166018
  return { summary: body, comment: body };
165656
166019
  }
166020
+ if (isNoProviderAvailableError(input.errorMessage)) {
166021
+ const body = formatNoProviderAvailableSummary({
166022
+ owner: input.repo.owner,
166023
+ name: input.repo.name,
166024
+ raw: input.errorMessage
166025
+ });
166026
+ return { summary: `### \u274C Pullfrog failed
166027
+
166028
+ ${body}`, comment: body };
166029
+ }
166030
+ if (isContextOverflowError(input.errorMessage)) {
166031
+ const body = formatContextOverflowSummary({
166032
+ owner: input.repo.owner,
166033
+ name: input.repo.name,
166034
+ raw: input.errorMessage
166035
+ });
166036
+ return { summary: `### \u274C Pullfrog failed
166037
+
166038
+ ${body}`, comment: body };
166039
+ }
165657
166040
  if (hangBody) {
165658
166041
  const isBillingExhausted = input.agentDiagnostic?.lastProviderError === "provider billing exhausted";
165659
166042
  return {
@@ -166034,7 +166417,8 @@ async function finalizeSuccessRun(input) {
166034
166417
  const rendered = !input.result.success ? renderRunError({
166035
166418
  errorMessage: input.result.error || "agent run failed",
166036
166419
  repo: input.repo,
166037
- agentDiagnostic: input.toolState.agentDiagnostic
166420
+ agentDiagnostic: input.toolState.agentDiagnostic,
166421
+ routerActive: !!input.toolContext.payload.proxyModel
166038
166422
  }) : null;
166039
166423
  if (rendered) {
166040
166424
  await reportErrorToComment({
@@ -166482,7 +166866,9 @@ async function main() {
166482
166866
  }
166483
166867
  if (access.kind === "proxy") payload.proxyModel = access.target;
166484
166868
  if (access.kind === "byok") payload.proxyModel = void 0;
166485
- if (runContext.oss && payload.proxyModel) payload.effort = 0;
166869
+ if (runContext.oss && payload.proxyModel) {
166870
+ payload.effort = ossEffortFloor({ payload });
166871
+ }
166486
166872
  const resolvedModel = payload.proxyModel ? void 0 : resolveModel({ slug: payload.model });
166487
166873
  vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
166488
166874
  const agent2 = resolveAgent({ model: resolvedModel });
@@ -166509,8 +166895,15 @@ async function main() {
166509
166895
  });
166510
166896
  timer.checkpoint("git");
166511
166897
  const pmSpec = await resolvePackageManagerSpec(process.cwd());
166512
- if (pmSpec) {
166513
- await ensurePackageManager({ spec: pmSpec, binDir: packageManagerBinDir(tmpdir3) });
166898
+ const pmDetected = await detect({ cwd: process.cwd(), strategies: ["lockfile"] });
166899
+ const pmName = pmSpec?.name ?? pmDetected?.name ?? "npm";
166900
+ if (payload.shell !== "disabled") {
166901
+ const pmError = await provisionPackageManager({
166902
+ name: pmName,
166903
+ declared: pmSpec,
166904
+ binDir: packageManagerBinDir(tmpdir3)
166905
+ });
166906
+ if (pmError) log.warning(`\xBB could not provision ${pmName}: ${pmError}`);
166514
166907
  }
166515
166908
  timer.checkpoint("packageManager");
166516
166909
  const setupHook = await executeLifecycleHook({
@@ -166790,7 +167183,8 @@ ${instructions.user}` : null,
166790
167183
  const rendered = renderRunError({
166791
167184
  errorMessage,
166792
167185
  repo: runContext.repo,
166793
- agentDiagnostic: toolState.agentDiagnostic
167186
+ agentDiagnostic: toolState.agentDiagnostic,
167187
+ routerActive: !!payload.proxyModel
166794
167188
  });
166795
167189
  await writeRunErrorOutputs({ rendered, toolState });
166796
167190
  if (toolContext) {