pullfrog 0.1.104 → 0.1.106

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -96,7 +96,7 @@ var require_arg = __commonJS({
96
96
  Object.setPrototypeOf(this, _ArgError.prototype);
97
97
  }
98
98
  };
99
- function arg10(opts, {
99
+ function arg11(opts, {
100
100
  argv = process.argv.slice(2),
101
101
  permissive = false,
102
102
  stopAtPositional = false
@@ -171,15 +171,15 @@ var require_arg = __commonJS({
171
171
  if (wholeArg.length > 1 && wholeArg[0] === "-") {
172
172
  const separatedArguments = wholeArg[1] === "-" || wholeArg.length === 2 ? [wholeArg] : wholeArg.slice(1).split("").map((a2) => `-${a2}`);
173
173
  for (let j = 0; j < separatedArguments.length; j++) {
174
- const arg11 = separatedArguments[j];
175
- const [originalArgName, argStr] = arg11[1] === "-" ? arg11.split(/=(.*)/, 2) : [arg11, void 0];
174
+ const arg12 = separatedArguments[j];
175
+ const [originalArgName, argStr] = arg12[1] === "-" ? arg12.split(/=(.*)/, 2) : [arg12, void 0];
176
176
  let argName = originalArgName;
177
177
  while (argName in aliases) {
178
178
  argName = aliases[argName];
179
179
  }
180
180
  if (!(argName in handlers2)) {
181
181
  if (permissive) {
182
- result._.push(arg11);
182
+ result._.push(arg12);
183
183
  continue;
184
184
  } else {
185
185
  throw new ArgError(
@@ -218,13 +218,13 @@ var require_arg = __commonJS({
218
218
  }
219
219
  return result;
220
220
  }
221
- arg10.flag = (fn2) => {
221
+ arg11.flag = (fn2) => {
222
222
  fn2[flagSymbol] = true;
223
223
  return fn2;
224
224
  };
225
- arg10.COUNT = arg10.flag((v, name, existingCount) => (existingCount || 0) + 1);
226
- arg10.ArgError = ArgError;
227
- module.exports = arg10;
225
+ arg11.COUNT = arg11.flag((v, name, existingCount) => (existingCount || 0) + 1);
226
+ arg11.ArgError = ArgError;
227
+ module.exports = arg11;
228
228
  }
229
229
  });
230
230
 
@@ -2393,13 +2393,13 @@ var init_doc = __esm({
2393
2393
  this.indent -= 1;
2394
2394
  }
2395
2395
  }
2396
- write(arg10) {
2397
- if (typeof arg10 === "function") {
2398
- arg10(this, { execution: "sync" });
2399
- arg10(this, { execution: "async" });
2396
+ write(arg11) {
2397
+ if (typeof arg11 === "function") {
2398
+ arg11(this, { execution: "sync" });
2399
+ arg11(this, { execution: "async" });
2400
2400
  return;
2401
2401
  }
2402
- const content = arg10;
2402
+ const content = arg11;
2403
2403
  const lines = content.split("\n").filter((x) => x);
2404
2404
  const minIndent = Math.min(...lines.map((x) => x.length - x.trimStart().length));
2405
2405
  const dedented = lines.map((x) => x.slice(minIndent)).map((x) => " ".repeat(this.indent * 2) + x);
@@ -19992,10 +19992,10 @@ var require_timers = __commonJS({
19992
19992
  * before the specified function or code is executed.
19993
19993
  * @param {*} arg
19994
19994
  */
19995
- constructor(callback, delay2, arg10) {
19995
+ constructor(callback, delay2, arg11) {
19996
19996
  this._onTimeout = callback;
19997
19997
  this._idleTimeout = delay2;
19998
- this._timerArg = arg10;
19998
+ this._timerArg = arg11;
19999
19999
  this.refresh();
20000
20000
  }
20001
20001
  /**
@@ -20039,8 +20039,8 @@ var require_timers = __commonJS({
20039
20039
  * when the timer expires.
20040
20040
  * @returns {NodeJS.Timeout|FastTimer}
20041
20041
  */
20042
- setTimeout(callback, delay2, arg10) {
20043
- return delay2 <= RESOLUTION_MS ? setTimeout(callback, delay2, arg10) : new FastTimer(callback, delay2, arg10);
20042
+ setTimeout(callback, delay2, arg11) {
20043
+ return delay2 <= RESOLUTION_MS ? setTimeout(callback, delay2, arg11) : new FastTimer(callback, delay2, arg11);
20044
20044
  },
20045
20045
  /**
20046
20046
  * The clearTimeout method cancels an instantiated Timer previously created
@@ -20066,8 +20066,8 @@ var require_timers = __commonJS({
20066
20066
  * when the timer expires.
20067
20067
  * @returns {FastTimer}
20068
20068
  */
20069
- setFastTimeout(callback, delay2, arg10) {
20070
- return new FastTimer(callback, delay2, arg10);
20069
+ setFastTimeout(callback, delay2, arg11) {
20070
+ return new FastTimer(callback, delay2, arg11);
20071
20071
  },
20072
20072
  /**
20073
20073
  * The clearTimeout method cancels an instantiated FastTimer previously
@@ -44727,20 +44727,20 @@ var require_escape = __commonJS({
44727
44727
  "node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.js"(exports, module) {
44728
44728
  "use strict";
44729
44729
  var metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
44730
- function escapeCommand(arg10) {
44731
- arg10 = arg10.replace(metaCharsRegExp, "^$1");
44732
- return arg10;
44733
- }
44734
- function escapeArgument(arg10, doubleEscapeMetaChars) {
44735
- arg10 = `${arg10}`;
44736
- arg10 = arg10.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
44737
- arg10 = arg10.replace(/(?=(\\+?)?)\1$/, "$1$1");
44738
- arg10 = `"${arg10}"`;
44739
- arg10 = arg10.replace(metaCharsRegExp, "^$1");
44730
+ function escapeCommand(arg11) {
44731
+ arg11 = arg11.replace(metaCharsRegExp, "^$1");
44732
+ return arg11;
44733
+ }
44734
+ function escapeArgument(arg11, doubleEscapeMetaChars) {
44735
+ arg11 = `${arg11}`;
44736
+ arg11 = arg11.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
44737
+ arg11 = arg11.replace(/(?=(\\+?)?)\1$/, "$1$1");
44738
+ arg11 = `"${arg11}"`;
44739
+ arg11 = arg11.replace(metaCharsRegExp, "^$1");
44740
44740
  if (doubleEscapeMetaChars) {
44741
- arg10 = arg10.replace(metaCharsRegExp, "^$1");
44741
+ arg11 = arg11.replace(metaCharsRegExp, "^$1");
44742
44742
  }
44743
- return arg10;
44743
+ return arg11;
44744
44744
  }
44745
44745
  module.exports.command = escapeCommand;
44746
44746
  module.exports.argument = escapeArgument;
@@ -44828,7 +44828,7 @@ var require_parse3 = __commonJS({
44828
44828
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
44829
44829
  parsed2.command = path4.normalize(parsed2.command);
44830
44830
  parsed2.command = escape2.command(parsed2.command);
44831
- parsed2.args = parsed2.args.map((arg10) => escape2.argument(arg10, needsDoubleEscapeMetaChars));
44831
+ parsed2.args = parsed2.args.map((arg11) => escape2.argument(arg11, needsDoubleEscapeMetaChars));
44832
44832
  const shellCommand = [parsed2.command].concat(parsed2.args).join(" ");
44833
44833
  parsed2.args = ["/d", "/s", "/c", `"${shellCommand}"`];
44834
44834
  parsed2.command = process.env.comspec || "cmd.exe";
@@ -45118,10 +45118,10 @@ var require_timers2 = __commonJS({
45118
45118
  * before the specified function or code is executed.
45119
45119
  * @param {*} arg
45120
45120
  */
45121
- constructor(callback, delay2, arg10) {
45121
+ constructor(callback, delay2, arg11) {
45122
45122
  this._onTimeout = callback;
45123
45123
  this._idleTimeout = delay2;
45124
- this._timerArg = arg10;
45124
+ this._timerArg = arg11;
45125
45125
  this.refresh();
45126
45126
  }
45127
45127
  /**
@@ -45165,8 +45165,8 @@ var require_timers2 = __commonJS({
45165
45165
  * when the timer expires.
45166
45166
  * @returns {NodeJS.Timeout|FastTimer}
45167
45167
  */
45168
- setTimeout(callback, delay2, arg10) {
45169
- return delay2 <= RESOLUTION_MS ? setTimeout(callback, delay2, arg10) : new FastTimer(callback, delay2, arg10);
45168
+ setTimeout(callback, delay2, arg11) {
45169
+ return delay2 <= RESOLUTION_MS ? setTimeout(callback, delay2, arg11) : new FastTimer(callback, delay2, arg11);
45170
45170
  },
45171
45171
  /**
45172
45172
  * The clearTimeout method cancels an instantiated Timer previously created
@@ -45192,8 +45192,8 @@ var require_timers2 = __commonJS({
45192
45192
  * when the timer expires.
45193
45193
  * @returns {FastTimer}
45194
45194
  */
45195
- setFastTimeout(callback, delay2, arg10) {
45196
- return new FastTimer(callback, delay2, arg10);
45195
+ setFastTimeout(callback, delay2, arg11) {
45196
+ return new FastTimer(callback, delay2, arg11);
45197
45197
  },
45198
45198
  /**
45199
45199
  * The clearTimeout method cancels an instantiated FastTimer previously
@@ -74716,9 +74716,9 @@ var init_types = __esm({
74716
74716
  const { status, ctx } = this._processInputParams(input2);
74717
74717
  const effect = this._def.effect || null;
74718
74718
  const checkCtx = {
74719
- addIssue: (arg10) => {
74720
- addIssueToContext(ctx, arg10);
74721
- if (arg10.fatal) {
74719
+ addIssue: (arg11) => {
74720
+ addIssueToContext(ctx, arg11);
74721
+ if (arg11.fatal) {
74722
74722
  status.abort();
74723
74723
  } else {
74724
74724
  status.dirty();
@@ -76884,13 +76884,13 @@ var require_code = __commonJS({
76884
76884
  return new _Code(expr);
76885
76885
  }
76886
76886
  exports.str = str;
76887
- function addCodeArg(code, arg10) {
76888
- if (arg10 instanceof _Code)
76889
- code.push(...arg10._items);
76890
- else if (arg10 instanceof Name)
76891
- code.push(arg10);
76887
+ function addCodeArg(code, arg11) {
76888
+ if (arg11 instanceof _Code)
76889
+ code.push(...arg11._items);
76890
+ else if (arg11 instanceof Name)
76891
+ code.push(arg11);
76892
76892
  else
76893
- code.push(interpolate(arg10));
76893
+ code.push(interpolate(arg11));
76894
76894
  }
76895
76895
  exports.addCodeArg = addCodeArg;
76896
76896
  function optimize(expr) {
@@ -88199,8 +88199,8 @@ var require_select = __commonJS({
88199
88199
  return selectors[":is"](sel);
88200
88200
  },
88201
88201
  ":nth-match": function(param, last) {
88202
- var args2 = param.split(/\s*,\s*/), arg10 = args2.shift(), test = compileGroup(args2.join(","));
88203
- return nth(arg10, test, last);
88202
+ var args2 = param.split(/\s*,\s*/), arg11 = args2.shift(), test = compileGroup(args2.join(","));
88203
+ return nth(arg11, test, last);
88204
88204
  },
88205
88205
  ":nth-last-match": function(param) {
88206
88206
  return selectors[":nth-match"](param, true);
@@ -108171,7 +108171,7 @@ var init_file_type = __esm({
108171
108171
  });
108172
108172
 
108173
108173
  // cli.ts
108174
- var import_arg9 = __toESM(require_arg(), 1);
108174
+ var import_arg10 = __toESM(require_arg(), 1);
108175
108175
  var import_picocolors5 = __toESM(require_picocolors(), 1);
108176
108176
  import { basename as basename2 } from "node:path";
108177
108177
 
@@ -109984,11 +109984,11 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
109984
109984
  array() {
109985
109985
  return array(this);
109986
109986
  },
109987
- or(arg10) {
109988
- return union([this, arg10]);
109987
+ or(arg11) {
109988
+ return union([this, arg11]);
109989
109989
  },
109990
- and(arg10) {
109991
- return intersection(this, arg10);
109990
+ and(arg11) {
109991
+ return intersection(this, arg11);
109992
109992
  },
109993
109993
  transform(tx) {
109994
109994
  return pipe(this, transform(tx));
@@ -112919,7 +112919,7 @@ var import_picocolors = __toESM(require_picocolors(), 1);
112919
112919
  // package.json
112920
112920
  var package_default = {
112921
112921
  name: "pullfrog",
112922
- version: "0.1.104",
112922
+ version: "0.1.106",
112923
112923
  cliContractVersion: "1",
112924
112924
  type: "module",
112925
112925
  bin: {
@@ -114155,7 +114155,7 @@ var repoConfigFields = [
114155
114155
  key: "address-reviews.enabled",
114156
114156
  field: "codingAddressReviews",
114157
114157
  kind: "toggle",
114158
- description: "address review feedback"
114158
+ description: "address reviews on Pullfrog-authored PRs"
114159
114159
  },
114160
114160
  {
114161
114161
  key: "fix-ci.own-prs",
@@ -115946,7 +115946,7 @@ var aube = {
115946
115946
  function denoAdd(args2) {
115947
115947
  if (args2.includes("--npm") || args2.includes("--jsr"))
115948
115948
  return ["deno", "add", ...args2];
115949
- return ["deno", "add", ...args2.map((arg10) => arg10.startsWith("-") || arg10.includes(":") ? arg10 : `npm:${arg10}`)];
115949
+ return ["deno", "add", ...args2.map((arg11) => arg11.startsWith("-") || arg11.includes(":") ? arg11 : `npm:${arg11}`)];
115950
115950
  }
115951
115951
  var deno = {
115952
115952
  "agent": ["deno", 0],
@@ -117863,9 +117863,34 @@ var AZURE_USE_CHAT_COMPLETIONS_ENV = "AZURE_USE_CHAT_COMPLETIONS";
117863
117863
  var OPENAI_COMPATIBLE_PROVIDER = "openai-compatible";
117864
117864
  var OPENAI_COMPATIBLE_BASE_URL_ENV = "OPENAI_COMPATIBLE_BASE_URL";
117865
117865
  var OPENAI_COMPATIBLE_API_KEY_ENV = "OPENAI_COMPATIBLE_API_KEY";
117866
- var OPENAI_COMPATIBLE_MODEL_ENV = "OPENAI_COMPATIBLE_MODEL";
117867
117866
  var OPENAI_COMPATIBLE_CONTEXT_ENV = "OPENAI_COMPATIBLE_CONTEXT";
117868
117867
  var OPENAI_COMPATIBLE_MAX_OUTPUT_ENV = "OPENAI_COMPATIBLE_MAX_OUTPUT";
117868
+ function isOpenAICompatibleSetName(name) {
117869
+ return name !== "byok" && name.length <= 32 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name);
117870
+ }
117871
+ function openAICompatibleSetName(slug2) {
117872
+ const prefix = `${OPENAI_COMPATIBLE_PROVIDER}/`;
117873
+ if (!slug2.startsWith(prefix)) return void 0;
117874
+ const name = slug2.slice(prefix.length);
117875
+ return isOpenAICompatibleSetName(name) ? name : void 0;
117876
+ }
117877
+ var OPENAI_COMPATIBLE_FIELDS = [
117878
+ "baseUrl",
117879
+ "apiKey",
117880
+ "model",
117881
+ "context",
117882
+ "maxOutput"
117883
+ ];
117884
+ function openAICompatibleEnv(name) {
117885
+ const prefix = `OPENAI_COMPATIBLE_${name ? `${name.toUpperCase().replaceAll("-", "_")}_` : ""}`;
117886
+ return {
117887
+ baseUrl: `${prefix}BASE_URL`,
117888
+ apiKey: `${prefix}API_KEY`,
117889
+ model: `${prefix}MODEL`,
117890
+ context: `${prefix}CONTEXT`,
117891
+ maxOutput: `${prefix}MAX_OUTPUT`
117892
+ };
117893
+ }
117869
117894
  var PROVIDER_GATEWAY_URL_ENV = {
117870
117895
  anthropic: "ANTHROPIC_BASE_URL",
117871
117896
  openai: "OPENAI_BASE_URL"
@@ -117910,7 +117935,7 @@ function findDanglingPromptToolRefs(params) {
117910
117935
  return [...new Set(extractMcpToolRefs(params.agentId, params.prompt))].filter((name) => !registered.has(name)).sort();
117911
117936
  }
117912
117937
  function hasSimilarIssues(params) {
117913
- return params.repoIntelligence && !!params.event.issue_number && !params.event.is_pr;
117938
+ return params.repoIntelligence && !params.event.is_pr;
117914
117939
  }
117915
117940
 
117916
117941
  // utils/activity.ts
@@ -118187,11 +118212,11 @@ function ts() {
118187
118212
  return isDebugEnabled() ? `[${(/* @__PURE__ */ new Date()).toISOString()}] ` : "";
118188
118213
  }
118189
118214
  function formatArgs(args2) {
118190
- return args2.map((arg10) => {
118191
- if (typeof arg10 === "string") return arg10;
118192
- if (arg10 instanceof Error) return `${arg10.message}
118193
- ${arg10.stack}`;
118194
- return JSON.stringify(arg10);
118215
+ return args2.map((arg11) => {
118216
+ if (typeof arg11 === "string") return arg11;
118217
+ if (arg11 instanceof Error) return `${arg11.message}
118218
+ ${arg11.stack}`;
118219
+ return JSON.stringify(arg11);
118195
118220
  }).join(" ");
118196
118221
  }
118197
118222
  function startGroup2(name) {
@@ -118396,7 +118421,7 @@ import { chmodSync, createWriteStream, existsSync as existsSync4, mkdirSync } fr
118396
118421
  import { join as join2 } from "node:path";
118397
118422
  import { pipeline } from "node:stream/promises";
118398
118423
  function resolveNpm() {
118399
- const npmCli = process.env.npm_execpath;
118424
+ const npmCli = process.env.NPM_EXECPATH;
118400
118425
  if (npmCli?.endsWith("npm-cli.js")) return { command: process.execPath, args: [npmCli] };
118401
118426
  return { command: "npm", args: [] };
118402
118427
  }
@@ -118697,7 +118722,11 @@ function resolveRunEffort(ctx) {
118697
118722
  const configured = ctx.payload.effort !== void 0;
118698
118723
  const position = ctx.payload.effort ?? DEFAULT_EFFORT_POSITION;
118699
118724
  const alias = resolveRunAlias(ctx);
118700
- if (!alias) return { position, configured, rung: void 0, alias: void 0 };
118725
+ if (!alias) {
118726
+ const declarable = configured && !ctx.resolvedModel?.startsWith(`${AZURE_PROVIDER}/`);
118727
+ const rung = declarable && ctx.declaredVariants ? resolveRung({ position, published: ctx.declaredVariants }) : void 0;
118728
+ return { position, configured, rung, alias: void 0, declarable };
118729
+ }
118701
118730
  return {
118702
118731
  position,
118703
118732
  configured,
@@ -118706,7 +118735,8 @@ function resolveRunEffort(ctx) {
118706
118735
  position,
118707
118736
  useOpenRouter: !!ctx.payload.proxyModel
118708
118737
  }),
118709
- alias
118738
+ alias,
118739
+ declarable: false
118710
118740
  };
118711
118741
  }
118712
118742
 
@@ -122724,7 +122754,7 @@ var buildClientParams = (args2, fields) => {
122724
122754
  };
122725
122755
  const map2 = buildKeyMap(fields);
122726
122756
  let config3;
122727
- for (const [index, arg10] of args2.entries()) {
122757
+ for (const [index, arg11] of args2.entries()) {
122728
122758
  if (fields[index]) {
122729
122759
  config3 = fields[index];
122730
122760
  }
@@ -122737,13 +122767,13 @@ var buildClientParams = (args2, fields) => {
122737
122767
  const name = field.map || config3.key;
122738
122768
  if (field.in) {
122739
122769
  ;
122740
- params[field.in][name] = arg10;
122770
+ params[field.in][name] = arg11;
122741
122771
  }
122742
122772
  } else {
122743
- params.body = arg10;
122773
+ params.body = arg11;
122744
122774
  }
122745
122775
  } else {
122746
- for (const [key, value2] of Object.entries(arg10 ?? {})) {
122776
+ for (const [key, value2] of Object.entries(arg11 ?? {})) {
122747
122777
  const field = map2.get(key);
122748
122778
  if (field) {
122749
122779
  if (field.in) {
@@ -127788,6 +127818,17 @@ function parseModel2(value2) {
127788
127818
  if (slash <= 0) return void 0;
127789
127819
  return { providerID: value2.slice(0, slash), modelID: value2.slice(slash + 1) };
127790
127820
  }
127821
+ async function resolveDeclaredRung(ctx, params) {
127822
+ const resp = await params.client.config.providers();
127823
+ const provider2 = resp.data?.providers.find((p) => p.id === params.model.providerID);
127824
+ const variants = provider2?.models[params.model.modelID]?.variants ?? {};
127825
+ const name = `${params.model.providerID}/${params.model.modelID}`;
127826
+ const rung = resolveRunEffort({ ...ctx, declaredVariants: Object.keys(variants) }).rung;
127827
+ log2.info(
127828
+ `\xBB effort: ${rung ? `${rung} (declared by opencode for ${name})` : `not applied \u2014 opencode declares no variants for ${name}`}`
127829
+ );
127830
+ return rung;
127831
+ }
127791
127832
  function bootOpencodeServer(params) {
127792
127833
  const logLevel = isDebugEnabled() ? "INFO" : "ERROR";
127793
127834
  if (logLevel !== "ERROR") log2.info(`\xBB opencode log level: ${logLevel} (debug run)`);
@@ -128442,6 +128483,11 @@ var opencode = agent({
128442
128483
  log2.info(`\xBB opencode session: ${sessionID}`);
128443
128484
  const labeler = new SessionLabeler();
128444
128485
  labeler.labelFor(sessionID);
128486
+ const sdkModel = parseModel2(model);
128487
+ const variant = effort.declarable && sdkModel ? await resolveDeclaredRung(
128488
+ { ...ctx, resolvedModel: rawModel },
128489
+ { client: client2, model: sdkModel }
128490
+ ) : effort.rung;
128445
128491
  const runnerCtx = {
128446
128492
  client: client2,
128447
128493
  sessionID,
@@ -128450,7 +128496,7 @@ var opencode = agent({
128450
128496
  labeler,
128451
128497
  toolState: ctx.toolState,
128452
128498
  // `rawModel` folds in the auto-select pick — see the opencode.ts twin.
128453
- variant: effort.rung,
128499
+ variant,
128454
128500
  todoTracker: ctx.todoTracker,
128455
128501
  onActivityTimeout: ctx.onActivityTimeout,
128456
128502
  onTurnRecovered: ctx.onTurnRecovered,
@@ -128512,7 +128558,6 @@ var opencode = agent({
128512
128558
  timeoutMs: AGENT_ACTIVITY_TIMEOUT_MS,
128513
128559
  abortTurn: () => turnController.abort()
128514
128560
  });
128515
- const sdkModel = parseModel2(model);
128516
128561
  let salvagesLeft = 1;
128517
128562
  const runTurn = async (text) => {
128518
128563
  const attempt = (prompt) => {
@@ -129383,12 +129428,12 @@ var CompiledFunction = class extends CastableBase {
129383
129428
  constructor(...args2) {
129384
129429
  super();
129385
129430
  this.argNames = args2;
129386
- for (const arg10 of args2) {
129387
- if (arg10 in this) {
129388
- throw new Error(`Arg name '${arg10}' would overwrite an existing property on FunctionBody`);
129431
+ for (const arg11 of args2) {
129432
+ if (arg11 in this) {
129433
+ throw new Error(`Arg name '${arg11}' would overwrite an existing property on FunctionBody`);
129389
129434
  }
129390
129435
  ;
129391
- this[arg10] = arg10;
129436
+ this[arg11] = arg11;
129392
129437
  }
129393
129438
  }
129394
129439
  indentation = 0;
@@ -129473,12 +129518,12 @@ var NodeCompiler = class extends CompiledFunction {
129473
129518
  this.optimistic = ctx.optimistic === true;
129474
129519
  }
129475
129520
  invoke(node3, opts) {
129476
- const arg10 = opts?.arg ?? this.data;
129521
+ const arg11 = opts?.arg ?? this.data;
129477
129522
  const requiresContext = typeof node3 === "string" ? true : this.requiresContextFor(node3);
129478
129523
  const id = typeof node3 === "string" ? node3 : node3.id;
129479
129524
  if (requiresContext)
129480
- return `${this.referenceToId(id, opts)}(${arg10}, ${this.ctx})`;
129481
- return `${this.referenceToId(id, opts)}(${arg10})`;
129525
+ return `${this.referenceToId(id, opts)}(${arg11}, ${this.ctx})`;
129526
+ return `${this.referenceToId(id, opts)}(${arg11})`;
129482
129527
  }
129483
129528
  referenceToId(id, opts) {
129484
129529
  const invokedKind = opts?.kind ?? this.traversalKind;
@@ -135474,11 +135519,11 @@ var Context = class {
135474
135519
  if (!this.#var) return {};
135475
135520
  return Object.fromEntries(this.#var);
135476
135521
  }
135477
- #newResponse(data, arg10, headers) {
135522
+ #newResponse(data, arg11, headers) {
135478
135523
  let responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders;
135479
- if (typeof arg10 === "object" && arg10.headers) {
135524
+ if (typeof arg11 === "object" && arg11.headers) {
135480
135525
  responseHeaders ??= new Headers();
135481
- for (const [key, value2] of new Headers(arg10.headers)) if (key === "set-cookie") responseHeaders.append(key, value2);
135526
+ for (const [key, value2] of new Headers(arg11.headers)) if (key === "set-cookie") responseHeaders.append(key, value2);
135482
135527
  else responseHeaders.set(key, value2);
135483
135528
  }
135484
135529
  if (headers) {
@@ -135498,7 +135543,7 @@ var Context = class {
135498
135543
  }
135499
135544
  }
135500
135545
  }
135501
- const status = typeof arg10 === "number" ? arg10 : arg10?.status ?? this.#status;
135546
+ const status = typeof arg11 === "number" ? arg11 : arg11?.status ?? this.#status;
135502
135547
  return createResponseInstance(data, {
135503
135548
  status,
135504
135549
  headers: responseHeaders ?? headers
@@ -135526,7 +135571,7 @@ var Context = class {
135526
135571
  * })
135527
135572
  * ```
135528
135573
  */
135529
- body = (data, arg10, headers) => this.#newResponse(data, arg10, headers);
135574
+ body = (data, arg11, headers) => this.#newResponse(data, arg11, headers);
135530
135575
  /**
135531
135576
  * `.text()` can render text as `Content-Type:text/plain`.
135532
135577
  *
@@ -135539,8 +135584,8 @@ var Context = class {
135539
135584
  * })
135540
135585
  * ```
135541
135586
  */
135542
- text = (text, arg10, headers) => {
135543
- return !this.#preparedHeaders && !this.#status && !arg10 && !headers && !this.finalized ? new Response(text) : this.#newResponse(text, arg10, setDefaultContentType(TEXT_PLAIN, headers));
135587
+ text = (text, arg11, headers) => {
135588
+ return !this.#preparedHeaders && !this.#status && !arg11 && !headers && !this.finalized ? new Response(text) : this.#newResponse(text, arg11, setDefaultContentType(TEXT_PLAIN, headers));
135544
135589
  };
135545
135590
  /**
135546
135591
  * `.json()` can render JSON as `Content-Type:application/json`.
@@ -135554,11 +135599,11 @@ var Context = class {
135554
135599
  * })
135555
135600
  * ```
135556
135601
  */
135557
- json = (object5, arg10, headers) => {
135558
- return this.#newResponse(JSON.stringify(object5), arg10, setDefaultContentType("application/json", headers));
135602
+ json = (object5, arg11, headers) => {
135603
+ return this.#newResponse(JSON.stringify(object5), arg11, setDefaultContentType("application/json", headers));
135559
135604
  };
135560
- html = (html, arg10, headers) => {
135561
- const res = (html2) => this.#newResponse(html2, arg10, setDefaultContentType("text/html; charset=UTF-8", headers));
135605
+ html = (html, arg11, headers) => {
135606
+ const res = (html2) => this.#newResponse(html2, arg11, setDefaultContentType("text/html; charset=UTF-8", headers));
135562
135607
  return typeof html === "object" ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res) : res(html);
135563
135608
  };
135564
135609
  /**
@@ -142445,10 +142490,10 @@ var require_code$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
142445
142490
  return new _Code(expr);
142446
142491
  }
142447
142492
  exports.str = str;
142448
- function addCodeArg(code, arg10) {
142449
- if (arg10 instanceof _Code) code.push(...arg10._items);
142450
- else if (arg10 instanceof Name) code.push(arg10);
142451
- else code.push(interpolate(arg10));
142493
+ function addCodeArg(code, arg11) {
142494
+ if (arg11 instanceof _Code) code.push(...arg11._items);
142495
+ else if (arg11 instanceof Name) code.push(arg11);
142496
+ else code.push(interpolate(arg11));
142452
142497
  }
142453
142498
  exports.addCodeArg = addCodeArg;
142454
142499
  function optimize(expr) {
@@ -156782,10 +156827,10 @@ var require_code$12 = /* @__PURE__ */ __commonJSMin2(((exports) => {
156782
156827
  return new _Code(expr);
156783
156828
  }
156784
156829
  exports.str = str;
156785
- function addCodeArg(code, arg10) {
156786
- if (arg10 instanceof _Code) code.push(...arg10._items);
156787
- else if (arg10 instanceof Name) code.push(arg10);
156788
- else code.push(interpolate(arg10));
156830
+ function addCodeArg(code, arg11) {
156831
+ if (arg11 instanceof _Code) code.push(...arg11._items);
156832
+ else if (arg11 instanceof Name) code.push(arg11);
156833
+ else code.push(interpolate(arg11));
156789
156834
  }
156790
156835
  exports.addCodeArg = addCodeArg;
156791
156836
  function optimize(expr) {
@@ -164983,13 +165028,13 @@ var Doc2 = class {
164983
165028
  fn2(this);
164984
165029
  this.indent -= 1;
164985
165030
  }
164986
- write(arg10) {
164987
- if (typeof arg10 === "function") {
164988
- arg10(this, { execution: "sync" });
164989
- arg10(this, { execution: "async" });
165031
+ write(arg11) {
165032
+ if (typeof arg11 === "function") {
165033
+ arg11(this, { execution: "sync" });
165034
+ arg11(this, { execution: "async" });
164990
165035
  return;
164991
165036
  }
164992
- const lines = arg10.split("\n").filter((x) => x);
165037
+ const lines = arg11.split("\n").filter((x) => x);
164993
165038
  const minIndent = Math.min(...lines.map((x) => x.length - x.trimStart().length));
164994
165039
  const dedented = lines.map((x) => x.slice(minIndent)).map((x) => " ".repeat(this.indent * 2) + x);
164995
165040
  for (const line of dedented) this.content.push(line);
@@ -167798,11 +167843,11 @@ var ZodType3 = /* @__PURE__ */ $constructor2("ZodType", (inst, def) => {
167798
167843
  array() {
167799
167844
  return array2(this);
167800
167845
  },
167801
- or(arg10) {
167802
- return union2([this, arg10]);
167846
+ or(arg11) {
167847
+ return union2([this, arg11]);
167803
167848
  },
167804
- and(arg10) {
167805
- return intersection2(this, arg10);
167849
+ and(arg11) {
167850
+ return intersection2(this, arg11);
167806
167851
  },
167807
167852
  transform(tx) {
167808
167853
  return pipe2(this, transform2(tx));
@@ -171487,14 +171532,14 @@ var require_http_errors = /* @__PURE__ */ __commonJSMin3(((exports, module) => {
171487
171532
  var status$1 = 500;
171488
171533
  var props = {};
171489
171534
  for (var i$3 = 0; i$3 < arguments.length; i$3++) {
171490
- var arg10 = arguments[i$3];
171491
- var type2 = typeof arg10;
171492
- if (type2 === "object" && arg10 instanceof Error) {
171493
- err = arg10;
171535
+ var arg11 = arguments[i$3];
171536
+ var type2 = typeof arg11;
171537
+ if (type2 === "object" && arg11 instanceof Error) {
171538
+ err = arg11;
171494
171539
  status$1 = err.status || err.statusCode || status$1;
171495
- } else if (type2 === "number" && i$3 === 0) status$1 = arg10;
171496
- else if (type2 === "string") msg = arg10;
171497
- else if (type2 === "object") props = arg10;
171540
+ } else if (type2 === "number" && i$3 === 0) status$1 = arg11;
171541
+ else if (type2 === "string") msg = arg11;
171542
+ else if (type2 === "object") props = arg11;
171498
171543
  else throw new TypeError("argument #" + (i$3 + 1) + " unsupported type " + type2);
171499
171544
  }
171500
171545
  if (typeof status$1 === "number" && (status$1 < 400 || status$1 >= 600)) deprecate("non-error status code; use only 4xx or 5xx status codes");
@@ -182062,11 +182107,11 @@ ${error63 instanceof Error ? error63.stack : JSON.stringify(error63)}`
182062
182107
  );
182063
182108
  }
182064
182109
  const args2 = request2.params.arguments;
182065
- for (const arg10 of prompt.arguments ?? []) {
182066
- if (arg10.required && !(args2 && arg10.name in args2)) {
182110
+ for (const arg11 of prompt.arguments ?? []) {
182111
+ if (arg11.required && !(args2 && arg11.name in args2)) {
182067
182112
  throw new McpError(
182068
182113
  ErrorCode.InvalidRequest,
182069
- `Prompt '${request2.params.name}' requires argument '${arg10.name}': ${arg10.description || "No description provided"}`
182114
+ `Prompt '${request2.params.name}' requires argument '${arg11.name}': ${arg11.description || "No description provided"}`
182070
182115
  );
182071
182116
  }
182072
182117
  }
@@ -183292,7 +183337,7 @@ var FastMCP = class extends FastMCPEventEmitter {
183292
183337
  #parseRuntimeConfig(overrides) {
183293
183338
  const args2 = process.argv.slice(2);
183294
183339
  const getArg = (name) => {
183295
- const index = args2.findIndex((arg10) => arg10 === `--${name}`);
183340
+ const index = args2.findIndex((arg11) => arg11 === `--${name}`);
183296
183341
  return index !== -1 && index + 1 < args2.length ? args2[index + 1] : void 0;
183297
183342
  };
183298
183343
  const transportArg = getArg("transport");
@@ -184570,11 +184615,11 @@ var GenericRoot = class extends Callable {
184570
184615
  constructor(paramDefs, bodyDef, $2, arg$, hkt) {
184571
184616
  super((...args2) => {
184572
184617
  const argNodes = flatMorph(this.names, (i2, name) => {
184573
- const arg10 = this.arg$.parse(args2[i2]);
184574
- if (!arg10.extends(this.constraints[i2])) {
184575
- throwParseError(writeUnsatisfiedParameterConstraintMessage(name, this.constraints[i2].expression, arg10.expression));
184618
+ const arg11 = this.arg$.parse(args2[i2]);
184619
+ if (!arg11.extends(this.constraints[i2])) {
184620
+ throwParseError(writeUnsatisfiedParameterConstraintMessage(name, this.constraints[i2].expression, arg11.expression));
184576
184621
  }
184577
- return [name, arg10];
184622
+ return [name, arg11];
184578
184623
  });
184579
184624
  if (this.defIsLazy()) {
184580
184625
  const def = this.bodyDef(argNodes);
@@ -184622,7 +184667,7 @@ var GenericRoot = class extends Callable {
184622
184667
  return this.baseInstantiation.internal.references;
184623
184668
  }
184624
184669
  };
184625
- var writeUnsatisfiedParameterConstraintMessage = (name, constraint, arg10) => `${name} must be assignable to ${constraint} (was ${arg10})`;
184670
+ var writeUnsatisfiedParameterConstraintMessage = (name, constraint, arg11) => `${name} must be assignable to ${constraint} (was ${arg11})`;
184626
184671
 
184627
184672
  // node_modules/.pnpm/@ark+schema@0.56.0/node_modules/@ark/schema/out/predicate.js
184628
184673
  var implementation = implementNode({
@@ -189120,7 +189165,7 @@ var _parseGenericArgs = (name, g, s, argNodes) => {
189120
189165
  argNodes.push(argState.root);
189121
189166
  if (argState.finalizer === ">") {
189122
189167
  if (argNodes.length !== g.params.length) {
189123
- return s.error(writeInvalidGenericArgCountMessage(name, g.names, argNodes.map((arg10) => arg10.expression)));
189168
+ return s.error(writeInvalidGenericArgCountMessage(name, g.names, argNodes.map((arg11) => arg11.expression)));
189124
189169
  }
189125
189170
  return argNodes;
189126
189171
  }
@@ -189149,10 +189194,10 @@ var parseGenericInstantiation = (name, g, s) => {
189149
189194
  var unenclosedToNode = (s, token) => maybeParseReference(s, token) ?? maybeParseUnenclosedLiteral(s, token) ?? s.error(token === "" ? s.scanner.lookahead === "#" ? writePrefixedPrivateReferenceMessage(s.shiftedBy(1).scanner.shiftUntilLookahead(terminatingChars)) : writeMissingOperandMessage(s) : writeUnresolvableMessage(token));
189150
189195
  var maybeParseReference = (s, token) => {
189151
189196
  if (s.ctx.args?.[token]) {
189152
- const arg10 = s.ctx.args[token];
189153
- if (typeof arg10 !== "string")
189154
- return arg10;
189155
- return s.ctx.$.node("alias", { reference: arg10 }, { prereduced: true });
189197
+ const arg11 = s.ctx.args[token];
189198
+ if (typeof arg11 !== "string")
189199
+ return arg11;
189200
+ return s.ctx.$.node("alias", { reference: arg11 }, { prereduced: true });
189156
189201
  }
189157
189202
  const resolution = s.ctx.$.maybeResolve(token);
189158
189203
  if (hasArkKind(resolution, "root"))
@@ -193650,14 +193695,15 @@ function computeIncrementalDiff(params) {
193650
193695
  const tips = [`origin/${params.baseBranch}`, ...params.formerBaseTips];
193651
193696
  const oldBase = versionBase({ sha: params.beforeSha, tips });
193652
193697
  const newBase = versionBase({ sha: params.headSha, tips });
193698
+ const replayed = oldBase === newBase ? null : replay({ sha: params.beforeSha, from: oldBase, onto: newBase });
193653
193699
  const raw2 = $(
193654
193700
  "sh",
193655
193701
  [
193656
193702
  "-c",
193657
193703
  'git range-diff --no-color --creation-factor=1000 "$1..$(git commit-tree "$2^{tree}" -p "$1" -m x)" "$3..$(git commit-tree "$4^{tree}" -p "$3" -m x)"',
193658
193704
  "--",
193659
- oldBase,
193660
- params.beforeSha,
193705
+ replayed ? newBase : oldBase,
193706
+ replayed ?? params.beforeSha,
193661
193707
  newBase,
193662
193708
  params.headSha
193663
193709
  ],
@@ -193692,6 +193738,22 @@ function versionBase(params) {
193692
193738
  }
193693
193739
  return best.sha;
193694
193740
  }
193741
+ function replay(params) {
193742
+ try {
193743
+ return git([
193744
+ "merge-tree",
193745
+ "--write-tree",
193746
+ `--merge-base=${params.from}`,
193747
+ params.onto,
193748
+ params.sha
193749
+ ]);
193750
+ } catch {
193751
+ log2.info(
193752
+ `\xBB incremental diff: ${params.sha.slice(0, 7)} does not replay onto the new base; comparing each on its own`
193753
+ );
193754
+ return null;
193755
+ }
193756
+ }
193695
193757
  function isDiffPrefix(ch) {
193696
193758
  return ch === " " || ch === "+" || ch === "-";
193697
193759
  }
@@ -199349,13 +199411,13 @@ function GitTool(ctx) {
199349
199411
  if (blocked) {
199350
199412
  throw new Error(blocked);
199351
199413
  }
199352
- for (const arg10 of args2) {
199414
+ for (const arg11 of args2) {
199353
199415
  const isBlocked = NOSHELL_BLOCKED_ARGS.some(
199354
- (flag) => arg10 === flag || arg10.startsWith(flag + "=")
199416
+ (flag) => arg11 === flag || arg11.startsWith(flag + "=")
199355
199417
  );
199356
199418
  if (isBlocked) {
199357
199419
  throw new Error(
199358
- `Blocked: '${arg10}' flag can execute arbitrary code and is not allowed.`
199420
+ `Blocked: '${arg11}' flag can execute arbitrary code and is not allowed.`
199359
199421
  );
199360
199422
  }
199361
199423
  }
@@ -199902,13 +199964,16 @@ function buildImplementPlanLink(ctx, issueNumber, commentId) {
199902
199964
  const apiUrl = getApiUrl();
199903
199965
  return `[Implement plan \u2794](${apiUrl}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${issueNumber}?action=implement&comment_id=${commentId})`;
199904
199966
  }
199905
- function buildEnrichmentLinks(ctx) {
199967
+ function runIssueNumber(ctx) {
199968
+ return ctx.payload.event.issue_number ?? primaryRepoState(ctx.toolState).issueNumber;
199969
+ }
199970
+ function buildEnrichmentLinks(ctx, issueNumber) {
199906
199971
  const event = ctx.payload.event;
199907
- if (event.trigger !== "issues_opened" || event.is_pr || ctx.payload.prompt || ctx.toolState.selectedMode === "Build") {
199908
- return [];
199909
- }
199972
+ const mode = ctx.toolState.selectedMode;
199973
+ const enriching = mode === "Enrich" || event.trigger === "issues_opened" && !ctx.payload.prompt && mode !== "Build";
199974
+ if (issueNumber === void 0 || event.is_pr || !enriching) return [];
199910
199975
  return [
199911
- `[Implement a fix \u2794](${getApiUrl()}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${event.issue_number}?action=build)`
199976
+ `[Implement a fix \u2794](${getApiUrl()}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${issueNumber}?action=build)`
199912
199977
  ];
199913
199978
  }
199914
199979
  function addFooter(ctx, body) {
@@ -199944,10 +200009,11 @@ function CreateCommentTool(ctx) {
199944
200009
  });
199945
200010
  ctx.toolState.wasUpdated = true;
199946
200011
  log2.info(`\xBB created comment ${result.data.id}`);
199947
- if (issueNumber === ctx.payload.event.issue_number) {
200012
+ const ownTarget = issueNumber === runIssueNumber(ctx);
200013
+ if (ownTarget) {
199948
200014
  ctx.toolState.standaloneCommentId = result.data.id;
199949
200015
  }
199950
- const enrichmentLinks = issueNumber === ctx.payload.event.issue_number ? buildEnrichmentLinks(ctx) : [];
200016
+ const enrichmentLinks = ownTarget ? buildEnrichmentLinks(ctx, issueNumber) : [];
199951
200017
  if (commentType === "Plan" || enrichmentLinks.length > 0) {
199952
200018
  if (commentType === "Plan" && result.data.node_id) {
199953
200019
  await patchWorkflowRunFields(ctx, { planCommentNodeId: result.data.node_id });
@@ -200027,9 +200093,9 @@ async function reportProgress(ctx, params) {
200027
200093
  if (params.liveProgress && !ctx.payload.progressComments) {
200028
200094
  return { body, action: "skipped" };
200029
200095
  }
200030
- const issueNumber = ctx.payload.event.issue_number ?? primaryRepoState(ctx.toolState).issueNumber;
200096
+ const issueNumber = runIssueNumber(ctx);
200031
200097
  const isPlanMode = ctx.toolState.selectedMode === "Plan";
200032
- const enrichmentLinks = params.liveProgress ? [] : buildEnrichmentLinks(ctx);
200098
+ const enrichmentLinks = params.liveProgress ? [] : buildEnrichmentLinks(ctx, issueNumber);
200033
200099
  const apiCtx = { octokit: ctx.octokit, owner: ctx.repo.owner, repo: ctx.repo.name };
200034
200100
  if (target_plan_comment === true && ctx.toolState.existingPlanCommentId === void 0) {
200035
200101
  log2.warning("target_plan_comment requested but no existingPlanCommentId in tool state");
@@ -200947,11 +201013,25 @@ import { execFileSync as execFileSync7, execSync as execSync2 } from "node:child
200947
201013
  import { mkdtempSync as mkdtempSync3, readdirSync, realpathSync as realpathSync2, rmSync as rmSync4, unlinkSync as unlinkSync2 } from "node:fs";
200948
201014
  import { tmpdir as tmpdir3 } from "node:os";
200949
201015
  import { join as join16 } from "node:path";
201016
+ var TEMP_DIR_STATE = "temp_dir";
200950
201017
  function createTempDirectory() {
200951
201018
  const path4 = mkdtempSync3(join16(tmpdir3(), "pullfrog-"));
200952
201019
  process.env.PULLFROG_TEMP_DIR = path4;
200953
201020
  log2.info(`\xBB created temp dir at ${path4}`);
200954
- return { path: path4, [Symbol.dispose]: () => removeTempDirectory(path4) };
201021
+ const tracked = process.env.RUNNER_ENVIRONMENT !== "github-hosted";
201022
+ if (tracked) saveSecretState(TEMP_DIR_STATE, path4);
201023
+ return {
201024
+ path: path4,
201025
+ [Symbol.dispose]: () => {
201026
+ if (removeTempDirectory(path4) && tracked) saveSecretState(TEMP_DIR_STATE, "");
201027
+ }
201028
+ };
201029
+ }
201030
+ function removeAbandonedTempDirectory() {
201031
+ const path4 = getState(TEMP_DIR_STATE);
201032
+ if (!path4) return;
201033
+ log2.info(`\xBB removing temp dir left by an interrupted run at ${path4}`);
201034
+ removeTempDirectory(path4);
200955
201035
  }
200956
201036
  function removeTempDirectory(path4) {
200957
201037
  try {
@@ -200962,10 +201042,12 @@ function removeTempDirectory(path4) {
200962
201042
  rmSync4(path4, { recursive: true, force: true });
200963
201043
  }
200964
201044
  log2.debug(`\xBB removed temp dir at ${path4}`);
201045
+ return true;
200965
201046
  } catch (err) {
200966
201047
  log2.warning(
200967
201048
  `\xBB could not remove temp dir at ${path4}: ${err instanceof Error ? err.message : String(err)}`
200968
201049
  );
201050
+ return false;
200969
201051
  }
200970
201052
  }
200971
201053
  function wipeRunnerLeakSurface() {
@@ -202767,8 +202849,8 @@ var GhParams = type({
202767
202849
  'gh arguments as an argv array, e.g. ["pr", "list", "--json", "number,title"] or ["api", "graphql", "-f", "query=..."]'
202768
202850
  )
202769
202851
  });
202770
- function shellQuote(arg10) {
202771
- return `'${arg10.replace(/'/g, "'\\''")}'`;
202852
+ function shellQuote(arg11) {
202853
+ return `'${arg11.replace(/'/g, "'\\''")}'`;
202772
202854
  }
202773
202855
  function GhTool(ctx) {
202774
202856
  const permissions = mirrorRolePermissions(ctx.payload.event.authorPermission);
@@ -203040,7 +203122,7 @@ function GetIssueCommentsTool(ctx) {
203040
203122
  description: "Get all comments for a GitHub issue. Returns all comments including the issue body and all subsequent discussion comments. Example: `get_issue_comments({ issue_number: 1234 })`.",
203041
203123
  parameters: GetIssueComments,
203042
203124
  execute: execute(async ({ issue_number }) => {
203043
- primaryRepoState(ctx.toolState).issueNumber = issue_number;
203125
+ primaryRepoState(ctx.toolState).issueNumber ??= issue_number;
203044
203126
  const comments = await ctx.octokit.paginate(ctx.octokit.rest.issues.listComments, {
203045
203127
  owner: ctx.repo.owner,
203046
203128
  repo: ctx.repo.name,
@@ -203078,7 +203160,7 @@ function GetIssueEventsTool(ctx) {
203078
203160
  description: "Get timeline events for a GitHub issue that aren't reflected in the current state. Returns cross-references to other issues/PRs and commit references. Note: current labels, assignees, state, and milestone are already available via get_issue.",
203079
203161
  parameters: GetIssueEvents,
203080
203162
  execute: execute(async ({ issue_number }) => {
203081
- primaryRepoState(ctx.toolState).issueNumber = issue_number;
203163
+ primaryRepoState(ctx.toolState).issueNumber ??= issue_number;
203082
203164
  const events = await ctx.octokit.paginate(ctx.octokit.rest.issues.listEventsForTimeline, {
203083
203165
  owner: ctx.repo.owner,
203084
203166
  repo: ctx.repo.name,
@@ -203162,7 +203244,7 @@ function IssueInfoTool(ctx) {
203162
203244
  tmpdir: ctx.tmpdir,
203163
203245
  githubToken: ctx.githubInstallationToken
203164
203246
  });
203165
- primaryRepoState(ctx.toolState).issueNumber = issue_number;
203247
+ primaryRepoState(ctx.toolState).issueNumber ??= issue_number;
203166
203248
  const hints = [];
203167
203249
  if (data.comments > 0) {
203168
203250
  hints.push("use get_issue_comments to retrieve all comments for this issue");
@@ -204630,8 +204712,11 @@ function SimilarIssuesTool(ctx) {
204630
204712
  mutates: true,
204631
204713
  parameters: SimilarIssues,
204632
204714
  execute: execute(async (input2) => {
204633
- if (ctx.payload.event.is_pr || ctx.payload.event.issue_number !== input2.issue_number) {
204634
- throw new Error("find_similar_issues is limited to the issue that triggered this run");
204715
+ const repoState = primaryRepoState(ctx.toolState);
204716
+ repoState.issueNumber ??= input2.issue_number;
204717
+ const subject = ctx.payload.event.issue_number ?? repoState.issueNumber;
204718
+ if (ctx.payload.event.is_pr || subject !== input2.issue_number) {
204719
+ throw new Error(`find_similar_issues is limited to this run's issue, #${subject}`);
204635
204720
  }
204636
204721
  const response = await apiFetch({
204637
204722
  path: `/api/repo/${ctx.repo.owner}/${ctx.repo.name}/issues/${input2.issue_number}/similar`,
@@ -204913,7 +204998,7 @@ function buildCommonTools(ctx, outputSchema) {
204913
204998
  if (hasSimilarIssues({ repoIntelligence: ctx.repoIntelligence, event: ctx.payload.event })) {
204914
204999
  tools.push(SimilarIssuesTool(ctx));
204915
205000
  }
204916
- if (ctx.payload.event.issue_number !== void 0 && !ctx.payload.event.is_pr) {
205001
+ if (!ctx.payload.event.is_pr) {
204917
205002
  tools.push(SearchIssuesTool(ctx));
204918
205003
  }
204919
205004
  const isStandalone = ctx.payload.event.trigger === "unknown";
@@ -205311,11 +205396,11 @@ function buildOpenAICompatibleSetupError(params) {
205311
205396
  missing: params.missing,
205312
205397
  where: `Set them on the OpenAI-compatible provider in [Pullfrog's provider settings](${getApiUrl()}/console/${params.owner}#billing), or in the workflow's \`env:\` block with the key as an [Actions secret](${secretsUrl(params)}):`,
205313
205398
  env: [
205314
- `${OPENAI_COMPATIBLE_BASE_URL_ENV}: https://your-endpoint.example.com/v1`,
205315
- `${OPENAI_COMPATIBLE_API_KEY_ENV}: \${{ secrets.${OPENAI_COMPATIBLE_API_KEY_ENV} }}`,
205316
- `${OPENAI_COMPATIBLE_MODEL_ENV}: <model-id>`,
205317
- `${OPENAI_COMPATIBLE_CONTEXT_ENV}: "128000"`,
205318
- `${OPENAI_COMPATIBLE_MAX_OUTPUT_ENV}: "16384"`
205399
+ `${params.env.baseUrl}: https://your-endpoint.example.com/v1`,
205400
+ `${params.env.apiKey}: \${{ secrets.${params.env.apiKey} }}`,
205401
+ `${params.env.model}: <model-id>`,
205402
+ `${params.env.context}: "128000"`,
205403
+ `${params.env.maxOutput}: "16384"`
205319
205404
  ],
205320
205405
  note: "Use the real context and output limits of the model your endpoint serves: Pullfrog can't discover them, and without them long runs grow until the endpoint refuses them.",
205321
205406
  guide: "https://docs.pullfrog.com/openai-compatible"
@@ -205349,17 +205434,16 @@ function hasPositiveNumberEnvVar(name) {
205349
205434
  return Number(process.env[name]) > 0;
205350
205435
  }
205351
205436
  function validateOpenAICompatibleSetup(params) {
205437
+ const env2 = openAICompatibleEnv(params.set);
205352
205438
  const missing = [];
205353
- if (!hasEnvVar2(OPENAI_COMPATIBLE_BASE_URL_ENV)) missing.push(OPENAI_COMPATIBLE_BASE_URL_ENV);
205354
- if (!hasEnvVar2(OPENAI_COMPATIBLE_API_KEY_ENV)) missing.push(OPENAI_COMPATIBLE_API_KEY_ENV);
205355
- if (!hasEnvVar2(OPENAI_COMPATIBLE_MODEL_ENV)) missing.push(OPENAI_COMPATIBLE_MODEL_ENV);
205356
- if (!hasPositiveNumberEnvVar(OPENAI_COMPATIBLE_CONTEXT_ENV))
205357
- missing.push(OPENAI_COMPATIBLE_CONTEXT_ENV);
205358
- if (!hasPositiveNumberEnvVar(OPENAI_COMPATIBLE_MAX_OUTPUT_ENV))
205359
- missing.push(OPENAI_COMPATIBLE_MAX_OUTPUT_ENV);
205439
+ if (!hasEnvVar2(env2.baseUrl)) missing.push(env2.baseUrl);
205440
+ if (!hasEnvVar2(env2.apiKey)) missing.push(env2.apiKey);
205441
+ if (!hasEnvVar2(env2.model)) missing.push(env2.model);
205442
+ if (!hasPositiveNumberEnvVar(env2.context)) missing.push(env2.context);
205443
+ if (!hasPositiveNumberEnvVar(env2.maxOutput)) missing.push(env2.maxOutput);
205360
205444
  if (missing.length > 0) {
205361
205445
  throw new Error(
205362
- buildOpenAICompatibleSetupError({ owner: params.owner, name: params.name, missing })
205446
+ buildOpenAICompatibleSetupError({ owner: params.owner, name: params.name, missing, env: env2 })
205363
205447
  );
205364
205448
  }
205365
205449
  }
@@ -205415,7 +205499,11 @@ function validateAgentApiKey(params) {
205415
205499
  return;
205416
205500
  }
205417
205501
  if (params.model.startsWith(`${OPENAI_COMPATIBLE_PROVIDER}/`)) {
205418
- validateOpenAICompatibleSetup({ owner: params.owner, name: params.name });
205502
+ validateOpenAICompatibleSetup({
205503
+ owner: params.owner,
205504
+ name: params.name,
205505
+ set: params.openAICompatibleSet
205506
+ });
205419
205507
  return;
205420
205508
  }
205421
205509
  if (params.model.startsWith(`${AZURE_PROVIDER}/`)) {
@@ -205729,17 +205817,37 @@ function resolveSlug(slug2) {
205729
205817
  }
205730
205818
  return `${AZURE_PROVIDER}/${deployment}`;
205731
205819
  }
205732
- if (alias?.routing === "openai-compatible") {
205733
- const modelId = process.env[OPENAI_COMPATIBLE_MODEL_ENV]?.trim();
205820
+ const set2 = heldOpenAICompatibleSet(slug2);
205821
+ if (alias?.routing === "openai-compatible" || set2) {
205822
+ const modelEnv = openAICompatibleEnv(set2).model;
205823
+ const modelId = process.env[modelEnv]?.trim();
205734
205824
  if (!modelId) {
205735
205825
  throw new Error(
205736
- `\`${OPENAI_COMPATIBLE_MODEL_ENV}\` ${BYOK_SLUG_MARKER} \`${slug2}\`. Set it to the model ID your endpoint serves, on the OpenAI-compatible provider in Pullfrog or in the workflow's \`env:\` block. [OpenAI-compatible setup guide](https://docs.pullfrog.com/openai-compatible)`
205826
+ `\`${modelEnv}\` ${BYOK_SLUG_MARKER} \`${slug2}\`. Set it to the model ID your endpoint serves, on the OpenAI-compatible provider in Pullfrog or in the workflow's \`env:\` block. [OpenAI-compatible setup guide](https://docs.pullfrog.com/openai-compatible)`
205737
205827
  );
205738
205828
  }
205739
205829
  return `${OPENAI_COMPATIBLE_PROVIDER}/${modelId}`;
205740
205830
  }
205741
205831
  return resolveCliModel(slug2);
205742
205832
  }
205833
+ function heldOpenAICompatibleSet(slug2) {
205834
+ const set2 = openAICompatibleSetName(slug2);
205835
+ return set2 && Object.values(openAICompatibleEnv(set2)).some(hasEnvVar3) ? set2 : void 0;
205836
+ }
205837
+ function activateOpenAICompatibleSet(ctx) {
205838
+ const slug2 = process.env.PULLFROG_MODEL?.trim() || ctx.slug?.trim();
205839
+ const set2 = slug2 ? heldOpenAICompatibleSet(slug2) : void 0;
205840
+ if (!set2) return void 0;
205841
+ const from = openAICompatibleEnv(set2);
205842
+ const to = openAICompatibleEnv();
205843
+ for (const field of OPENAI_COMPATIBLE_FIELDS) {
205844
+ const value2 = process.env[from[field]];
205845
+ if (value2 === void 0) delete process.env[to[field]];
205846
+ else process.env[to[field]] = value2;
205847
+ }
205848
+ log2.info(`\xBB using the OpenAI-compatible endpoint "${set2}"`);
205849
+ return set2;
205850
+ }
205743
205851
  function resolveModel(ctx) {
205744
205852
  const envModel = process.env.PULLFROG_MODEL?.trim();
205745
205853
  if (envModel) {
@@ -206739,7 +206847,7 @@ Rules:
206739
206847
  ### GitHub
206740
206848
 
206741
206849
  Use MCP tools from ${pullfrogMcpName} for all GitHub operations. Never use the \`gh\` CLI \u2014 it is not authenticated and will fail. The MCP tools handle authentication and enforce permissions.
206742
- ${hasSimilarIssues({ repoIntelligence: ctx.repoIntelligence, event: ctx.payload.event }) ? `
206850
+ ${ctx.payload.event.issue_number !== void 0 && hasSimilarIssues({ repoIntelligence: ctx.repoIntelligence, event: ctx.payload.event }) ? `
206743
206851
  #### Duplicate detection (enabled for this repository)
206744
206852
 
206745
206853
  Call \`${t2("find_similar_issues")}\` for #${ctx.payload.event.issue_number} before planning. If it duplicates an existing issue, link that instead of producing a plan; never close or label on similarity alone.
@@ -208618,6 +208726,9 @@ function resolveModelForLog(ctx) {
208618
208726
  function resolveEffortForLog(ctx) {
208619
208727
  const effort = resolveRunEffort(ctx);
208620
208728
  if (!ctx.resolvedModel && !ctx.payload.proxyModel) return "pending \u2014 model not chosen yet";
208729
+ if (effort.declarable && ctx.agentName === "opencode") {
208730
+ return "pending \u2014 reading the variants opencode declares";
208731
+ }
208621
208732
  if (!effort.alias) return "not applied \u2014 model not recognized";
208622
208733
  if (!effort.rung) return "n/a (model has no effort control)";
208623
208734
  return effort.configured ? effort.rung : `${effort.rung} (default)`;
@@ -208636,9 +208747,7 @@ function logRunStartup(ctx) {
208636
208747
  log2.info(
208637
208748
  `\xBB model: ${resolveModelForLog({ payload: ctx.payload, resolvedModel: ctx.resolvedModel })}`
208638
208749
  );
208639
- log2.info(
208640
- `\xBB effort: ${resolveEffortForLog({ payload: ctx.payload, resolvedModel: ctx.resolvedModel })}`
208641
- );
208750
+ log2.info(`\xBB effort: ${resolveEffortForLog(ctx)}`);
208642
208751
  const routing = ctx.payload.routing;
208643
208752
  if (routing) {
208644
208753
  log2.info(
@@ -208909,6 +209018,7 @@ async function main() {
208909
209018
  const count = Object.keys(runContext.dbSecrets).length;
208910
209019
  if (count > 0) log2.info(`\xBB ${count} db secret(s) loaded`);
208911
209020
  }
209021
+ const openAICompatibleSet = activateOpenAICompatibleSet({ slug: payload.model });
208912
209022
  await initializeCredentialPool({ ctx: runContext, slug: payload.model, injected });
208913
209023
  installCodexAuth();
208914
209024
  installXaiAuth();
@@ -209057,7 +209167,8 @@ async function main() {
209057
209167
  owner: runContext.repo.owner,
209058
209168
  name: runContext.repo.name,
209059
209169
  secretsUnavailable: runContext.secretsUnavailable,
209060
- routerUnfunded: runContext.routerUnfunded
209170
+ routerUnfunded: runContext.routerUnfunded,
209171
+ openAICompatibleSet
209061
209172
  });
209062
209173
  } catch (missingKey) {
209063
209174
  const funded = runContext.trialFallback && missingKey instanceof NoUsableCredentialError ? await resolveTrialFallback({
@@ -209587,6 +209698,7 @@ async function runCli5(params) {
209587
209698
  async function run(args2) {
209588
209699
  if (args2.includes("--post") && !args2.includes("token")) {
209589
209700
  await runOAuthWriteback().catch((error63) => warning(`oauth post-hook: ${error63}`));
209701
+ removeAbandonedTempDirectory();
209590
209702
  return;
209591
209703
  }
209592
209704
  try {
@@ -209988,7 +210100,7 @@ function resolveTarget2(repo) {
209988
210100
  return { owner: match3[1], repo: match3[2] };
209989
210101
  }
209990
210102
  function cliVersion() {
209991
- const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.104");
210103
+ const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec("0.1.106");
209992
210104
  if (!parts) return "0.0.0";
209993
210105
  return `${Number(parts[1])}.${Number(parts[2])}.${Number(parts[3])}`;
209994
210106
  }
@@ -210044,11 +210156,41 @@ async function runCli7(input2) {
210044
210156
  });
210045
210157
  }
210046
210158
 
210047
- // commands/watch.ts
210159
+ // commands/run.ts
210048
210160
  var import_arg8 = __toESM(require_arg(), 1);
210161
+ async function runCli8(input2) {
210162
+ const args2 = (0, import_arg8.default)(
210163
+ { "--repo": String, "-R": "--repo", "--help": Boolean, "-h": "--help" },
210164
+ { argv: input2.args }
210165
+ );
210166
+ if (input2.showHelp || args2["--help"] || !args2._.length) {
210167
+ console.log(`usage: ${input2.prog} run PROMPT
210168
+
210169
+ start a Pullfrog run, like the console's prompt box, and print its URL.
210170
+ name the issue or pull request in the prompt:
210171
+
210172
+ ${input2.prog} run "enrich issue #42"
210173
+ gh issue list --json number --jq '.[].number' | xargs -I{} ${input2.prog} run "enrich issue #{}"
210174
+
210175
+ --repo, -R OWNER/REPO select a repository (default: GitHub origin)`);
210176
+ return;
210177
+ }
210178
+ if (args2._.length > 1) throw new Error("quote the prompt as one argument");
210179
+ const target = resolveTarget({ org: void 0, repo: args2["--repo"] });
210180
+ const data = await configurationApi({
210181
+ target,
210182
+ path: "run",
210183
+ method: "POST",
210184
+ body: { prompt: args2._[0] }
210185
+ });
210186
+ console.log(external_exports.object({ url: external_exports.string() }).parse(data).url);
210187
+ }
210188
+
210189
+ // commands/watch.ts
210190
+ var import_arg9 = __toESM(require_arg(), 1);
210049
210191
  var import_picocolors4 = __toESM(require_picocolors(), 1);
210050
210192
  function parseWatchArgs(args2) {
210051
- return (0, import_arg8.default)(
210193
+ return (0, import_arg9.default)(
210052
210194
  {
210053
210195
  "--pr": Number,
210054
210196
  "--pretty": Boolean,
@@ -210095,7 +210237,7 @@ function emit(events, pretty) {
210095
210237
  `);
210096
210238
  }
210097
210239
  }
210098
- async function runCli8(input2) {
210240
+ async function runCli9(input2) {
210099
210241
  let parsed2;
210100
210242
  try {
210101
210243
  parsed2 = parseWatchArgs(input2.args);
@@ -210155,7 +210297,7 @@ async function runCli8(input2) {
210155
210297
  }
210156
210298
 
210157
210299
  // cli.ts
210158
- var VERSION10 = "0.1.104";
210300
+ var VERSION10 = "0.1.106";
210159
210301
  var bin = basename2(process.argv[1] || "");
210160
210302
  var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
210161
210303
  var rawArgs = process.argv.slice(2);
@@ -210167,6 +210309,7 @@ function printMainUsage(stream) {
210167
210309
  stream(" console open the repository or organization console");
210168
210310
  stream(" secret list secret names, save or delete scoped credentials");
210169
210311
  stream(" init install pullfrog on the current repository and open its dashboard");
210312
+ stream(" run start a run from a prompt, like the console's prompt box");
210170
210313
  stream(" auth manage provider credentials for the current repository");
210171
210314
  stream(" watch stream a PR's activity as one JSON line per event");
210172
210315
  stream(" mcp run a stdio MCP server exposing PR activity as an agent tool");
@@ -210176,7 +210319,7 @@ function printMainUsage(stream) {
210176
210319
  stream(" -v, --version show version");
210177
210320
  }
210178
210321
  function parseGlobalArgs(args2) {
210179
- return (0, import_arg9.default)(
210322
+ return (0, import_arg10.default)(
210180
210323
  {
210181
210324
  "--help": Boolean,
210182
210325
  "--version": Boolean,
@@ -210227,6 +210370,10 @@ async function run3() {
210227
210370
  });
210228
210371
  return;
210229
210372
  }
210373
+ if (command === "run") {
210374
+ await runCli8({ args: commandArgs, prog: PROG, showHelp: globalParsed["--help"] === true });
210375
+ return;
210376
+ }
210230
210377
  if (command === "config" || command === "console" || command === "secret") {
210231
210378
  const runCommand = command === "config" ? runCli3 : command === "secret" ? runCli : runCli4;
210232
210379
  await runCommand({ args: commandArgs, prog: PROG, showHelp: globalParsed["--help"] === true });
@@ -210257,7 +210404,7 @@ async function run3() {
210257
210404
  return;
210258
210405
  }
210259
210406
  if (command === "watch") {
210260
- await runCli8({
210407
+ await runCli9({
210261
210408
  args: commandArgs,
210262
210409
  prog: PROG,
210263
210410
  showHelp: globalParsed["--help"] === true