pullfrog 0.1.33 → 0.1.35

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 arg5(opts, {
99
+ function arg6(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((a) => `-${a}`);
173
173
  for (let j3 = 0; j3 < separatedArguments.length; j3++) {
174
- const arg6 = separatedArguments[j3];
175
- const [originalArgName, argStr] = arg6[1] === "-" ? arg6.split(/=(.*)/, 2) : [arg6, void 0];
174
+ const arg7 = separatedArguments[j3];
175
+ const [originalArgName, argStr] = arg7[1] === "-" ? arg7.split(/=(.*)/, 2) : [arg7, 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(arg6);
182
+ result._.push(arg7);
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
- arg5.flag = (fn2) => {
221
+ arg6.flag = (fn2) => {
222
222
  fn2[flagSymbol] = true;
223
223
  return fn2;
224
224
  };
225
- arg5.COUNT = arg5.flag((v, name, existingCount) => (existingCount || 0) + 1);
226
- arg5.ArgError = ArgError;
227
- module.exports = arg5;
225
+ arg6.COUNT = arg6.flag((v, name, existingCount) => (existingCount || 0) + 1);
226
+ arg6.ArgError = ArgError;
227
+ module.exports = arg6;
228
228
  }
229
229
  });
230
230
 
@@ -19353,11 +19353,11 @@ var require_toolrunner = __commonJS({
19353
19353
  const upperToolPath = this.toolPath.toUpperCase();
19354
19354
  return this._endsWith(upperToolPath, ".CMD") || this._endsWith(upperToolPath, ".BAT");
19355
19355
  }
19356
- _windowsQuoteCmdArg(arg5) {
19356
+ _windowsQuoteCmdArg(arg6) {
19357
19357
  if (!this._isCmdFile()) {
19358
- return this._uvQuoteCmdArg(arg5);
19358
+ return this._uvQuoteCmdArg(arg6);
19359
19359
  }
19360
- if (!arg5) {
19360
+ if (!arg6) {
19361
19361
  return '""';
19362
19362
  }
19363
19363
  const cmdSpecialChars = [
@@ -19385,22 +19385,22 @@ var require_toolrunner = __commonJS({
19385
19385
  '"'
19386
19386
  ];
19387
19387
  let needsQuotes = false;
19388
- for (const char of arg5) {
19388
+ for (const char of arg6) {
19389
19389
  if (cmdSpecialChars.some((x) => x === char)) {
19390
19390
  needsQuotes = true;
19391
19391
  break;
19392
19392
  }
19393
19393
  }
19394
19394
  if (!needsQuotes) {
19395
- return arg5;
19395
+ return arg6;
19396
19396
  }
19397
19397
  let reverse = '"';
19398
19398
  let quoteHit = true;
19399
- for (let i = arg5.length; i > 0; i--) {
19400
- reverse += arg5[i - 1];
19401
- if (quoteHit && arg5[i - 1] === "\\") {
19399
+ for (let i = arg6.length; i > 0; i--) {
19400
+ reverse += arg6[i - 1];
19401
+ if (quoteHit && arg6[i - 1] === "\\") {
19402
19402
  reverse += "\\";
19403
- } else if (arg5[i - 1] === '"') {
19403
+ } else if (arg6[i - 1] === '"') {
19404
19404
  quoteHit = true;
19405
19405
  reverse += '"';
19406
19406
  } else {
@@ -19410,23 +19410,23 @@ var require_toolrunner = __commonJS({
19410
19410
  reverse += '"';
19411
19411
  return reverse.split("").reverse().join("");
19412
19412
  }
19413
- _uvQuoteCmdArg(arg5) {
19414
- if (!arg5) {
19413
+ _uvQuoteCmdArg(arg6) {
19414
+ if (!arg6) {
19415
19415
  return '""';
19416
19416
  }
19417
- if (!arg5.includes(" ") && !arg5.includes(" ") && !arg5.includes('"')) {
19418
- return arg5;
19417
+ if (!arg6.includes(" ") && !arg6.includes(" ") && !arg6.includes('"')) {
19418
+ return arg6;
19419
19419
  }
19420
- if (!arg5.includes('"') && !arg5.includes("\\")) {
19421
- return `"${arg5}"`;
19420
+ if (!arg6.includes('"') && !arg6.includes("\\")) {
19421
+ return `"${arg6}"`;
19422
19422
  }
19423
19423
  let reverse = '"';
19424
19424
  let quoteHit = true;
19425
- for (let i = arg5.length; i > 0; i--) {
19426
- reverse += arg5[i - 1];
19427
- if (quoteHit && arg5[i - 1] === "\\") {
19425
+ for (let i = arg6.length; i > 0; i--) {
19426
+ reverse += arg6[i - 1];
19427
+ if (quoteHit && arg6[i - 1] === "\\") {
19428
19428
  reverse += "\\";
19429
- } else if (arg5[i - 1] === '"') {
19429
+ } else if (arg6[i - 1] === '"') {
19430
19430
  quoteHit = true;
19431
19431
  reverse += "\\";
19432
19432
  } else {
@@ -19480,8 +19480,8 @@ var require_toolrunner = __commonJS({
19480
19480
  return new Promise((resolve3, reject) => __awaiter(this, void 0, void 0, function* () {
19481
19481
  this._debug(`exec tool: ${this.toolPath}`);
19482
19482
  this._debug("arguments:");
19483
- for (const arg5 of this.args) {
19484
- this._debug(` ${arg5}`);
19483
+ for (const arg6 of this.args) {
19484
+ this._debug(` ${arg6}`);
19485
19485
  }
19486
19486
  const optionsNonNull = this._cloneExecOptions(this.options);
19487
19487
  if (!optionsNonNull.silent && optionsNonNull.outStream) {
@@ -19578,12 +19578,12 @@ var require_toolrunner = __commonJS({
19578
19578
  const args2 = [];
19579
19579
  let inQuotes = false;
19580
19580
  let escaped = false;
19581
- let arg5 = "";
19581
+ let arg6 = "";
19582
19582
  function append2(c2) {
19583
19583
  if (escaped && c2 !== '"') {
19584
- arg5 += "\\";
19584
+ arg6 += "\\";
19585
19585
  }
19586
- arg5 += c2;
19586
+ arg6 += c2;
19587
19587
  escaped = false;
19588
19588
  }
19589
19589
  for (let i = 0; i < argString.length; i++) {
@@ -19605,16 +19605,16 @@ var require_toolrunner = __commonJS({
19605
19605
  continue;
19606
19606
  }
19607
19607
  if (c2 === " " && !inQuotes) {
19608
- if (arg5.length > 0) {
19609
- args2.push(arg5);
19610
- arg5 = "";
19608
+ if (arg6.length > 0) {
19609
+ args2.push(arg6);
19610
+ arg6 = "";
19611
19611
  }
19612
19612
  continue;
19613
19613
  }
19614
19614
  append2(c2);
19615
19615
  }
19616
- if (arg5.length > 0) {
19617
- args2.push(arg5.trim());
19616
+ if (arg6.length > 0) {
19617
+ args2.push(arg6.trim());
19618
19618
  }
19619
19619
  return args2;
19620
19620
  }
@@ -28041,20 +28041,20 @@ var require_escape = __commonJS({
28041
28041
  "node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.js"(exports, module) {
28042
28042
  "use strict";
28043
28043
  var metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
28044
- function escapeCommand(arg5) {
28045
- arg5 = arg5.replace(metaCharsRegExp, "^$1");
28046
- return arg5;
28047
- }
28048
- function escapeArgument(arg5, doubleEscapeMetaChars) {
28049
- arg5 = `${arg5}`;
28050
- arg5 = arg5.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
28051
- arg5 = arg5.replace(/(?=(\\+?)?)\1$/, "$1$1");
28052
- arg5 = `"${arg5}"`;
28053
- arg5 = arg5.replace(metaCharsRegExp, "^$1");
28044
+ function escapeCommand(arg6) {
28045
+ arg6 = arg6.replace(metaCharsRegExp, "^$1");
28046
+ return arg6;
28047
+ }
28048
+ function escapeArgument(arg6, doubleEscapeMetaChars) {
28049
+ arg6 = `${arg6}`;
28050
+ arg6 = arg6.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
28051
+ arg6 = arg6.replace(/(?=(\\+?)?)\1$/, "$1$1");
28052
+ arg6 = `"${arg6}"`;
28053
+ arg6 = arg6.replace(metaCharsRegExp, "^$1");
28054
28054
  if (doubleEscapeMetaChars) {
28055
- arg5 = arg5.replace(metaCharsRegExp, "^$1");
28055
+ arg6 = arg6.replace(metaCharsRegExp, "^$1");
28056
28056
  }
28057
- return arg5;
28057
+ return arg6;
28058
28058
  }
28059
28059
  module.exports.command = escapeCommand;
28060
28060
  module.exports.argument = escapeArgument;
@@ -28142,7 +28142,7 @@ var require_parse3 = __commonJS({
28142
28142
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
28143
28143
  parsed2.command = path4.normalize(parsed2.command);
28144
28144
  parsed2.command = escape2.command(parsed2.command);
28145
- parsed2.args = parsed2.args.map((arg5) => escape2.argument(arg5, needsDoubleEscapeMetaChars));
28145
+ parsed2.args = parsed2.args.map((arg6) => escape2.argument(arg6, needsDoubleEscapeMetaChars));
28146
28146
  const shellCommand = [parsed2.command].concat(parsed2.args).join(" ");
28147
28147
  parsed2.args = ["/d", "/s", "/c", `"${shellCommand}"`];
28148
28148
  parsed2.command = process.env.comspec || "cmd.exe";
@@ -28430,10 +28430,10 @@ var require_timers2 = __commonJS({
28430
28430
  * before the specified function or code is executed.
28431
28431
  * @param {*} arg
28432
28432
  */
28433
- constructor(callback, delay2, arg5) {
28433
+ constructor(callback, delay2, arg6) {
28434
28434
  this._onTimeout = callback;
28435
28435
  this._idleTimeout = delay2;
28436
- this._timerArg = arg5;
28436
+ this._timerArg = arg6;
28437
28437
  this.refresh();
28438
28438
  }
28439
28439
  /**
@@ -28477,8 +28477,8 @@ var require_timers2 = __commonJS({
28477
28477
  * when the timer expires.
28478
28478
  * @returns {NodeJS.Timeout|FastTimer}
28479
28479
  */
28480
- setTimeout(callback, delay2, arg5) {
28481
- return delay2 <= RESOLUTION_MS ? setTimeout(callback, delay2, arg5) : new FastTimer(callback, delay2, arg5);
28480
+ setTimeout(callback, delay2, arg6) {
28481
+ return delay2 <= RESOLUTION_MS ? setTimeout(callback, delay2, arg6) : new FastTimer(callback, delay2, arg6);
28482
28482
  },
28483
28483
  /**
28484
28484
  * The clearTimeout method cancels an instantiated Timer previously created
@@ -28504,8 +28504,8 @@ var require_timers2 = __commonJS({
28504
28504
  * when the timer expires.
28505
28505
  * @returns {FastTimer}
28506
28506
  */
28507
- setFastTimeout(callback, delay2, arg5) {
28508
- return new FastTimer(callback, delay2, arg5);
28507
+ setFastTimeout(callback, delay2, arg6) {
28508
+ return new FastTimer(callback, delay2, arg6);
28509
28509
  },
28510
28510
  /**
28511
28511
  * The clearTimeout method cancels an instantiated FastTimer previously
@@ -55420,9 +55420,9 @@ var init_types = __esm({
55420
55420
  const { status, ctx } = this._processInputParams(input);
55421
55421
  const effect = this._def.effect || null;
55422
55422
  const checkCtx = {
55423
- addIssue: (arg5) => {
55424
- addIssueToContext(ctx, arg5);
55425
- if (arg5.fatal) {
55423
+ addIssue: (arg6) => {
55424
+ addIssueToContext(ctx, arg6);
55425
+ if (arg6.fatal) {
55426
55426
  status.abort();
55427
55427
  } else {
55428
55428
  status.dirty();
@@ -57613,13 +57613,13 @@ var init_doc = __esm({
57613
57613
  fn2(this);
57614
57614
  this.indent -= 1;
57615
57615
  }
57616
- write(arg5) {
57617
- if (typeof arg5 === "function") {
57618
- arg5(this, { execution: "sync" });
57619
- arg5(this, { execution: "async" });
57616
+ write(arg6) {
57617
+ if (typeof arg6 === "function") {
57618
+ arg6(this, { execution: "sync" });
57619
+ arg6(this, { execution: "async" });
57620
57620
  return;
57621
57621
  }
57622
- const content = arg5;
57622
+ const content = arg6;
57623
57623
  const lines = content.split("\n").filter((x) => x);
57624
57624
  const minIndent = Math.min(...lines.map((x) => x.length - x.trimStart().length));
57625
57625
  const dedented = lines.map((x) => x.slice(minIndent)).map((x) => " ".repeat(this.indent * 2) + x);
@@ -69675,13 +69675,13 @@ var require_code = __commonJS({
69675
69675
  return new _Code(expr);
69676
69676
  }
69677
69677
  exports.str = str;
69678
- function addCodeArg(code, arg5) {
69679
- if (arg5 instanceof _Code)
69680
- code.push(...arg5._items);
69681
- else if (arg5 instanceof Name)
69682
- code.push(arg5);
69678
+ function addCodeArg(code, arg6) {
69679
+ if (arg6 instanceof _Code)
69680
+ code.push(...arg6._items);
69681
+ else if (arg6 instanceof Name)
69682
+ code.push(arg6);
69683
69683
  else
69684
- code.push(interpolate(arg5));
69684
+ code.push(interpolate(arg6));
69685
69685
  }
69686
69686
  exports.addCodeArg = addCodeArg;
69687
69687
  function optimize(expr) {
@@ -81022,8 +81022,8 @@ var require_select = __commonJS({
81022
81022
  return selectors[":is"](sel);
81023
81023
  },
81024
81024
  ":nth-match": function(param, last) {
81025
- var args2 = param.split(/\s*,\s*/), arg5 = args2.shift(), test = compileGroup(args2.join(","));
81026
- return nth(arg5, test, last);
81025
+ var args2 = param.split(/\s*,\s*/), arg6 = args2.shift(), test = compileGroup(args2.join(","));
81026
+ return nth(arg6, test, last);
81027
81027
  },
81028
81028
  ":nth-last-match": function(param) {
81029
81029
  return selectors[":nth-match"](param, true);
@@ -100072,8 +100072,8 @@ var init_file_type = __esm({
100072
100072
  });
100073
100073
 
100074
100074
  // cli.ts
100075
- var import_arg4 = __toESM(require_arg(), 1);
100076
- var import_picocolors4 = __toESM(require_picocolors(), 1);
100075
+ var import_arg5 = __toESM(require_arg(), 1);
100076
+ var import_picocolors5 = __toESM(require_picocolors(), 1);
100077
100077
  import { basename as basename2 } from "node:path";
100078
100078
 
100079
100079
  // commands/auth.ts
@@ -101370,6 +101370,8 @@ async function promptScope(ctx) {
101370
101370
 
101371
101371
  // commands/auth.ts
101372
101372
  var CODEX_AUTH_SECRET = "CODEX_AUTH_JSON";
101373
+ var CLAUDE_OAUTH_SECRET = "CLAUDE_CODE_OAUTH_TOKEN";
101374
+ var CLAUDE_OAUTH_TOKEN_PREFIX = "sk-ant-oat";
101373
101375
  function stripAnsi(s) {
101374
101376
  return s.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "");
101375
101377
  }
@@ -101404,7 +101406,8 @@ function printAuthUsage(params) {
101404
101406
  params.stream("manage provider credentials for the current repository.");
101405
101407
  params.stream("");
101406
101408
  params.stream("providers:");
101407
- params.stream(" codex mint a Codex (ChatGPT) subscription credential");
101409
+ params.stream(" codex mint a Codex (ChatGPT) subscription credential");
101410
+ params.stream(" claude save a Claude Code subscription OAuth token");
101408
101411
  params.stream("");
101409
101412
  params.stream("options:");
101410
101413
  params.stream(" -h, --help show help");
@@ -101417,6 +101420,14 @@ function printCodexUsage(params) {
101417
101420
  params.stream("options:");
101418
101421
  params.stream(" -h, --help show help");
101419
101422
  }
101423
+ function printClaudeUsage(params) {
101424
+ params.stream(`usage: ${params.prog} auth claude [options]
101425
+ `);
101426
+ params.stream("save a Claude Code subscription OAuth token as CLAUDE_CODE_OAUTH_TOKEN.");
101427
+ params.stream("");
101428
+ params.stream("options:");
101429
+ params.stream(" -h, --help show help");
101430
+ }
101420
101431
  async function runCli(params) {
101421
101432
  const firstArg = params.args[0];
101422
101433
  const helpAtTopLevel = params.showHelp || params.args.length === 0 || params.args.length === 1 && (firstArg === "--help" || firstArg === "-h");
@@ -101430,6 +101441,10 @@ async function runCli(params) {
101430
101441
  await runCodex({ args: rest, prog: params.prog });
101431
101442
  return;
101432
101443
  }
101444
+ if (subcommand === "claude") {
101445
+ await runClaude({ args: rest, prog: params.prog });
101446
+ return;
101447
+ }
101433
101448
  console.error(`unknown auth provider: ${import_picocolors2.default.bold(subcommand)}
101434
101449
  `);
101435
101450
  printAuthUsage({ stream: console.error, prog: params.prog });
@@ -101592,6 +101607,120 @@ async function runCodexAuth() {
101592
101607
  process.exit(1);
101593
101608
  }
101594
101609
  }
101610
+ function parseClaudeArgs(args2) {
101611
+ return (0, import_arg.default)(
101612
+ {
101613
+ "--help": Boolean,
101614
+ "-h": "--help"
101615
+ },
101616
+ { argv: args2 }
101617
+ );
101618
+ }
101619
+ async function runClaude(params) {
101620
+ let parsed2;
101621
+ try {
101622
+ parsed2 = parseClaudeArgs(params.args);
101623
+ } catch (error49) {
101624
+ const message = error49 instanceof Error ? error49.message : String(error49);
101625
+ console.error(`${message}
101626
+ `);
101627
+ printClaudeUsage({ stream: console.error, prog: params.prog });
101628
+ process.exit(1);
101629
+ }
101630
+ if (parsed2["--help"]) {
101631
+ printClaudeUsage({ stream: console.log, prog: params.prog });
101632
+ return;
101633
+ }
101634
+ await runClaudeAuth();
101635
+ }
101636
+ async function runClaudeAuth() {
101637
+ mt(import_picocolors2.default.bgGreen(import_picocolors2.default.black(" pullfrog auth claude ")));
101638
+ const spin = fe();
101639
+ setActiveSpin(spin);
101640
+ try {
101641
+ spin.start("authenticating with github");
101642
+ const token = getGhToken();
101643
+ spin.stop("github authenticated");
101644
+ spin.start("detecting repository");
101645
+ const remote = parseGitRemote();
101646
+ spin.stop(`detected repo ${import_picocolors2.default.cyan(`${remote.owner}/${remote.repo}`)}`);
101647
+ spin.start("checking pullfrog app installation");
101648
+ const status = await fetchStatus({ token, owner: remote.owner, repo: remote.repo });
101649
+ if (!status.installed) {
101650
+ spin.stop(import_picocolors2.default.red("pullfrog app not installed on this repo"));
101651
+ bail(
101652
+ `install pullfrog on ${import_picocolors2.default.bold(`${remote.owner}/${remote.repo}`)} before configuring auth.
101653
+ ${import_picocolors2.default.dim("run:")} ${import_picocolors2.default.cyan(`npx pullfrog init`)}`
101654
+ );
101655
+ }
101656
+ spin.stop(`pullfrog app is installed on ${import_picocolors2.default.cyan(`@${remote.owner}`)}`);
101657
+ if (status.pullfrogSecrets.includes(CLAUDE_OAUTH_SECRET)) {
101658
+ const overwrite = await _t({
101659
+ message: `${import_picocolors2.default.cyan(CLAUDE_OAUTH_SECRET)} is already configured \u2014 overwrite?`,
101660
+ options: [
101661
+ { value: true, label: "overwrite", hint: "replace with a freshly minted token" },
101662
+ { value: false, label: "cancel" }
101663
+ ]
101664
+ });
101665
+ handleCancel(overwrite);
101666
+ if (!overwrite) {
101667
+ pt("canceled.");
101668
+ return;
101669
+ }
101670
+ }
101671
+ const scope2 = status.isOrg ? await promptScope({ owner: remote.owner, repo: remote.repo }) : "account";
101672
+ O2.info(
101673
+ [
101674
+ `mint a long-lived Claude Code OAuth token, then paste it below.`,
101675
+ ``,
101676
+ `${import_picocolors2.default.dim("run:")} ${import_picocolors2.default.cyan("claude setup-token")}`,
101677
+ `it opens your browser, works with Pro/Max subscriptions, and prints a`,
101678
+ `token starting with ${import_picocolors2.default.cyan("sk-ant-oat\u2026")}. copy that token.`
101679
+ ].join("\n")
101680
+ );
101681
+ const oauthToken = await bt({
101682
+ message: `paste your Claude Code OAuth token ${import_picocolors2.default.dim("(Enter to cancel)")}`,
101683
+ mask: "*"
101684
+ });
101685
+ handleCancel(oauthToken);
101686
+ if (!oauthToken) {
101687
+ pt("canceled.");
101688
+ return;
101689
+ }
101690
+ const value2 = oauthToken.trim();
101691
+ if (!value2.startsWith(CLAUDE_OAUTH_TOKEN_PREFIX)) {
101692
+ O2.warn(
101693
+ `that doesn't look like a ${import_picocolors2.default.cyan("claude setup-token")} token (expected ${import_picocolors2.default.cyan(`${CLAUDE_OAUTH_TOKEN_PREFIX}\u2026`)}). saving it anyway.`
101694
+ );
101695
+ }
101696
+ spin.start(`saving ${import_picocolors2.default.cyan(CLAUDE_OAUTH_SECRET)} to Pullfrog`);
101697
+ const result = await setPullfrogSecret({
101698
+ token,
101699
+ owner: remote.owner,
101700
+ repo: remote.repo,
101701
+ name: CLAUDE_OAUTH_SECRET,
101702
+ value: value2,
101703
+ scope: scope2
101704
+ });
101705
+ if (!result.saved) {
101706
+ spin.stop(import_picocolors2.default.red("could not save secret"));
101707
+ O2.warn(
101708
+ `${result.error}
101709
+ ${import_picocolors2.default.dim("set it manually at:")} ${PULLFROG_API_URL}/console/${remote.owner}`
101710
+ );
101711
+ process.exit(1);
101712
+ }
101713
+ spin.stop(`saved ${import_picocolors2.default.cyan(CLAUDE_OAUTH_SECRET)} to Pullfrog (${scope2})`);
101714
+ setActiveSpin(null);
101715
+ gt("done.");
101716
+ } catch (error49) {
101717
+ spin.stop(import_picocolors2.default.red("failed"));
101718
+ setActiveSpin(null);
101719
+ const message = error49 instanceof Error ? error49.message : String(error49);
101720
+ O2.error(message);
101721
+ process.exit(1);
101722
+ }
101723
+ }
101595
101724
 
101596
101725
  // commands/gha.ts
101597
101726
  var core11 = __toESM(require_core(), 1);
@@ -101659,37 +101788,40 @@ var providers = {
101659
101788
  managedCredentials: ["CODEX_AUTH_JSON"],
101660
101789
  models: {
101661
101790
  gpt: {
101662
- displayName: "GPT",
101663
- resolve: "openai/gpt-5.5",
101664
- openRouterResolve: "openrouter/openai/gpt-5.5",
101791
+ displayName: "GPT Sol",
101792
+ resolve: "openai/gpt-5.6-sol",
101793
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
101665
101794
  preferred: true,
101666
- subagentModel: "gpt-5.4"
101795
+ subagentModel: "gpt-terra"
101667
101796
  },
101797
+ // Sol served at reasoning.mode=pro — same $/token as Sol, just more tokens
101798
+ // burned; not a pricier premium tier. models.dev has no -pro id, so direct-key
101799
+ // (BYOK) resolves to plain Sol; only the Router/OpenRouter path gets sol-pro.
101668
101800
  "gpt-pro": {
101669
- displayName: "GPT Pro",
101670
- resolve: "openai/gpt-5.5-pro",
101671
- openRouterResolve: "openrouter/openai/gpt-5.5-pro",
101801
+ displayName: "GPT Sol Pro",
101802
+ description: "Maximum reasoning effort",
101803
+ resolve: "openai/gpt-5.6-sol",
101804
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
101672
101805
  subagentModel: "gpt"
101673
101806
  },
101674
- // hidden subagent target `gpt` lenses run against this. surfacing
101675
- // it in the picker would just confuse users (it's the prior-flagship,
101676
- // and they already have `gpt` and `gpt-mini` to choose from).
101677
- "gpt-5.4": {
101678
- displayName: "GPT 5.4",
101679
- resolve: "openai/gpt-5.4",
101680
- openRouterResolve: "openrouter/openai/gpt-5.4",
101681
- hidden: true
101807
+ // gpt-5.6's balanced mid-tier (Sol/Terra/Luna are durable capability tiers,
101808
+ // not version bumps). selectable on its own and doubles as `gpt`'s cheaper
101809
+ // lens-fanout subagent replaces the old hidden gpt-5.4 subagent target.
101810
+ "gpt-terra": {
101811
+ displayName: "GPT Terra",
101812
+ resolve: "openai/gpt-5.6-terra",
101813
+ openRouterResolve: "openrouter/openai/gpt-5.6-terra"
101682
101814
  },
101683
101815
  "gpt-mini": {
101684
- displayName: "GPT Mini",
101685
- resolve: "openai/gpt-5.4-mini",
101686
- openRouterResolve: "openrouter/openai/gpt-5.4-mini"
101816
+ displayName: "GPT Luna",
101817
+ resolve: "openai/gpt-5.6-luna",
101818
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna"
101687
101819
  },
101688
101820
  // legacy aliases — openai unified the codex line into the main GPT family
101689
101821
  // and is shutting down every "-codex" snapshot on 2026-07-23. transparently
101690
101822
  // upgrade existing users via the fallback chain. UI display sites resolve
101691
101823
  // to the terminal alias's label (so dropdown trigger + PR footers show
101692
- // "GPT" / "GPT Mini", not the historical name).
101824
+ // "GPT Sol" / "GPT Luna", not the historical name).
101693
101825
  "gpt-codex": {
101694
101826
  displayName: "GPT Codex",
101695
101827
  resolve: "openai/gpt-5.3-codex",
@@ -101702,6 +101834,13 @@ var providers = {
101702
101834
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
101703
101835
  fallback: "openai/gpt-mini"
101704
101836
  },
101837
+ // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
101838
+ "gpt-5.4": {
101839
+ displayName: "GPT 5.4",
101840
+ resolve: "openai/gpt-5.4",
101841
+ openRouterResolve: "openrouter/openai/gpt-5.4",
101842
+ fallback: "openai/gpt"
101843
+ },
101705
101844
  o3: {
101706
101845
  displayName: "O3",
101707
101846
  resolve: "openai/o3",
@@ -101831,28 +101970,29 @@ var providers = {
101831
101970
  openRouterResolve: "openrouter/anthropic/claude-haiku-4.5"
101832
101971
  },
101833
101972
  gpt: {
101834
- displayName: "GPT",
101835
- resolve: "opencode/gpt-5.5",
101836
- openRouterResolve: "openrouter/openai/gpt-5.5",
101837
- subagentModel: "gpt-5.4"
101973
+ displayName: "GPT Sol",
101974
+ resolve: "opencode/gpt-5.6-sol",
101975
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
101976
+ subagentModel: "gpt-terra"
101838
101977
  },
101978
+ // see openai/gpt-pro — Zen has no -pro id, so direct resolves to plain Sol.
101839
101979
  "gpt-pro": {
101840
- displayName: "GPT Pro",
101841
- resolve: "opencode/gpt-5.5-pro",
101842
- openRouterResolve: "openrouter/openai/gpt-5.5-pro",
101980
+ displayName: "GPT Sol Pro",
101981
+ description: "Maximum reasoning effort",
101982
+ resolve: "opencode/gpt-5.6-sol",
101983
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
101843
101984
  subagentModel: "gpt"
101844
101985
  },
101845
- // hidden subagent target — see openai provider above for context.
101846
- "gpt-5.4": {
101847
- displayName: "GPT 5.4",
101848
- resolve: "opencode/gpt-5.4",
101849
- openRouterResolve: "openrouter/openai/gpt-5.4",
101850
- hidden: true
101986
+ // gpt-5.6 balanced mid-tierselectable + `gpt`'s subagent. see openai above.
101987
+ "gpt-terra": {
101988
+ displayName: "GPT Terra",
101989
+ resolve: "opencode/gpt-5.6-terra",
101990
+ openRouterResolve: "openrouter/openai/gpt-5.6-terra"
101851
101991
  },
101852
101992
  "gpt-mini": {
101853
- displayName: "GPT Mini",
101854
- resolve: "opencode/gpt-5.4-mini",
101855
- openRouterResolve: "openrouter/openai/gpt-5.4-mini"
101993
+ displayName: "GPT Luna",
101994
+ resolve: "opencode/gpt-5.6-luna",
101995
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna"
101856
101996
  },
101857
101997
  // legacy aliases — see openai provider above for context.
101858
101998
  "gpt-codex": {
@@ -101867,6 +102007,13 @@ var providers = {
101867
102007
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
101868
102008
  fallback: "opencode/gpt-mini"
101869
102009
  },
102010
+ // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
102011
+ "gpt-5.4": {
102012
+ displayName: "GPT 5.4",
102013
+ resolve: "opencode/gpt-5.4",
102014
+ openRouterResolve: "openrouter/openai/gpt-5.4",
102015
+ fallback: "opencode/gpt"
102016
+ },
101870
102017
  "gemini-pro": {
101871
102018
  displayName: "Gemini Pro",
101872
102019
  resolve: "opencode/gemini-3.1-pro",
@@ -101983,29 +102130,34 @@ var providers = {
101983
102130
  resolve: "openrouter/~anthropic/claude-haiku-latest",
101984
102131
  openRouterResolve: "openrouter/~anthropic/claude-haiku-latest"
101985
102132
  },
102133
+ // pinned to the explicit gpt-5.6 tiers (not the ~openai/gpt-latest rolling
102134
+ // alias): after the Sol/Terra/Luna rename, ~gpt-mini-latest no longer maps
102135
+ // to Luna, so rolling aliases would silently diverge `gpt`/`gpt-mini` from
102136
+ // the chosen tiers across funding paths.
101986
102137
  gpt: {
101987
- displayName: "GPT",
101988
- resolve: "openrouter/~openai/gpt-latest",
101989
- openRouterResolve: "openrouter/~openai/gpt-latest",
101990
- subagentModel: "gpt-5.4"
102138
+ displayName: "GPT Sol",
102139
+ resolve: "openrouter/openai/gpt-5.6-sol",
102140
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol",
102141
+ subagentModel: "gpt-terra"
101991
102142
  },
102143
+ // see openai/gpt-pro. openrouter serves sol-pro directly on both routes.
101992
102144
  "gpt-pro": {
101993
- displayName: "GPT Pro",
101994
- resolve: "openrouter/openai/gpt-5.5-pro",
101995
- openRouterResolve: "openrouter/openai/gpt-5.5-pro",
102145
+ displayName: "GPT Sol Pro",
102146
+ description: "Maximum reasoning effort",
102147
+ resolve: "openrouter/openai/gpt-5.6-sol-pro",
102148
+ openRouterResolve: "openrouter/openai/gpt-5.6-sol-pro",
101996
102149
  subagentModel: "gpt"
101997
102150
  },
101998
- // hidden subagent target — see openai provider above for context.
101999
- "gpt-5.4": {
102000
- displayName: "GPT 5.4",
102001
- resolve: "openrouter/openai/gpt-5.4",
102002
- openRouterResolve: "openrouter/openai/gpt-5.4",
102003
- hidden: true
102151
+ // gpt-5.6 balanced mid-tierselectable + `gpt`'s subagent. see openai above.
102152
+ "gpt-terra": {
102153
+ displayName: "GPT Terra",
102154
+ resolve: "openrouter/openai/gpt-5.6-terra",
102155
+ openRouterResolve: "openrouter/openai/gpt-5.6-terra"
102004
102156
  },
102005
102157
  "gpt-mini": {
102006
- displayName: "GPT Mini",
102007
- resolve: "openrouter/~openai/gpt-mini-latest",
102008
- openRouterResolve: "openrouter/~openai/gpt-mini-latest"
102158
+ displayName: "GPT Luna",
102159
+ resolve: "openrouter/openai/gpt-5.6-luna",
102160
+ openRouterResolve: "openrouter/openai/gpt-5.6-luna"
102009
102161
  },
102010
102162
  // legacy aliases — see openai provider for context.
102011
102163
  "gpt-codex": {
@@ -102020,6 +102172,13 @@ var providers = {
102020
102172
  openRouterResolve: "openrouter/openai/gpt-5.1-codex-mini",
102021
102173
  fallback: "openrouter/gpt-mini"
102022
102174
  },
102175
+ // dropped hidden subagent tier — folds stored pins forward to gpt (Sol).
102176
+ "gpt-5.4": {
102177
+ displayName: "GPT 5.4",
102178
+ resolve: "openrouter/openai/gpt-5.4",
102179
+ openRouterResolve: "openrouter/openai/gpt-5.4",
102180
+ fallback: "openrouter/gpt"
102181
+ },
102023
102182
  "o4-mini": {
102024
102183
  displayName: "O4 Mini",
102025
102184
  resolve: "openrouter/openai/o4-mini",
@@ -102099,6 +102258,7 @@ var modelAliases = Object.entries(providers).flatMap(
102099
102258
  slug: `${providerKey}/${modelId}`,
102100
102259
  provider: providerKey,
102101
102260
  displayName: def.displayName,
102261
+ description: def.description,
102102
102262
  resolve: def.resolve,
102103
102263
  openRouterResolve: def.openRouterResolve,
102104
102264
  preferred: def.preferred ?? false,
@@ -102439,11 +102599,11 @@ function ts() {
102439
102599
  return isDebugEnabled() ? `[${(/* @__PURE__ */ new Date()).toISOString()}] ` : "";
102440
102600
  }
102441
102601
  function formatArgs(args2) {
102442
- return args2.map((arg5) => {
102443
- if (typeof arg5 === "string") return arg5;
102444
- if (arg5 instanceof Error) return `${arg5.message}
102445
- ${arg5.stack}`;
102446
- return JSON.stringify(arg5);
102602
+ return args2.map((arg6) => {
102603
+ if (typeof arg6 === "string") return arg6;
102604
+ if (arg6 instanceof Error) return `${arg6.message}
102605
+ ${arg6.stack}`;
102606
+ return JSON.stringify(arg6);
102447
102607
  }).join(" ");
102448
102608
  }
102449
102609
  function startGroup2(name) {
@@ -102841,7 +103001,7 @@ var import_semver = __toESM(require_semver2(), 1);
102841
103001
  // package.json
102842
103002
  var package_default = {
102843
103003
  name: "pullfrog",
102844
- version: "0.1.33",
103004
+ version: "0.1.35",
102845
103005
  type: "module",
102846
103006
  bin: {
102847
103007
  pullfrog: "dist/cli.mjs",
@@ -104598,7 +104758,7 @@ function tailLines2(text, maxCodeUnits) {
104598
104758
  const firstNewline = tail.indexOf("\n");
104599
104759
  return firstNewline > 0 && firstNewline < tail.length - 1 ? tail.slice(firstNewline + 1) : tail;
104600
104760
  }
104601
- async function runClaude(params) {
104761
+ async function runClaude2(params) {
104602
104762
  const startTime = performance5.now();
104603
104763
  let eventCount = 0;
104604
104764
  const labeler = new SessionLabeler();
@@ -105124,7 +105284,7 @@ var claude = agent({
105124
105284
  log.debug(`\xBB starting Pullfrog (Claude Code): ${cliPath} ${baseArgs.join(" ")}`);
105125
105285
  log.debug(`\xBB working directory: ${repoDir}`);
105126
105286
  const gateServer = __using(_stack, await startGateServer(ctx), true);
105127
- const result = await runClaude({
105287
+ const result = await runClaude2({
105128
105288
  label: "Pullfrog",
105129
105289
  cmd: cliPath,
105130
105290
  cwd: repoDir,
@@ -105940,7 +106100,7 @@ var buildClientParams = (args2, fields) => {
105940
106100
  };
105941
106101
  const map2 = buildKeyMap(fields);
105942
106102
  let config3;
105943
- for (const [index, arg5] of args2.entries()) {
106103
+ for (const [index, arg6] of args2.entries()) {
105944
106104
  if (fields[index]) {
105945
106105
  config3 = fields[index];
105946
106106
  }
@@ -105953,13 +106113,13 @@ var buildClientParams = (args2, fields) => {
105953
106113
  const name = field.map || config3.key;
105954
106114
  if (field.in) {
105955
106115
  ;
105956
- params[field.in][name] = arg5;
106116
+ params[field.in][name] = arg6;
105957
106117
  }
105958
106118
  } else {
105959
- params.body = arg5;
106119
+ params.body = arg6;
105960
106120
  }
105961
106121
  } else {
105962
- for (const [key, value2] of Object.entries(arg5 ?? {})) {
106122
+ for (const [key, value2] of Object.entries(arg6 ?? {})) {
105963
106123
  const field = map2.get(key);
105964
106124
  if (field) {
105965
106125
  if (field.in) {
@@ -111617,12 +111777,12 @@ var CompiledFunction = class extends CastableBase {
111617
111777
  constructor(...args2) {
111618
111778
  super();
111619
111779
  this.argNames = args2;
111620
- for (const arg5 of args2) {
111621
- if (arg5 in this) {
111622
- throw new Error(`Arg name '${arg5}' would overwrite an existing property on FunctionBody`);
111780
+ for (const arg6 of args2) {
111781
+ if (arg6 in this) {
111782
+ throw new Error(`Arg name '${arg6}' would overwrite an existing property on FunctionBody`);
111623
111783
  }
111624
111784
  ;
111625
- this[arg5] = arg5;
111785
+ this[arg6] = arg6;
111626
111786
  }
111627
111787
  }
111628
111788
  indentation = 0;
@@ -111707,12 +111867,12 @@ var NodeCompiler = class extends CompiledFunction {
111707
111867
  this.optimistic = ctx.optimistic === true;
111708
111868
  }
111709
111869
  invoke(node2, opts) {
111710
- const arg5 = opts?.arg ?? this.data;
111870
+ const arg6 = opts?.arg ?? this.data;
111711
111871
  const requiresContext = typeof node2 === "string" ? true : this.requiresContextFor(node2);
111712
111872
  const id = typeof node2 === "string" ? node2 : node2.id;
111713
111873
  if (requiresContext)
111714
- return `${this.referenceToId(id, opts)}(${arg5}, ${this.ctx})`;
111715
- return `${this.referenceToId(id, opts)}(${arg5})`;
111874
+ return `${this.referenceToId(id, opts)}(${arg6}, ${this.ctx})`;
111875
+ return `${this.referenceToId(id, opts)}(${arg6})`;
111716
111876
  }
111717
111877
  referenceToId(id, opts) {
111718
111878
  const invokedKind = opts?.kind ?? this.traversalKind;
@@ -112673,8 +112833,8 @@ var ZodType2 = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
112673
112833
  inst.nullish = () => optional(nullable(inst));
112674
112834
  inst.nonoptional = (params) => nonoptional(inst, params);
112675
112835
  inst.array = () => array(inst);
112676
- inst.or = (arg5) => union([inst, arg5]);
112677
- inst.and = (arg5) => intersection(inst, arg5);
112836
+ inst.or = (arg6) => union([inst, arg6]);
112837
+ inst.and = (arg6) => intersection(inst, arg6);
112678
112838
  inst.transform = (tx) => pipe(inst, transform(tx));
112679
112839
  inst.default = (def2) => _default2(inst, def2);
112680
112840
  inst.prefault = (def2) => prefault(inst, def2);
@@ -119734,10 +119894,10 @@ var Context = class {
119734
119894
  }
119735
119895
  return Object.fromEntries(this.#var);
119736
119896
  }
119737
- #newResponse(data, arg5, headers) {
119897
+ #newResponse(data, arg6, headers) {
119738
119898
  const responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders ?? new Headers();
119739
- if (typeof arg5 === "object" && "headers" in arg5) {
119740
- const argHeaders = arg5.headers instanceof Headers ? arg5.headers : new Headers(arg5.headers);
119899
+ if (typeof arg6 === "object" && "headers" in arg6) {
119900
+ const argHeaders = arg6.headers instanceof Headers ? arg6.headers : new Headers(arg6.headers);
119741
119901
  for (const [key, value2] of argHeaders) {
119742
119902
  if (key.toLowerCase() === "set-cookie") {
119743
119903
  responseHeaders.append(key, value2);
@@ -119758,7 +119918,7 @@ var Context = class {
119758
119918
  }
119759
119919
  }
119760
119920
  }
119761
- const status = typeof arg5 === "number" ? arg5 : arg5?.status ?? this.#status;
119921
+ const status = typeof arg6 === "number" ? arg6 : arg6?.status ?? this.#status;
119762
119922
  return createResponseInstance(data, { status, headers: responseHeaders });
119763
119923
  }
119764
119924
  newResponse = (...args2) => this.#newResponse(...args2);
@@ -119783,7 +119943,7 @@ var Context = class {
119783
119943
  * })
119784
119944
  * ```
119785
119945
  */
119786
- body = (data, arg5, headers) => this.#newResponse(data, arg5, headers);
119946
+ body = (data, arg6, headers) => this.#newResponse(data, arg6, headers);
119787
119947
  /**
119788
119948
  * `.text()` can render text as `Content-Type:text/plain`.
119789
119949
  *
@@ -119796,10 +119956,10 @@ var Context = class {
119796
119956
  * })
119797
119957
  * ```
119798
119958
  */
119799
- text = (text, arg5, headers) => {
119800
- return !this.#preparedHeaders && !this.#status && !arg5 && !headers && !this.finalized ? new Response(text) : this.#newResponse(
119959
+ text = (text, arg6, headers) => {
119960
+ return !this.#preparedHeaders && !this.#status && !arg6 && !headers && !this.finalized ? new Response(text) : this.#newResponse(
119801
119961
  text,
119802
- arg5,
119962
+ arg6,
119803
119963
  setDefaultContentType(TEXT_PLAIN, headers)
119804
119964
  );
119805
119965
  };
@@ -119815,15 +119975,15 @@ var Context = class {
119815
119975
  * })
119816
119976
  * ```
119817
119977
  */
119818
- json = (object5, arg5, headers) => {
119978
+ json = (object5, arg6, headers) => {
119819
119979
  return this.#newResponse(
119820
119980
  JSON.stringify(object5),
119821
- arg5,
119981
+ arg6,
119822
119982
  setDefaultContentType("application/json", headers)
119823
119983
  );
119824
119984
  };
119825
- html = (html, arg5, headers) => {
119826
- const res = (html2) => this.#newResponse(html2, arg5, setDefaultContentType("text/html; charset=UTF-8", headers));
119985
+ html = (html, arg6, headers) => {
119986
+ const res = (html2) => this.#newResponse(html2, arg6, setDefaultContentType("text/html; charset=UTF-8", headers));
119827
119987
  return typeof html === "object" ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res) : res(html);
119828
119988
  };
119829
119989
  /**
@@ -121892,13 +122052,13 @@ var Doc2 = class {
121892
122052
  fn2(this);
121893
122053
  this.indent -= 1;
121894
122054
  }
121895
- write(arg5) {
121896
- if (typeof arg5 === "function") {
121897
- arg5(this, { execution: "sync" });
121898
- arg5(this, { execution: "async" });
122055
+ write(arg6) {
122056
+ if (typeof arg6 === "function") {
122057
+ arg6(this, { execution: "sync" });
122058
+ arg6(this, { execution: "async" });
121899
122059
  return;
121900
122060
  }
121901
- const lines = arg5.split("\n").filter((x) => x);
122061
+ const lines = arg6.split("\n").filter((x) => x);
121902
122062
  const minIndent = Math.min(...lines.map((x) => x.length - x.trimStart().length));
121903
122063
  const dedented = lines.map((x) => x.slice(minIndent)).map((x) => " ".repeat(this.indent * 2) + x);
121904
122064
  for (const line$1 of dedented) this.content.push(line$1);
@@ -123569,8 +123729,8 @@ var ZodType3 = /* @__PURE__ */ $constructor2("ZodType", (inst, def$30) => {
123569
123729
  inst.nullish = () => optional2(nullable2(inst));
123570
123730
  inst.nonoptional = (params) => nonoptional2(inst, params);
123571
123731
  inst.array = () => array2(inst);
123572
- inst.or = (arg5) => union2([inst, arg5]);
123573
- inst.and = (arg5) => intersection2(inst, arg5);
123732
+ inst.or = (arg6) => union2([inst, arg6]);
123733
+ inst.and = (arg6) => intersection2(inst, arg6);
123574
123734
  inst.transform = (tx) => pipe2(inst, transform2(tx));
123575
123735
  inst.default = (def$31) => _default3(inst, def$31);
123576
123736
  inst.prefault = (def$31) => prefault2(inst, def$31);
@@ -125362,14 +125522,14 @@ var require_http_errors = /* @__PURE__ */ __commonJSMin(((exports, module) => {
125362
125522
  var status$1 = 500;
125363
125523
  var props = {};
125364
125524
  for (var i$3 = 0; i$3 < arguments.length; i$3++) {
125365
- var arg5 = arguments[i$3];
125366
- var type2 = typeof arg5;
125367
- if (type2 === "object" && arg5 instanceof Error) {
125368
- err = arg5;
125525
+ var arg6 = arguments[i$3];
125526
+ var type2 = typeof arg6;
125527
+ if (type2 === "object" && arg6 instanceof Error) {
125528
+ err = arg6;
125369
125529
  status$1 = err.status || err.statusCode || status$1;
125370
- } else if (type2 === "number" && i$3 === 0) status$1 = arg5;
125371
- else if (type2 === "string") msg = arg5;
125372
- else if (type2 === "object") props = arg5;
125530
+ } else if (type2 === "number" && i$3 === 0) status$1 = arg6;
125531
+ else if (type2 === "string") msg = arg6;
125532
+ else if (type2 === "object") props = arg6;
125373
125533
  else throw new TypeError("argument #" + (i$3 + 1) + " unsupported type " + type2);
125374
125534
  }
125375
125535
  if (typeof status$1 === "number" && (status$1 < 400 || status$1 >= 600)) deprecate("non-error status code; use only 4xx or 5xx status codes");
@@ -135563,10 +135723,10 @@ var require_code$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
135563
135723
  return new _Code(expr);
135564
135724
  }
135565
135725
  exports.str = str;
135566
- function addCodeArg(code, arg5) {
135567
- if (arg5 instanceof _Code) code.push(...arg5._items);
135568
- else if (arg5 instanceof Name) code.push(arg5);
135569
- else code.push(interpolate(arg5));
135726
+ function addCodeArg(code, arg6) {
135727
+ if (arg6 instanceof _Code) code.push(...arg6._items);
135728
+ else if (arg6 instanceof Name) code.push(arg6);
135729
+ else code.push(interpolate(arg6));
135570
135730
  }
135571
135731
  exports.addCodeArg = addCodeArg;
135572
135732
  function optimize(expr) {
@@ -142500,11 +142660,11 @@ ${error49 instanceof Error ? error49.stack : JSON.stringify(error49)}`
142500
142660
  );
142501
142661
  }
142502
142662
  const args2 = request2.params.arguments;
142503
- for (const arg5 of prompt.arguments ?? []) {
142504
- if (arg5.required && !(args2 && arg5.name in args2)) {
142663
+ for (const arg6 of prompt.arguments ?? []) {
142664
+ if (arg6.required && !(args2 && arg6.name in args2)) {
142505
142665
  throw new McpError(
142506
142666
  ErrorCode.InvalidRequest,
142507
- `Prompt '${request2.params.name}' requires argument '${arg5.name}': ${arg5.description || "No description provided"}`
142667
+ `Prompt '${request2.params.name}' requires argument '${arg6.name}': ${arg6.description || "No description provided"}`
142508
142668
  );
142509
142669
  }
142510
142670
  }
@@ -143722,7 +143882,7 @@ var FastMCP = class extends FastMCPEventEmitter {
143722
143882
  #parseRuntimeConfig(overrides) {
143723
143883
  const args2 = process.argv.slice(2);
143724
143884
  const getArg = (name) => {
143725
- const index = args2.findIndex((arg5) => arg5 === `--${name}`);
143885
+ const index = args2.findIndex((arg6) => arg6 === `--${name}`);
143726
143886
  return index !== -1 && index + 1 < args2.length ? args2[index + 1] : void 0;
143727
143887
  };
143728
143888
  const transportArg = getArg("transport");
@@ -145097,11 +145257,11 @@ var GenericRoot = class extends Callable {
145097
145257
  constructor(paramDefs, bodyDef, $3, arg$, hkt) {
145098
145258
  super((...args2) => {
145099
145259
  const argNodes = flatMorph(this.names, (i, name) => {
145100
- const arg5 = this.arg$.parse(args2[i]);
145101
- if (!arg5.extends(this.constraints[i])) {
145102
- throwParseError(writeUnsatisfiedParameterConstraintMessage(name, this.constraints[i].expression, arg5.expression));
145260
+ const arg6 = this.arg$.parse(args2[i]);
145261
+ if (!arg6.extends(this.constraints[i])) {
145262
+ throwParseError(writeUnsatisfiedParameterConstraintMessage(name, this.constraints[i].expression, arg6.expression));
145103
145263
  }
145104
- return [name, arg5];
145264
+ return [name, arg6];
145105
145265
  });
145106
145266
  if (this.defIsLazy()) {
145107
145267
  const def = this.bodyDef(argNodes);
@@ -145149,7 +145309,7 @@ var GenericRoot = class extends Callable {
145149
145309
  return this.baseInstantiation.internal.references;
145150
145310
  }
145151
145311
  };
145152
- var writeUnsatisfiedParameterConstraintMessage = (name, constraint, arg5) => `${name} must be assignable to ${constraint} (was ${arg5})`;
145312
+ var writeUnsatisfiedParameterConstraintMessage = (name, constraint, arg6) => `${name} must be assignable to ${constraint} (was ${arg6})`;
145153
145313
 
145154
145314
  // node_modules/.pnpm/@ark+schema@0.56.0/node_modules/@ark/schema/out/predicate.js
145155
145315
  var implementation = implementNode({
@@ -149647,7 +149807,7 @@ var _parseGenericArgs = (name, g, s, argNodes) => {
149647
149807
  argNodes.push(argState.root);
149648
149808
  if (argState.finalizer === ">") {
149649
149809
  if (argNodes.length !== g.params.length) {
149650
- return s.error(writeInvalidGenericArgCountMessage(name, g.names, argNodes.map((arg5) => arg5.expression)));
149810
+ return s.error(writeInvalidGenericArgCountMessage(name, g.names, argNodes.map((arg6) => arg6.expression)));
149651
149811
  }
149652
149812
  return argNodes;
149653
149813
  }
@@ -149676,10 +149836,10 @@ var parseGenericInstantiation = (name, g, s) => {
149676
149836
  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));
149677
149837
  var maybeParseReference = (s, token) => {
149678
149838
  if (s.ctx.args?.[token]) {
149679
- const arg5 = s.ctx.args[token];
149680
- if (typeof arg5 !== "string")
149681
- return arg5;
149682
- return s.ctx.$.node("alias", { reference: arg5 }, { prereduced: true });
149839
+ const arg6 = s.ctx.args[token];
149840
+ if (typeof arg6 !== "string")
149841
+ return arg6;
149842
+ return s.ctx.$.node("alias", { reference: arg6 }, { prereduced: true });
149683
149843
  }
149684
149844
  const resolution = s.ctx.$.maybeResolve(token);
149685
149845
  if (hasArkKind(resolution, "root"))
@@ -158379,13 +158539,13 @@ function GitTool(ctx) {
158379
158539
  if (blocked) {
158380
158540
  throw new Error(blocked);
158381
158541
  }
158382
- for (const arg5 of args2) {
158542
+ for (const arg6 of args2) {
158383
158543
  const isBlocked = NOSHELL_BLOCKED_ARGS.some(
158384
- (flag) => arg5 === flag || arg5.startsWith(flag + "=")
158544
+ (flag) => arg6 === flag || arg6.startsWith(flag + "=")
158385
158545
  );
158386
158546
  if (isBlocked) {
158387
158547
  throw new Error(
158388
- `Blocked: '${arg5}' flag can execute arbitrary code and is not allowed.`
158548
+ `Blocked: '${arg6}' flag can execute arbitrary code and is not allowed.`
158389
158549
  );
158390
158550
  }
158391
158551
  }
@@ -165316,6 +165476,11 @@ async function mintProxyKey(ctx) {
165316
165476
  body?.error ?? "billing service temporarily unavailable \u2014 retry shortly"
165317
165477
  );
165318
165478
  }
165479
+ if (response.status === 404) {
165480
+ throw new TransientError(
165481
+ "Pullfrog couldn't match this repository to its account \u2014 it may have just been renamed or transferred. The link refreshes automatically on the next run; if it keeps failing, reinstall the GitHub App on the repo's current owner."
165482
+ );
165483
+ }
165319
165484
  if (!response.ok) {
165320
165485
  log.warning(`proxy key mint failed (${response.status})`);
165321
165486
  return null;
@@ -165880,28 +166045,7 @@ ${genericBody}`,
165880
166045
  // utils/runLifecycle.ts
165881
166046
  var core10 = __toESM(require_core(), 1);
165882
166047
 
165883
- // utils/checksGate.ts
165884
- var OK_CONCLUSIONS = /* @__PURE__ */ new Set(["success", "neutral", "skipped"]);
165885
- var PULLFROG_CHECKS = /* @__PURE__ */ new Set(["pullfrog", "pullfrog-approval"]);
165886
- function checkRunsGate(params) {
165887
- for (const run4 of params.checkRuns) {
165888
- if (PULLFROG_CHECKS.has(run4.name.toLowerCase())) continue;
165889
- if (run4.status !== "completed")
165890
- return { ok: false, reason: `check "${run4.name}" ${run4.status}` };
165891
- if (!OK_CONCLUSIONS.has(run4.conclusion ?? "")) {
165892
- return { ok: false, reason: `check "${run4.name}" concluded ${run4.conclusion}` };
165893
- }
165894
- }
165895
- return { ok: true, reason: "all checks passed" };
165896
- }
165897
- function hasVerifiedCheck(params) {
165898
- return params.checkRuns.some(
165899
- (r) => !PULLFROG_CHECKS.has(r.name.toLowerCase()) && r.status === "completed"
165900
- );
165901
- }
165902
-
165903
166048
  // utils/autoMerge.ts
165904
- var NON_MERGEABLE_STATES = /* @__PURE__ */ new Set(["dirty", "behind", "blocked"]);
165905
166049
  function hasBlockingHumanReview(reviews) {
165906
166050
  const latestByReviewer = /* @__PURE__ */ new Map();
165907
166051
  for (const review of reviews) {
@@ -165918,6 +166062,20 @@ function hasBlockingHumanReview(reviews) {
165918
166062
  }
165919
166063
  return false;
165920
166064
  }
166065
+ var ENABLE_AUTO_MERGE = (
166066
+ /* GraphQL */
166067
+ `
166068
+ mutation ($pullRequestId: ID!, $headSha: GitObjectID!) {
166069
+ enablePullRequestAutoMerge(input: {
166070
+ pullRequestId: $pullRequestId
166071
+ mergeMethod: SQUASH
166072
+ expectedHeadOid: $headSha
166073
+ }) { clientMutationId }
166074
+ }`
166075
+ );
166076
+ var isAlreadyMergeable = (error49) => error49 instanceof Error && /clean status/i.test(error49.message);
166077
+ var isHeadChanged = (error49) => error49 instanceof Error && /head has changed|expected head/i.test(error49.message);
166078
+ var isAutoMergeDisallowed = (error49) => error49 instanceof Error && /not allowed/i.test(error49.message);
165921
166079
  async function autoMergeAfterApprove(ctx) {
165922
166080
  if (!ctx.autoMergeEnabled) return;
165923
166081
  if (!ctx.prApproveEnabled) return;
@@ -165928,6 +166086,12 @@ async function autoMergeAfterApprove(ctx) {
165928
166086
  const skip = (reason) => log.info(
165929
166087
  `autoMerge: pr=#${pullNumber} approvalSha=${approval.sha?.slice(0, 7)} \u2192 skipped: ${reason}`
165930
166088
  );
166089
+ const comment = (body) => ctx.octokit.rest.issues.createComment({
166090
+ owner: ctx.repo.owner,
166091
+ repo: ctx.repo.name,
166092
+ issue_number: pullNumber,
166093
+ body: addFooter(ctx, body)
166094
+ }).catch((err) => log.debug(`autoMerge comment failed: ${err}`));
165931
166095
  const pr = await ctx.octokit.rest.pulls.get({
165932
166096
  owner: ctx.repo.owner,
165933
166097
  repo: ctx.repo.name,
@@ -165935,6 +166099,7 @@ async function autoMergeAfterApprove(ctx) {
165935
166099
  });
165936
166100
  if (pr.data.state !== "open") return skip("pr not open");
165937
166101
  if (pr.data.draft) return skip("pr is draft");
166102
+ if (pr.data.auto_merge) return skip("auto-merge already enabled");
165938
166103
  const headSha = pr.data.head.sha;
165939
166104
  if (approval.sha !== headSha) return skip(`approval sha != head ${headSha.slice(0, 7)}`);
165940
166105
  const outstanding = await countOutstandingPullfrogThreads(ctx, pullNumber);
@@ -165946,40 +166111,49 @@ async function autoMergeAfterApprove(ctx) {
165946
166111
  per_page: 100
165947
166112
  });
165948
166113
  if (hasBlockingHumanReview(reviews)) return skip("human changes requested");
165949
- if (pr.data.mergeable !== true) return skip(`not mergeable (mergeable=${pr.data.mergeable})`);
165950
- if (pr.data.mergeable_state && NON_MERGEABLE_STATES.has(pr.data.mergeable_state)) {
165951
- return skip(`mergeable_state=${pr.data.mergeable_state}`);
166114
+ try {
166115
+ await op(
166116
+ () => ctx.octokit.graphql(ENABLE_AUTO_MERGE, {
166117
+ pullRequestId: pr.data.node_id,
166118
+ headSha
166119
+ }),
166120
+ {
166121
+ name: "enablePullRequestAutoMerge",
166122
+ retries: [500, 2e3],
166123
+ bail: (error49) => !isTransientOctokitError(error49)
166124
+ }
166125
+ )();
166126
+ log.info(`autoMerge: pr=#${pullNumber} @ ${headSha.slice(0, 7)} \u2192 native auto-merge enabled`);
166127
+ await comment(
166128
+ "> \u2705 Approved \u2014 auto-merge enabled; GitHub will merge once required checks pass."
166129
+ );
166130
+ return;
166131
+ } catch (error49) {
166132
+ if (isHeadChanged(error49)) return skip("head moved during enable");
166133
+ if (isAutoMergeDisallowed(error49)) {
166134
+ await comment(
166135
+ "> \u26A0\uFE0F Approved, but auto-merge is off for this repo. Enable `Allow auto-merge` in Settings > General > Pull Requests."
166136
+ );
166137
+ return;
166138
+ }
166139
+ if (!isAlreadyMergeable(error49)) throw error49;
165952
166140
  }
165953
- const checkRuns = await ctx.octokit.paginate(ctx.octokit.rest.checks.listForRef, {
165954
- owner: ctx.repo.owner,
165955
- repo: ctx.repo.name,
165956
- ref: headSha,
165957
- per_page: 100
165958
- });
165959
- const gate = checkRunsGate({ checkRuns });
165960
- if (!gate.ok) return skip(`ci: ${gate.reason}`);
165961
- if (!hasVerifiedCheck({ checkRuns })) return skip("no completed external check-run to verify");
166141
+ const base = await ctx.octokit.rest.repos.getBranch({ owner: ctx.repo.owner, repo: ctx.repo.name, branch: pr.data.base.ref }).catch(() => null);
166142
+ if (!base?.data.protected) return skip("base branch not protected \u2014 refusing CI-ungated merge");
165962
166143
  const merge4 = await ctx.octokit.rest.pulls.merge({
165963
166144
  owner: ctx.repo.owner,
165964
166145
  repo: ctx.repo.name,
165965
166146
  pull_number: pullNumber,
165966
166147
  sha: headSha,
165967
166148
  merge_method: "squash",
165968
- commit_title: `${pr.data.title} (#${pullNumber})`,
165969
- commit_message: "merged autonomously by Pullfrog after a clean approval."
166149
+ commit_title: `${pr.data.title} (#${pullNumber})`
165970
166150
  });
165971
166151
  log.info(
165972
- `autoMerge: pr=#${pullNumber} approvalSha=${headSha.slice(0, 7)} outstanding=0 \u2192 merged ${merge4.data.sha?.slice(0, 7)}`
166152
+ `autoMerge: pr=#${pullNumber} @ ${headSha.slice(0, 7)} \u2192 merged directly ${merge4.data.sha?.slice(0, 7)}`
166153
+ );
166154
+ await comment(
166155
+ "> \u2705 Merged autonomously after Pullfrog approved this PR and resolved all of its own review threads."
165973
166156
  );
165974
- await ctx.octokit.rest.issues.createComment({
165975
- owner: ctx.repo.owner,
165976
- repo: ctx.repo.name,
165977
- issue_number: pullNumber,
165978
- body: addFooter(
165979
- ctx,
165980
- "> \u2705 Merged autonomously after Pullfrog approved this PR and resolved all of its own review threads."
165981
- )
165982
- }).catch((err) => log.debug(`autoMerge comment failed: ${err}`));
165983
166157
  }
165984
166158
 
165985
166159
  // utils/reviewCleanup.ts
@@ -167764,8 +167938,122 @@ async function run2() {
167764
167938
  }
167765
167939
  }
167766
167940
 
167941
+ // commands/watch.ts
167942
+ var import_arg4 = __toESM(require_arg(), 1);
167943
+ var import_picocolors4 = __toESM(require_picocolors(), 1);
167944
+ var REQUEST_TIMEOUT_MS = 35e3;
167945
+ function parseWatchArgs(args2) {
167946
+ return (0, import_arg4.default)(
167947
+ {
167948
+ "--pr": Number,
167949
+ "--pretty": Boolean,
167950
+ "--since": String,
167951
+ "--help": Boolean,
167952
+ "-h": "--help",
167953
+ "-p": "--pretty"
167954
+ },
167955
+ { argv: args2 }
167956
+ );
167957
+ }
167958
+ function printUsage(prog, stream) {
167959
+ stream(`usage: ${prog} watch [<owner>/<repo>] --pr <number> [options]
167960
+ `);
167961
+ stream("subscribe to a PR's activity and print one JSON line per event.\n");
167962
+ stream("arguments:");
167963
+ stream(" <owner>/<repo> target repo (defaults to the current git remote)");
167964
+ stream("");
167965
+ stream("options:");
167966
+ stream(" --pr <number> pull request number to watch (required)");
167967
+ stream(" --since <cursor> resume from a cursor emitted by a prior event");
167968
+ stream(" -p, --pretty human-readable output instead of JSON lines");
167969
+ stream(" -h, --help show help");
167970
+ }
167971
+ function resolveRepo(positional) {
167972
+ if (!positional) return parseGitRemote();
167973
+ const match3 = positional.match(/^([^/\s]+)\/([^/\s]+)$/);
167974
+ if (!match3) bail(`invalid repo "${positional}" \u2014 expected <owner>/<repo>`);
167975
+ return { owner: match3[1], repo: match3[2] };
167976
+ }
167977
+ async function pollOnce(ctx) {
167978
+ const params = new URLSearchParams({
167979
+ owner: ctx.owner,
167980
+ repo: ctx.repo,
167981
+ pr: String(ctx.pr)
167982
+ });
167983
+ if (ctx.cursor !== void 0) params.set("since", ctx.cursor);
167984
+ const controller = new AbortController();
167985
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
167986
+ try {
167987
+ const response = await fetch(`${PULLFROG_API_URL}/api/cli/pr-events?${params}`, {
167988
+ headers: { authorization: `Bearer ${ctx.token}` },
167989
+ signal: controller.signal
167990
+ });
167991
+ if (response.status === 401 || response.status === 403) {
167992
+ bail("invalid or expired github token \u2014 run `gh auth login`.");
167993
+ }
167994
+ if (response.status === 404) {
167995
+ bail(`repository ${ctx.owner}/${ctx.repo} not found or Pullfrog not installed on it.`);
167996
+ }
167997
+ if (!response.ok) {
167998
+ throw new Error(`pr-events returned ${response.status}`);
167999
+ }
168000
+ return await response.json();
168001
+ } finally {
168002
+ clearTimeout(timeout);
168003
+ }
168004
+ }
168005
+ function formatPretty(event) {
168006
+ const time4 = new Date(event.createdAt).toLocaleTimeString();
168007
+ const action = typeof event.data.action === "string" ? event.data.action : "";
168008
+ const actor = typeof event.data.author === "string" ? event.data.author : typeof event.data.reviewer === "string" ? event.data.reviewer : "";
168009
+ const detail = [action, actor && import_picocolors4.default.dim(`by ${actor}`)].filter(Boolean).join(" ");
168010
+ return `${import_picocolors4.default.dim(time4)} ${import_picocolors4.default.cyan(event.kind)} ${import_picocolors4.default.bold(`#${event.pr}`)} ${detail}`.trimEnd();
168011
+ }
168012
+ async function runCli4(input) {
168013
+ let parsed2;
168014
+ try {
168015
+ parsed2 = parseWatchArgs(input.args);
168016
+ } catch (error49) {
168017
+ console.error(`${error49 instanceof Error ? error49.message : String(error49)}
168018
+ `);
168019
+ printUsage(input.prog, console.error);
168020
+ process.exit(1);
168021
+ }
168022
+ if (input.showHelp || parsed2["--help"]) {
168023
+ printUsage(input.prog, console.log);
168024
+ process.exit(0);
168025
+ }
168026
+ const target = resolveRepo(parsed2._[0]);
168027
+ const pr = parsed2["--pr"];
168028
+ if (pr === void 0 || !Number.isInteger(pr) || pr <= 0) {
168029
+ bail("--pr <number> is required");
168030
+ }
168031
+ const token = getGhToken();
168032
+ const pretty = parsed2["--pretty"] === true;
168033
+ let cursor = parsed2["--since"];
168034
+ const poll = op(pollOnce, {
168035
+ name: "pr-events poll",
168036
+ retries: [1e3, 2e3, 5e3, 1e4, 15e3]
168037
+ });
168038
+ for (; ; ) {
168039
+ try {
168040
+ const result = await poll({ owner: target.owner, repo: target.repo, pr, token, cursor });
168041
+ cursor = result.cursor;
168042
+ for (const event of result.events) {
168043
+ process.stdout.write(pretty ? `${formatPretty(event)}
168044
+ ` : `${JSON.stringify(event)}
168045
+ `);
168046
+ }
168047
+ } catch (error49) {
168048
+ const message = error49 instanceof Error ? error49.message : String(error49);
168049
+ console.error(import_picocolors4.default.dim(`watch: ${message} \u2014 retrying in 30s`));
168050
+ await new Promise((resolve3) => setTimeout(resolve3, 3e4));
168051
+ }
168052
+ }
168053
+ }
168054
+
167767
168055
  // cli.ts
167768
- var VERSION10 = "0.1.33";
168056
+ var VERSION10 = "0.1.35";
167769
168057
  var bin = basename2(process.argv[1] || "");
167770
168058
  var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
167771
168059
  var rawArgs = process.argv.slice(2);
@@ -167775,13 +168063,14 @@ function printMainUsage(stream) {
167775
168063
  stream("commands:");
167776
168064
  stream(" init set up pullfrog on the current repository");
167777
168065
  stream(" auth manage provider credentials for the current repository");
168066
+ stream(" watch stream a PR's activity as one JSON line per event");
167778
168067
  stream("");
167779
168068
  stream("global options:");
167780
168069
  stream(" -h, --help show help");
167781
168070
  stream(" -v, --version show version");
167782
168071
  }
167783
168072
  function parseGlobalArgs(args2) {
167784
- return (0, import_arg4.default)(
168073
+ return (0, import_arg5.default)(
167785
168074
  {
167786
168075
  "--help": Boolean,
167787
168076
  "--version": Boolean,
@@ -167816,7 +168105,7 @@ async function run3() {
167816
168105
  const commandArgs = globalParsed._.slice(1);
167817
168106
  if (!command) {
167818
168107
  if (globalParsed["--help"]) {
167819
- console.log(`${import_picocolors4.default.bold("pullfrog")} v${VERSION10}
168108
+ console.log(`${import_picocolors5.default.bold("pullfrog")} v${VERSION10}
167820
168109
  `);
167821
168110
  printMainUsage(console.log);
167822
168111
  process.exit(0);
@@ -167848,11 +168137,19 @@ async function run3() {
167848
168137
  });
167849
168138
  return;
167850
168139
  }
168140
+ if (command === "watch") {
168141
+ await runCli4({
168142
+ args: commandArgs,
168143
+ prog: PROG,
168144
+ showHelp: globalParsed["--help"] === true
168145
+ });
168146
+ return;
168147
+ }
167851
168148
  if (globalParsed["--help"]) {
167852
168149
  printMainUsage(console.log);
167853
168150
  process.exit(0);
167854
168151
  }
167855
- console.error(`unknown command: ${import_picocolors4.default.bold(command)}
168152
+ console.error(`unknown command: ${import_picocolors5.default.bold(command)}
167856
168153
  `);
167857
168154
  printMainUsage(console.error);
167858
168155
  process.exit(1);
@@ -167861,7 +168158,7 @@ try {
167861
168158
  await run3();
167862
168159
  } catch (error49) {
167863
168160
  const message = error49 instanceof Error ? error49.message : String(error49);
167864
- console.error(import_picocolors4.default.red(message));
168161
+ console.error(import_picocolors5.default.red(message));
167865
168162
  process.exit(1);
167866
168163
  }
167867
168164
  /*! Bundled license information: