@kenkaiiii/gg-boss 4.11.3 → 4.12.1

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.
@@ -3225,8 +3225,8 @@ var require_utils = __commonJS({
3225
3225
  }
3226
3226
  return ind;
3227
3227
  }
3228
- function removeDotSegments(path46) {
3229
- let input = path46;
3228
+ function removeDotSegments(path48) {
3229
+ let input = path48;
3230
3230
  const output = [];
3231
3231
  let nextSlash = -1;
3232
3232
  let len = 0;
@@ -3426,8 +3426,8 @@ var require_schemes = __commonJS({
3426
3426
  wsComponent.secure = void 0;
3427
3427
  }
3428
3428
  if (wsComponent.resourceName) {
3429
- const [path46, query] = wsComponent.resourceName.split("?");
3430
- wsComponent.path = path46 && path46 !== "/" ? path46 : void 0;
3429
+ const [path48, query] = wsComponent.resourceName.split("?");
3430
+ wsComponent.path = path48 && path48 !== "/" ? path48 : void 0;
3431
3431
  wsComponent.query = query;
3432
3432
  wsComponent.resourceName = void 0;
3433
3433
  }
@@ -3486,7 +3486,7 @@ var require_schemes = __commonJS({
3486
3486
  urnComponent.nss = (uuidComponent.uuid || "").toLowerCase();
3487
3487
  return urnComponent;
3488
3488
  }
3489
- var http = (
3489
+ var http2 = (
3490
3490
  /** @type {SchemeHandler} */
3491
3491
  {
3492
3492
  scheme: "http",
@@ -3499,7 +3499,7 @@ var require_schemes = __commonJS({
3499
3499
  /** @type {SchemeHandler} */
3500
3500
  {
3501
3501
  scheme: "https",
3502
- domainHost: http.domainHost,
3502
+ domainHost: http2.domainHost,
3503
3503
  parse: httpParse,
3504
3504
  serialize: httpSerialize
3505
3505
  }
@@ -3543,7 +3543,7 @@ var require_schemes = __commonJS({
3543
3543
  var SCHEMES = (
3544
3544
  /** @type {Record<SchemeName, SchemeHandler>} */
3545
3545
  {
3546
- http,
3546
+ http: http2,
3547
3547
  https,
3548
3548
  ws,
3549
3549
  wss,
@@ -6835,12 +6835,12 @@ var require_dist = __commonJS({
6835
6835
  throw new Error(`Unknown format "${name}"`);
6836
6836
  return f;
6837
6837
  };
6838
- function addFormats(ajv, list, fs39, exportName) {
6838
+ function addFormats(ajv, list, fs40, exportName) {
6839
6839
  var _a6;
6840
6840
  var _b;
6841
6841
  (_a6 = (_b = ajv.opts.code).formats) !== null && _a6 !== void 0 ? _a6 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
6842
6842
  for (const f of list)
6843
- ajv.addFormat(f, fs39[f]);
6843
+ ajv.addFormat(f, fs40[f]);
6844
6844
  }
6845
6845
  module.exports = exports = formatsPlugin;
6846
6846
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -6855,8 +6855,8 @@ var require_windows = __commonJS({
6855
6855
  init_esm_shims();
6856
6856
  module.exports = isexe;
6857
6857
  isexe.sync = sync;
6858
- var fs39 = __require("fs");
6859
- function checkPathExt(path46, options) {
6858
+ var fs40 = __require("fs");
6859
+ function checkPathExt(path48, options) {
6860
6860
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
6861
6861
  if (!pathext) {
6862
6862
  return true;
@@ -6867,25 +6867,25 @@ var require_windows = __commonJS({
6867
6867
  }
6868
6868
  for (var i = 0; i < pathext.length; i++) {
6869
6869
  var p = pathext[i].toLowerCase();
6870
- if (p && path46.substr(-p.length).toLowerCase() === p) {
6870
+ if (p && path48.substr(-p.length).toLowerCase() === p) {
6871
6871
  return true;
6872
6872
  }
6873
6873
  }
6874
6874
  return false;
6875
6875
  }
6876
- function checkStat(stat, path46, options) {
6876
+ function checkStat(stat, path48, options) {
6877
6877
  if (!stat.isSymbolicLink() && !stat.isFile()) {
6878
6878
  return false;
6879
6879
  }
6880
- return checkPathExt(path46, options);
6880
+ return checkPathExt(path48, options);
6881
6881
  }
6882
- function isexe(path46, options, cb) {
6883
- fs39.stat(path46, function(er, stat) {
6884
- cb(er, er ? false : checkStat(stat, path46, options));
6882
+ function isexe(path48, options, cb) {
6883
+ fs40.stat(path48, function(er, stat) {
6884
+ cb(er, er ? false : checkStat(stat, path48, options));
6885
6885
  });
6886
6886
  }
6887
- function sync(path46, options) {
6888
- return checkStat(fs39.statSync(path46), path46, options);
6887
+ function sync(path48, options) {
6888
+ return checkStat(fs40.statSync(path48), path48, options);
6889
6889
  }
6890
6890
  }
6891
6891
  });
@@ -6897,14 +6897,14 @@ var require_mode = __commonJS({
6897
6897
  init_esm_shims();
6898
6898
  module.exports = isexe;
6899
6899
  isexe.sync = sync;
6900
- var fs39 = __require("fs");
6901
- function isexe(path46, options, cb) {
6902
- fs39.stat(path46, function(er, stat) {
6900
+ var fs40 = __require("fs");
6901
+ function isexe(path48, options, cb) {
6902
+ fs40.stat(path48, function(er, stat) {
6903
6903
  cb(er, er ? false : checkStat(stat, options));
6904
6904
  });
6905
6905
  }
6906
- function sync(path46, options) {
6907
- return checkStat(fs39.statSync(path46), options);
6906
+ function sync(path48, options) {
6907
+ return checkStat(fs40.statSync(path48), options);
6908
6908
  }
6909
6909
  function checkStat(stat, options) {
6910
6910
  return stat.isFile() && checkMode(stat, options);
@@ -6930,7 +6930,7 @@ var require_isexe = __commonJS({
6930
6930
  "../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports, module) {
6931
6931
  "use strict";
6932
6932
  init_esm_shims();
6933
- var fs39 = __require("fs");
6933
+ var fs40 = __require("fs");
6934
6934
  var core;
6935
6935
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
6936
6936
  core = require_windows();
@@ -6939,7 +6939,7 @@ var require_isexe = __commonJS({
6939
6939
  }
6940
6940
  module.exports = isexe;
6941
6941
  isexe.sync = sync;
6942
- function isexe(path46, options, cb) {
6942
+ function isexe(path48, options, cb) {
6943
6943
  if (typeof options === "function") {
6944
6944
  cb = options;
6945
6945
  options = {};
@@ -6949,7 +6949,7 @@ var require_isexe = __commonJS({
6949
6949
  throw new TypeError("callback not provided");
6950
6950
  }
6951
6951
  return new Promise(function(resolve2, reject) {
6952
- isexe(path46, options || {}, function(er, is) {
6952
+ isexe(path48, options || {}, function(er, is) {
6953
6953
  if (er) {
6954
6954
  reject(er);
6955
6955
  } else {
@@ -6958,7 +6958,7 @@ var require_isexe = __commonJS({
6958
6958
  });
6959
6959
  });
6960
6960
  }
6961
- core(path46, options || {}, function(er, is) {
6961
+ core(path48, options || {}, function(er, is) {
6962
6962
  if (er) {
6963
6963
  if (er.code === "EACCES" || options && options.ignoreErrors) {
6964
6964
  er = null;
@@ -6968,9 +6968,9 @@ var require_isexe = __commonJS({
6968
6968
  cb(er, is);
6969
6969
  });
6970
6970
  }
6971
- function sync(path46, options) {
6971
+ function sync(path48, options) {
6972
6972
  try {
6973
- return core.sync(path46, options || {});
6973
+ return core.sync(path48, options || {});
6974
6974
  } catch (er) {
6975
6975
  if (options && options.ignoreErrors || er.code === "EACCES") {
6976
6976
  return false;
@@ -6988,7 +6988,7 @@ var require_which = __commonJS({
6988
6988
  "use strict";
6989
6989
  init_esm_shims();
6990
6990
  var isWindows3 = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
6991
- var path46 = __require("path");
6991
+ var path48 = __require("path");
6992
6992
  var COLON = isWindows3 ? ";" : ":";
6993
6993
  var isexe = require_isexe();
6994
6994
  var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
@@ -7026,7 +7026,7 @@ var require_which = __commonJS({
7026
7026
  return opt.all && found.length ? resolve2(found) : reject(getNotFoundError(cmd));
7027
7027
  const ppRaw = pathEnv[i];
7028
7028
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
7029
- const pCmd = path46.join(pathPart, cmd);
7029
+ const pCmd = path48.join(pathPart, cmd);
7030
7030
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
7031
7031
  resolve2(subStep(p, i, 0));
7032
7032
  });
@@ -7053,7 +7053,7 @@ var require_which = __commonJS({
7053
7053
  for (let i = 0; i < pathEnv.length; i++) {
7054
7054
  const ppRaw = pathEnv[i];
7055
7055
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
7056
- const pCmd = path46.join(pathPart, cmd);
7056
+ const pCmd = path48.join(pathPart, cmd);
7057
7057
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
7058
7058
  for (let j = 0; j < pathExt.length; j++) {
7059
7059
  const cur = p + pathExt[j];
@@ -7103,7 +7103,7 @@ var require_resolveCommand = __commonJS({
7103
7103
  "../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js"(exports, module) {
7104
7104
  "use strict";
7105
7105
  init_esm_shims();
7106
- var path46 = __require("path");
7106
+ var path48 = __require("path");
7107
7107
  var which = require_which();
7108
7108
  var getPathKey = require_path_key();
7109
7109
  function resolveCommandAttempt(parsed, withoutPathExt) {
@@ -7121,7 +7121,7 @@ var require_resolveCommand = __commonJS({
7121
7121
  try {
7122
7122
  resolved = which.sync(parsed.command, {
7123
7123
  path: env2[getPathKey({ env: env2 })],
7124
- pathExt: withoutPathExt ? path46.delimiter : void 0
7124
+ pathExt: withoutPathExt ? path48.delimiter : void 0
7125
7125
  });
7126
7126
  } catch (e) {
7127
7127
  } finally {
@@ -7130,7 +7130,7 @@ var require_resolveCommand = __commonJS({
7130
7130
  }
7131
7131
  }
7132
7132
  if (resolved) {
7133
- resolved = path46.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
7133
+ resolved = path48.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
7134
7134
  }
7135
7135
  return resolved;
7136
7136
  }
@@ -7187,8 +7187,8 @@ var require_shebang_command = __commonJS({
7187
7187
  if (!match) {
7188
7188
  return null;
7189
7189
  }
7190
- const [path46, argument] = match[0].replace(/#! ?/, "").split(" ");
7191
- const binary = path46.split("/").pop();
7190
+ const [path48, argument] = match[0].replace(/#! ?/, "").split(" ");
7191
+ const binary = path48.split("/").pop();
7192
7192
  if (binary === "env") {
7193
7193
  return argument;
7194
7194
  }
@@ -7202,16 +7202,16 @@ var require_readShebang = __commonJS({
7202
7202
  "../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js"(exports, module) {
7203
7203
  "use strict";
7204
7204
  init_esm_shims();
7205
- var fs39 = __require("fs");
7205
+ var fs40 = __require("fs");
7206
7206
  var shebangCommand = require_shebang_command();
7207
7207
  function readShebang(command) {
7208
7208
  const size = 150;
7209
7209
  const buffer = Buffer.alloc(size);
7210
7210
  let fd2;
7211
7211
  try {
7212
- fd2 = fs39.openSync(command, "r");
7213
- fs39.readSync(fd2, buffer, 0, size, 0);
7214
- fs39.closeSync(fd2);
7212
+ fd2 = fs40.openSync(command, "r");
7213
+ fs40.readSync(fd2, buffer, 0, size, 0);
7214
+ fs40.closeSync(fd2);
7215
7215
  } catch (e) {
7216
7216
  }
7217
7217
  return shebangCommand(buffer.toString());
@@ -7225,7 +7225,7 @@ var require_parse = __commonJS({
7225
7225
  "../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js"(exports, module) {
7226
7226
  "use strict";
7227
7227
  init_esm_shims();
7228
- var path46 = __require("path");
7228
+ var path48 = __require("path");
7229
7229
  var resolveCommand = require_resolveCommand();
7230
7230
  var escape4 = require_escape();
7231
7231
  var readShebang = require_readShebang();
@@ -7250,7 +7250,7 @@ var require_parse = __commonJS({
7250
7250
  const needsShell = !isExecutableRegExp.test(commandFile);
7251
7251
  if (parsed.options.forceShell || needsShell) {
7252
7252
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
7253
- parsed.command = path46.normalize(parsed.command);
7253
+ parsed.command = path48.normalize(parsed.command);
7254
7254
  parsed.command = escape4.command(parsed.command);
7255
7255
  parsed.args = parsed.args.map((arg) => escape4.argument(arg, needsDoubleEscapeMetaChars));
7256
7256
  const shellCommand = [parsed.command].concat(parsed.args).join(" ");
@@ -17765,10 +17765,10 @@ var require_react_reconciler_development = __commonJS({
17765
17765
  fiber = fiber.next, id2--;
17766
17766
  return fiber;
17767
17767
  }
17768
- function copyWithSetImpl(obj, path46, index, value) {
17769
- if (index >= path46.length) return value;
17770
- var key = path46[index], updated = isArrayImpl(obj) ? obj.slice() : assign({}, obj);
17771
- updated[key] = copyWithSetImpl(obj[key], path46, index + 1, value);
17768
+ function copyWithSetImpl(obj, path48, index, value) {
17769
+ if (index >= path48.length) return value;
17770
+ var key = path48[index], updated = isArrayImpl(obj) ? obj.slice() : assign({}, obj);
17771
+ updated[key] = copyWithSetImpl(obj[key], path48, index + 1, value);
17772
17772
  return updated;
17773
17773
  }
17774
17774
  function copyWithRename(obj, oldPath, newPath) {
@@ -17795,11 +17795,11 @@ var require_react_reconciler_development = __commonJS({
17795
17795
  );
17796
17796
  return updated;
17797
17797
  }
17798
- function copyWithDeleteImpl(obj, path46, index) {
17799
- var key = path46[index], updated = isArrayImpl(obj) ? obj.slice() : assign({}, obj);
17800
- if (index + 1 === path46.length)
17798
+ function copyWithDeleteImpl(obj, path48, index) {
17799
+ var key = path48[index], updated = isArrayImpl(obj) ? obj.slice() : assign({}, obj);
17800
+ if (index + 1 === path48.length)
17801
17801
  return isArrayImpl(updated) ? updated.splice(key, 1) : delete updated[key], updated;
17802
- updated[key] = copyWithDeleteImpl(obj[key], path46, index + 1);
17802
+ updated[key] = copyWithDeleteImpl(obj[key], path48, index + 1);
17803
17803
  return updated;
17804
17804
  }
17805
17805
  function shouldSuspendImpl() {
@@ -31076,29 +31076,29 @@ var require_react_reconciler_development = __commonJS({
31076
31076
  var didWarnAboutNestedUpdates = false;
31077
31077
  var didWarnAboutFindNodeInStrictMode = {};
31078
31078
  var overrideHookState = null, overrideHookStateDeletePath = null, overrideHookStateRenamePath = null, overrideProps = null, overridePropsDeletePath = null, overridePropsRenamePath = null, scheduleUpdate = null, scheduleRetry = null, setErrorHandler = null, setSuspenseHandler = null;
31079
- overrideHookState = function(fiber, id2, path46, value) {
31079
+ overrideHookState = function(fiber, id2, path48, value) {
31080
31080
  id2 = findHook(fiber, id2);
31081
- null !== id2 && (path46 = copyWithSetImpl(id2.memoizedState, path46, 0, value), id2.memoizedState = path46, id2.baseState = path46, fiber.memoizedProps = assign({}, fiber.memoizedProps), path46 = enqueueConcurrentRenderForLane(fiber, 2), null !== path46 && scheduleUpdateOnFiber(path46, fiber, 2));
31081
+ null !== id2 && (path48 = copyWithSetImpl(id2.memoizedState, path48, 0, value), id2.memoizedState = path48, id2.baseState = path48, fiber.memoizedProps = assign({}, fiber.memoizedProps), path48 = enqueueConcurrentRenderForLane(fiber, 2), null !== path48 && scheduleUpdateOnFiber(path48, fiber, 2));
31082
31082
  };
31083
- overrideHookStateDeletePath = function(fiber, id2, path46) {
31083
+ overrideHookStateDeletePath = function(fiber, id2, path48) {
31084
31084
  id2 = findHook(fiber, id2);
31085
- null !== id2 && (path46 = copyWithDeleteImpl(id2.memoizedState, path46, 0), id2.memoizedState = path46, id2.baseState = path46, fiber.memoizedProps = assign({}, fiber.memoizedProps), path46 = enqueueConcurrentRenderForLane(fiber, 2), null !== path46 && scheduleUpdateOnFiber(path46, fiber, 2));
31085
+ null !== id2 && (path48 = copyWithDeleteImpl(id2.memoizedState, path48, 0), id2.memoizedState = path48, id2.baseState = path48, fiber.memoizedProps = assign({}, fiber.memoizedProps), path48 = enqueueConcurrentRenderForLane(fiber, 2), null !== path48 && scheduleUpdateOnFiber(path48, fiber, 2));
31086
31086
  };
31087
31087
  overrideHookStateRenamePath = function(fiber, id2, oldPath, newPath) {
31088
31088
  id2 = findHook(fiber, id2);
31089
31089
  null !== id2 && (oldPath = copyWithRename(id2.memoizedState, oldPath, newPath), id2.memoizedState = oldPath, id2.baseState = oldPath, fiber.memoizedProps = assign({}, fiber.memoizedProps), oldPath = enqueueConcurrentRenderForLane(fiber, 2), null !== oldPath && scheduleUpdateOnFiber(oldPath, fiber, 2));
31090
31090
  };
31091
- overrideProps = function(fiber, path46, value) {
31092
- fiber.pendingProps = copyWithSetImpl(fiber.memoizedProps, path46, 0, value);
31091
+ overrideProps = function(fiber, path48, value) {
31092
+ fiber.pendingProps = copyWithSetImpl(fiber.memoizedProps, path48, 0, value);
31093
31093
  fiber.alternate && (fiber.alternate.pendingProps = fiber.pendingProps);
31094
- path46 = enqueueConcurrentRenderForLane(fiber, 2);
31095
- null !== path46 && scheduleUpdateOnFiber(path46, fiber, 2);
31094
+ path48 = enqueueConcurrentRenderForLane(fiber, 2);
31095
+ null !== path48 && scheduleUpdateOnFiber(path48, fiber, 2);
31096
31096
  };
31097
- overridePropsDeletePath = function(fiber, path46) {
31098
- fiber.pendingProps = copyWithDeleteImpl(fiber.memoizedProps, path46, 0);
31097
+ overridePropsDeletePath = function(fiber, path48) {
31098
+ fiber.pendingProps = copyWithDeleteImpl(fiber.memoizedProps, path48, 0);
31099
31099
  fiber.alternate && (fiber.alternate.pendingProps = fiber.pendingProps);
31100
- path46 = enqueueConcurrentRenderForLane(fiber, 2);
31101
- null !== path46 && scheduleUpdateOnFiber(path46, fiber, 2);
31100
+ path48 = enqueueConcurrentRenderForLane(fiber, 2);
31101
+ null !== path48 && scheduleUpdateOnFiber(path48, fiber, 2);
31102
31102
  };
31103
31103
  overridePropsRenamePath = function(fiber, oldPath, newPath) {
31104
31104
  fiber.pendingProps = copyWithRename(
@@ -33840,13 +33840,13 @@ function __classPrivateFieldGet(receiver, state3, kind, f) {
33840
33840
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.94.0_zod@4.4.3/node_modules/@anthropic-ai/sdk/internal/utils/uuid.mjs
33841
33841
  init_esm_shims();
33842
33842
  var uuid4 = function() {
33843
- const { crypto: crypto12 } = globalThis;
33844
- if (crypto12?.randomUUID) {
33845
- uuid4 = crypto12.randomUUID.bind(crypto12);
33846
- return crypto12.randomUUID();
33843
+ const { crypto: crypto13 } = globalThis;
33844
+ if (crypto13?.randomUUID) {
33845
+ uuid4 = crypto13.randomUUID.bind(crypto13);
33846
+ return crypto13.randomUUID();
33847
33847
  }
33848
33848
  const u8 = new Uint8Array(1);
33849
- const randomByte = crypto12 ? () => crypto12.getRandomValues(u8)[0] : () => Math.random() * 255 & 255;
33849
+ const randomByte = crypto13 ? () => crypto13.getRandomValues(u8)[0] : () => Math.random() * 255 & 255;
33850
33850
  return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c2) => (+c2 ^ randomByte() & 15 >> +c2 / 4).toString(16));
33851
33851
  };
33852
33852
 
@@ -34333,15 +34333,15 @@ function redactSensitive(body) {
34333
34333
  }
34334
34334
  return null;
34335
34335
  }
34336
- async function checkCredentialsFileSafety(path46, onWarn = (m) => console.warn(`anthropic-sdk: ${m}`)) {
34336
+ async function checkCredentialsFileSafety(path48, onWarn = (m) => console.warn(`anthropic-sdk: ${m}`)) {
34337
34337
  if (typeof process === "undefined" || process.platform === "win32")
34338
34338
  return;
34339
- const fs39 = await import("fs");
34340
- let resolved = path46;
34339
+ const fs40 = await import("fs");
34340
+ let resolved = path48;
34341
34341
  let st;
34342
34342
  try {
34343
- resolved = await fs39.promises.realpath(path46);
34344
- st = await fs39.promises.stat(resolved);
34343
+ resolved = await fs40.promises.realpath(path48);
34344
+ st = await fs40.promises.stat(resolved);
34345
34345
  } catch {
34346
34346
  return;
34347
34347
  }
@@ -34357,27 +34357,27 @@ async function checkCredentialsFileSafety(path46, onWarn = (m) => console.warn(`
34357
34357
  }
34358
34358
  }
34359
34359
  async function writeCredentialsFileAtomic(targetPath, data) {
34360
- const fs39 = await import("fs");
34361
- const path46 = await import("path");
34362
- const dir = path46.dirname(targetPath);
34363
- await fs39.promises.mkdir(dir, { recursive: true, mode: 448 });
34360
+ const fs40 = await import("fs");
34361
+ const path48 = await import("path");
34362
+ const dir = path48.dirname(targetPath);
34363
+ await fs40.promises.mkdir(dir, { recursive: true, mode: 448 });
34364
34364
  const tmpPath = `${targetPath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
34365
34365
  try {
34366
- const fh = await fs39.promises.open(tmpPath, "w", 384);
34366
+ const fh = await fs40.promises.open(tmpPath, "w", 384);
34367
34367
  try {
34368
34368
  await fh.writeFile(JSON.stringify(data, null, 2));
34369
34369
  await fh.sync();
34370
34370
  } finally {
34371
34371
  await fh.close();
34372
34372
  }
34373
- await fs39.promises.rename(tmpPath, targetPath);
34373
+ await fs40.promises.rename(tmpPath, targetPath);
34374
34374
  } catch (err) {
34375
- await fs39.promises.unlink(tmpPath).catch(() => {
34375
+ await fs40.promises.unlink(tmpPath).catch(() => {
34376
34376
  });
34377
34377
  throw err;
34378
34378
  }
34379
34379
  try {
34380
- const dirFh = await fs39.promises.open(dir, "r");
34380
+ const dirFh = await fs40.promises.open(dir, "r");
34381
34381
  try {
34382
34382
  await dirFh.sync();
34383
34383
  } finally {
@@ -34679,12 +34679,12 @@ var loadConfigWithSource = async (profile) => {
34679
34679
  return null;
34680
34680
  }
34681
34681
  validateProfileName(profileName);
34682
- const fs39 = await import("fs");
34683
- const path46 = await import("path");
34684
- const configPath = path46.join(rootConfigPath, "configs", `${profileName}.json`);
34682
+ const fs40 = await import("fs");
34683
+ const path48 = await import("path");
34684
+ const configPath = path48.join(rootConfigPath, "configs", `${profileName}.json`);
34685
34685
  let configRaw;
34686
34686
  try {
34687
- configRaw = await fs39.promises.readFile(configPath, "utf-8");
34687
+ configRaw = await fs40.promises.readFile(configPath, "utf-8");
34688
34688
  } catch (err) {
34689
34689
  if (err?.code !== "ENOENT") {
34690
34690
  throw new Error(`failed to read config file ${configPath}: ${err}`);
@@ -34765,14 +34765,14 @@ var getCredentialsPath = async (config2, profile) => {
34765
34765
  return null;
34766
34766
  }
34767
34767
  validateProfileName(profileName);
34768
- const path46 = await import("path");
34769
- return path46.join(rootConfigPath, "credentials", `${profileName}.json`);
34768
+ const path48 = await import("path");
34769
+ return path48.join(rootConfigPath, "credentials", `${profileName}.json`);
34770
34770
  };
34771
34771
  var getRootConfigPath = async () => {
34772
34772
  if (!supportsLocalConfigFiles()) {
34773
34773
  return null;
34774
34774
  }
34775
- const path46 = await import("path");
34775
+ const path48 = await import("path");
34776
34776
  const configDir = readEnv("ANTHROPIC_CONFIG_DIR");
34777
34777
  if (configDir) {
34778
34778
  return configDir;
@@ -34781,21 +34781,21 @@ var getRootConfigPath = async () => {
34781
34781
  if (os13 === "Windows") {
34782
34782
  const appData = readEnv("APPDATA");
34783
34783
  if (appData) {
34784
- return path46.join(appData, "Anthropic");
34784
+ return path48.join(appData, "Anthropic");
34785
34785
  }
34786
34786
  const userProfile = readEnv("USERPROFILE");
34787
34787
  if (userProfile) {
34788
- return path46.join(userProfile, "AppData", "Roaming", "Anthropic");
34788
+ return path48.join(userProfile, "AppData", "Roaming", "Anthropic");
34789
34789
  }
34790
34790
  return null;
34791
34791
  }
34792
34792
  const xdgConfigHome = readEnv("XDG_CONFIG_HOME");
34793
34793
  if (xdgConfigHome) {
34794
- return path46.join(xdgConfigHome, "anthropic");
34794
+ return path48.join(xdgConfigHome, "anthropic");
34795
34795
  }
34796
34796
  const home = readEnv("HOME");
34797
34797
  if (home) {
34798
- return path46.join(home, ".config", "anthropic");
34798
+ return path48.join(home, ".config", "anthropic");
34799
34799
  }
34800
34800
  return null;
34801
34801
  };
@@ -34812,11 +34812,11 @@ var getActiveProfileName = async () => {
34812
34812
  if (profileName) {
34813
34813
  return profileName;
34814
34814
  }
34815
- const fs39 = await import("fs");
34816
- const path46 = await import("path");
34817
- const filePath = path46.join(rootConfigPath, "active_config");
34815
+ const fs40 = await import("fs");
34816
+ const path48 = await import("path");
34817
+ const filePath = path48.join(rootConfigPath, "active_config");
34818
34818
  try {
34819
- return (await fs39.promises.readFile(filePath, "utf-8")).trim() || "default";
34819
+ return (await fs40.promises.readFile(filePath, "utf-8")).trim() || "default";
34820
34820
  } catch (err) {
34821
34821
  if (err?.code !== "ENOENT") {
34822
34822
  throw new Error(`failed to read ${filePath}: ${err}`);
@@ -34827,21 +34827,21 @@ var getActiveProfileName = async () => {
34827
34827
 
34828
34828
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.94.0_zod@4.4.3/node_modules/@anthropic-ai/sdk/lib/credentials/identity-token.mjs
34829
34829
  init_esm_shims();
34830
- function identityTokenFromFile(path46) {
34831
- if (!path46) {
34830
+ function identityTokenFromFile(path48) {
34831
+ if (!path48) {
34832
34832
  throw new AnthropicError("Identity token file path is empty");
34833
34833
  }
34834
34834
  return async () => {
34835
- const fs39 = await import("fs");
34835
+ const fs40 = await import("fs");
34836
34836
  let content;
34837
34837
  try {
34838
- content = await fs39.promises.readFile(path46, "utf-8");
34838
+ content = await fs40.promises.readFile(path48, "utf-8");
34839
34839
  } catch (err) {
34840
- throw new AnthropicError(`Failed to read identity token file at ${path46}: ${err}`);
34840
+ throw new AnthropicError(`Failed to read identity token file at ${path48}: ${err}`);
34841
34841
  }
34842
34842
  const token = content.trim();
34843
34843
  if (!token) {
34844
- throw new AnthropicError(`Identity token file at ${path46} is empty`);
34844
+ throw new AnthropicError(`Identity token file at ${path48} is empty`);
34845
34845
  }
34846
34846
  return token;
34847
34847
  };
@@ -34916,11 +34916,11 @@ function oidcFederationProvider(config2) {
34916
34916
  init_esm_shims();
34917
34917
  function userOAuthProvider(config2) {
34918
34918
  return async (opts) => {
34919
- const fs39 = await import("fs");
34919
+ const fs40 = await import("fs");
34920
34920
  await checkCredentialsFileSafety(config2.credentialsPath, config2.onSafetyWarning);
34921
34921
  let raw;
34922
34922
  try {
34923
- raw = await fs39.promises.readFile(config2.credentialsPath, "utf-8");
34923
+ raw = await fs40.promises.readFile(config2.credentialsPath, "utf-8");
34924
34924
  } catch (err) {
34925
34925
  throw new WorkloadIdentityError(`Credentials file not found at ${config2.credentialsPath}: ${err}`);
34926
34926
  }
@@ -35084,11 +35084,11 @@ function resolveIdentityTokenProvider(auth2) {
35084
35084
  }
35085
35085
  function cachedExchangeProvider(exchange, credentialsPath, onCacheWriteError, onSafetyWarning) {
35086
35086
  return async (opts) => {
35087
- const fs39 = await import("fs");
35087
+ const fs40 = await import("fs");
35088
35088
  await checkCredentialsFileSafety(credentialsPath, onSafetyWarning);
35089
35089
  let existing;
35090
35090
  try {
35091
- const raw = await fs39.promises.readFile(credentialsPath, "utf-8");
35091
+ const raw = await fs40.promises.readFile(credentialsPath, "utf-8");
35092
35092
  existing = JSON.parse(raw);
35093
35093
  const token = existing?.["access_token"];
35094
35094
  if (token && !opts?.forceRefresh) {
@@ -35927,12 +35927,12 @@ function encodeURIPath(str2) {
35927
35927
  return str2.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
35928
35928
  }
35929
35929
  var EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
35930
- var createPathTagFunction = (pathEncoder = encodeURIPath) => function path46(statics, ...params) {
35930
+ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path48(statics, ...params) {
35931
35931
  if (statics.length === 1)
35932
35932
  return statics[0];
35933
35933
  let postPath = false;
35934
35934
  const invalidSegments = [];
35935
- const path47 = statics.reduce((previousValue, currentValue, index) => {
35935
+ const path49 = statics.reduce((previousValue, currentValue, index) => {
35936
35936
  if (/[?#]/.test(currentValue)) {
35937
35937
  postPath = true;
35938
35938
  }
@@ -35949,7 +35949,7 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path46(sta
35949
35949
  }
35950
35950
  return previousValue + currentValue + (index === params.length ? "" : encoded);
35951
35951
  }, "");
35952
- const pathOnly = path47.split(/[?#]/, 1)[0];
35952
+ const pathOnly = path49.split(/[?#]/, 1)[0];
35953
35953
  const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
35954
35954
  let match;
35955
35955
  while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
@@ -35970,10 +35970,10 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path46(sta
35970
35970
  }, "");
35971
35971
  throw new AnthropicError(`Path parameters result in path with invalid segments:
35972
35972
  ${invalidSegments.map((e) => e.error).join("\n")}
35973
- ${path47}
35973
+ ${path49}
35974
35974
  ${underline}`);
35975
35975
  }
35976
- return path47;
35976
+ return path49;
35977
35977
  };
35978
35978
  var path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
35979
35979
 
@@ -40734,9 +40734,9 @@ var BaseAnthropic = class {
40734
40734
  makeStatusError(status, error51, message, headers) {
40735
40735
  return APIError.generate(status, error51, message, headers);
40736
40736
  }
40737
- buildURL(path46, query, defaultBaseURL) {
40737
+ buildURL(path48, query, defaultBaseURL) {
40738
40738
  const baseURL = !__classPrivateFieldGet(this, _BaseAnthropic_instances, "m", _BaseAnthropic_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
40739
- const url2 = isAbsoluteURL(path46) ? new URL(path46) : new URL(baseURL + (baseURL.endsWith("/") && path46.startsWith("/") ? path46.slice(1) : path46));
40739
+ const url2 = isAbsoluteURL(path48) ? new URL(path48) : new URL(baseURL + (baseURL.endsWith("/") && path48.startsWith("/") ? path48.slice(1) : path48));
40740
40740
  const defaultQuery = this.defaultQuery();
40741
40741
  const pathQuery = Object.fromEntries(url2.searchParams);
40742
40742
  if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) {
@@ -40780,24 +40780,24 @@ var BaseAnthropic = class {
40780
40780
  request.headers = headers;
40781
40781
  }
40782
40782
  }
40783
- get(path46, opts) {
40784
- return this.methodRequest("get", path46, opts);
40783
+ get(path48, opts) {
40784
+ return this.methodRequest("get", path48, opts);
40785
40785
  }
40786
- post(path46, opts) {
40787
- return this.methodRequest("post", path46, opts);
40786
+ post(path48, opts) {
40787
+ return this.methodRequest("post", path48, opts);
40788
40788
  }
40789
- patch(path46, opts) {
40790
- return this.methodRequest("patch", path46, opts);
40789
+ patch(path48, opts) {
40790
+ return this.methodRequest("patch", path48, opts);
40791
40791
  }
40792
- put(path46, opts) {
40793
- return this.methodRequest("put", path46, opts);
40792
+ put(path48, opts) {
40793
+ return this.methodRequest("put", path48, opts);
40794
40794
  }
40795
- delete(path46, opts) {
40796
- return this.methodRequest("delete", path46, opts);
40795
+ delete(path48, opts) {
40796
+ return this.methodRequest("delete", path48, opts);
40797
40797
  }
40798
- methodRequest(method, path46, opts) {
40798
+ methodRequest(method, path48, opts) {
40799
40799
  return this.request(Promise.resolve(opts).then((opts2) => {
40800
- return { method, path: path46, ...opts2 };
40800
+ return { method, path: path48, ...opts2 };
40801
40801
  }));
40802
40802
  }
40803
40803
  request(options, remainingRetries = null) {
@@ -40902,8 +40902,8 @@ var BaseAnthropic = class {
40902
40902
  }));
40903
40903
  return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
40904
40904
  }
40905
- getAPIList(path46, Page3, opts) {
40906
- return this.requestAPIList(Page3, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path46, ...opts2 })) : { method: "get", path: path46, ...opts });
40905
+ getAPIList(path48, Page3, opts) {
40906
+ return this.requestAPIList(Page3, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path48, ...opts2 })) : { method: "get", path: path48, ...opts });
40907
40907
  }
40908
40908
  requestAPIList(Page3, options) {
40909
40909
  const request = this.makeRequest(options, null, void 0);
@@ -40997,14 +40997,14 @@ var BaseAnthropic = class {
40997
40997
  }
40998
40998
  async buildRequest(inputOptions, { retryCount = 0 } = {}) {
40999
40999
  const options = { ...inputOptions };
41000
- const { method, path: path46, query, defaultBaseURL } = options;
41000
+ const { method, path: path48, query, defaultBaseURL } = options;
41001
41001
  if (this._authState.resolution) {
41002
41002
  await this._authState.resolution;
41003
41003
  }
41004
41004
  if (!this._baseURLIsExplicit && this._authState.baseURL && this.baseURL !== this._authState.baseURL) {
41005
41005
  this.baseURL = this._authState.baseURL;
41006
41006
  }
41007
- const url2 = this.buildURL(path46, query, defaultBaseURL);
41007
+ const url2 = this.buildURL(path48, query, defaultBaseURL);
41008
41008
  if ("timeout" in options)
41009
41009
  validatePositiveInteger("timeout", options.timeout);
41010
41010
  options.timeout = options.timeout ?? this.timeout;
@@ -41891,10 +41891,10 @@ function mergeDefs(...defs) {
41891
41891
  function cloneDef(schema) {
41892
41892
  return mergeDefs(schema._zod.def);
41893
41893
  }
41894
- function getElementAtPath(obj, path46) {
41895
- if (!path46)
41894
+ function getElementAtPath(obj, path48) {
41895
+ if (!path48)
41896
41896
  return obj;
41897
- return path46.reduce((acc, key) => acc?.[key], obj);
41897
+ return path48.reduce((acc, key) => acc?.[key], obj);
41898
41898
  }
41899
41899
  function promiseAllObject(promisesObj) {
41900
41900
  const keys = Object.keys(promisesObj);
@@ -42303,11 +42303,11 @@ function explicitlyAborted(x, startIndex = 0) {
42303
42303
  }
42304
42304
  return false;
42305
42305
  }
42306
- function prefixIssues(path46, issues) {
42306
+ function prefixIssues(path48, issues) {
42307
42307
  return issues.map((iss) => {
42308
42308
  var _a6;
42309
42309
  (_a6 = iss).path ?? (_a6.path = []);
42310
- iss.path.unshift(path46);
42310
+ iss.path.unshift(path48);
42311
42311
  return iss;
42312
42312
  });
42313
42313
  }
@@ -42454,16 +42454,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
42454
42454
  }
42455
42455
  function formatError(error51, mapper = (issue2) => issue2.message) {
42456
42456
  const fieldErrors = { _errors: [] };
42457
- const processError = (error52, path46 = []) => {
42457
+ const processError = (error52, path48 = []) => {
42458
42458
  for (const issue2 of error52.issues) {
42459
42459
  if (issue2.code === "invalid_union" && issue2.errors.length) {
42460
- issue2.errors.map((issues) => processError({ issues }, [...path46, ...issue2.path]));
42460
+ issue2.errors.map((issues) => processError({ issues }, [...path48, ...issue2.path]));
42461
42461
  } else if (issue2.code === "invalid_key") {
42462
- processError({ issues: issue2.issues }, [...path46, ...issue2.path]);
42462
+ processError({ issues: issue2.issues }, [...path48, ...issue2.path]);
42463
42463
  } else if (issue2.code === "invalid_element") {
42464
- processError({ issues: issue2.issues }, [...path46, ...issue2.path]);
42464
+ processError({ issues: issue2.issues }, [...path48, ...issue2.path]);
42465
42465
  } else {
42466
- const fullpath = [...path46, ...issue2.path];
42466
+ const fullpath = [...path48, ...issue2.path];
42467
42467
  if (fullpath.length === 0) {
42468
42468
  fieldErrors._errors.push(mapper(issue2));
42469
42469
  } else {
@@ -42490,17 +42490,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
42490
42490
  }
42491
42491
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
42492
42492
  const result = { errors: [] };
42493
- const processError = (error52, path46 = []) => {
42493
+ const processError = (error52, path48 = []) => {
42494
42494
  var _a6, _b;
42495
42495
  for (const issue2 of error52.issues) {
42496
42496
  if (issue2.code === "invalid_union" && issue2.errors.length) {
42497
- issue2.errors.map((issues) => processError({ issues }, [...path46, ...issue2.path]));
42497
+ issue2.errors.map((issues) => processError({ issues }, [...path48, ...issue2.path]));
42498
42498
  } else if (issue2.code === "invalid_key") {
42499
- processError({ issues: issue2.issues }, [...path46, ...issue2.path]);
42499
+ processError({ issues: issue2.issues }, [...path48, ...issue2.path]);
42500
42500
  } else if (issue2.code === "invalid_element") {
42501
- processError({ issues: issue2.issues }, [...path46, ...issue2.path]);
42501
+ processError({ issues: issue2.issues }, [...path48, ...issue2.path]);
42502
42502
  } else {
42503
- const fullpath = [...path46, ...issue2.path];
42503
+ const fullpath = [...path48, ...issue2.path];
42504
42504
  if (fullpath.length === 0) {
42505
42505
  result.errors.push(mapper(issue2));
42506
42506
  continue;
@@ -42532,8 +42532,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
42532
42532
  }
42533
42533
  function toDotPath(_path) {
42534
42534
  const segs = [];
42535
- const path46 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
42536
- for (const seg of path46) {
42535
+ const path48 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
42536
+ for (const seg of path48) {
42537
42537
  if (typeof seg === "number")
42538
42538
  segs.push(`[${seg}]`);
42539
42539
  else if (typeof seg === "symbol")
@@ -55306,13 +55306,13 @@ function resolveRef(ref, ctx) {
55306
55306
  if (!ref.startsWith("#")) {
55307
55307
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
55308
55308
  }
55309
- const path46 = ref.slice(1).split("/").filter(Boolean);
55310
- if (path46.length === 0) {
55309
+ const path48 = ref.slice(1).split("/").filter(Boolean);
55310
+ if (path48.length === 0) {
55311
55311
  return ctx.rootSchema;
55312
55312
  }
55313
55313
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
55314
- if (path46[0] === defsKey) {
55315
- const key = path46[1];
55314
+ if (path48[0] === defsKey) {
55315
+ const key = path48[1];
55316
55316
  if (!key || !ctx.defs[key]) {
55317
55317
  throw new Error(`Reference not found: ${ref}`);
55318
55318
  }
@@ -55749,13 +55749,13 @@ function __classPrivateFieldGet2(receiver, state3, kind, f) {
55749
55749
  // ../../node_modules/.pnpm/openai@6.34.0_ws@8.20.0_zod@4.4.3/node_modules/openai/internal/utils/uuid.mjs
55750
55750
  init_esm_shims();
55751
55751
  var uuid43 = function() {
55752
- const { crypto: crypto12 } = globalThis;
55753
- if (crypto12?.randomUUID) {
55754
- uuid43 = crypto12.randomUUID.bind(crypto12);
55755
- return crypto12.randomUUID();
55752
+ const { crypto: crypto13 } = globalThis;
55753
+ if (crypto13?.randomUUID) {
55754
+ uuid43 = crypto13.randomUUID.bind(crypto13);
55755
+ return crypto13.randomUUID();
55756
55756
  }
55757
55757
  const u8 = new Uint8Array(1);
55758
- const randomByte = crypto12 ? () => crypto12.getRandomValues(u8)[0] : () => Math.random() * 255 & 255;
55758
+ const randomByte = crypto13 ? () => crypto13.getRandomValues(u8)[0] : () => Math.random() * 255 & 255;
55759
55759
  return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c2) => (+c2 ^ randomByte() & 15 >> +c2 / 4).toString(16));
55760
55760
  };
55761
55761
 
@@ -57541,12 +57541,12 @@ function encodeURIPath2(str2) {
57541
57541
  return str2.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
57542
57542
  }
57543
57543
  var EMPTY2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
57544
- var createPathTagFunction2 = (pathEncoder = encodeURIPath2) => function path46(statics, ...params) {
57544
+ var createPathTagFunction2 = (pathEncoder = encodeURIPath2) => function path48(statics, ...params) {
57545
57545
  if (statics.length === 1)
57546
57546
  return statics[0];
57547
57547
  let postPath = false;
57548
57548
  const invalidSegments = [];
57549
- const path47 = statics.reduce((previousValue, currentValue, index) => {
57549
+ const path49 = statics.reduce((previousValue, currentValue, index) => {
57550
57550
  if (/[?#]/.test(currentValue)) {
57551
57551
  postPath = true;
57552
57552
  }
@@ -57563,7 +57563,7 @@ var createPathTagFunction2 = (pathEncoder = encodeURIPath2) => function path46(s
57563
57563
  }
57564
57564
  return previousValue + currentValue + (index === params.length ? "" : encoded);
57565
57565
  }, "");
57566
- const pathOnly = path47.split(/[?#]/, 1)[0];
57566
+ const pathOnly = path49.split(/[?#]/, 1)[0];
57567
57567
  const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
57568
57568
  let match;
57569
57569
  while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
@@ -57584,10 +57584,10 @@ var createPathTagFunction2 = (pathEncoder = encodeURIPath2) => function path46(s
57584
57584
  }, "");
57585
57585
  throw new OpenAIError(`Path parameters result in path with invalid segments:
57586
57586
  ${invalidSegments.map((e) => e.error).join("\n")}
57587
- ${path47}
57587
+ ${path49}
57588
57588
  ${underline}`);
57589
57589
  }
57590
- return path47;
57590
+ return path49;
57591
57591
  };
57592
57592
  var path2 = /* @__PURE__ */ createPathTagFunction2(encodeURIPath2);
57593
57593
 
@@ -62713,9 +62713,9 @@ var OpenAI = class {
62713
62713
  this.apiKey = token;
62714
62714
  return true;
62715
62715
  }
62716
- buildURL(path46, query, defaultBaseURL) {
62716
+ buildURL(path48, query, defaultBaseURL) {
62717
62717
  const baseURL = !__classPrivateFieldGet2(this, _OpenAI_instances, "m", _OpenAI_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
62718
- const url2 = isAbsoluteURL2(path46) ? new URL(path46) : new URL(baseURL + (baseURL.endsWith("/") && path46.startsWith("/") ? path46.slice(1) : path46));
62718
+ const url2 = isAbsoluteURL2(path48) ? new URL(path48) : new URL(baseURL + (baseURL.endsWith("/") && path48.startsWith("/") ? path48.slice(1) : path48));
62719
62719
  const defaultQuery = this.defaultQuery();
62720
62720
  const pathQuery = Object.fromEntries(url2.searchParams);
62721
62721
  if (!isEmptyObj2(defaultQuery) || !isEmptyObj2(pathQuery)) {
@@ -62740,24 +62740,24 @@ var OpenAI = class {
62740
62740
  */
62741
62741
  async prepareRequest(request, { url: url2, options }) {
62742
62742
  }
62743
- get(path46, opts) {
62744
- return this.methodRequest("get", path46, opts);
62743
+ get(path48, opts) {
62744
+ return this.methodRequest("get", path48, opts);
62745
62745
  }
62746
- post(path46, opts) {
62747
- return this.methodRequest("post", path46, opts);
62746
+ post(path48, opts) {
62747
+ return this.methodRequest("post", path48, opts);
62748
62748
  }
62749
- patch(path46, opts) {
62750
- return this.methodRequest("patch", path46, opts);
62749
+ patch(path48, opts) {
62750
+ return this.methodRequest("patch", path48, opts);
62751
62751
  }
62752
- put(path46, opts) {
62753
- return this.methodRequest("put", path46, opts);
62752
+ put(path48, opts) {
62753
+ return this.methodRequest("put", path48, opts);
62754
62754
  }
62755
- delete(path46, opts) {
62756
- return this.methodRequest("delete", path46, opts);
62755
+ delete(path48, opts) {
62756
+ return this.methodRequest("delete", path48, opts);
62757
62757
  }
62758
- methodRequest(method, path46, opts) {
62758
+ methodRequest(method, path48, opts) {
62759
62759
  return this.request(Promise.resolve(opts).then((opts2) => {
62760
- return { method, path: path46, ...opts2 };
62760
+ return { method, path: path48, ...opts2 };
62761
62761
  }));
62762
62762
  }
62763
62763
  request(options, remainingRetries = null) {
@@ -62875,8 +62875,8 @@ var OpenAI = class {
62875
62875
  }));
62876
62876
  return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
62877
62877
  }
62878
- getAPIList(path46, Page3, opts) {
62879
- return this.requestAPIList(Page3, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path46, ...opts2 })) : { method: "get", path: path46, ...opts });
62878
+ getAPIList(path48, Page3, opts) {
62879
+ return this.requestAPIList(Page3, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path48, ...opts2 })) : { method: "get", path: path48, ...opts });
62880
62880
  }
62881
62881
  requestAPIList(Page3, options) {
62882
62882
  const request = this.makeRequest(options, null, void 0);
@@ -62967,8 +62967,8 @@ var OpenAI = class {
62967
62967
  }
62968
62968
  async buildRequest(inputOptions, { retryCount = 0 } = {}) {
62969
62969
  const options = { ...inputOptions };
62970
- const { method, path: path46, query, defaultBaseURL } = options;
62971
- const url2 = this.buildURL(path46, query, defaultBaseURL);
62970
+ const { method, path: path48, query, defaultBaseURL } = options;
62971
+ const url2 = this.buildURL(path48, query, defaultBaseURL);
62972
62972
  if ("timeout" in options)
62973
62973
  validatePositiveInteger2("timeout", options.timeout);
62974
62974
  options.timeout = options.timeout ?? this.timeout;
@@ -63372,7 +63372,7 @@ var EventStream2 = class {
63372
63372
  }
63373
63373
  }
63374
63374
  };
63375
- var StreamResult = class {
63375
+ var StreamResult = class _StreamResult {
63376
63376
  response;
63377
63377
  buffer = [];
63378
63378
  done = false;
@@ -63380,6 +63380,18 @@ var StreamResult = class {
63380
63380
  resolveResponse;
63381
63381
  rejectResponse;
63382
63382
  resolveWait = null;
63383
+ /**
63384
+ * High-water mark: when the buffer exceeds this many unconsumed events,
63385
+ * the pump pauses until the consumer drains below the low-water mark.
63386
+ * Prevents unbounded memory growth when a consumer is slow.
63387
+ * Only active when someone IS iterating — if nobody iterates (the `then()`
63388
+ * path), backpressure is skipped so the pump can complete and resolve.
63389
+ */
63390
+ static HIGH_WATER = 5e3;
63391
+ static LOW_WATER = 1e3;
63392
+ iterating = false;
63393
+ paused = false;
63394
+ resolveDrain = null;
63383
63395
  constructor(generator, signal) {
63384
63396
  this.response = new Promise((resolve2, reject) => {
63385
63397
  this.resolveResponse = resolve2;
@@ -63394,6 +63406,13 @@ var StreamResult = class {
63394
63406
  this.buffer.push(next.value);
63395
63407
  this.resolveWait?.();
63396
63408
  this.resolveWait = null;
63409
+ if (this.iterating && this.buffer.length > _StreamResult.HIGH_WATER) {
63410
+ this.paused = true;
63411
+ await new Promise((r2) => {
63412
+ this.resolveDrain = r2;
63413
+ });
63414
+ this.paused = false;
63415
+ }
63397
63416
  next = await this._nextWithAbort(generator, signal);
63398
63417
  }
63399
63418
  this.done = true;
@@ -63432,11 +63451,20 @@ var StreamResult = class {
63432
63451
  }
63433
63452
  }
63434
63453
  async *[Symbol.asyncIterator]() {
63454
+ this.iterating = true;
63435
63455
  let index = 0;
63436
63456
  while (true) {
63437
63457
  while (index < this.buffer.length) {
63438
63458
  yield this.buffer[index++];
63439
63459
  }
63460
+ if (this.paused && index > _StreamResult.LOW_WATER) {
63461
+ this.resolveDrain?.();
63462
+ this.resolveDrain = null;
63463
+ }
63464
+ if (index > 0 && !this.paused) {
63465
+ this.buffer.splice(0, index);
63466
+ index = 0;
63467
+ }
63440
63468
  if (this.error) throw this.error;
63441
63469
  if (this.done) return;
63442
63470
  await new Promise((r2) => {
@@ -63449,13 +63477,23 @@ var StreamResult = class {
63449
63477
  }
63450
63478
  }
63451
63479
  then(onfulfilled, onrejected) {
63480
+ if (this.paused) {
63481
+ this.paused = false;
63482
+ this.resolveDrain?.();
63483
+ this.resolveDrain = null;
63484
+ }
63452
63485
  return this.response.then(onfulfilled, onrejected);
63453
63486
  }
63454
63487
  };
63488
+ var schemaCache = /* @__PURE__ */ new WeakMap();
63455
63489
  function zodToJsonSchema(schema) {
63490
+ const cached4 = schemaCache.get(schema);
63491
+ if (cached4) return cached4;
63456
63492
  const jsonSchema = external_exports.toJSONSchema(schema);
63457
63493
  const { $schema: _schema, ...rest } = jsonSchema;
63458
- return normalizeRootForAnthropic(rest);
63494
+ const normalized = normalizeRootForAnthropic(rest);
63495
+ schemaCache.set(schema, normalized);
63496
+ return normalized;
63459
63497
  }
63460
63498
  function resolveToolSchema(tool) {
63461
63499
  return tool.rawInputSchema ?? zodToJsonSchema(tool.parameters);
@@ -64057,26 +64095,83 @@ function parseToolArguments(argsJson) {
64057
64095
  return {};
64058
64096
  }
64059
64097
  }
64098
+ var anthropicClientCache = /* @__PURE__ */ new Map();
64060
64099
  function createClient(options) {
64061
64100
  const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
64062
- return new Anthropic({
64101
+ const userAgent = isOAuth ? options.userAgent ?? "claude-cli/2.1.75 (external, cli)" : "";
64102
+ const cacheKey = `${options.apiKey ?? ""}|${options.baseUrl ?? ""}|${userAgent}`;
64103
+ if (!options.fetch) {
64104
+ const cached4 = anthropicClientCache.get(cacheKey);
64105
+ if (cached4) return cached4;
64106
+ }
64107
+ const client = new Anthropic({
64063
64108
  ...isOAuth ? { apiKey: null, authToken: options.apiKey } : { apiKey: options.apiKey },
64064
64109
  ...options.baseUrl ? { baseURL: options.baseUrl } : {},
64065
64110
  ...options.fetch ? { fetch: options.fetch } : {},
64066
- // Disable SDK retries — the agent loop has its own stall/overload retry
64067
- // logic that surfaces errors properly. SDK retries on 429s can cause
64068
- // multi-minute hangs when the provider stops responding mid-retry.
64069
64111
  maxRetries: 0,
64070
64112
  ...isOAuth ? {
64071
64113
  defaultHeaders: {
64072
- // Anthropic's OAuth edge validates the claude-cli version. Callers
64073
- // (ggcoder) resolve the live version at runtime; the literal here
64074
- // is the offline fallback for direct gg-ai consumers.
64075
- "user-agent": options.userAgent ?? "claude-cli/2.1.75 (external, cli)",
64114
+ "user-agent": userAgent,
64076
64115
  "x-app": "cli"
64077
64116
  }
64078
64117
  } : {}
64079
64118
  });
64119
+ if (!options.fetch) {
64120
+ if (anthropicClientCache.size >= 8) {
64121
+ const oldest = anthropicClientCache.keys().next().value;
64122
+ if (oldest) anthropicClientCache.delete(oldest);
64123
+ }
64124
+ anthropicClientCache.set(cacheKey, client);
64125
+ }
64126
+ return client;
64127
+ }
64128
+ async function prewarmAnthropicCache(options) {
64129
+ try {
64130
+ const client = createClient({
64131
+ apiKey: options.apiKey,
64132
+ baseUrl: options.baseUrl,
64133
+ userAgent: options.userAgent
64134
+ });
64135
+ const cacheControl = toAnthropicCacheControl(options.cacheRetention ?? "long", options.baseUrl);
64136
+ const { system, messages } = toAnthropicMessages(
64137
+ [
64138
+ { role: "system", content: options.system },
64139
+ { role: "user", content: "." }
64140
+ ],
64141
+ cacheControl
64142
+ );
64143
+ const isOAuth = options.apiKey.startsWith("sk-ant-oat");
64144
+ const fullSystem = isOAuth ? [
64145
+ {
64146
+ type: "text",
64147
+ text: "You are Claude Code, Anthropic's official CLI for Claude."
64148
+ },
64149
+ ...system ?? []
64150
+ ] : system;
64151
+ const tools = options.tools?.length ? toAnthropicTools(options.tools, {
64152
+ cacheControl,
64153
+ enableFineGrainedToolStreaming: true
64154
+ }) : void 0;
64155
+ await client.messages.create(
64156
+ {
64157
+ model: options.model,
64158
+ max_tokens: 1,
64159
+ messages,
64160
+ ...fullSystem ? { system: fullSystem } : {},
64161
+ ...tools ? {
64162
+ tools: [
64163
+ ...tools,
64164
+ ...options.serverTools ?? []
64165
+ ]
64166
+ } : {}
64167
+ },
64168
+ {
64169
+ signal: options.signal ?? void 0,
64170
+ ...isOAuth ? { headers: { "anthropic-beta": "claude-code-20250219,oauth-2025-04-20" } } : {}
64171
+ }
64172
+ );
64173
+ } catch {
64174
+ }
64080
64175
  }
64081
64176
  function streamAnthropic(options) {
64082
64177
  return new StreamResult(runStream(options), options.signal);
@@ -64640,13 +64735,27 @@ function extractOpenAIUsage(usage) {
64640
64735
  cacheRead
64641
64736
  };
64642
64737
  }
64738
+ var openaiClientCache = /* @__PURE__ */ new Map();
64643
64739
  function createClient2(options) {
64644
- return new OpenAI({
64740
+ const cacheKey = `${options.apiKey ?? ""}|${options.baseUrl ?? ""}|${JSON.stringify(options.defaultHeaders ?? {})}`;
64741
+ if (!options.fetch) {
64742
+ const cached4 = openaiClientCache.get(cacheKey);
64743
+ if (cached4) return cached4;
64744
+ }
64745
+ const client = new OpenAI({
64645
64746
  apiKey: options.apiKey,
64646
64747
  ...options.baseUrl ? { baseURL: options.baseUrl } : {},
64647
64748
  ...options.fetch ? { fetch: options.fetch } : {},
64648
64749
  ...options.defaultHeaders ? { defaultHeaders: options.defaultHeaders } : {}
64649
64750
  });
64751
+ if (!options.fetch) {
64752
+ if (openaiClientCache.size >= 8) {
64753
+ const oldest = openaiClientCache.keys().next().value;
64754
+ if (oldest) openaiClientCache.delete(oldest);
64755
+ }
64756
+ openaiClientCache.set(cacheKey, client);
64757
+ }
64758
+ return client;
64650
64759
  }
64651
64760
  function streamOpenAI(options) {
64652
64761
  return new StreamResult(runStream2(options), options.signal);
@@ -64704,11 +64813,11 @@ async function* runStream2(options) {
64704
64813
  }
64705
64814
  }
64706
64815
  if (getEnvironment()?.GGAI_DUMP_REQUEST) {
64707
- const fs39 = await import("fs");
64816
+ const fs40 = await import("fs");
64708
64817
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
64709
64818
  const dumpPath = `/tmp/ggai-request-${ts}.json`;
64710
- fs39.writeFileSync(dumpPath, JSON.stringify(params, null, 2));
64711
- fs39.appendFileSync(
64819
+ fs40.writeFileSync(dumpPath, JSON.stringify(params, null, 2));
64820
+ fs40.appendFileSync(
64712
64821
  "/tmp/ggai-requests.log",
64713
64822
  `[${ts}] ${dumpPath} messages=${params.messages.length}
64714
64823
  `
@@ -65052,9 +65161,6 @@ async function* runStream3(options) {
65052
65161
  body.tools = toCodexTools(options.tools);
65053
65162
  }
65054
65163
  body.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ggcoder");
65055
- if (options.cacheRetention === "long") {
65056
- body.prompt_cache_retention = "24h";
65057
- }
65058
65164
  if (options.temperature != null && !options.thinking) {
65059
65165
  body.temperature = options.temperature;
65060
65166
  }
@@ -66407,23 +66513,25 @@ async function* agentLoop(messages, options) {
66407
66513
  while (turn < maxTurns) {
66408
66514
  options.signal?.throwIfAborted();
66409
66515
  turn++;
66410
- let msgChars = 0;
66411
- for (const m of messages) {
66412
- if (typeof m.content === "string") msgChars += m.content.length;
66413
- else if (Array.isArray(m.content)) {
66414
- for (const p of m.content) {
66415
- if ("text" in p && typeof p.text === "string") msgChars += p.text.length;
66416
- if ("content" in p && typeof p.content === "string") msgChars += p.content.length;
66516
+ if (_diagFn2) {
66517
+ let msgChars = 0;
66518
+ for (const m of messages) {
66519
+ if (typeof m.content === "string") msgChars += m.content.length;
66520
+ else if (Array.isArray(m.content)) {
66521
+ for (const p of m.content) {
66522
+ if ("text" in p && typeof p.text === "string") msgChars += p.text.length;
66523
+ if ("content" in p && typeof p.content === "string") msgChars += p.content.length;
66524
+ }
66417
66525
  }
66418
66526
  }
66527
+ diag("turn_start", {
66528
+ turn,
66529
+ messages: messages.length,
66530
+ chars: msgChars,
66531
+ provider: options.provider,
66532
+ model: options.model
66533
+ });
66419
66534
  }
66420
- diag("turn_start", {
66421
- turn,
66422
- messages: messages.length,
66423
- chars: msgChars,
66424
- provider: options.provider,
66425
- model: options.model
66426
- });
66427
66535
  if (firstTurn && options.getSteeringMessages) {
66428
66536
  const steering = await options.getSteeringMessages();
66429
66537
  if (steering && steering.length > 0) {
@@ -66959,7 +67067,7 @@ async function* agentLoop(messages, options) {
66959
67067
  const hasSequentialToolCall = toolCalls.some(
66960
67068
  (toolCall) => toolMap.get(toolCall.name)?.executionMode === "sequential"
66961
67069
  );
66962
- const executionResult = hasSequentialToolCall ? yield* executeToolCallsSequential(toolCalls, toolResults, executionOptions) : yield* executeToolCallsParallel(toolCalls, toolResults, executionOptions);
67070
+ const executionResult = hasSequentialToolCall ? yield* executeToolCallsMixed(toolCalls, toolResults, executionOptions) : yield* executeToolCallsParallel(toolCalls, toolResults, executionOptions);
66963
67071
  messages.push({ role: "tool", content: executionResult.toolResults });
66964
67072
  const toolsAborted = executionResult.aborted;
66965
67073
  if (fatalToolArgumentError) {
@@ -67019,8 +67127,10 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
67019
67127
  } else {
67020
67128
  try {
67021
67129
  const parsed = tool.parameters.parse(toolCall.args);
67130
+ const callerSignal = options.signal;
67131
+ const toolTimeout = AbortSignal.timeout(3e5);
67022
67132
  const ctx = {
67023
- signal: options.signal ?? AbortSignal.timeout(3e5),
67133
+ signal: callerSignal ? AbortSignal.any([callerSignal, toolTimeout]) : toolTimeout,
67024
67134
  toolCallId: toolCall.id,
67025
67135
  onUpdate: (update) => {
67026
67136
  pushEvent({
@@ -67069,22 +67179,59 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
67069
67179
  });
67070
67180
  return { toolCallId: toolCall.id, content: resultContent, isError };
67071
67181
  }
67072
- async function* executeToolCallsSequential(toolCalls, initialToolResults, options) {
67182
+ async function* executeToolCallsMixed(toolCalls, initialToolResults, options) {
67073
67183
  const eventStream = new EventStream2();
67074
67184
  const state3 = { finalized: false };
67075
67185
  const resultsById = /* @__PURE__ */ new Map();
67076
67186
  const abortHandler = () => eventStream.abort(new Error("aborted"));
67077
67187
  options.signal?.addEventListener("abort", abortHandler, { once: true });
67188
+ const phases = [];
67189
+ let currentParallel = [];
67190
+ for (const toolCall of toolCalls) {
67191
+ const isSequential = options.toolMap.get(toolCall.name)?.executionMode === "sequential";
67192
+ if (isSequential) {
67193
+ if (currentParallel.length > 0) {
67194
+ phases.push({ parallel: currentParallel, sequential: null });
67195
+ currentParallel = [];
67196
+ }
67197
+ phases.push({ parallel: [], sequential: toolCall });
67198
+ } else {
67199
+ currentParallel.push(toolCall);
67200
+ }
67201
+ }
67202
+ if (currentParallel.length > 0) {
67203
+ phases.push({ parallel: currentParallel, sequential: null });
67204
+ }
67078
67205
  void (async () => {
67079
67206
  try {
67080
- for (const toolCall of toolCalls) {
67207
+ for (const phase of phases) {
67081
67208
  if (options.signal?.aborted) break;
67082
- const record2 = await executeSingleToolCall(
67083
- toolCall,
67084
- options,
67085
- (event) => pushToolEvent(eventStream, state3, event)
67086
- );
67087
- resultsById.set(record2.toolCallId, record2);
67209
+ if (phase.sequential) {
67210
+ const record2 = await executeSingleToolCall(
67211
+ phase.sequential,
67212
+ options,
67213
+ (event) => pushToolEvent(eventStream, state3, event)
67214
+ );
67215
+ resultsById.set(record2.toolCallId, record2);
67216
+ } else if (phase.parallel.length === 1) {
67217
+ const record2 = await executeSingleToolCall(
67218
+ phase.parallel[0],
67219
+ options,
67220
+ (event) => pushToolEvent(eventStream, state3, event)
67221
+ );
67222
+ resultsById.set(record2.toolCallId, record2);
67223
+ } else {
67224
+ await Promise.all(
67225
+ phase.parallel.map(async (toolCall) => {
67226
+ const record2 = await executeSingleToolCall(
67227
+ toolCall,
67228
+ options,
67229
+ (event) => pushToolEvent(eventStream, state3, event)
67230
+ );
67231
+ resultsById.set(record2.toolCallId, record2);
67232
+ })
67233
+ );
67234
+ }
67088
67235
  }
67089
67236
  if (!state3.finalized) eventStream.close();
67090
67237
  } catch (err) {
@@ -67799,7 +67946,7 @@ function getSummaryModel(provider, currentModelId) {
67799
67946
  // ../gg-core/dist/index.js
67800
67947
  init_esm_shims();
67801
67948
 
67802
- // ../gg-core/dist/chunk-TZNVRILI.js
67949
+ // ../gg-core/dist/chunk-KQJNZC6A.js
67803
67950
  init_esm_shims();
67804
67951
  import path3 from "path";
67805
67952
  import os2 from "os";
@@ -67813,6 +67960,7 @@ function getAppPaths() {
67813
67960
  telegramFile: path3.join(agentDir, "telegram.json"),
67814
67961
  agentHomeFile: path3.join(agentDir, "agent-home.json"),
67815
67962
  mcpFile: path3.join(agentDir, "mcp.json"),
67963
+ mcpAuthFile: path3.join(agentDir, "mcp-auth.json"),
67816
67964
  logFile: path3.join(agentDir, "debug.log"),
67817
67965
  skillsDir: path3.join(agentDir, "skills"),
67818
67966
  extensionsDir: path3.join(agentDir, "extensions"),
@@ -69085,7 +69233,7 @@ init_esm_shims();
69085
69233
  import { spawn as spawn2, spawnSync } from "child_process";
69086
69234
  import fs6 from "fs";
69087
69235
  import fsp from "fs/promises";
69088
- import path6 from "path";
69236
+ import path7 from "path";
69089
69237
  import os3 from "os";
69090
69238
  import crypto2 from "crypto";
69091
69239
 
@@ -69143,7 +69291,34 @@ var ENV_ALLOWLIST = /* @__PURE__ */ new Set([
69143
69291
  "ANDROID_SDK_ROOT",
69144
69292
  "RUBY_VERSION",
69145
69293
  "GEM_HOME",
69146
- "RBENV_ROOT"
69294
+ "RBENV_ROOT",
69295
+ // Windows essentials. Without these, child processes (cmd.exe, Git Bash,
69296
+ // node, npm, MCP stdio servers) misbehave or fail to spawn: SystemRoot +
69297
+ // PATHEXT are required by the Windows loader/resolver, ComSpec is the
69298
+ // cmd.exe path, and the USERPROFILE/APPDATA/TEMP family is where toolchains
69299
+ // read and write. Stripping them was a silent cause of broken shell calls.
69300
+ "SystemRoot",
69301
+ "SystemDrive",
69302
+ "windir",
69303
+ "PATHEXT",
69304
+ "ComSpec",
69305
+ "COMSPEC",
69306
+ "USERPROFILE",
69307
+ "HOMEDRIVE",
69308
+ "HOMEPATH",
69309
+ "APPDATA",
69310
+ "LOCALAPPDATA",
69311
+ "PROGRAMDATA",
69312
+ "ProgramData",
69313
+ "ProgramFiles",
69314
+ "ProgramFiles(x86)",
69315
+ "ProgramW6432",
69316
+ "TEMP",
69317
+ "TMP",
69318
+ "NUMBER_OF_PROCESSORS",
69319
+ "PROCESSOR_ARCHITECTURE",
69320
+ // Git Bash override for the agent shell (see core/shell.ts).
69321
+ "GG_BASH"
69147
69322
  ]);
69148
69323
  function getSafeToolEnv(sourceEnv = process.env) {
69149
69324
  const env2 = { TERM: "dumb", GG_CODER: "true" };
@@ -69155,8 +69330,68 @@ function getSafeToolEnv(sourceEnv = process.env) {
69155
69330
  return env2;
69156
69331
  }
69157
69332
 
69333
+ // ../ggcoder/dist/core/shell.js
69334
+ init_esm_shims();
69335
+ import { existsSync as existsSync2 } from "fs";
69336
+ import path6 from "path";
69337
+ function gitBashFixedCandidates(env2) {
69338
+ const programFiles = env2.ProgramFiles ?? "C:\\Program Files";
69339
+ const programFilesX86 = env2["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
69340
+ const localAppData = env2.LOCALAPPDATA;
69341
+ const candidates = [
69342
+ path6.win32.join(programFiles, "Git", "bin", "bash.exe"),
69343
+ path6.win32.join(programFilesX86, "Git", "bin", "bash.exe")
69344
+ ];
69345
+ if (localAppData) {
69346
+ candidates.push(path6.win32.join(localAppData, "Programs", "Git", "bin", "bash.exe"));
69347
+ }
69348
+ return candidates;
69349
+ }
69350
+ function gitBashFromPath(env2, exists) {
69351
+ const rawPath = env2.PATH ?? env2.Path ?? "";
69352
+ if (!rawPath)
69353
+ return null;
69354
+ for (const dir of rawPath.split(";")) {
69355
+ if (!dir)
69356
+ continue;
69357
+ const gitExe = path6.win32.join(dir, "git.exe");
69358
+ if (!exists(gitExe))
69359
+ continue;
69360
+ const gitRoot = path6.win32.dirname(path6.win32.dirname(gitExe));
69361
+ const bash2 = path6.win32.join(gitRoot, "bin", "bash.exe");
69362
+ if (exists(bash2))
69363
+ return bash2;
69364
+ }
69365
+ return null;
69366
+ }
69367
+ function findGitBash(env2, exists) {
69368
+ for (const candidate of gitBashFixedCandidates(env2)) {
69369
+ if (exists(candidate))
69370
+ return candidate;
69371
+ }
69372
+ return gitBashFromPath(env2, exists);
69373
+ }
69374
+ function resolveShell(command, opts = {}) {
69375
+ const platform2 = opts.platform ?? process.platform;
69376
+ const env2 = opts.env ?? process.env;
69377
+ const exists = opts.exists ?? existsSync2;
69378
+ const override = env2.GG_BASH?.trim();
69379
+ if (override) {
69380
+ return { file: override, args: ["-c", command], isCmdFallback: false };
69381
+ }
69382
+ if (platform2 !== "win32") {
69383
+ return { file: "bash", args: ["-c", command], isCmdFallback: false };
69384
+ }
69385
+ const gitBash = findGitBash(env2, exists);
69386
+ if (gitBash) {
69387
+ return { file: gitBash, args: ["-c", command], isCmdFallback: false };
69388
+ }
69389
+ const comspec = env2.ComSpec ?? env2.COMSPEC ?? "C:\\Windows\\System32\\cmd.exe";
69390
+ return { file: comspec, args: ["/d", "/s", "/c", command], isCmdFallback: true };
69391
+ }
69392
+
69158
69393
  // ../ggcoder/dist/core/process-manager.js
69159
- var BG_DIR = path6.join(os3.homedir(), ".gg", "bg");
69394
+ var BG_DIR = path7.join(os3.homedir(), ".gg", "bg");
69160
69395
  function stopProcessTree(pid, ops = {}) {
69161
69396
  if ((ops.platform ?? process.platform) === "win32") {
69162
69397
  (ops.spawnSync ?? spawnSync)("taskkill", ["/pid", String(pid), "/T", "/F"], {
@@ -69176,9 +69411,10 @@ var ProcessManager = class {
69176
69411
  async start(command, cwd2) {
69177
69412
  await fsp.mkdir(BG_DIR, { recursive: true });
69178
69413
  const id2 = crypto2.randomUUID().slice(0, 8);
69179
- const logFile = path6.join(BG_DIR, `${id2}.log`);
69414
+ const logFile = path7.join(BG_DIR, `${id2}.log`);
69180
69415
  const fd2 = fs6.openSync(logFile, "w");
69181
- const child = spawn2("bash", ["-c", command], {
69416
+ const shell2 = resolveShell(command);
69417
+ const child = spawn2(shell2.file, shell2.args, {
69182
69418
  cwd: cwd2,
69183
69419
  detached: true,
69184
69420
  // stdin is a pipe so callers can drive interactive processes (REPLs,
@@ -69321,7 +69557,7 @@ var ProcessManager = class {
69321
69557
 
69322
69558
  // ../ggcoder/dist/core/lsp/manager.js
69323
69559
  init_esm_shims();
69324
- import path8 from "path";
69560
+ import path9 from "path";
69325
69561
 
69326
69562
  // ../ggcoder/dist/core/logger.js
69327
69563
  init_esm_shims();
@@ -69690,7 +69926,7 @@ Diagnostics in ${relPath} (informational \u2014 may resolve after related edits)
69690
69926
  // ../ggcoder/dist/core/lsp/servers.js
69691
69927
  init_esm_shims();
69692
69928
  import fs7 from "fs";
69693
- import path7 from "path";
69929
+ import path8 from "path";
69694
69930
  import { fileURLToPath } from "url";
69695
69931
  var WINDOWS_SUFFIXES = [".cmd", ".exe", ".bat"];
69696
69932
  function isExecutableFile(candidate) {
@@ -69706,13 +69942,13 @@ function candidateNames(name) {
69706
69942
  return [name];
69707
69943
  return [name, ...WINDOWS_SUFFIXES.map((suffix) => `${name}${suffix}`)];
69708
69944
  }
69709
- var MODULE_DIR = path7.dirname(fileURLToPath(import.meta.url));
69945
+ var MODULE_DIR = path8.dirname(fileURLToPath(import.meta.url));
69710
69946
  function binDirsUpFrom(start) {
69711
69947
  const dirs = [];
69712
69948
  let dir = start;
69713
69949
  for (; ; ) {
69714
- dirs.push(path7.join(dir, "node_modules", ".bin"));
69715
- const parent = path7.dirname(dir);
69950
+ dirs.push(path8.join(dir, "node_modules", ".bin"));
69951
+ const parent = path8.dirname(dir);
69716
69952
  if (parent === dir)
69717
69953
  break;
69718
69954
  dir = parent;
@@ -69724,17 +69960,17 @@ function findExecutable(name, projectRoot) {
69724
69960
  const binDirs = [...binDirsUpFrom(projectRoot), ...binDirsUpFrom(MODULE_DIR)];
69725
69961
  for (const binDir of binDirs) {
69726
69962
  for (const candidate of names) {
69727
- const binPath = path7.join(binDir, candidate);
69963
+ const binPath = path8.join(binDir, candidate);
69728
69964
  if (isExecutableFile(binPath))
69729
69965
  return binPath;
69730
69966
  }
69731
69967
  }
69732
69968
  const pathEnv = process.env.PATH ?? "";
69733
- for (const pathDir of pathEnv.split(path7.delimiter)) {
69969
+ for (const pathDir of pathEnv.split(path8.delimiter)) {
69734
69970
  if (!pathDir)
69735
69971
  continue;
69736
69972
  for (const candidate of names) {
69737
- const binPath = path7.join(pathDir, candidate);
69973
+ const binPath = path8.join(pathDir, candidate);
69738
69974
  if (isExecutableFile(binPath))
69739
69975
  return binPath;
69740
69976
  }
@@ -69744,17 +69980,17 @@ function findExecutable(name, projectRoot) {
69744
69980
  function findInNodeModulesUp(relPath, start) {
69745
69981
  let dir = start;
69746
69982
  for (; ; ) {
69747
- const candidate = path7.join(dir, "node_modules", relPath);
69983
+ const candidate = path8.join(dir, "node_modules", relPath);
69748
69984
  if (fs7.existsSync(candidate))
69749
69985
  return candidate;
69750
- const parent = path7.dirname(dir);
69986
+ const parent = path8.dirname(dir);
69751
69987
  if (parent === dir)
69752
69988
  return null;
69753
69989
  dir = parent;
69754
69990
  }
69755
69991
  }
69756
69992
  function findPackageBinScript(pkgName, binName, start) {
69757
- const pkgJsonPath = findInNodeModulesUp(path7.join(pkgName, "package.json"), start);
69993
+ const pkgJsonPath = findInNodeModulesUp(path8.join(pkgName, "package.json"), start);
69758
69994
  if (!pkgJsonPath)
69759
69995
  return null;
69760
69996
  try {
@@ -69762,7 +69998,7 @@ function findPackageBinScript(pkgName, binName, start) {
69762
69998
  const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.[binName];
69763
69999
  if (!bin)
69764
70000
  return null;
69765
- const script = path7.join(path7.dirname(pkgJsonPath), bin);
70001
+ const script = path8.join(path8.dirname(pkgJsonPath), bin);
69766
70002
  return fs7.existsSync(script) ? script : null;
69767
70003
  } catch {
69768
70004
  return null;
@@ -69775,7 +70011,7 @@ function resolveNodeServer(pkgName, binName, projectRoot, args) {
69775
70011
  const bin = findExecutable(binName, projectRoot);
69776
70012
  return bin ? { command: bin, args } : null;
69777
70013
  }
69778
- var TSSERVER_REL_PATH = path7.join("typescript", "lib", "tsserver.js");
70014
+ var TSSERVER_REL_PATH = path8.join("typescript", "lib", "tsserver.js");
69779
70015
  function projectTsserverPath(projectRoot) {
69780
70016
  return findInNodeModulesUp(TSSERVER_REL_PATH, projectRoot);
69781
70017
  }
@@ -69865,27 +70101,27 @@ var LSP_SERVER_CATALOG = [
69865
70101
  }
69866
70102
  ];
69867
70103
  function serverForFile(filePath, catalog = LSP_SERVER_CATALOG) {
69868
- const extension = path7.extname(filePath).toLowerCase();
70104
+ const extension = path8.extname(filePath).toLowerCase();
69869
70105
  if (!extension)
69870
70106
  return null;
69871
70107
  return catalog.find((spec) => spec.extensions.includes(extension)) ?? null;
69872
70108
  }
69873
70109
  function findProjectRoot(filePath, markers, ceiling) {
69874
- const fileDir = path7.dirname(path7.resolve(filePath));
69875
- const cap = path7.resolve(ceiling);
69876
- const underCeiling = fileDir === cap || fileDir.startsWith(cap + path7.sep);
70110
+ const fileDir = path8.dirname(path8.resolve(filePath));
70111
+ const cap = path8.resolve(ceiling);
70112
+ const underCeiling = fileDir === cap || fileDir.startsWith(cap + path8.sep);
69877
70113
  let dir = fileDir;
69878
70114
  for (; ; ) {
69879
70115
  for (const marker of markers) {
69880
70116
  try {
69881
- fs7.statSync(path7.join(dir, marker));
70117
+ fs7.statSync(path8.join(dir, marker));
69882
70118
  return dir;
69883
70119
  } catch {
69884
70120
  }
69885
70121
  }
69886
70122
  if (underCeiling && dir === cap)
69887
70123
  break;
69888
- const parent = path7.dirname(dir);
70124
+ const parent = path8.dirname(dir);
69889
70125
  if (parent === dir)
69890
70126
  break;
69891
70127
  dir = parent;
@@ -69956,12 +70192,12 @@ var LspManager = class {
69956
70192
  log("WARN", "lsp", `${spec.id} server died`, { root });
69957
70193
  return "";
69958
70194
  }
69959
- const uri = client.syncDocument(path8.resolve(this.cwd, filePath), content);
70195
+ const uri = client.syncDocument(path9.resolve(this.cwd, filePath), content);
69960
70196
  const diagnostics = await client.collectDiagnostics(uri, budgetMs);
69961
70197
  this.warmKeys.add(key);
69962
70198
  if (diagnostics === null)
69963
70199
  return "";
69964
- const relPath = path8.relative(this.cwd, path8.resolve(this.cwd, filePath));
70200
+ const relPath = path9.relative(this.cwd, path9.resolve(this.cwd, filePath));
69965
70201
  return formatDiagnostics(relPath, diagnostics);
69966
70202
  }
69967
70203
  ensureClient(key, spec, root) {
@@ -70012,18 +70248,18 @@ function withBudget(work, budgetMs) {
70012
70248
  // ../ggcoder/dist/tools/read.js
70013
70249
  init_esm_shims();
70014
70250
  import fs12 from "fs/promises";
70015
- import path12 from "path";
70251
+ import path13 from "path";
70016
70252
 
70017
70253
  // ../ggcoder/dist/tools/path-utils.js
70018
70254
  init_esm_shims();
70019
70255
  import fs8 from "fs/promises";
70020
- import path9 from "path";
70256
+ import path10 from "path";
70021
70257
  import os4 from "os";
70022
70258
  function resolvePath(cwd2, filePath) {
70023
70259
  if (filePath.startsWith("~")) {
70024
- filePath = path9.join(os4.homedir(), filePath.slice(1));
70260
+ filePath = path10.join(os4.homedir(), filePath.slice(1));
70025
70261
  }
70026
- return path9.resolve(cwd2, filePath);
70262
+ return path10.resolve(cwd2, filePath);
70027
70263
  }
70028
70264
  async function rejectSymlink(resolved) {
70029
70265
  try {
@@ -70090,9 +70326,9 @@ function truncateTail(content, maxLines = MAX_LINES, maxBytes = MAX_BYTES2) {
70090
70326
  init_esm_shims();
70091
70327
  import fs9 from "fs/promises";
70092
70328
  import os5 from "os";
70093
- import path10 from "path";
70329
+ import path11 from "path";
70094
70330
  async function writeOverflow(content, prefix) {
70095
- const filePath = path10.join(os5.tmpdir(), `gg-${prefix}-${Date.now()}.txt`);
70331
+ const filePath = path11.join(os5.tmpdir(), `gg-${prefix}-${Date.now()}.txt`);
70096
70332
  await fs9.writeFile(filePath, content, { encoding: "utf-8", mode: 384 });
70097
70333
  return filePath;
70098
70334
  }
@@ -70103,18 +70339,18 @@ import fs10 from "fs/promises";
70103
70339
  import { spawn as spawn4 } from "child_process";
70104
70340
  import { createReadStream } from "fs";
70105
70341
  var localOperations = {
70106
- readFile: (path46) => fs10.readFile(path46, "utf-8"),
70107
- writeFile: async (path46, content) => {
70342
+ readFile: (path48) => fs10.readFile(path48, "utf-8"),
70343
+ writeFile: async (path48, content) => {
70108
70344
  const { dirname: dirname3 } = await import("path");
70109
- await fs10.mkdir(dirname3(path46), { recursive: true });
70110
- await fs10.writeFile(path46, content, "utf-8");
70345
+ await fs10.mkdir(dirname3(path48), { recursive: true });
70346
+ await fs10.writeFile(path48, content, "utf-8");
70111
70347
  },
70112
- stat: (path46) => fs10.stat(path46),
70113
- lstat: (path46) => fs10.lstat(path46),
70114
- readdir: (path46, options) => fs10.readdir(path46, options),
70115
- mkdir: (path46) => fs10.mkdir(path46, { recursive: true }).then(() => {
70348
+ stat: (path48) => fs10.stat(path48),
70349
+ lstat: (path48) => fs10.lstat(path48),
70350
+ readdir: (path48, options) => fs10.readdir(path48, options),
70351
+ mkdir: (path48) => fs10.mkdir(path48, { recursive: true }).then(() => {
70116
70352
  }),
70117
- createReadStream: (path46, encoding) => createReadStream(path46, { encoding }),
70353
+ createReadStream: (path48, encoding) => createReadStream(path48, { encoding }),
70118
70354
  spawn: (command, args, options) => spawn4(command, args, {
70119
70355
  cwd: options.cwd,
70120
70356
  env: options.env,
@@ -70160,7 +70396,7 @@ async function assertFresh(tracker, resolvedPath, ops) {
70160
70396
  init_esm_shims();
70161
70397
  import fs11 from "fs/promises";
70162
70398
  import os6 from "os";
70163
- import path11 from "path";
70399
+ import path12 from "path";
70164
70400
  import { execFile } from "child_process";
70165
70401
  import { promisify } from "util";
70166
70402
  var execFileAsync = promisify(execFile);
@@ -70208,7 +70444,7 @@ async function compressVideoToFit(inputPath, targetBytes = COMPRESS_TARGET_BYTES
70208
70444
  }
70209
70445
  const totalKbps = Math.floor(targetBytes * 8 / durationSec / 1e3 * 0.9);
70210
70446
  const videoKbps = Math.max(COMPRESS_MIN_VIDEO_KBPS, totalKbps - COMPRESS_AUDIO_KBPS);
70211
- const outPath = path11.join(os6.tmpdir(), `ggcoder-compressed-${Date.now()}.mp4`);
70447
+ const outPath = path12.join(os6.tmpdir(), `ggcoder-compressed-${Date.now()}.mp4`);
70212
70448
  try {
70213
70449
  await execFileAsync("ffmpeg", [
70214
70450
  "-y",
@@ -70280,7 +70516,7 @@ var VIDEO_MEDIA_TYPES = {
70280
70516
  };
70281
70517
  var MEDIA_TYPES = IMAGE_MEDIA_TYPES;
70282
70518
  function isAttachablePath(filePath) {
70283
- const ext = path11.extname(filePath).toLowerCase();
70519
+ const ext = path12.extname(filePath).toLowerCase();
70284
70520
  return ATTACHABLE_EXTENSIONS.has(ext);
70285
70521
  }
70286
70522
  function resolvePath2(filePath, cwd2) {
@@ -70293,9 +70529,9 @@ function resolvePath2(filePath, cwd2) {
70293
70529
  }
70294
70530
  resolved = resolved.replace(/\\(.)/g, "$1");
70295
70531
  if (resolved.startsWith("~/")) {
70296
- resolved = path11.join(process.env.HOME ?? "/", resolved.slice(2));
70297
- } else if (!path11.isAbsolute(resolved)) {
70298
- resolved = path11.join(cwd2, resolved);
70532
+ resolved = path12.join(process.env.HOME ?? "/", resolved.slice(2));
70533
+ } else if (!path12.isAbsolute(resolved)) {
70534
+ resolved = path12.join(cwd2, resolved);
70299
70535
  }
70300
70536
  return resolved;
70301
70537
  }
@@ -70408,8 +70644,8 @@ async function downscaleForPreview(buffer) {
70408
70644
  }
70409
70645
  }
70410
70646
  async function readImageFile(filePath) {
70411
- const ext = path11.extname(filePath).toLowerCase();
70412
- const fileName = path11.basename(filePath);
70647
+ const ext = path12.extname(filePath).toLowerCase();
70648
+ const fileName = path12.basename(filePath);
70413
70649
  if (VIDEO_EXTENSIONS.has(ext)) {
70414
70650
  try {
70415
70651
  const mediaType = VIDEO_MEDIA_TYPES[ext] ?? "video/mp4";
@@ -70574,7 +70810,7 @@ function createReadTool(cwd2, readFiles, ops = localOperations, onFileRead, vide
70574
70810
  async execute({ file_path, offset, limit: limit2 }, context) {
70575
70811
  const resolved = resolvePath(cwd2, file_path);
70576
70812
  await rejectSymlink(resolved);
70577
- const ext = path12.extname(resolved).toLowerCase();
70813
+ const ext = path13.extname(resolved).toLowerCase();
70578
70814
  if (IMAGE_EXTENSIONS.has(ext)) {
70579
70815
  try {
70580
70816
  const rawBuffer = await fs12.readFile(resolved);
@@ -70701,7 +70937,7 @@ init_esm_shims();
70701
70937
  // ../ggcoder/dist/tools/write.js
70702
70938
  init_esm_shims();
70703
70939
  import fs13 from "fs/promises";
70704
- import path13 from "path";
70940
+ import path14 from "path";
70705
70941
 
70706
70942
  // ../ggcoder/dist/core/runtime-mode.js
70707
70943
  init_esm_shims();
@@ -70735,9 +70971,9 @@ function createWriteTool(cwd2, readFiles, ops = localOperations, planModeRefOrOn
70735
70971
  const resolved = resolvePath(cwd2, file_path);
70736
70972
  await rejectSymlink(resolved);
70737
70973
  if (isPlanModeActive(planModeRef)) {
70738
- const plansDir = path13.join(cwd2, ".gg", "plans");
70739
- const relative = path13.relative(plansDir, resolved);
70740
- if (relative.startsWith("..") || path13.isAbsolute(relative)) {
70974
+ const plansDir = path14.join(cwd2, ".gg", "plans");
70975
+ const relative = path14.relative(plansDir, resolved);
70976
+ if (relative.startsWith("..") || path14.isAbsolute(relative)) {
70741
70977
  return `Error: write is restricted in plan mode. You can only write to .gg/plans/. Got: ${file_path}`;
70742
70978
  }
70743
70979
  await fs13.mkdir(plansDir, { recursive: true });
@@ -70767,7 +71003,7 @@ function createWriteTool(cwd2, readFiles, ops = localOperations, planModeRefOrOn
70767
71003
 
70768
71004
  // ../ggcoder/dist/tools/edit.js
70769
71005
  init_esm_shims();
70770
- import path14 from "path";
71006
+ import path15 from "path";
70771
71007
 
70772
71008
  // ../ggcoder/dist/tools/edit-diff.js
70773
71009
  init_esm_shims();
@@ -70876,16 +71112,16 @@ var Diff = class {
70876
71112
  }
70877
71113
  }
70878
71114
  }
70879
- addToPath(path46, added, removed, oldPosInc, options) {
70880
- const last = path46.lastComponent;
71115
+ addToPath(path48, added, removed, oldPosInc, options) {
71116
+ const last = path48.lastComponent;
70881
71117
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
70882
71118
  return {
70883
- oldPos: path46.oldPos + oldPosInc,
71119
+ oldPos: path48.oldPos + oldPosInc,
70884
71120
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
70885
71121
  };
70886
71122
  } else {
70887
71123
  return {
70888
- oldPos: path46.oldPos + oldPosInc,
71124
+ oldPos: path48.oldPos + oldPosInc,
70889
71125
  lastComponent: { count: 1, added, removed, previousComponent: last }
70890
71126
  };
70891
71127
  }
@@ -71451,16 +71687,22 @@ function fuzzyFindText(content, oldText) {
71451
71687
  }
71452
71688
  const oldLines = oldText.split("\n");
71453
71689
  const contentLines = content.split("\n");
71454
- const normalizedOldLines = oldLines.map(normalizeForFuzzyMatch);
71690
+ const normalizedOldJoined = oldLines.map(normalizeForFuzzyMatch).join("\n");
71691
+ const normalizedCache = new Array(contentLines.length);
71455
71692
  for (let startLine = 0; startLine + oldLines.length <= contentLines.length; startLine++) {
71456
- const candidateLines = contentLines.slice(startLine, startLine + oldLines.length);
71457
- const normalizedCandidate = candidateLines.map(normalizeForFuzzyMatch);
71458
- if (normalizedCandidate.join("\n") !== normalizedOldLines.join("\n"))
71693
+ let normalizedCandidate = "";
71694
+ for (let j = startLine; j < startLine + oldLines.length; j++) {
71695
+ normalizedCandidate += normalizedCache[j] ??= normalizeForFuzzyMatch(contentLines[j]);
71696
+ if (j < startLine + oldLines.length - 1)
71697
+ normalizedCandidate += "\n";
71698
+ }
71699
+ if (normalizedCandidate !== normalizedOldJoined)
71459
71700
  continue;
71460
71701
  let actualIndex = 0;
71461
71702
  for (let i = 0; i < startLine; i++) {
71462
71703
  actualIndex += contentLines[i].length + 1;
71463
71704
  }
71705
+ const candidateLines = contentLines.slice(startLine, startLine + oldLines.length);
71464
71706
  return {
71465
71707
  found: true,
71466
71708
  index: actualIndex,
@@ -71491,8 +71733,14 @@ function countOccurrences(content, oldText) {
71491
71733
  }
71492
71734
  const oldLines = oldText.split("\n");
71493
71735
  const contentLines = content.split("\n");
71736
+ const normalizedCache = new Array(contentLines.length);
71494
71737
  for (let startLine = 0; startLine + oldLines.length <= contentLines.length; startLine++) {
71495
- const normalizedCandidate = contentLines.slice(startLine, startLine + oldLines.length).map(normalizeForFuzzyMatch).join("\n");
71738
+ let normalizedCandidate = "";
71739
+ for (let j = startLine; j < startLine + oldLines.length; j++) {
71740
+ normalizedCandidate += normalizedCache[j] ??= normalizeForFuzzyMatch(contentLines[j]);
71741
+ if (j < startLine + oldLines.length - 1)
71742
+ normalizedCandidate += "\n";
71743
+ }
71496
71744
  if (normalizedCandidate === normalizedOld)
71497
71745
  count++;
71498
71746
  }
@@ -71652,7 +71900,7 @@ function createEditTool(cwd2, readFiles, ops = localOperations, planModeRefOrOnF
71652
71900
  const hasCRLF = original.includes("\r\n");
71653
71901
  const originalNormalized = hasCRLF ? original.replace(/\r\n/g, "\n") : original;
71654
71902
  let working = originalNormalized;
71655
- const fileName = path14.basename(resolved);
71903
+ const fileName = path15.basename(resolved);
71656
71904
  const outcomes = new Array(edits.length);
71657
71905
  for (let i = 0; i < edits.length; i++) {
71658
71906
  const { old_text, new_text, replace_all } = edits[i];
@@ -71754,7 +72002,7 @@ ${f.closestSnippet}`;
71754
72002
  ` : "";
71755
72003
  throw new Error(header + formatFailures());
71756
72004
  }
71757
- const relPath = path14.relative(cwd2, resolved);
72005
+ const relPath = path15.relative(cwd2, resolved);
71758
72006
  const diff3 = generateDiff(originalNormalized, working, relPath);
71759
72007
  const changed = working !== originalNormalized;
71760
72008
  let diagnosticsNote = "";
@@ -71951,7 +72199,8 @@ Use task_output with id="${result.id}" to read output, task_send to type input/a
71951
72199
  }
71952
72200
  const effectiveTimeout = timeoutMs ?? DEFAULT_TIMEOUT;
71953
72201
  return new Promise((resolve2) => {
71954
- const child = ops.spawn("bash", ["-c", command], {
72202
+ const shell2 = resolveShell(command);
72203
+ const child = ops.spawn(shell2.file, shell2.args, {
71955
72204
  cwd: cwd2,
71956
72205
  detached: true,
71957
72206
  stdio: ["ignore", "pipe", "pipe"],
@@ -72009,6 +72258,9 @@ ${output}`;
72009
72258
  output = `[Truncated: showing last ${result.keptLines} of ${result.totalLines} lines.${overflowNotice}]
72010
72259
  ${output}`;
72011
72260
  }
72261
+ if (shell2.isCmdFallback) {
72262
+ output = "[Ran under Windows cmd.exe \u2014 bash is unavailable. Use cmd syntax (dir, findstr, type); POSIX commands and quoting will fail. Install Git for Windows to get bash.]\n" + output;
72263
+ }
72012
72264
  const exitCode = timedOut ? `TIMEOUT (${effectiveTimeout}ms)` : killed ? "KILLED" : String(code ?? 1);
72013
72265
  resolve2(`Exit code: ${exitCode}
72014
72266
  ${output}`);
@@ -72027,7 +72279,7 @@ Failed to spawn: ${err.message}`);
72027
72279
  // ../ggcoder/dist/tools/find.js
72028
72280
  init_esm_shims();
72029
72281
  import fs14 from "fs/promises";
72030
- import path15 from "path";
72282
+ import path16 from "path";
72031
72283
  var FindParams = external_exports.object({
72032
72284
  pattern: external_exports.string().describe("Glob pattern to match files (e.g. '**/*.ts', 'src/**/*.tsx')"),
72033
72285
  path: external_exports.string().optional().describe("Directory to search in (defaults to cwd)")
@@ -72073,7 +72325,7 @@ ${filtered.length} file(s) found`;
72073
72325
  }
72074
72326
  async function loadGitignore(dir) {
72075
72327
  try {
72076
- const content = await fs14.readFile(path15.join(dir, ".gitignore"), "utf-8");
72328
+ const content = await fs14.readFile(path16.join(dir, ".gitignore"), "utf-8");
72077
72329
  return content.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
72078
72330
  } catch {
72079
72331
  return [];
@@ -72083,7 +72335,7 @@ async function loadGitignore(dir) {
72083
72335
  // ../ggcoder/dist/tools/grep.js
72084
72336
  init_esm_shims();
72085
72337
  import readline from "readline";
72086
- import path16 from "path";
72338
+ import path17 from "path";
72087
72339
  var GrepParams = external_exports.object({
72088
72340
  pattern: external_exports.string().describe("Search pattern (regex supported)"),
72089
72341
  path: external_exports.string().optional().describe("File or directory to search (defaults to cwd)"),
@@ -72139,10 +72391,10 @@ function createGrepTool(cwd2, ops = localOperations) {
72139
72391
  }
72140
72392
  scannedCandidates += 1;
72141
72393
  const entry = typeof item === "string" ? item : item.path;
72142
- const ext = path16.extname(entry).toLowerCase();
72394
+ const ext = path17.extname(entry).toLowerCase();
72143
72395
  if (BINARY_EXTENSIONS.has(ext))
72144
72396
  continue;
72145
- const filePath = path16.join(dir, entry);
72397
+ const filePath = path17.join(dir, entry);
72146
72398
  const fileResults = await searchFile(filePath, regex2, cwd2, maxResults - results.length, ops);
72147
72399
  results.push(...fileResults);
72148
72400
  }
@@ -72152,7 +72404,7 @@ function createGrepTool(cwd2, ops = localOperations) {
72152
72404
  }
72153
72405
  async function searchFile(filePath, regex2, cwd2, maxResults, ops) {
72154
72406
  const results = [];
72155
- const relPath = path16.relative(cwd2, filePath);
72407
+ const relPath = path17.relative(cwd2, filePath);
72156
72408
  try {
72157
72409
  const fileStat = await ops.stat(filePath);
72158
72410
  if (fileStat.size > MAX_FILE_SIZE)
@@ -72214,7 +72466,7 @@ ${results.length} match(es) found`;
72214
72466
 
72215
72467
  // ../ggcoder/dist/tools/ls.js
72216
72468
  init_esm_shims();
72217
- import path17 from "path";
72469
+ import path18 from "path";
72218
72470
  var LsParams = external_exports.object({
72219
72471
  path: external_exports.string().optional().describe("Directory path (defaults to cwd)"),
72220
72472
  all: external_exports.boolean().optional().describe("Show hidden files (default: false)")
@@ -72234,16 +72486,17 @@ function createLsTool(cwd2, ops = localOperations) {
72234
72486
  for (const dir of dirs) {
72235
72487
  lines.push(`d - ${dir.name}/`);
72236
72488
  }
72237
- for (const file2 of files) {
72489
+ const fileLines = await Promise.all(files.map(async (file2) => {
72238
72490
  try {
72239
- const stat = await ops.stat(path17.join(resolved, file2.name));
72491
+ const stat = await ops.stat(path18.join(resolved, file2.name));
72240
72492
  const size = formatSize(stat.size);
72241
72493
  const type2 = file2.isSymbolicLink() ? "l" : "f";
72242
- lines.push(`${type2} ${size.padStart(8)} ${file2.name}`);
72494
+ return `${type2} ${size.padStart(8)} ${file2.name}`;
72243
72495
  } catch {
72244
- lines.push(`? - ${file2.name}`);
72496
+ return `? - ${file2.name}`;
72245
72497
  }
72246
- }
72498
+ }));
72499
+ lines.push(...fileLines);
72247
72500
  if (lines.length === 0)
72248
72501
  return "Empty directory.";
72249
72502
  return lines.join("\n");
@@ -72264,7 +72517,7 @@ function formatSize(bytes) {
72264
72517
  init_esm_shims();
72265
72518
  import { spawn as spawn5 } from "child_process";
72266
72519
  import { createInterface } from "readline";
72267
- import { existsSync as existsSync2 } from "fs";
72520
+ import { existsSync as existsSync3 } from "fs";
72268
72521
  import { fileURLToPath as fileURLToPath2 } from "url";
72269
72522
  var SUB_AGENT_MAX_TURNS = 10;
72270
72523
  var SUB_AGENT_MAX_OUTPUT_CHARS = 1e5;
@@ -72273,7 +72526,7 @@ var SUB_AGENT_MAX_STDERR_CHARS = 1e4;
72273
72526
  var SUB_AGENT_TIMEOUT_MS = 10 * 60 * 1e3;
72274
72527
  function resolveCliEntry() {
72275
72528
  const cliPath = fileURLToPath2(new URL("../cli.js", import.meta.url));
72276
- return existsSync2(cliPath) ? cliPath : process.argv[1];
72529
+ return existsSync3(cliPath) ? cliPath : process.argv[1];
72277
72530
  }
72278
72531
  var SubAgentParams = external_exports.object({
72279
72532
  task: external_exports.string().describe("The task to delegate to the sub-agent"),
@@ -73722,7 +73975,7 @@ function createWebSearchTool() {
73722
73975
  // ../ggcoder/dist/tools/source-path.js
73723
73976
  init_esm_shims();
73724
73977
  import { spawn as spawn6 } from "child_process";
73725
- import path18 from "path";
73978
+ import path19 from "path";
73726
73979
  import { fileURLToPath as fileURLToPath3 } from "url";
73727
73980
  var SOURCE_PATH_TIMEOUT_MS = 12e4;
73728
73981
  var MAX_STDERR_CHARS = 1e4;
@@ -73822,8 +74075,8 @@ function getBundledOpenSrcBinPath() {
73822
74075
  const override = process.env[OPENSRC_BIN_ENV]?.trim();
73823
74076
  if (override)
73824
74077
  return override;
73825
- const currentDir = path18.dirname(fileURLToPath3(import.meta.url));
73826
- return path18.resolve(currentDir, "../../node_modules/opensrc/bin/opensrc.js");
74078
+ const currentDir = path19.dirname(fileURLToPath3(import.meta.url));
74079
+ return path19.resolve(currentDir, "../../node_modules/opensrc/bin/opensrc.js");
73827
74080
  }
73828
74081
  function getOpenSrcEnv() {
73829
74082
  return {
@@ -74071,7 +74324,7 @@ ${list}`;
74071
74324
 
74072
74325
  // ../ggcoder/dist/tools/screenshot.js
74073
74326
  init_esm_shims();
74074
- import path19 from "path";
74327
+ import path20 from "path";
74075
74328
  import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
74076
74329
  var INSTALL_HINT = "Browser engine not installed. Add the optional dependency and download Chromium:\n pnpm add -w playwright && npx playwright install chromium\nThen retry the screenshot.";
74077
74330
  var ActionInput = external_exports.object({
@@ -74109,7 +74362,7 @@ function isBrowserBinaryMissing(err) {
74109
74362
  }
74110
74363
  function defaultOutPath(cwd2) {
74111
74364
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
74112
- return path19.join(cwd2, ".gg", "screenshots", `${stamp}.png`);
74365
+ return path20.join(cwd2, ".gg", "screenshots", `${stamp}.png`);
74113
74366
  }
74114
74367
  async function runActions(page, actions) {
74115
74368
  for (const action of actions ?? []) {
@@ -74160,7 +74413,7 @@ function createScreenshotTool(cwd2) {
74160
74413
  await runActions(page, args.actions);
74161
74414
  const raw = await page.screenshot({ fullPage: args.full_page ?? false });
74162
74415
  context.signal.removeEventListener("abort", onAbort);
74163
- await mkdir2(path19.dirname(outPath), { recursive: true });
74416
+ await mkdir2(path20.dirname(outPath), { recursive: true });
74164
74417
  await writeFile2(outPath, raw);
74165
74418
  const { buffer, mediaType } = await shrinkToFit(raw, "image/png");
74166
74419
  const previewBuffer = await downscaleForPreview(buffer);
@@ -74192,6 +74445,215 @@ function createScreenshotTool(cwd2) {
74192
74445
  };
74193
74446
  }
74194
74447
 
74448
+ // ../ggcoder/dist/tools/generate-image.js
74449
+ init_esm_shims();
74450
+ import path21 from "path";
74451
+ import { mkdir as mkdir3, writeFile as writeFile3, readFile as readFile2 } from "fs/promises";
74452
+ var CODEX_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
74453
+ var IMAGE_GEN_MODEL = "gpt-5.5";
74454
+ var GenerateImageParams = external_exports.object({
74455
+ prompt: external_exports.string().describe("Text description of the image to generate or the edit to apply"),
74456
+ image: external_exports.string().optional().describe("Path to an existing image file to edit (use the path returned by a previous generate_image call, or a user-attached image path). When omitted, a new image is generated from scratch."),
74457
+ size: external_exports.string().optional().describe("Output resolution. gpt-image-2 accepts any size where both edges are multiples of 16px, max edge \u22643840px, long:short ratio \u22643:1, total pixels 655,360\u20138,294,400. Popular: 1024x1024, 1536x1024, 1024x1536, 2048x2048. Default: auto."),
74458
+ quality: external_exports.enum(["low", "medium", "high", "auto"]).optional().describe("Rendering quality. Use 'low' for fast drafts, 'high' for final assets. Default: auto."),
74459
+ n: external_exports.number().int().min(1).max(4).optional().describe("Number of images to generate (1\u20134, default 1)"),
74460
+ out_path: external_exports.string().optional().describe("Where to save the generated image (relative to cwd or absolute). Defaults to .gg/generated/<timestamp>.png"),
74461
+ output_format: external_exports.enum(["png", "jpeg", "webp"]).optional().describe("Output file format (default png)"),
74462
+ background: external_exports.enum(["opaque", "auto"]).optional().describe("Background type (default auto; gpt-image-2 does not support transparent)")
74463
+ });
74464
+ function defaultOutPath2(cwd2, format) {
74465
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
74466
+ const ext = format === "png" ? "png" : format === "jpeg" ? "jpg" : "webp";
74467
+ return path21.join(cwd2, ".gg", "generated", `${stamp}.${ext}`);
74468
+ }
74469
+ function mediaTypeFor(format) {
74470
+ if (format === "jpeg")
74471
+ return "image/jpeg";
74472
+ if (format === "webp")
74473
+ return "image/webp";
74474
+ return "image/png";
74475
+ }
74476
+ function createGenerateImageTool(cwd2, auth2) {
74477
+ return {
74478
+ name: "generate_image",
74479
+ description: "Generate or edit images using OpenAI's gpt-image-2 model. Works even when a different chat provider is active \u2014 only requires OpenAI to be connected. Only use this tool when the user explicitly asks to create, generate, or edit an image. Pass `image` with a file path to edit an existing image (e.g. a previously generated one or a user attachment). Use `out_path` to save to a specific location (defaults to .gg/generated/).",
74480
+ parameters: GenerateImageParams,
74481
+ async execute(args, context) {
74482
+ if (context.signal.aborted)
74483
+ return "Image generation aborted before start.";
74484
+ let token;
74485
+ let accountId;
74486
+ try {
74487
+ const creds = await auth2.resolveCredentials("openai");
74488
+ token = creds.accessToken;
74489
+ accountId = creds.accountId;
74490
+ } catch {
74491
+ return "OpenAI is not connected. The user needs to connect their OpenAI account to use image generation.";
74492
+ }
74493
+ const outputFormat = args.output_format ?? "png";
74494
+ const mediaType = mediaTypeFor(outputFormat);
74495
+ const outPath = args.out_path ? resolvePath(cwd2, args.out_path) : defaultOutPath2(cwd2, outputFormat);
74496
+ try {
74497
+ const imageTool = {
74498
+ type: "image_generation",
74499
+ output_format: outputFormat
74500
+ };
74501
+ if (args.size)
74502
+ imageTool.size = args.size;
74503
+ if (args.quality)
74504
+ imageTool.quality = args.quality;
74505
+ if (args.n)
74506
+ imageTool.n = args.n;
74507
+ if (args.background)
74508
+ imageTool.background = args.background;
74509
+ const inputContent = [
74510
+ { type: "input_text", text: args.prompt }
74511
+ ];
74512
+ if (args.image) {
74513
+ const imagePath = resolvePath(cwd2, args.image);
74514
+ let fileBuffer;
74515
+ try {
74516
+ fileBuffer = await readFile2(imagePath);
74517
+ } catch {
74518
+ return `Could not read the image at ${args.image}. Check the path is correct.`;
74519
+ }
74520
+ const refMediaType = imagePath.toLowerCase().endsWith(".jpg") || imagePath.toLowerCase().endsWith(".jpeg") ? "image/jpeg" : imagePath.toLowerCase().endsWith(".webp") ? "image/webp" : "image/png";
74521
+ inputContent.push({
74522
+ type: "input_image",
74523
+ image_url: `data:${refMediaType};base64,${fileBuffer.toString("base64")}`
74524
+ });
74525
+ imageTool.action = "edit";
74526
+ } else {
74527
+ imageTool.action = "generate";
74528
+ }
74529
+ const imageBuffers = await callImageGeneration(inputContent, imageTool, token, accountId, context.signal);
74530
+ if (imageBuffers.length === 0) {
74531
+ return "Image generation returned no results. The prompt may have been blocked by content moderation.";
74532
+ }
74533
+ const savedPaths = [];
74534
+ for (let i = 0; i < imageBuffers.length; i++) {
74535
+ const buf = imageBuffers[i];
74536
+ const savePath = imageBuffers.length === 1 ? outPath : insertIndex(outPath, i);
74537
+ await mkdir3(path21.dirname(savePath), { recursive: true });
74538
+ await writeFile3(savePath, buf);
74539
+ savedPaths.push(savePath);
74540
+ }
74541
+ const primary = imageBuffers[0];
74542
+ const primaryPath = savedPaths[0];
74543
+ const { buffer: shrunk, mediaType: detectedType } = await shrinkToFit(primary, mediaType);
74544
+ const previewBuffer = await downscaleForPreview(shrunk);
74545
+ const imagePreviews = [
74546
+ {
74547
+ base64: previewBuffer.toString("base64"),
74548
+ mediaType: detectedType,
74549
+ path: primaryPath
74550
+ }
74551
+ ];
74552
+ for (let i = 1; i < imageBuffers.length; i++) {
74553
+ const extraBuf = imageBuffers[i];
74554
+ const extraPath = savedPaths[i];
74555
+ const extraShrunk = await shrinkToFit(extraBuf, mediaType);
74556
+ const extraPreview = await downscaleForPreview(extraShrunk.buffer);
74557
+ imagePreviews.push({
74558
+ base64: extraPreview.toString("base64"),
74559
+ mediaType: extraShrunk.mediaType,
74560
+ path: extraPath
74561
+ });
74562
+ }
74563
+ const summary = savedPaths.length === 1 ? `Generated image \u2192 ${primaryPath}` : `Generated ${savedPaths.length} images \u2192 ${savedPaths.join(", ")}`;
74564
+ const allContent = [
74565
+ { type: "text", text: summary },
74566
+ {
74567
+ type: "image",
74568
+ mediaType: detectedType,
74569
+ data: shrunk.toString("base64")
74570
+ }
74571
+ ];
74572
+ return {
74573
+ content: allContent,
74574
+ details: { imagePreviews }
74575
+ };
74576
+ } catch (err) {
74577
+ if (context.signal.aborted)
74578
+ return "Image generation aborted.";
74579
+ const reason = err instanceof Error ? err.message : String(err);
74580
+ return `Image generation failed: ${reason}`;
74581
+ }
74582
+ }
74583
+ };
74584
+ }
74585
+ function insertIndex(filePath, index) {
74586
+ const ext = path21.extname(filePath);
74587
+ const base = filePath.slice(0, filePath.length - ext.length);
74588
+ return `${base}_${index}${ext}`;
74589
+ }
74590
+ async function callImageGeneration(inputContent, imageTool, token, accountId, signal) {
74591
+ const body = {
74592
+ model: IMAGE_GEN_MODEL,
74593
+ store: false,
74594
+ stream: true,
74595
+ instructions: "Generate the image the user requested.",
74596
+ input: [{ role: "user", content: inputContent }],
74597
+ tools: [imageTool],
74598
+ tool_choice: "auto",
74599
+ reasoning: { effort: "low" }
74600
+ };
74601
+ const response = await fetch(CODEX_ENDPOINT, {
74602
+ method: "POST",
74603
+ headers: {
74604
+ "Content-Type": "application/json",
74605
+ Authorization: `Bearer ${token}`,
74606
+ ...accountId ? { "chatgpt-account-id": accountId } : {},
74607
+ originator: "ggcoder"
74608
+ },
74609
+ body: JSON.stringify(body),
74610
+ signal
74611
+ });
74612
+ if (!response.ok) {
74613
+ const text = await response.text();
74614
+ let detail = text;
74615
+ try {
74616
+ const parsed = JSON.parse(text);
74617
+ if (parsed.detail)
74618
+ detail = parsed.detail;
74619
+ else if (parsed.error?.message)
74620
+ detail = parsed.error.message;
74621
+ } catch {
74622
+ }
74623
+ throw new Error(`OpenAI Image API (${response.status}): ${detail}`);
74624
+ }
74625
+ if (!response.body) {
74626
+ throw new Error("OpenAI Image API returned no response body.");
74627
+ }
74628
+ const reader = response.body.getReader();
74629
+ const decoder = new TextDecoder();
74630
+ let buffer = "";
74631
+ const imageBuffers = [];
74632
+ while (true) {
74633
+ const { done, value } = await reader.read();
74634
+ if (done)
74635
+ break;
74636
+ buffer += decoder.decode(value, { stream: true });
74637
+ const lines = buffer.split("\n");
74638
+ buffer = lines.pop() ?? "";
74639
+ for (const line of lines) {
74640
+ if (!line.startsWith("data: "))
74641
+ continue;
74642
+ const data = line.slice(6);
74643
+ if (data === "[DONE]")
74644
+ continue;
74645
+ try {
74646
+ const evt = JSON.parse(data);
74647
+ if (evt.type === "response.output_item.done" && evt.item?.type === "image_generation_call" && evt.item.result) {
74648
+ imageBuffers.push(Buffer.from(evt.item.result, "base64"));
74649
+ }
74650
+ } catch {
74651
+ }
74652
+ }
74653
+ }
74654
+ return imageBuffers;
74655
+ }
74656
+
74195
74657
  // ../ggcoder/dist/tools/enter-plan.js
74196
74658
  init_esm_shims();
74197
74659
  var EnterPlanParams = external_exports.object({
@@ -74213,7 +74675,7 @@ function createEnterPlanTool(onEnterPlan) {
74213
74675
  // ../ggcoder/dist/tools/exit-plan.js
74214
74676
  init_esm_shims();
74215
74677
  import fs15 from "fs/promises";
74216
- import path20 from "path";
74678
+ import path23 from "path";
74217
74679
  var ExitPlanParams = external_exports.object({
74218
74680
  plan_path: external_exports.string().describe("Path to the plan markdown file; must be under .gg/plans/")
74219
74681
  });
@@ -74225,9 +74687,9 @@ function createExitPlanTool(cwd2, onExitPlan) {
74225
74687
  executionMode: "sequential",
74226
74688
  async execute({ plan_path }) {
74227
74689
  const resolved = resolvePath(cwd2, plan_path);
74228
- const plansDir = path20.join(cwd2, ".gg", "plans");
74229
- const relative = path20.relative(plansDir, resolved);
74230
- if (relative.startsWith("..") || path20.isAbsolute(relative)) {
74690
+ const plansDir = path23.join(cwd2, ".gg", "plans");
74691
+ const relative = path23.relative(plansDir, resolved);
74692
+ if (relative.startsWith("..") || path23.isAbsolute(relative)) {
74231
74693
  return `Error: plan_path must be under .gg/plans/. Got: ${plan_path}`;
74232
74694
  }
74233
74695
  try {
@@ -74244,7 +74706,7 @@ function createExitPlanTool(cwd2, onExitPlan) {
74244
74706
  }
74245
74707
 
74246
74708
  // ../ggcoder/dist/tools/index.js
74247
- function createTools(cwd2, opts) {
74709
+ async function createTools(cwd2, opts) {
74248
74710
  const readFiles = /* @__PURE__ */ new Map();
74249
74711
  const processManager = new ProcessManager();
74250
74712
  const ops = opts?.operations ?? localOperations;
@@ -74284,6 +74746,14 @@ function createTools(cwd2, opts) {
74284
74746
  if (opts?.onExitPlan) {
74285
74747
  tools.push(createExitPlanTool(cwd2, opts.onExitPlan));
74286
74748
  }
74749
+ if (opts?.authStorage) {
74750
+ try {
74751
+ if (await opts.authStorage.hasProviderAuth("openai")) {
74752
+ tools.push(createGenerateImageTool(cwd2, opts.authStorage));
74753
+ }
74754
+ } catch {
74755
+ }
74756
+ }
74287
74757
  const rebuildReadTool = (model) => createReadTool(cwd2, readFiles, ops, opts?.onFileRead, getVideoByteLimit(model));
74288
74758
  return { tools, processManager, rebuildReadTool, lspManager };
74289
74759
  }
@@ -74291,18 +74761,18 @@ function createTools(cwd2, opts) {
74291
74761
  // ../ggcoder/dist/system-prompt.js
74292
74762
  init_esm_shims();
74293
74763
  import fs20 from "fs/promises";
74294
- import path26 from "path";
74764
+ import path28 from "path";
74295
74765
 
74296
74766
  // ../ggcoder/dist/core/skills.js
74297
74767
  init_esm_shims();
74298
74768
  import fs16 from "fs/promises";
74299
- import path21 from "path";
74769
+ import path24 from "path";
74300
74770
  async function discoverSkills(options) {
74301
74771
  const skills = [];
74302
74772
  const globalSkills = await loadSkillsFromDir(options.globalSkillsDir, "global");
74303
74773
  skills.push(...globalSkills);
74304
74774
  if (options.projectDir) {
74305
- const projectSkillsDir = path21.join(options.projectDir, ".gg", "skills");
74775
+ const projectSkillsDir = path24.join(options.projectDir, ".gg", "skills");
74306
74776
  const projectSkills = await loadSkillsFromDir(projectSkillsDir, "project");
74307
74777
  skills.push(...projectSkills);
74308
74778
  }
@@ -74317,20 +74787,20 @@ async function loadSkillsFromDir(dir, source2) {
74317
74787
  return skills;
74318
74788
  }
74319
74789
  for (const entry of dirents) {
74320
- const entryPath = path21.join(dir, entry.name);
74790
+ const entryPath = path24.join(dir, entry.name);
74321
74791
  if (entry.isFile() && entry.name.endsWith(".md")) {
74322
74792
  try {
74323
74793
  const content = await fs16.readFile(entryPath, "utf-8");
74324
74794
  const skill = parseSkillFile(content, source2);
74325
74795
  if (!skill.name)
74326
- skill.name = path21.basename(entry.name, ".md");
74796
+ skill.name = path24.basename(entry.name, ".md");
74327
74797
  skills.push(skill);
74328
74798
  } catch {
74329
74799
  }
74330
74800
  continue;
74331
74801
  }
74332
74802
  if (entry.isDirectory()) {
74333
- const skillFile = path21.join(entryPath, "SKILL.md");
74803
+ const skillFile = path24.join(entryPath, "SKILL.md");
74334
74804
  try {
74335
74805
  const content = await fs16.readFile(skillFile, "utf-8");
74336
74806
  const skill = parseSkillFile(content, source2);
@@ -74391,6 +74861,7 @@ var TOOL_PROMPT_HINTS = {
74391
74861
  exit_plan: "Submit a .gg/plans/ markdown plan for user approval and leave plan mode.",
74392
74862
  subagent: "Delegate focused, isolated subtasks (research, parallel exploration).",
74393
74863
  skill: "Invoke a named skill for specialized instructions.",
74864
+ generate_image: "Generate or edit images using OpenAI's gpt-image-2 model. Only use when the user explicitly asks to create or edit an image \u2014 never generate images proactively. Requires OpenAI to be connected. Pass `image` with a file path to edit an existing image. Save with `out_path`.",
74394
74865
  "mcp__kencode-search__referenceSources": "Get curated, categorized reference repos for examples, inspiration, architecture, UI, agents, SaaS, workflows, and domain patterns. Repo-only starting points; fetch docs/source, then verify code with searchCode.",
74395
74866
  "mcp__kencode-search__discoverRepos": "Search GitHub repos live by keyword/language/topic/stars/recency. Use for current/top repos or long-tail discovery; returns metadata, not snippets. Follow with docs/source and searchCode.",
74396
74867
  "mcp__kencode-search__searchCode": "Verify public GitHub code by literal text or RE2 regex; NOT semantic. Put code/import/API tokens in `query`; `path` is a literal file-path substring, not a concept. Start broad/peek, then narrow by repo/path. RE2 multi-line needs `(?s)`."
@@ -74425,6 +74896,7 @@ var DEFAULT_TOOL_NAMES = [
74425
74896
  "exit_plan",
74426
74897
  "subagent",
74427
74898
  "skill",
74899
+ "generate_image",
74428
74900
  "mcp__kencode-search__referenceSources",
74429
74901
  "mcp__kencode-search__discoverRepos",
74430
74902
  "mcp__kencode-search__searchCode"
@@ -74433,12 +74905,12 @@ var DEFAULT_TOOL_NAMES = [
74433
74905
  // ../ggcoder/dist/core/style-packs/index.js
74434
74906
  init_esm_shims();
74435
74907
  import fs18 from "fs";
74436
- import path24 from "path";
74908
+ import path26 from "path";
74437
74909
 
74438
74910
  // ../ggcoder/dist/core/language-detector.js
74439
74911
  init_esm_shims();
74440
74912
  import fs17 from "fs";
74441
- import path23 from "path";
74913
+ import path25 from "path";
74442
74914
  var MARKERS = {
74443
74915
  typescript: { manifests: ["tsconfig.json"], extensions: [".ts", ".tsx", ".mts", ".cts"] },
74444
74916
  // JS is only flagged when there's a package.json AND no tsconfig — pure JS projects.
@@ -74726,7 +75198,7 @@ var PACKS = {
74726
75198
 
74727
75199
  // ../ggcoder/dist/core/style-packs/index.js
74728
75200
  function loadPack(id2, cwd2) {
74729
- const overridePath = path24.join(cwd2, ".gg", "styles", `${id2}.md`);
75201
+ const overridePath = path26.join(cwd2, ".gg", "styles", `${id2}.md`);
74730
75202
  try {
74731
75203
  const stat = fs18.statSync(overridePath);
74732
75204
  if (stat.isFile()) {
@@ -74770,7 +75242,7 @@ Universal rules for agent-written code:
74770
75242
  // ../ggcoder/dist/core/verify-commands.js
74771
75243
  init_esm_shims();
74772
75244
  import fs19 from "fs";
74773
- import path25 from "path";
75245
+ import path27 from "path";
74774
75246
  function detectVerifyCommands(cwd2, active) {
74775
75247
  const cmds = [];
74776
75248
  if (active.has("typescript") || active.has("javascript")) {
@@ -74797,12 +75269,12 @@ function detectVerifyCommands(cwd2, active) {
74797
75269
  const testScript = pick2("test", "test:unit");
74798
75270
  if (testScript)
74799
75271
  cmds.push({ label: "test", command: `${runner} ${testScript}`, language: lang });
74800
- } else if (active.has("typescript") && fileExists2(path25.join(cwd2, "tsconfig.json"))) {
75272
+ } else if (active.has("typescript") && fileExists2(path27.join(cwd2, "tsconfig.json"))) {
74801
75273
  cmds.push({ label: "typecheck", command: "tsc --noEmit", language: "typescript" });
74802
75274
  }
74803
75275
  }
74804
75276
  if (active.has("python")) {
74805
- const pyproject = readFileSafe(path25.join(cwd2, "pyproject.toml"));
75277
+ const pyproject = readFileSafe(path27.join(cwd2, "pyproject.toml"));
74806
75278
  if (pyproject) {
74807
75279
  if (/\[tool\.ruff/.test(pyproject)) {
74808
75280
  cmds.push({ label: "lint", command: "ruff check .", language: "python" });
@@ -74834,10 +75306,10 @@ function detectVerifyCommands(cwd2, active) {
74834
75306
  }
74835
75307
  if (active.has("java") || active.has("kotlin")) {
74836
75308
  const lang = active.has("kotlin") ? "kotlin" : "java";
74837
- if (fileExists2(path25.join(cwd2, "gradlew"))) {
75309
+ if (fileExists2(path27.join(cwd2, "gradlew"))) {
74838
75310
  cmds.push({ label: "build", command: "./gradlew build", language: lang });
74839
75311
  cmds.push({ label: "test", command: "./gradlew test", language: lang });
74840
- } else if (fileExists2(path25.join(cwd2, "pom.xml"))) {
75312
+ } else if (fileExists2(path27.join(cwd2, "pom.xml"))) {
74841
75313
  cmds.push({ label: "verify", command: "mvn verify", language: lang });
74842
75314
  }
74843
75315
  }
@@ -74851,7 +75323,7 @@ function detectVerifyCommands(cwd2, active) {
74851
75323
  cmds.push({ label: "test", command: "dotnet test", language: "csharp" });
74852
75324
  }
74853
75325
  if (active.has("ruby")) {
74854
- if (fileExists2(path25.join(cwd2, "Gemfile"))) {
75326
+ if (fileExists2(path27.join(cwd2, "Gemfile"))) {
74855
75327
  cmds.push({ label: "lint", command: "bundle exec rubocop", language: "ruby" });
74856
75328
  cmds.push({ label: "test", command: "bundle exec rspec", language: "ruby" });
74857
75329
  }
@@ -74861,7 +75333,7 @@ function detectVerifyCommands(cwd2, active) {
74861
75333
  cmds.push({ label: "test", command: "mix test", language: "elixir" });
74862
75334
  }
74863
75335
  if (active.has("php")) {
74864
- if (fileExists2(path25.join(cwd2, "composer.json"))) {
75336
+ if (fileExists2(path27.join(cwd2, "composer.json"))) {
74865
75337
  cmds.push({ label: "test", command: "composer test", language: "php" });
74866
75338
  }
74867
75339
  }
@@ -74893,7 +75365,7 @@ function readFileSafe(p) {
74893
75365
  }
74894
75366
  }
74895
75367
  function readPackageJsonScripts(cwd2) {
74896
- const raw = readFileSafe(path25.join(cwd2, "package.json"));
75368
+ const raw = readFileSafe(path27.join(cwd2, "package.json"));
74897
75369
  if (!raw)
74898
75370
  return null;
74899
75371
  try {
@@ -74904,11 +75376,11 @@ function readPackageJsonScripts(cwd2) {
74904
75376
  }
74905
75377
  }
74906
75378
  function detectNodeRunner(cwd2) {
74907
- if (fileExists2(path25.join(cwd2, "pnpm-lock.yaml")))
75379
+ if (fileExists2(path27.join(cwd2, "pnpm-lock.yaml")))
74908
75380
  return "pnpm";
74909
- if (fileExists2(path25.join(cwd2, "yarn.lock")))
75381
+ if (fileExists2(path27.join(cwd2, "yarn.lock")))
74910
75382
  return "yarn";
74911
- if (fileExists2(path25.join(cwd2, "bun.lockb")))
75383
+ if (fileExists2(path27.join(cwd2, "bun.lockb")))
74912
75384
  return "bun";
74913
75385
  return "npm run";
74914
75386
  }
@@ -75068,17 +75540,17 @@ async function collectProjectContext(cwd2) {
75068
75540
  while (!visited.has(dir)) {
75069
75541
  visited.add(dir);
75070
75542
  for (const name of CONTEXT_FILES) {
75071
- const filePath = path26.join(dir, name);
75543
+ const filePath = path28.join(dir, name);
75072
75544
  try {
75073
75545
  const content = await fs20.readFile(filePath, "utf-8");
75074
- const relPath = path26.relative(cwd2, filePath) || name;
75546
+ const relPath = path28.relative(cwd2, filePath) || name;
75075
75547
  contextParts.push(`### ${relPath}
75076
75548
 
75077
75549
  ${content.trim()}`);
75078
75550
  } catch {
75079
75551
  }
75080
75552
  }
75081
- const parent = path26.dirname(dir);
75553
+ const parent = path28.dirname(dir);
75082
75554
  if (parent === dir)
75083
75555
  break;
75084
75556
  dir = parent;
@@ -75145,10 +75617,10 @@ async function buildSystemPrompt(cwd2, skills, planMode, approvedPlanPath, toolN
75145
75617
  // ../ggcoder/dist/session.js
75146
75618
  init_esm_shims();
75147
75619
  import fs21 from "fs/promises";
75148
- import path27 from "path";
75620
+ import path29 from "path";
75149
75621
  import os7 from "os";
75150
75622
  import crypto4 from "crypto";
75151
- var SESSION_DIR = path27.join(os7.homedir(), ".gg", "sessions");
75623
+ var SESSION_DIR = path29.join(os7.homedir(), ".gg", "sessions");
75152
75624
 
75153
75625
  // ../ggcoder/dist/core/index.js
75154
75626
  init_esm_shims();
@@ -75266,7 +75738,7 @@ import fs23 from "fs/promises";
75266
75738
 
75267
75739
  // ../ggcoder/dist/config.js
75268
75740
  init_esm_shims();
75269
- import path28 from "path";
75741
+ import path30 from "path";
75270
75742
  import fs22 from "fs/promises";
75271
75743
  import fsSync from "fs";
75272
75744
  async function ensureAppDirs() {
@@ -75332,7 +75804,7 @@ Rules:
75332
75804
  `
75333
75805
  };
75334
75806
  for (const [filename, content] of Object.entries(defaults2)) {
75335
- const filePath = path28.join(agentsDir, filename);
75807
+ const filePath = path30.join(agentsDir, filename);
75336
75808
  try {
75337
75809
  await fs22.access(filePath);
75338
75810
  } catch {
@@ -75345,7 +75817,7 @@ async function seedDefaultSkills(skillsDir) {
75345
75817
  "find-skills.md": FIND_SKILLS_MD
75346
75818
  };
75347
75819
  for (const [filename, content] of Object.entries(defaults2)) {
75348
- const filePath = path28.join(skillsDir, filename);
75820
+ const filePath = path30.join(skillsDir, filename);
75349
75821
  try {
75350
75822
  await fs22.access(filePath);
75351
75823
  } catch {
@@ -75472,7 +75944,11 @@ var SettingsSchema = external_exports.object({
75472
75944
  lspDiagnostics: external_exports.boolean().default(true),
75473
75945
  enabledTools: external_exports.array(external_exports.string()).optional(),
75474
75946
  /** Delete session transcripts older than this many days at startup. 0 disables pruning. */
75475
- sessionRetentionDays: external_exports.number().int().min(0).default(30)
75947
+ sessionRetentionDays: external_exports.number().int().min(0).default(30),
75948
+ /** Speed optimization profile.
75949
+ * - "baseline": 5-min cache TTL, no pre-warm
75950
+ * - "optimized": 1-h cache TTL, cache pre-warming on first prompt (default) */
75951
+ speedProfile: external_exports.enum(["baseline", "optimized"]).default("optimized")
75476
75952
  });
75477
75953
  var DEFAULT_SETTINGS = {
75478
75954
  autoCompact: true,
@@ -75484,7 +75960,8 @@ var DEFAULT_SETTINGS = {
75484
75960
  showTokenUsage: true,
75485
75961
  idealReviewEnabled: true,
75486
75962
  lspDiagnostics: true,
75487
- sessionRetentionDays: 30
75963
+ sessionRetentionDays: 30,
75964
+ speedProfile: "optimized"
75488
75965
  };
75489
75966
  var SettingsManager = class {
75490
75967
  settings = { ...DEFAULT_SETTINGS };
@@ -75525,7 +76002,7 @@ init_esm_shims();
75525
76002
  import fs24 from "fs/promises";
75526
76003
  import { createReadStream as createReadStream2 } from "fs";
75527
76004
  import { createInterface as createInterface2 } from "readline";
75528
- import path29 from "path";
76005
+ import path31 from "path";
75529
76006
  import crypto6 from "crypto";
75530
76007
  var DISPLAY_ITEM_CUSTOM_KIND = "display_item";
75531
76008
  function isCompletedItemLike(value) {
@@ -75560,7 +76037,7 @@ var SessionManager = class _SessionManager {
75560
76037
  this.onPersistError?.(err);
75561
76038
  }
75562
76039
  dirForCwd(cwd2) {
75563
- return path29.join(this.sessionsDir, encodeCwd(cwd2));
76040
+ return path31.join(this.sessionsDir, encodeCwd(cwd2));
75564
76041
  }
75565
76042
  async create(cwd2, provider, model) {
75566
76043
  const id2 = crypto6.randomUUID();
@@ -75568,7 +76045,7 @@ var SessionManager = class _SessionManager {
75568
76045
  const dir = this.dirForCwd(cwd2);
75569
76046
  await fs24.mkdir(dir, { recursive: true });
75570
76047
  const fileName = `${timestamp.replace(/[:.]/g, "-")}_${id2.slice(0, 8)}.jsonl`;
75571
- const filePath = path29.join(dir, fileName);
76048
+ const filePath = path31.join(dir, fileName);
75572
76049
  const header = {
75573
76050
  type: "session",
75574
76051
  version: 2,
@@ -75640,7 +76117,7 @@ var SessionManager = class _SessionManager {
75640
76117
  for (const file2 of files) {
75641
76118
  if (!file2.endsWith(".jsonl"))
75642
76119
  continue;
75643
- const filePath = path29.join(dir, file2);
76120
+ const filePath = path31.join(dir, file2);
75644
76121
  try {
75645
76122
  const rl = createInterface2({
75646
76123
  input: createReadStream2(filePath, { encoding: "utf-8" }),
@@ -75703,7 +76180,7 @@ var SessionManager = class _SessionManager {
75703
76180
  if (options.maxAgeDays <= 0)
75704
76181
  return result;
75705
76182
  const cutoffMs = Date.now() - options.maxAgeDays * 864e5;
75706
- const keep = new Set((options.keepPaths ?? []).map((p) => path29.resolve(p)));
76183
+ const keep = new Set((options.keepPaths ?? []).map((p) => path31.resolve(p)));
75707
76184
  let cwdDirs;
75708
76185
  try {
75709
76186
  cwdDirs = await fs24.readdir(this.sessionsDir);
@@ -75711,7 +76188,7 @@ var SessionManager = class _SessionManager {
75711
76188
  return result;
75712
76189
  }
75713
76190
  for (const dirName of cwdDirs) {
75714
- const dir = path29.join(this.sessionsDir, dirName);
76191
+ const dir = path31.join(this.sessionsDir, dirName);
75715
76192
  let files;
75716
76193
  try {
75717
76194
  const stat = await fs24.stat(dir);
@@ -75725,8 +76202,8 @@ var SessionManager = class _SessionManager {
75725
76202
  for (const file2 of files) {
75726
76203
  if (!file2.endsWith(".jsonl"))
75727
76204
  continue;
75728
- const filePath = path29.join(dir, file2);
75729
- if (keep.has(path29.resolve(filePath)))
76205
+ const filePath = path31.join(dir, file2);
76206
+ if (keep.has(path31.resolve(filePath)))
75730
76207
  continue;
75731
76208
  try {
75732
76209
  const stat = await fs24.stat(filePath);
@@ -76726,9 +77203,9 @@ function getPromptCommand(name) {
76726
77203
  // ../ggcoder/dist/core/custom-commands.js
76727
77204
  init_esm_shims();
76728
77205
  import fs25 from "fs/promises";
76729
- import path30 from "path";
77206
+ import path33 from "path";
76730
77207
  async function loadCustomCommands(cwd2) {
76731
- const commandsDir = path30.join(cwd2, ".gg", "commands");
77208
+ const commandsDir = path33.join(cwd2, ".gg", "commands");
76732
77209
  const commands = [];
76733
77210
  let files;
76734
77211
  try {
@@ -76739,11 +77216,11 @@ async function loadCustomCommands(cwd2) {
76739
77216
  for (const file2 of files) {
76740
77217
  if (!file2.endsWith(".md"))
76741
77218
  continue;
76742
- const filePath = path30.join(commandsDir, file2);
77219
+ const filePath = path33.join(commandsDir, file2);
76743
77220
  try {
76744
77221
  const raw = await fs25.readFile(filePath, "utf-8");
76745
77222
  const parsed = parseSkillFile(raw, "project");
76746
- const name = parsed.name || path30.basename(file2, ".md");
77223
+ const name = parsed.name || path33.basename(file2, ".md");
76747
77224
  commands.push({
76748
77225
  name,
76749
77226
  description: parsed.description || `Custom command from .gg/commands/${file2}`,
@@ -76765,7 +77242,7 @@ init_esm_shims();
76765
77242
  // ../ggcoder/dist/core/extensions/loader.js
76766
77243
  init_esm_shims();
76767
77244
  import fs26 from "fs/promises";
76768
- import path31 from "path";
77245
+ import path34 from "path";
76769
77246
  var ExtensionLoader = class {
76770
77247
  loaded = [];
76771
77248
  async loadAll(extensionsDir, context) {
@@ -76778,7 +77255,7 @@ var ExtensionLoader = class {
76778
77255
  for (const file2 of files) {
76779
77256
  if (!file2.endsWith(".js"))
76780
77257
  continue;
76781
- const filePath = path31.join(extensionsDir, file2);
77258
+ const filePath = path34.join(extensionsDir, file2);
76782
77259
  try {
76783
77260
  const mod = await import(filePath);
76784
77261
  const factory = typeof mod.default === "function" ? mod.default : mod.createExtension;
@@ -83012,7 +83489,171 @@ var StdioClientTransport = class {
83012
83489
  };
83013
83490
 
83014
83491
  // ../ggcoder/dist/core/mcp/client.js
83492
+ import http from "http";
83015
83493
  import os8 from "os";
83494
+
83495
+ // ../ggcoder/dist/core/mcp/oauth-provider.js
83496
+ init_esm_shims();
83497
+ import crypto8 from "crypto";
83498
+
83499
+ // ../ggcoder/dist/core/mcp/oauth-store.js
83500
+ init_esm_shims();
83501
+ import fs27 from "fs/promises";
83502
+ var McpOAuthStore = class {
83503
+ filePath;
83504
+ constructor(filePath = getAppPaths().mcpAuthFile) {
83505
+ this.filePath = filePath;
83506
+ }
83507
+ async readAll() {
83508
+ try {
83509
+ const raw = await fs27.readFile(this.filePath, "utf-8");
83510
+ const parsed = JSON.parse(raw);
83511
+ return { version: 1, servers: parsed.servers ?? {} };
83512
+ } catch {
83513
+ return { version: 1, servers: {} };
83514
+ }
83515
+ }
83516
+ async writeAll(data) {
83517
+ try {
83518
+ await fs27.writeFile(this.filePath, JSON.stringify(data, null, 2), {
83519
+ encoding: "utf-8",
83520
+ mode: 384
83521
+ });
83522
+ } catch (err) {
83523
+ log("WARN", "mcp", "failed to persist MCP OAuth store", {
83524
+ message: err instanceof Error ? err.message : String(err)
83525
+ });
83526
+ }
83527
+ }
83528
+ async get(name) {
83529
+ const all = await this.readAll();
83530
+ return all.servers[name] ?? {};
83531
+ }
83532
+ /** Merge a partial entry into the server's record (read-modify-write). */
83533
+ async patch(name, patch) {
83534
+ const all = await this.readAll();
83535
+ all.servers[name] = { ...all.servers[name] ?? {}, ...patch };
83536
+ await this.writeAll(all);
83537
+ }
83538
+ /** Drop a server's whole OAuth record (used on logout / removal). */
83539
+ async clear(name) {
83540
+ const all = await this.readAll();
83541
+ if (all.servers[name]) {
83542
+ delete all.servers[name];
83543
+ await this.writeAll(all);
83544
+ }
83545
+ }
83546
+ /** Whether this server has saved tokens (i.e. has completed login at least once). */
83547
+ async hasTokens(name) {
83548
+ const entry = await this.get(name);
83549
+ return !!entry.tokens?.access_token;
83550
+ }
83551
+ };
83552
+
83553
+ // ../ggcoder/dist/core/mcp/oauth-provider.js
83554
+ var MCP_OAUTH_CALLBACK_PORT = 41999;
83555
+ var MCP_OAUTH_CALLBACK_PATH = "/oauth/callback";
83556
+ function mcpOAuthRedirectUrl() {
83557
+ return `http://localhost:${MCP_OAUTH_CALLBACK_PORT}${MCP_OAUTH_CALLBACK_PATH}`;
83558
+ }
83559
+ var McpOAuthProvider = class {
83560
+ store;
83561
+ serverName;
83562
+ onRedirect;
83563
+ scope;
83564
+ constructor(opts) {
83565
+ this.serverName = opts.serverName;
83566
+ this.store = opts.store ?? new McpOAuthStore();
83567
+ this.onRedirect = opts.onRedirect;
83568
+ this.scope = opts.scope;
83569
+ }
83570
+ get redirectUrl() {
83571
+ return mcpOAuthRedirectUrl();
83572
+ }
83573
+ get clientMetadata() {
83574
+ return {
83575
+ client_name: "GG Coder",
83576
+ client_uri: "https://github.com/kenkaiii/gg-coder",
83577
+ redirect_uris: [this.redirectUrl],
83578
+ grant_types: ["authorization_code", "refresh_token"],
83579
+ response_types: ["code"],
83580
+ token_endpoint_auth_method: "none",
83581
+ ...this.scope ? { scope: this.scope } : {}
83582
+ };
83583
+ }
83584
+ async state() {
83585
+ const entry = await this.store.get(this.serverName);
83586
+ if (entry.state)
83587
+ return entry.state;
83588
+ const fresh = crypto8.randomBytes(16).toString("hex");
83589
+ await this.store.patch(this.serverName, { state: fresh });
83590
+ return fresh;
83591
+ }
83592
+ async clientInformation() {
83593
+ const entry = await this.store.get(this.serverName);
83594
+ return entry.clientInformation;
83595
+ }
83596
+ async saveClientInformation(info) {
83597
+ await this.store.patch(this.serverName, {
83598
+ clientInformation: info
83599
+ });
83600
+ }
83601
+ async tokens() {
83602
+ const entry = await this.store.get(this.serverName);
83603
+ return entry.tokens;
83604
+ }
83605
+ async saveTokens(tokens2) {
83606
+ await this.store.patch(this.serverName, { tokens: tokens2 });
83607
+ }
83608
+ redirectToAuthorization(authorizationUrl) {
83609
+ this.onRedirect?.(authorizationUrl);
83610
+ }
83611
+ async saveCodeVerifier(codeVerifier) {
83612
+ await this.store.patch(this.serverName, { codeVerifier });
83613
+ }
83614
+ async codeVerifier() {
83615
+ const entry = await this.store.get(this.serverName);
83616
+ if (!entry.codeVerifier) {
83617
+ throw new Error("No PKCE code verifier saved for this MCP server.");
83618
+ }
83619
+ return entry.codeVerifier;
83620
+ }
83621
+ };
83622
+
83623
+ // ../ggcoder/dist/core/mcp/loopback.js
83624
+ init_esm_shims();
83625
+ function isLocalhost(url2) {
83626
+ const h = normalizeHost(url2.hostname);
83627
+ return h === "localhost" || h === "127.0.0.1" || h === "::1" || h === "0.0.0.0";
83628
+ }
83629
+ function alternateLoopback(hostname4) {
83630
+ const h = normalizeHost(hostname4);
83631
+ if (h === "localhost")
83632
+ return "127.0.0.1";
83633
+ if (h === "127.0.0.1")
83634
+ return "localhost";
83635
+ if (h === "::1")
83636
+ return "127.0.0.1";
83637
+ if (h === "0.0.0.0")
83638
+ return "127.0.0.1";
83639
+ return void 0;
83640
+ }
83641
+ function normalizeHost(hostname4) {
83642
+ let h = hostname4.toLowerCase();
83643
+ if (h.startsWith("[") && h.endsWith("]"))
83644
+ h = h.slice(1, -1);
83645
+ return h;
83646
+ }
83647
+ function isNetworkError(err) {
83648
+ if (err == null)
83649
+ return false;
83650
+ const msg = err instanceof Error ? err.message : String(err);
83651
+ const cause = err.cause;
83652
+ const text = `${msg} ${cause?.message ?? ""} ${cause?.code ?? ""}`.toLowerCase();
83653
+ return text.includes("econnrefused") || text.includes("econnreset") || text.includes("enotfound") || text.includes("eai_again") || text.includes("fetch failed") || text.includes("failed to fetch") || text.includes("connection refused") || text.includes("network request failed") || text.includes("sse error");
83654
+ }
83655
+
83656
+ // ../ggcoder/dist/core/mcp/client.js
83016
83657
  var MCPClientManager = class {
83017
83658
  servers = [];
83018
83659
  async connectAll(configs) {
@@ -83034,9 +83675,10 @@ var MCPClientManager = class {
83034
83675
  if (result.status === "fulfilled") {
83035
83676
  return { name, ok: true, toolCount: result.value.length, tools: result.value };
83036
83677
  }
83037
- const error51 = formatConnectError(result.reason);
83678
+ const requiresAuth = isUnauthorized(result.reason);
83679
+ const error51 = requiresAuth ? "Requires login." : formatConnectError(result.reason);
83038
83680
  log("WARN", "mcp", `Failed to connect to MCP server "${name}"`, { error: error51 });
83039
- return { name, ok: false, toolCount: 0, tools: [], error: error51 };
83681
+ return { name, ok: false, toolCount: 0, tools: [], error: error51, requiresAuth };
83040
83682
  });
83041
83683
  const connected = results.filter((r2) => r2.ok).length;
83042
83684
  const toolCount = results.reduce((sum, r2) => sum + r2.toolCount, 0);
@@ -83061,8 +83703,120 @@ var MCPClientManager = class {
83061
83703
  }
83062
83704
  return { name: config2.name, ok: true, toolCount: tools.length, tools };
83063
83705
  } catch (err) {
83064
- const error51 = formatConnectError(err);
83065
- return { name: config2.name, ok: false, toolCount: 0, tools: [], error: error51 };
83706
+ const requiresAuth = isUnauthorized(err);
83707
+ const error51 = requiresAuth ? "Requires login." : formatConnectError(err);
83708
+ return { name: config2.name, ok: false, toolCount: 0, tools: [], error: error51, requiresAuth };
83709
+ }
83710
+ }
83711
+ /**
83712
+ * Run the interactive OAuth login for one remote MCP server end-to-end:
83713
+ * start a loopback callback server, let the SDK open the browser via
83714
+ * `onAuthorizationUrl`, capture the redirect, exchange the code, then verify
83715
+ * the authorized connection by listing tools. Tokens are persisted by the
83716
+ * provider so later (non-interactive) connects succeed silently.
83717
+ *
83718
+ * `onAuthorizationUrl` is invoked with the authorize URL so the host can open
83719
+ * it (the gg-app broadcasts it to the webview, which opens the system
83720
+ * browser; the CLI prints it). Never throws — returns `{ ok:false, error }`.
83721
+ */
83722
+ async login(config2, onAuthorizationUrl, timeoutMs = 18e4) {
83723
+ if (!config2.url) {
83724
+ return { ok: false, toolCount: 0, error: "Login is only supported for HTTP MCP servers." };
83725
+ }
83726
+ const url2 = new URL(config2.url);
83727
+ const store2 = new McpOAuthStore();
83728
+ await store2.patch(config2.name, { codeVerifier: void 0, state: void 0 });
83729
+ let codeResolve;
83730
+ let codeReject;
83731
+ const codePromise = new Promise((resolve2, reject) => {
83732
+ codeResolve = resolve2;
83733
+ codeReject = reject;
83734
+ });
83735
+ const provider = new McpOAuthProvider({
83736
+ serverName: config2.name,
83737
+ store: store2,
83738
+ onRedirect: (authUrl) => onAuthorizationUrl(authUrl.toString())
83739
+ });
83740
+ const expectedState = await provider.state();
83741
+ const server = http.createServer((req, res) => {
83742
+ const reqUrl = new URL(req.url || "", `http://localhost:${MCP_OAUTH_CALLBACK_PORT}`);
83743
+ if (reqUrl.pathname !== MCP_OAUTH_CALLBACK_PATH) {
83744
+ res.statusCode = 404;
83745
+ res.end("Not found");
83746
+ return;
83747
+ }
83748
+ const err = reqUrl.searchParams.get("error");
83749
+ const code = reqUrl.searchParams.get("code");
83750
+ const state3 = reqUrl.searchParams.get("state");
83751
+ res.writeHead(200, { "Content-Type": "text/html" });
83752
+ if (err) {
83753
+ res.end(`<html><body><h1>Login failed</h1><p>${escapeHtml(err)}</p></body></html>`);
83754
+ codeReject?.(new Error(`Authorization failed: ${err}`));
83755
+ return;
83756
+ }
83757
+ if (!code) {
83758
+ res.end("<html><body><h1>Login failed</h1><p>No authorization code.</p></body></html>");
83759
+ codeReject?.(new Error("No authorization code in callback."));
83760
+ return;
83761
+ }
83762
+ if (state3 !== expectedState) {
83763
+ res.end("<html><body><h1>Login failed</h1><p>State mismatch.</p></body></html>");
83764
+ codeReject?.(new Error("OAuth state mismatch."));
83765
+ return;
83766
+ }
83767
+ res.end("<html><body><h1>Login successful!</h1><p>You can close this tab and return to GG Coder.</p></body></html>");
83768
+ codeResolve?.(code);
83769
+ });
83770
+ try {
83771
+ await new Promise((resolve2, reject) => {
83772
+ server.once("error", reject);
83773
+ server.listen(MCP_OAUTH_CALLBACK_PORT, "127.0.0.1", () => resolve2());
83774
+ });
83775
+ } catch (err) {
83776
+ const msg = err instanceof Error ? err.message : String(err);
83777
+ const hint = msg.includes("EADDRINUSE") || msg.includes("in use") ? `Port ${MCP_OAUTH_CALLBACK_PORT} is in use \u2014 close whatever is using it and retry.` : msg;
83778
+ return { ok: false, toolCount: 0, error: `Could not start login callback server: ${hint}` };
83779
+ }
83780
+ const overallTimeout = setTimeout(() => {
83781
+ codeReject?.(new Error("Login timed out waiting for the browser callback."));
83782
+ }, timeoutMs);
83783
+ overallTimeout.unref();
83784
+ try {
83785
+ const loginTransport = new StreamableHTTPClientTransport(url2, {
83786
+ requestInit: config2.headers ? { headers: config2.headers } : void 0,
83787
+ authProvider: provider
83788
+ });
83789
+ const loginClient = new Client({ name: "ggcoder", version: "1.0.0" });
83790
+ try {
83791
+ await loginClient.connect(loginTransport);
83792
+ const { tools: tools2 } = await loginClient.listTools();
83793
+ await loginClient.close().catch(() => {
83794
+ });
83795
+ return { ok: true, toolCount: tools2.length };
83796
+ } catch (err) {
83797
+ if (!isUnauthorized(err))
83798
+ throw err;
83799
+ }
83800
+ const code = await codePromise;
83801
+ await loginTransport.finishAuth(code);
83802
+ await loginClient.close().catch(() => {
83803
+ });
83804
+ const verifyTransport = new StreamableHTTPClientTransport(url2, {
83805
+ requestInit: config2.headers ? { headers: config2.headers } : void 0,
83806
+ authProvider: provider
83807
+ });
83808
+ const verifyClient = new Client({ name: "ggcoder", version: "1.0.0" });
83809
+ await verifyClient.connect(verifyTransport);
83810
+ const { tools } = await verifyClient.listTools();
83811
+ await verifyClient.close().catch(() => {
83812
+ });
83813
+ return { ok: true, toolCount: tools.length };
83814
+ } catch (err) {
83815
+ return { ok: false, toolCount: 0, error: formatConnectError(err) };
83816
+ } finally {
83817
+ clearTimeout(overallTimeout);
83818
+ server.close();
83819
+ await store2.patch(config2.name, { codeVerifier: void 0, state: void 0 });
83066
83820
  }
83067
83821
  }
83068
83822
  async connectServer(config2) {
@@ -83093,23 +83847,23 @@ var MCPClientManager = class {
83093
83847
  }
83094
83848
  } else {
83095
83849
  const url2 = new URL(config2.url);
83096
- const reqInit = config2.headers ? { headers: config2.headers } : void 0;
83850
+ const isLocal = isLocalhost(url2);
83097
83851
  try {
83098
- transport = new StreamableHTTPClientTransport(url2, {
83099
- requestInit: reqInit
83100
- });
83101
- client = new Client({ name: "ggcoder", version: "1.0.0" });
83102
- await client.connect(transport, { timeout });
83103
- } catch (streamableErr) {
83104
- log("INFO", "mcp", `StreamableHTTP failed for "${config2.name}", trying SSE fallback`, {
83105
- error: String(streamableErr)
83106
- });
83107
- transport = new SSEClientTransport(url2, {
83108
- eventSourceInit: config2.headers ? { fetch: createHeaderFetch(config2.headers) } : void 0,
83109
- requestInit: reqInit
83852
+ const r2 = await this.connectHttp(url2, config2, isLocal, timeout);
83853
+ client = r2.client;
83854
+ transport = r2.transport;
83855
+ } catch (err) {
83856
+ const alt = isLocal ? alternateLoopback(url2.hostname) : void 0;
83857
+ if (!alt || !isNetworkError(err))
83858
+ throw err;
83859
+ log("INFO", "mcp", `localhost connect failed for "${config2.name}", retrying as ${alt}`, {
83860
+ error: String(err)
83110
83861
  });
83111
- client = new Client({ name: "ggcoder", version: "1.0.0" });
83112
- await client.connect(transport, { timeout });
83862
+ const altUrl = new URL(url2);
83863
+ altUrl.hostname = alt;
83864
+ const r2 = await this.connectHttp(altUrl, config2, isLocal, timeout);
83865
+ client = r2.client;
83866
+ transport = r2.transport;
83113
83867
  }
83114
83868
  }
83115
83869
  this.servers.push({ name: config2.name, client, transport, lastCallTime: 0 });
@@ -83154,6 +83908,50 @@ var MCPClientManager = class {
83154
83908
  };
83155
83909
  });
83156
83910
  }
83911
+ /**
83912
+ * Connect a single HTTP (Streamable HTTP or SSE) server and return the live
83913
+ * client + transport. Transport selection:
83914
+ * - `transport === "sse"` → legacy SSE directly (Playwright MCP `--port`).
83915
+ * - otherwise → Streamable HTTP first, SSE fallback for older servers.
83916
+ *
83917
+ * An OAuth provider is attached only for REMOTE servers — localhost never
83918
+ * needs OAuth and attaching it there is dead weight that can misdiagnose a
83919
+ * protocol mismatch as a login requirement.
83920
+ */
83921
+ async connectHttp(url2, config2, isLocal, timeout) {
83922
+ const reqInit = config2.headers ? { headers: config2.headers } : void 0;
83923
+ const authProvider = isLocal ? void 0 : new McpOAuthProvider({ serverName: config2.name });
83924
+ const sseTransport = () => new SSEClientTransport(url2, {
83925
+ eventSourceInit: config2.headers ? { fetch: createHeaderFetch(config2.headers) } : void 0,
83926
+ requestInit: reqInit,
83927
+ authProvider
83928
+ });
83929
+ if (config2.transport === "sse") {
83930
+ const transport = sseTransport();
83931
+ const client = new Client({ name: "ggcoder", version: "1.0.0" });
83932
+ await client.connect(transport, { timeout });
83933
+ return { client, transport };
83934
+ }
83935
+ try {
83936
+ const transport = new StreamableHTTPClientTransport(url2, {
83937
+ requestInit: reqInit,
83938
+ authProvider
83939
+ });
83940
+ const client = new Client({ name: "ggcoder", version: "1.0.0" });
83941
+ await client.connect(transport, { timeout });
83942
+ return { client, transport };
83943
+ } catch (streamableErr) {
83944
+ if (!isLocal && isUnauthorized(streamableErr))
83945
+ throw streamableErr;
83946
+ log("INFO", "mcp", `StreamableHTTP failed for "${config2.name}", trying SSE fallback`, {
83947
+ error: String(streamableErr)
83948
+ });
83949
+ const transport = sseTransport();
83950
+ const client = new Client({ name: "ggcoder", version: "1.0.0" });
83951
+ await client.connect(transport, { timeout });
83952
+ return { client, transport };
83953
+ }
83954
+ }
83157
83955
  async dispose() {
83158
83956
  for (const server of this.servers) {
83159
83957
  try {
@@ -83171,6 +83969,15 @@ function formatConnectError(reason) {
83171
83969
  }
83172
83970
  return msg;
83173
83971
  }
83972
+ function isUnauthorized(reason) {
83973
+ if (reason instanceof UnauthorizedError)
83974
+ return true;
83975
+ const msg = reason instanceof Error ? reason.message : String(reason);
83976
+ return msg.includes("Unauthorized") || msg.includes("401") || msg.toLowerCase().includes("invalid_token");
83977
+ }
83978
+ function escapeHtml(value) {
83979
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
83980
+ }
83174
83981
  function createHeaderFetch(extraHeaders) {
83175
83982
  return (url2, init) => {
83176
83983
  const existing = init?.headers ?? {};
@@ -83183,8 +83990,8 @@ init_esm_shims();
83183
83990
 
83184
83991
  // ../ggcoder/dist/core/mcp/store.js
83185
83992
  init_esm_shims();
83186
- import path33 from "path";
83187
- import fs27 from "fs/promises";
83993
+ import path35 from "path";
83994
+ import fs28 from "fs/promises";
83188
83995
  var StoredServerEntrySchema = external_exports.object({
83189
83996
  type: external_exports.enum(["stdio", "http", "streamable-http", "sse"]).optional(),
83190
83997
  url: external_exports.string().optional(),
@@ -83202,12 +84009,12 @@ function globalMcpPath() {
83202
84009
  return getAppPaths().mcpFile;
83203
84010
  }
83204
84011
  function projectMcpPath(cwd2) {
83205
- return path33.join(cwd2, ".gg", "mcp.json");
84012
+ return path35.join(cwd2, ".gg", "mcp.json");
83206
84013
  }
83207
84014
  async function readMcpFile(filePath) {
83208
84015
  let content;
83209
84016
  try {
83210
- content = await fs27.readFile(filePath, "utf-8");
84017
+ content = await fs28.readFile(filePath, "utf-8");
83211
84018
  } catch {
83212
84019
  return { mcpServers: {} };
83213
84020
  }
@@ -83227,6 +84034,10 @@ function fromStoredEntry(name, entry) {
83227
84034
  config2.url = entry.url;
83228
84035
  if (entry.headers)
83229
84036
  config2.headers = entry.headers;
84037
+ if (entry.type === "sse")
84038
+ config2.transport = "sse";
84039
+ else if (entry.type === "http" || entry.type === "streamable-http")
84040
+ config2.transport = "http";
83230
84041
  } else if (entry.command) {
83231
84042
  config2.command = entry.command;
83232
84043
  if (entry.args)
@@ -83310,12 +84121,12 @@ init_esm_shims();
83310
84121
 
83311
84122
  // ../ggcoder/dist/core/agents.js
83312
84123
  init_esm_shims();
83313
- import fs28 from "fs/promises";
83314
- import path34 from "path";
84124
+ import fs29 from "fs/promises";
84125
+ import path36 from "path";
83315
84126
  async function discoverAgents(options) {
83316
84127
  const agents = [];
83317
84128
  if (options.projectDir) {
83318
- const projectAgentsDir = path34.join(options.projectDir, ".gg", "agents");
84129
+ const projectAgentsDir = path36.join(options.projectDir, ".gg", "agents");
83319
84130
  const projectAgents = await loadAgentsFromDir(projectAgentsDir, "project");
83320
84131
  agents.push(...projectAgents);
83321
84132
  }
@@ -83333,19 +84144,19 @@ async function loadAgentsFromDir(dir, source2) {
83333
84144
  const agents = [];
83334
84145
  let files;
83335
84146
  try {
83336
- files = await fs28.readdir(dir);
84147
+ files = await fs29.readdir(dir);
83337
84148
  } catch {
83338
84149
  return agents;
83339
84150
  }
83340
84151
  for (const file2 of files) {
83341
84152
  if (!file2.endsWith(".md"))
83342
84153
  continue;
83343
- const filePath = path34.join(dir, file2);
84154
+ const filePath = path36.join(dir, file2);
83344
84155
  try {
83345
- const content = await fs28.readFile(filePath, "utf-8");
84156
+ const content = await fs29.readFile(filePath, "utf-8");
83346
84157
  const agent = parseAgentFile(content, source2);
83347
84158
  if (!agent.name) {
83348
- agent.name = path34.basename(file2, ".md");
84159
+ agent.name = path36.basename(file2, ".md");
83349
84160
  }
83350
84161
  agents.push(agent);
83351
84162
  } catch {
@@ -83664,9 +84475,9 @@ The user's original request was:
83664
84475
  }
83665
84476
 
83666
84477
  // ../ggcoder/dist/core/agent-session.js
83667
- import crypto8 from "crypto";
83668
- import fs29 from "fs/promises";
83669
- import path35 from "path";
84478
+ import crypto9 from "crypto";
84479
+ import fs30 from "fs/promises";
84480
+ import path37 from "path";
83670
84481
  var AgentSession = class {
83671
84482
  eventBus = new EventBus();
83672
84483
  slashCommands = new SlashCommandRegistry();
@@ -83676,6 +84487,10 @@ var AgentSession = class {
83676
84487
  extensionLoader = new ExtensionLoader();
83677
84488
  messages = [];
83678
84489
  tools = [];
84490
+ /** Rebuilds the read tool for a new model (video byte cap is baked in at
84491
+ * creation). Called from switchModel so video-capable models get the
84492
+ * read-tool's native-video path after a mid-session model change. */
84493
+ rebuildReadTool;
83679
84494
  skills = [];
83680
84495
  cacheKeyLogged = false;
83681
84496
  // ── Self-correction hook state (mirrors the TUI's useAgentLoop refs) ──
@@ -83702,9 +84517,13 @@ var AgentSession = class {
83702
84517
  regroundingInjected = false;
83703
84518
  compactionOccurred = false;
83704
84519
  originalRequest = "";
84520
+ /** True after the cache has been pre-warmed for this session. Ensures we only
84521
+ * fire the warm-up call once (before the first real turn). */
84522
+ cachePrewarmed = false;
83705
84523
  // Messages queued by the user while a run is in flight. Drained at the
83706
84524
  // mid-loop steering boundary (user steering wins over the hooks), mirroring
83707
- // the TUI's getSteeringMessages.
84525
+ // the TUI's getSteeringMessages. Each entry carries its own attachments so a
84526
+ // user can queue media (images/video/files) mid-run, not just plain text.
83708
84527
  userQueue = [];
83709
84528
  processManager;
83710
84529
  lspManager;
@@ -83761,10 +84580,10 @@ var AgentSession = class {
83761
84580
  this.authStorage = new AuthStorage(paths.authFile);
83762
84581
  await this.authStorage.load();
83763
84582
  this.sessionManager = new SessionManager(paths.sessionsDir);
83764
- const localGGDir = path35.join(this.cwd, ".gg");
83765
- await fs29.mkdir(path35.join(localGGDir, "skills"), { recursive: true });
83766
- await fs29.mkdir(path35.join(localGGDir, "commands"), { recursive: true });
83767
- await fs29.mkdir(path35.join(localGGDir, "agents"), { recursive: true });
84583
+ const localGGDir = path37.join(this.cwd, ".gg");
84584
+ await fs30.mkdir(path37.join(localGGDir, "skills"), { recursive: true });
84585
+ await fs30.mkdir(path37.join(localGGDir, "commands"), { recursive: true });
84586
+ await fs30.mkdir(path37.join(localGGDir, "agents"), { recursive: true });
83768
84587
  this.skills = await discoverSkills({
83769
84588
  globalSkillsDir: paths.skillsDir,
83770
84589
  projectDir: this.cwd
@@ -83773,12 +84592,13 @@ var AgentSession = class {
83773
84592
  globalAgentsDir: paths.agentsDir,
83774
84593
  projectDir: this.cwd
83775
84594
  });
83776
- const { tools, processManager, lspManager } = createTools(this.cwd, {
84595
+ const { tools, processManager, rebuildReadTool, lspManager } = await createTools(this.cwd, {
83777
84596
  agents,
83778
84597
  skills: this.skills,
83779
84598
  provider: this.provider,
83780
84599
  model: this.model,
83781
84600
  lspDiagnostics: this.settingsManager.get("lspDiagnostics"),
84601
+ authStorage: this.authStorage,
83782
84602
  // Lazy — sessionId/model/provider can change after createTools() runs, so
83783
84603
  // sub-agent spawns read the current parent state at execution time.
83784
84604
  getProvider: () => this.provider,
@@ -83793,22 +84613,14 @@ var AgentSession = class {
83793
84613
  } : {}
83794
84614
  });
83795
84615
  this.tools = tools;
84616
+ this.rebuildReadTool = rebuildReadTool;
83796
84617
  this.processManager = processManager;
83797
84618
  this.lspManager = lspManager;
83798
84619
  this.mcpManager = new MCPClientManager();
83799
- try {
83800
- let apiKey;
83801
- if (this.provider === "glm") {
83802
- try {
83803
- const glmCreds = await this.authStorage.resolveCredentials("glm");
83804
- apiKey = glmCreds.accessToken;
83805
- } catch {
83806
- }
83807
- }
83808
- const mcpTools = await this.mcpManager.connectAll(getMCPServers(this.provider, apiKey));
83809
- this.tools.push(...mcpTools);
83810
- } catch (err) {
83811
- log("WARN", "mcp", `MCP initialization failed: ${err instanceof Error ? err.message : String(err)}`);
84620
+ if (this.opts.backgroundMcpConnect) {
84621
+ void this.connectMcpServers();
84622
+ } else {
84623
+ await this.connectMcpServers();
83812
84624
  }
83813
84625
  const basePrompt = this.customSystemPrompt ?? await buildSystemPrompt(this.cwd, this.skills, false, void 0, this.tools.map((tool) => tool.name), void 0, this.provider);
83814
84626
  this.messages = [{ role: "system", content: basePrompt }];
@@ -83865,6 +84677,36 @@ var AgentSession = class {
83865
84677
  await this.extensionLoader.loadAll(paths.extensionsDir, extContext);
83866
84678
  this.eventBus.emit("session_start", { sessionId: this.sessionId });
83867
84679
  }
84680
+ /**
84681
+ * Connect all configured MCP servers and append their tools to `this.tools`.
84682
+ * Resolves the GLM api key first (Z.AI's bundled servers need it). Never
84683
+ * throws — a failed connect is logged and skipped — so it is safe to either
84684
+ * `await` (CLI: tools ready before the first turn) or fire-and-forget
84685
+ * (sidecar: `backgroundMcpConnect`, so a slow stdio server can't stall
84686
+ * startup). Tools are pushed onto the live array the agent loop reads each
84687
+ * turn, so background-connected servers become available on the next prompt.
84688
+ */
84689
+ async connectMcpServers() {
84690
+ if (!this.mcpManager)
84691
+ return;
84692
+ try {
84693
+ let apiKey;
84694
+ if (this.provider === "glm") {
84695
+ try {
84696
+ const glmCreds = await this.authStorage.resolveCredentials("glm");
84697
+ apiKey = glmCreds.accessToken;
84698
+ } catch {
84699
+ }
84700
+ }
84701
+ const mcpTools = await this.mcpManager.connectAll(await getAllMcpServers(this.provider, apiKey, this.cwd));
84702
+ this.tools.push(...mcpTools);
84703
+ if (this.opts.backgroundMcpConnect && mcpTools.length > 0) {
84704
+ await this.rebuildSystemPromptInPlace();
84705
+ }
84706
+ } catch (err) {
84707
+ log("WARN", "mcp", `MCP initialization failed: ${err instanceof Error ? err.message : String(err)}`);
84708
+ }
84709
+ }
83868
84710
  /**
83869
84711
  * Process user input. Handles slash commands or runs agent loop.
83870
84712
  */
@@ -83909,13 +84751,47 @@ ${parsed.args}` : promptText;
83909
84751
  * attachments are always a direct conversational turn.
83910
84752
  */
83911
84753
  async promptWithAttachments(text, attachments) {
84754
+ const parts = this.buildAttachmentParts(text, attachments);
84755
+ if (parts.length === 0)
84756
+ return;
84757
+ const userMessage = { role: "user", content: parts };
84758
+ this.messages.push(userMessage);
84759
+ await this.persistMessage(userMessage);
84760
+ this.lastPersistedIndex = this.messages.length;
84761
+ await this.runLoop();
84762
+ }
84763
+ /**
84764
+ * Build the native content blocks (text + image/video notes + file notes) for
84765
+ * a user message with attachments. Shared by {@link promptWithAttachments} and
84766
+ * the mid-run steering drain so queued media is delivered identically.
84767
+ */
84768
+ buildAttachmentParts(text, attachments) {
83912
84769
  const parts = [];
83913
84770
  const fileNotes = [];
84771
+ const modelSupportsVideo = getModel(this.model)?.supportsVideo ?? false;
83914
84772
  for (const a of attachments) {
83915
84773
  if (a.kind === "image") {
83916
84774
  parts.push({ type: "image", mediaType: a.mediaType, data: a.data });
84775
+ if (a.path) {
84776
+ parts.push({ type: "text", text: `[Image saved at ${a.path}]` });
84777
+ }
83917
84778
  } else if (a.kind === "video") {
83918
- parts.push({ type: "video", mediaType: a.mediaType, data: a.data });
84779
+ if (modelSupportsVideo && a.path) {
84780
+ parts.push({
84781
+ type: "text",
84782
+ text: `The user attached a video at ${a.path}. You CAN watch it: call the read tool on this exact path now, then answer based on what you see. Do not say you cannot watch video \u2014 reading the file lets you analyze it.`
84783
+ });
84784
+ } else if (a.path) {
84785
+ parts.push({
84786
+ type: "text",
84787
+ text: `[User attached a video file at ${a.path}. You cannot watch video directly; if needed, use ffmpeg to extract frames or audio.]`
84788
+ });
84789
+ } else {
84790
+ parts.push({
84791
+ type: "text",
84792
+ text: `[User attached a video file but it could not be saved for analysis.]`
84793
+ });
84794
+ }
83919
84795
  } else if (a.path) {
83920
84796
  fileNotes.push(`- ${a.name} (saved at ${a.path})`);
83921
84797
  }
@@ -83929,13 +84805,7 @@ ${fileNotes.join("\n")}`);
83929
84805
  }
83930
84806
  if (textParts.length > 0)
83931
84807
  parts.unshift({ type: "text", text: textParts.join("\n\n") });
83932
- if (parts.length === 0)
83933
- return;
83934
- const userMessage = { role: "user", content: parts };
83935
- this.messages.push(userMessage);
83936
- await this.persistMessage(userMessage);
83937
- this.lastPersistedIndex = this.messages.length;
83938
- await this.runLoop();
84808
+ return parts;
83939
84809
  }
83940
84810
  /**
83941
84811
  * Reset per-run self-correction hook state. Mirrors the TUI's run_start
@@ -84027,8 +84897,15 @@ ${fileNotes.join("\n")}`);
84027
84897
  */
84028
84898
  getHookSteeringMessages() {
84029
84899
  if (this.userQueue.length > 0) {
84030
- const merged = this.userQueue.splice(0).join("\n\n");
84031
- return [{ role: "user", content: merged }];
84900
+ const queued = this.userQueue.splice(0);
84901
+ if (queued.every((m) => m.attachments.length === 0)) {
84902
+ const merged = queued.map((m) => m.text).join("\n\n");
84903
+ return [{ role: "user", content: merged }];
84904
+ }
84905
+ const parts = [];
84906
+ for (const m of queued)
84907
+ parts.push(...this.buildAttachmentParts(m.text, m.attachments));
84908
+ return [{ role: "user", content: parts }];
84032
84909
  }
84033
84910
  if (!this.settingsManager.get("idealReviewEnabled"))
84034
84911
  return null;
@@ -84114,7 +84991,9 @@ ${fileNotes.join("\n")}`);
84114
84991
  // Kimi For Coding gates the managed endpoint on coding-agent identity
84115
84992
  // headers; attach them only when the Kimi OAuth token is in use.
84116
84993
  defaultHeaders: this.provider === "moonshot" && isKimiCodingEndpoint(effectiveBaseUrl) ? kimiCodingHeaders() : void 0,
84117
- cacheRetention: "short",
84994
+ // speedProfile "optimized": 1-h cache TTL (survives turns >5 min apart)
84995
+ // + pre-warm before the first turn. "baseline": current 5-min default.
84996
+ cacheRetention: this.isSpeedOptimized() ? "long" : "short",
84118
84997
  promptCacheKey: this.getPromptCacheKey(),
84119
84998
  supportsImages: modelInfo?.supportsImages,
84120
84999
  supportsVideo: modelInfo?.supportsVideo,
@@ -84133,6 +85012,7 @@ ${fileNotes.join("\n")}`);
84133
85012
  }
84134
85013
  };
84135
85014
  try {
85015
+ await this.maybePrewarmCache(creds);
84136
85016
  await runAgentLoop(creds.accessToken, creds.accountId, creds.projectId);
84137
85017
  } catch (err) {
84138
85018
  if (isAbortError4(err) || this.opts.signal?.aborted) {
@@ -84164,7 +85044,15 @@ ${fileNotes.join("\n")}`);
84164
85044
  this.model = model;
84165
85045
  setEstimatorModel(model);
84166
85046
  this.maxTokens = this.resolveMaxTokens(model);
84167
- this.eventBus.emit("model_change", { provider: this.provider, model: this.model });
85047
+ this.eventBus.emit("model_change", {
85048
+ provider: this.provider,
85049
+ model: this.model,
85050
+ supportsVideo: getModel(this.model)?.supportsVideo ?? false
85051
+ });
85052
+ if (this.rebuildReadTool) {
85053
+ const newReadTool = this.rebuildReadTool(model);
85054
+ this.tools = this.tools.map((t) => t.name === "read" ? newReadTool : t);
85055
+ }
84168
85056
  if (provider && provider !== prevProvider) {
84169
85057
  const hasWebSearch = this.tools.some((t) => t.name === "web_search");
84170
85058
  if (this.provider === "anthropic" && hasWebSearch) {
@@ -84290,19 +85178,21 @@ ${fileNotes.join("\n")}`);
84290
85178
  getPlanMode() {
84291
85179
  return this.planModeRef.current;
84292
85180
  }
84293
- /** Queue a user message to be injected mid-run as steering. Returns the new
84294
- * queue length. No-op semantics are the caller's concern. */
84295
- queueMessage(text) {
84296
- this.userQueue.push(text);
85181
+ /** Queue a user message (optionally with attachments) to be injected mid-run
85182
+ * as steering. Returns the new queue length. No-op semantics are the caller's
85183
+ * concern. */
85184
+ queueMessage(text, attachments = []) {
85185
+ this.userQueue.push({ text, attachments });
84297
85186
  return this.userQueue.length;
84298
85187
  }
84299
85188
  /** Number of messages currently queued. */
84300
85189
  getQueuedCount() {
84301
85190
  return this.userQueue.length;
84302
85191
  }
84303
- /** Clear the queue, returning the combined text (to restore to the composer). */
85192
+ /** Clear the queue, returning the combined text (to restore to the composer).
85193
+ * Queued attachments are dropped on cancel — the composer only restores text. */
84304
85194
  drainQueue() {
84305
- return this.userQueue.splice(0).join("\n\n");
85195
+ return this.userQueue.splice(0).map((m) => m.text).join("\n\n");
84306
85196
  }
84307
85197
  /** Snapshot of background processes (bash run_in_background), newest-state. */
84308
85198
  listBackgroundProcesses() {
@@ -84390,6 +85280,42 @@ ${fileNotes.join("\n")}`);
84390
85280
  setSignal(signal) {
84391
85281
  this.opts = { ...this.opts, signal };
84392
85282
  }
85283
+ /** True when speedProfile is "optimized" (1-h cache TTL + pre-warm). */
85284
+ isSpeedOptimized() {
85285
+ return this.settingsManager?.get("speedProfile") === "optimized";
85286
+ }
85287
+ /** Fire a cache pre-warm request for Anthropic so the first real turn is a
85288
+ * cache read instead of a cold write. No-op for other providers and when
85289
+ * speedProfile is not "optimized". Entirely best-effort — any failure is
85290
+ * swallowed so prewarm never blocks or aborts the real prompt. */
85291
+ async maybePrewarmCache(creds) {
85292
+ if (this.cachePrewarmed || !this.isSpeedOptimized() || this.provider !== "anthropic") {
85293
+ return;
85294
+ }
85295
+ this.cachePrewarmed = true;
85296
+ try {
85297
+ const userAgent = await getClaudeCliUserAgent();
85298
+ const systemText = typeof this.messages[0]?.content === "string" ? this.messages[0].content : "";
85299
+ if (!systemText)
85300
+ return;
85301
+ await prewarmAnthropicCache({
85302
+ apiKey: creds.accessToken,
85303
+ model: this.model,
85304
+ system: systemText,
85305
+ tools: this.tools.map((t) => ({
85306
+ name: t.name,
85307
+ description: t.description,
85308
+ parameters: t.parameters,
85309
+ ...t.rawInputSchema ? { rawInputSchema: t.rawInputSchema } : {}
85310
+ })),
85311
+ baseUrl: this.baseUrl ?? creds.baseUrl,
85312
+ userAgent,
85313
+ cacheRetention: "long",
85314
+ signal: this.opts.signal
85315
+ });
85316
+ } catch {
85317
+ }
85318
+ }
84393
85319
  getPromptCacheKey() {
84394
85320
  if (this.opts.promptCacheKey)
84395
85321
  return this.opts.promptCacheKey;
@@ -84462,7 +85388,7 @@ ${fileNotes.join("\n")}`);
84462
85388
  async persistMessage(message) {
84463
85389
  if (!this.sessionPath)
84464
85390
  return;
84465
- const entryId = crypto8.randomUUID();
85391
+ const entryId = crypto9.randomUUID();
84466
85392
  const entry = {
84467
85393
  type: "message",
84468
85394
  id: entryId,
@@ -85278,7 +86204,7 @@ import process14 from "process";
85278
86204
  init_esm_shims();
85279
86205
  var import_react15 = __toESM(require_react(), 1);
85280
86206
  import process13 from "process";
85281
- import fs32 from "fs";
86207
+ import fs33 from "fs";
85282
86208
 
85283
86209
  // ../../node_modules/.pnpm/es-toolkit@1.46.1/node_modules/es-toolkit/dist/compat/index.mjs
85284
86210
  init_esm_shims();
@@ -87471,7 +88397,7 @@ function wrapAnsi2(string4, columns, options) {
87471
88397
  init_esm_shims();
87472
88398
  import process5 from "process";
87473
88399
  import { execFileSync as execFileSync2 } from "child_process";
87474
- import fs30 from "fs";
88400
+ import fs31 from "fs";
87475
88401
  import tty from "tty";
87476
88402
  var defaultColumns = 80;
87477
88403
  var defaultRows = 24;
@@ -87501,7 +88427,7 @@ var isForegroundProcess = () => {
87501
88427
  return true;
87502
88428
  }
87503
88429
  try {
87504
- const statContents = fs30.readFileSync("/proc/self/stat", "utf8");
88430
+ const statContents = fs31.readFileSync("/proc/self/stat", "utf8");
87505
88431
  const closingParenthesisIndex = statContents.lastIndexOf(") ");
87506
88432
  if (closingParenthesisIndex === -1) {
87507
88433
  return false;
@@ -87545,8 +88471,8 @@ function terminalSize() {
87545
88471
  }
87546
88472
  var devTty = () => {
87547
88473
  try {
87548
- const flags = process5.platform === "darwin" ? fs30.constants.O_EVTONLY | fs30.constants.O_NONBLOCK : fs30.constants.O_NONBLOCK;
87549
- const { columns, rows } = tty.WriteStream(fs30.openSync("/dev/tty", flags));
88474
+ const flags = process5.platform === "darwin" ? fs31.constants.O_EVTONLY | fs31.constants.O_NONBLOCK : fs31.constants.O_NONBLOCK;
88475
+ const { columns, rows } = tty.WriteStream(fs31.openSync("/dev/tty", flags));
87550
88476
  return { columns, rows };
87551
88477
  } catch {
87552
88478
  }
@@ -89486,8 +90412,8 @@ var cleanupYogaNode = (node) => {
89486
90412
  var currentUpdatePriority = import_constants3.NoEventPriority;
89487
90413
  var currentRootNode;
89488
90414
  async function loadPackageJson() {
89489
- const fs39 = await import("fs");
89490
- const content = fs39.readFileSync(new URL("../package.json", import.meta.url), "utf8");
90415
+ const fs40 = await import("fs");
90416
+ const content = fs40.readFileSync(new URL("../package.json", import.meta.url), "utf8");
89491
90417
  return JSON.parse(content);
89492
90418
  }
89493
90419
  var packageJson = isDev() ? await loadPackageJson() : { name: void 0, version: void 0 };
@@ -91049,7 +91975,7 @@ var import_react13 = __toESM(require_react(), 1);
91049
91975
  init_esm_shims();
91050
91976
  var import_react12 = __toESM(require_react(), 1);
91051
91977
  var import_stack_utils = __toESM(require_stack_utils(), 1);
91052
- import * as fs31 from "fs";
91978
+ import * as fs32 from "fs";
91053
91979
  import { cwd } from "process";
91054
91980
 
91055
91981
  // ../../node_modules/.pnpm/code-excerpt@4.0.0/node_modules/code-excerpt/dist/index.js
@@ -91177,8 +92103,8 @@ function Text({ color: color2, backgroundColor, dimColor = false, bold = false,
91177
92103
  }
91178
92104
 
91179
92105
  // ../../node_modules/.pnpm/@kenkaiiii+ink@6.8.0-gg.2_@types+react@19.2.14_react@19.2.5/node_modules/@kenkaiiii/ink/build/components/ErrorOverview.js
91180
- var cleanupPath = (path46) => {
91181
- return path46?.replace(`file://${cwd()}/`, "");
92106
+ var cleanupPath = (path48) => {
92107
+ return path48?.replace(`file://${cwd()}/`, "");
91182
92108
  };
91183
92109
  var stackUtils = new import_stack_utils.default({
91184
92110
  cwd: cwd(),
@@ -91190,8 +92116,8 @@ function ErrorOverview({ error: error51 }) {
91190
92116
  const filePath = cleanupPath(origin?.file);
91191
92117
  let excerpt;
91192
92118
  let lineWidth = 0;
91193
- if (filePath && origin?.line && fs31.existsSync(filePath)) {
91194
- const sourceCode = fs31.readFileSync(filePath, "utf8");
92119
+ if (filePath && origin?.line && fs32.existsSync(filePath)) {
92120
+ const sourceCode = fs32.readFileSync(filePath, "utf8");
91195
92121
  excerpt = dist_default3(sourceCode, origin.line);
91196
92122
  if (excerpt) {
91197
92123
  for (const { line } of excerpt) {
@@ -92010,7 +92936,7 @@ var Ink = class {
92010
92936
  }
92011
92937
  if (process13.env["GG_INK_DEBUG"] === "1" && (delta !== 0 || this.framePadDebt > 0)) {
92012
92938
  try {
92013
- fs32.appendFileSync("/tmp/gg-ink-debug.log", JSON.stringify({
92939
+ fs33.appendFileSync("/tmp/gg-ink-debug.log", JSON.stringify({
92014
92940
  t: Date.now() % 1e5,
92015
92941
  delta,
92016
92942
  ins: insertLineCount,
@@ -93732,7 +94658,7 @@ var import_react37 = __toESM(require_react(), 1);
93732
94658
 
93733
94659
  // ../ggcoder/dist/core/session-compaction.js
93734
94660
  init_esm_shims();
93735
- import crypto9 from "crypto";
94661
+ import crypto10 from "crypto";
93736
94662
 
93737
94663
  // ../ggcoder/dist/ui/hooks/useContextCompaction.js
93738
94664
  init_esm_shims();
@@ -94463,8 +95389,8 @@ function shortenValue(value, maxLength = MAX_DETAIL_LENGTH) {
94463
95389
  const tailLength = maxLength - 1 - headLength;
94464
95390
  return `${normalized.slice(0, headLength)}\u2026${normalized.slice(-tailLength)}`;
94465
95391
  }
94466
- function basename2(path46) {
94467
- const trimmed = path46.replace(/\/+$/u, "");
95392
+ function basename2(path48) {
95393
+ const trimmed = path48.replace(/\/+$/u, "");
94468
95394
  return trimmed.split("/").filter(Boolean).at(-1) ?? trimmed;
94469
95395
  }
94470
95396
  function uniqueValues(values) {
@@ -109447,7 +110373,7 @@ function collapseSubmittedUserText(text) {
109447
110373
  }
109448
110374
 
109449
110375
  // ../ggcoder/dist/ui/terminal-history.js
109450
- import path36 from "path";
110376
+ import path38 from "path";
109451
110377
  import { pathToFileURL as pathToFileURL2 } from "url";
109452
110378
 
109453
110379
  // ../ggcoder/dist/ui/utils/terminal-graphics.js
@@ -110475,7 +111401,7 @@ function TaskPickerMenu({ tasks, selectedIndex, width }) {
110475
111401
  // ../ggcoder/dist/ui/components/InputArea.js
110476
111402
  import { homedir as homedir2 } from "os";
110477
111403
  import { join as join2 } from "path";
110478
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync2, renameSync, unlinkSync, existsSync as existsSync4 } from "fs";
111404
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync2, renameSync, unlinkSync, existsSync as existsSync5 } from "fs";
110479
111405
  var MAX_VISIBLE_LINES = 12;
110480
111406
  var PROMPT = "> ";
110481
111407
  var PLACEHOLDER = " Type your message or / to run a command";
@@ -110615,7 +111541,7 @@ function compactHistory2() {
110615
111541
  lineCountEstimate = trimmed.length;
110616
111542
  } catch {
110617
111543
  try {
110618
- if (existsSync4(tempPath))
111544
+ if (existsSync5(tempPath))
110619
111545
  unlinkSync(tempPath);
110620
111546
  } catch {
110621
111547
  }
@@ -111727,7 +112653,7 @@ var import_react67 = __toESM(require_react(), 1);
111727
112653
 
111728
112654
  // ../ggcoder/dist/ui/pixel.js
111729
112655
  init_esm_shims();
111730
- import { existsSync as existsSync5, readFileSync as readFileSync6 } from "fs";
112656
+ import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
111731
112657
  import { homedir as homedir3 } from "os";
111732
112658
  import { join as join4 } from "path";
111733
112659
 
@@ -111767,7 +112693,7 @@ function visualWidth2(str2) {
111767
112693
  }
111768
112694
 
111769
112695
  // ../ggcoder/dist/ui/components/PlanOverlay.js
111770
- import { readdir, readFile as readFile2, unlink } from "fs/promises";
112696
+ import { readdir, readFile as readFile3, unlink } from "fs/promises";
111771
112697
  import { join as join5 } from "path";
111772
112698
  var PLAN_LOGO = [
111773
112699
  " \u2584\u2580\u2580\u2580 \u2584\u2580\u2580\u2580",
@@ -111804,11 +112730,11 @@ import { execFile as execFile4 } from "child_process";
111804
112730
 
111805
112731
  // ../ggcoder/dist/core/auto-update.js
111806
112732
  init_esm_shims();
111807
- import path37 from "path";
112733
+ import path39 from "path";
111808
112734
  import os10 from "os";
111809
112735
  var updater = createAutoUpdater({
111810
112736
  packageName: "@kenkaiiii/ggcoder",
111811
- stateFilePath: () => path37.join(os10.homedir(), ".gg", "update-state.json")
112737
+ stateFilePath: () => path39.join(os10.homedir(), ".gg", "update-state.json")
111812
112738
  });
111813
112739
  var checkAndAutoUpdate = updater.checkAndAutoUpdate;
111814
112740
  var getPendingUpdate = updater.getPendingUpdate;
@@ -111817,10 +112743,10 @@ var stopPeriodicUpdateCheck = updater.stopPeriodicUpdateCheck;
111817
112743
 
111818
112744
  // ../ggcoder/dist/core/setup-history.js
111819
112745
  init_esm_shims();
111820
- import fs33 from "fs";
111821
- import path38 from "path";
112746
+ import fs34 from "fs";
112747
+ import path40 from "path";
111822
112748
  import os11 from "os";
111823
- var HISTORY_PATH = path38.join(os11.homedir(), ".gg", "setup-history.json");
112749
+ var HISTORY_PATH = path40.join(os11.homedir(), ".gg", "setup-history.json");
111824
112750
 
111825
112751
  // ../ggcoder/dist/ui/components/RewindOverlay.js
111826
112752
  init_esm_shims();
@@ -112064,7 +112990,7 @@ function MessageResponse({ children, height, accentColor }) {
112064
112990
 
112065
112991
  // ../ggcoder/dist/ui/utils/highlight.js
112066
112992
  init_esm_shims();
112067
- import path39 from "path";
112993
+ import path41 from "path";
112068
112994
  var EXT_TO_LANG = {
112069
112995
  ts: "typescript",
112070
112996
  tsx: "typescript",
@@ -112092,7 +113018,7 @@ var EXT_TO_LANG = {
112092
113018
  dockerfile: "dockerfile"
112093
113019
  };
112094
113020
  function langFromPath(filePath) {
112095
- const ext = path39.extname(filePath).replace(/^\./, "").toLowerCase();
113021
+ const ext = path41.extname(filePath).replace(/^\./, "").toLowerCase();
112096
113022
  return EXT_TO_LANG[ext];
112097
113023
  }
112098
113024
  var hlModule;
@@ -112940,11 +113866,11 @@ var VIEWPORT_CLEAR = DISABLE_MODIFY_OTHER_KEYS + "\x1B[2J\x1B[H";
112940
113866
 
112941
113867
  // ../ggcoder/dist/core/project-discovery.js
112942
113868
  init_esm_shims();
112943
- import fs34 from "fs/promises";
113869
+ import fs35 from "fs/promises";
112944
113870
  import { createReadStream as createReadStream3 } from "fs";
112945
113871
  import readline3 from "readline";
112946
113872
  import os12 from "os";
112947
- import path40 from "path";
113873
+ import path43 from "path";
112948
113874
  async function discoverProjects() {
112949
113875
  const [gg, cc, cx] = await Promise.all([
112950
113876
  discoverGgcoderProjects(),
@@ -112987,21 +113913,21 @@ async function discoverGgcoderProjects() {
112987
113913
  const sessionsDir = getAppPaths().sessionsDir;
112988
113914
  let entries;
112989
113915
  try {
112990
- entries = await fs34.readdir(sessionsDir);
113916
+ entries = await fs35.readdir(sessionsDir);
112991
113917
  } catch {
112992
113918
  return [];
112993
113919
  }
112994
113920
  const results = [];
112995
113921
  for (const entry of entries) {
112996
- const dir = path40.join(sessionsDir, entry);
113922
+ const dir = path43.join(sessionsDir, entry);
112997
113923
  const mtime = await maxJsonlMtime(dir);
112998
113924
  if (mtime === null)
112999
113925
  continue;
113000
- const decoded = path40.resolve("/" + entry.replace(/_/g, "/"));
113926
+ const decoded = path43.resolve("/" + entry.replace(/_/g, "/"));
113001
113927
  if (!await isDirectory(decoded))
113002
113928
  continue;
113003
113929
  results.push({
113004
- name: path40.basename(decoded),
113930
+ name: path43.basename(decoded),
113005
113931
  path: decoded,
113006
113932
  lastActiveMs: mtime,
113007
113933
  lastActiveDisplay: formatRelativeTime(mtime),
@@ -113011,15 +113937,15 @@ async function discoverGgcoderProjects() {
113011
113937
  return results;
113012
113938
  }
113013
113939
  async function discoverClaudeProjects() {
113014
- const projectsDir = path40.join(os12.homedir(), ".claude", "projects");
113940
+ const projectsDir = path43.join(os12.homedir(), ".claude", "projects");
113015
113941
  let entries;
113016
113942
  try {
113017
- entries = await fs34.readdir(projectsDir);
113943
+ entries = await fs35.readdir(projectsDir);
113018
113944
  } catch {
113019
113945
  return [];
113020
113946
  }
113021
113947
  const results = await Promise.all(entries.map(async (entry) => {
113022
- const dir = path40.join(projectsDir, entry);
113948
+ const dir = path43.join(projectsDir, entry);
113023
113949
  const mtime = await maxJsonlMtime(dir);
113024
113950
  if (mtime === null)
113025
113951
  return null;
@@ -113029,7 +113955,7 @@ async function discoverClaudeProjects() {
113029
113955
  if (!await isDirectory(cwd2))
113030
113956
  return null;
113031
113957
  return {
113032
- name: path40.basename(cwd2),
113958
+ name: path43.basename(cwd2),
113033
113959
  path: cwd2,
113034
113960
  lastActiveMs: mtime,
113035
113961
  lastActiveDisplay: formatRelativeTime(mtime),
@@ -113039,7 +113965,7 @@ async function discoverClaudeProjects() {
113039
113965
  return results.filter((p) => p !== null);
113040
113966
  }
113041
113967
  async function discoverCodexProjects() {
113042
- const sessionsDir = path40.join(os12.homedir(), ".codex", "sessions");
113968
+ const sessionsDir = path43.join(os12.homedir(), ".codex", "sessions");
113043
113969
  if (!await isDirectory(sessionsDir))
113044
113970
  return [];
113045
113971
  const files = await collectJsonlFiles(sessionsDir, 4);
@@ -113060,7 +113986,7 @@ async function discoverCodexProjects() {
113060
113986
  if (!await isDirectory(cwd2))
113061
113987
  continue;
113062
113988
  results.push({
113063
- name: path40.basename(cwd2),
113989
+ name: path43.basename(cwd2),
113064
113990
  path: cwd2,
113065
113991
  lastActiveMs: mtime,
113066
113992
  lastActiveDisplay: formatRelativeTime(mtime),
@@ -113071,7 +113997,7 @@ async function discoverCodexProjects() {
113071
113997
  }
113072
113998
  async function isDirectory(p) {
113073
113999
  try {
113074
- const s = await fs34.stat(p);
114000
+ const s = await fs35.stat(p);
113075
114001
  return s.isDirectory();
113076
114002
  } catch {
113077
114003
  return false;
@@ -113096,15 +114022,15 @@ async function collectJsonlFiles(dir, maxDepth) {
113096
114022
  async function walk(current, depth) {
113097
114023
  let entries;
113098
114024
  try {
113099
- entries = await fs34.readdir(current, { withFileTypes: true });
114025
+ entries = await fs35.readdir(current, { withFileTypes: true });
113100
114026
  } catch {
113101
114027
  return;
113102
114028
  }
113103
114029
  for (const e of entries) {
113104
- const full = path40.join(current, e.name);
114030
+ const full = path43.join(current, e.name);
113105
114031
  if (e.isFile() && e.name.endsWith(".jsonl")) {
113106
114032
  try {
113107
- const s = await fs34.stat(full);
114033
+ const s = await fs35.stat(full);
113108
114034
  out.push({ path: full, mtime: s.mtimeMs });
113109
114035
  } catch {
113110
114036
  }
@@ -114472,17 +115398,17 @@ var EventQueue = class {
114472
115398
 
114473
115399
  // src/settings.ts
114474
115400
  init_esm_shims();
114475
- import fs35 from "fs/promises";
114476
- import path41 from "path";
115401
+ import fs36 from "fs/promises";
115402
+ import path44 from "path";
114477
115403
  function settingsPath() {
114478
- return path41.join(getAppPaths().agentDir, "boss", "settings.json");
115404
+ return path44.join(getAppPaths().agentDir, "boss", "settings.json");
114479
115405
  }
114480
115406
  async function ensureDir() {
114481
- await fs35.mkdir(path41.dirname(settingsPath()), { recursive: true, mode: 448 });
115407
+ await fs36.mkdir(path44.dirname(settingsPath()), { recursive: true, mode: 448 });
114482
115408
  }
114483
115409
  async function loadSettings() {
114484
115410
  try {
114485
- const content = await fs35.readFile(settingsPath(), "utf-8");
115411
+ const content = await fs36.readFile(settingsPath(), "utf-8");
114486
115412
  const parsed = JSON.parse(content);
114487
115413
  if (!parsed || typeof parsed !== "object") return {};
114488
115414
  return parsed;
@@ -114497,8 +115423,8 @@ async function saveSettings(patch) {
114497
115423
  const merged = { ...current, ...patch };
114498
115424
  await ensureDir();
114499
115425
  const tmp = `${settingsPath()}.${process.pid}.tmp`;
114500
- await fs35.writeFile(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
114501
- await fs35.rename(tmp, settingsPath());
115426
+ await fs36.writeFile(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
115427
+ await fs36.rename(tmp, settingsPath());
114502
115428
  });
114503
115429
  writeChain = next.catch(() => void 0);
114504
115430
  await next;
@@ -114890,18 +115816,18 @@ init_esm_shims();
114890
115816
  // src/tasks-store.ts
114891
115817
  init_esm_shims();
114892
115818
  var import_react98 = __toESM(require_react(), 1);
114893
- import fs36 from "fs/promises";
114894
- import path43 from "path";
114895
- import crypto10 from "crypto";
115819
+ import fs37 from "fs/promises";
115820
+ import path45 from "path";
115821
+ import crypto11 from "crypto";
114896
115822
  function getPlanPath() {
114897
- return path43.join(getAppPaths().agentDir, "boss", "plan.json");
115823
+ return path45.join(getAppPaths().agentDir, "boss", "plan.json");
114898
115824
  }
114899
115825
  async function ensureDir2() {
114900
- await fs36.mkdir(path43.dirname(getPlanPath()), { recursive: true, mode: 448 });
115826
+ await fs37.mkdir(path45.dirname(getPlanPath()), { recursive: true, mode: 448 });
114901
115827
  }
114902
115828
  async function loadPlan() {
114903
115829
  try {
114904
- const content = await fs36.readFile(getPlanPath(), "utf-8");
115830
+ const content = await fs37.readFile(getPlanPath(), "utf-8");
114905
115831
  const parsed = JSON.parse(content);
114906
115832
  return Array.isArray(parsed.tasks) ? parsed.tasks : [];
114907
115833
  } catch {
@@ -114915,8 +115841,8 @@ async function persist(tasks) {
114915
115841
  await ensureDir2();
114916
115842
  const finalPath = getPlanPath();
114917
115843
  const tmpPath = `${finalPath}.${process.pid}.tmp`;
114918
- await fs36.writeFile(tmpPath, snapshot, "utf-8");
114919
- await fs36.rename(tmpPath, finalPath);
115844
+ await fs37.writeFile(tmpPath, snapshot, "utf-8");
115845
+ await fs37.rename(tmpPath, finalPath);
114920
115846
  });
114921
115847
  persistChain = next.catch(() => void 0);
114922
115848
  await next;
@@ -114939,7 +115865,7 @@ function useTasksState() {
114939
115865
  return (0, import_react98.useSyncExternalStore)(subscribe2, getSnapshot2, getSnapshot2);
114940
115866
  }
114941
115867
  function newId() {
114942
- return crypto10.randomBytes(6).toString("hex");
115868
+ return crypto11.randomBytes(6).toString("hex");
114943
115869
  }
114944
115870
  function now() {
114945
115871
  return (/* @__PURE__ */ new Date()).toISOString();
@@ -115186,11 +116112,11 @@ function createTaskTools(deps) {
115186
116112
  init_esm_shims();
115187
116113
  import { spawn as spawn8, execFileSync as execFileSync4 } from "child_process";
115188
116114
  import { fileURLToPath as fileURLToPath6 } from "url";
115189
- import path44 from "path";
115190
- import fs37 from "fs";
116115
+ import path46 from "path";
116116
+ import fs38 from "fs";
115191
116117
  function readMp3DurationMs(file2) {
115192
116118
  try {
115193
- const buf = fs37.readFileSync(file2);
116119
+ const buf = fs38.readFileSync(file2);
115194
116120
  let i = 0;
115195
116121
  if (buf.length >= 10 && buf[0] === 73 && buf[1] === 68 && buf[2] === 51) {
115196
116122
  const tagSize = (buf[6] & 127) << 21 | (buf[7] & 127) << 14 | (buf[8] & 127) << 7 | buf[9] & 127;
@@ -115247,10 +116173,10 @@ function getSplashAudioDurationMs() {
115247
116173
  return ms && ms > 0 ? ms : 1500;
115248
116174
  }
115249
116175
  function assetPath(name) {
115250
- const here = path44.dirname(fileURLToPath6(import.meta.url));
115251
- const dist = path44.join(here, name);
115252
- if (fs37.existsSync(dist)) return dist;
115253
- return path44.join(here, "..", "assets", name);
116176
+ const here = path46.dirname(fileURLToPath6(import.meta.url));
116177
+ const dist = path46.join(here, name);
116178
+ if (fs38.existsSync(dist)) return dist;
116179
+ return path46.join(here, "..", "assets", name);
115254
116180
  }
115255
116181
  function splashAssetPath() {
115256
116182
  return assetPath("splash.mp3");
@@ -115290,15 +116216,15 @@ function trySpawn(cmd, args) {
115290
116216
  }
115291
116217
  function isWsl() {
115292
116218
  if (process.platform !== "linux") return false;
115293
- return !!process.env.WSL_DISTRO_NAME || fs37.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop");
116219
+ return !!process.env.WSL_DISTRO_NAME || fs38.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop");
115294
116220
  }
115295
116221
  async function tryPlayOnWindowsHost(file2) {
115296
116222
  try {
115297
- const here = path44.dirname(fileURLToPath6(import.meta.url));
115298
- const devAssets = path44.resolve(here, "..", "assets");
115299
- const resolved = path44.resolve(file2);
115300
- const inDist = resolved === here || resolved.startsWith(here + path44.sep);
115301
- const inAssets = resolved === devAssets || resolved.startsWith(devAssets + path44.sep);
116223
+ const here = path46.dirname(fileURLToPath6(import.meta.url));
116224
+ const devAssets = path46.resolve(here, "..", "assets");
116225
+ const resolved = path46.resolve(file2);
116226
+ const inDist = resolved === here || resolved.startsWith(here + path46.sep);
116227
+ const inAssets = resolved === devAssets || resolved.startsWith(devAssets + path46.sep);
115302
116228
  if (!inDist && !inAssets) {
115303
116229
  return false;
115304
116230
  }
@@ -115362,7 +116288,7 @@ async function tryPlayOnWindowsHost(file2) {
115362
116288
  }
115363
116289
  }
115364
116290
  async function playFile(file2) {
115365
- if (!fs37.existsSync(file2)) return;
116291
+ if (!fs38.existsSync(file2)) return;
115366
116292
  const platform2 = process.platform;
115367
116293
  if (platform2 === "darwin") {
115368
116294
  await trySpawn("afplay", [file2]);
@@ -115460,37 +116386,37 @@ function truncateOversizedToolResults2(messages, opts = {}) {
115460
116386
 
115461
116387
  // src/sessions.ts
115462
116388
  init_esm_shims();
115463
- import fs38 from "fs/promises";
115464
- import path45 from "path";
115465
- import crypto11 from "crypto";
116389
+ import fs39 from "fs/promises";
116390
+ import path47 from "path";
116391
+ import crypto12 from "crypto";
115466
116392
  var BOSS_SUBDIR = "boss";
115467
116393
  var SESSIONS_SUBDIR = "sessions";
115468
116394
  function getBossDir() {
115469
- return path45.join(getAppPaths().agentDir, BOSS_SUBDIR);
116395
+ return path47.join(getAppPaths().agentDir, BOSS_SUBDIR);
115470
116396
  }
115471
116397
  function getSessionsDir() {
115472
- return path45.join(getBossDir(), SESSIONS_SUBDIR);
116398
+ return path47.join(getBossDir(), SESSIONS_SUBDIR);
115473
116399
  }
115474
116400
  async function ensureSessionsDir() {
115475
116401
  const dir = getSessionsDir();
115476
- await fs38.mkdir(dir, { recursive: true, mode: 448 });
116402
+ await fs39.mkdir(dir, { recursive: true, mode: 448 });
115477
116403
  return dir;
115478
116404
  }
115479
116405
  async function createSession2() {
115480
116406
  await ensureSessionsDir();
115481
- const id2 = `${Date.now()}-${crypto11.randomBytes(4).toString("hex")}`;
115482
- const filePath = path45.join(getSessionsDir(), `${id2}.jsonl`);
115483
- await fs38.writeFile(filePath, "", "utf-8");
116407
+ const id2 = `${Date.now()}-${crypto12.randomBytes(4).toString("hex")}`;
116408
+ const filePath = path47.join(getSessionsDir(), `${id2}.jsonl`);
116409
+ await fs39.writeFile(filePath, "", "utf-8");
115484
116410
  return { id: id2, filePath };
115485
116411
  }
115486
116412
  async function appendMessages(filePath, msgs) {
115487
116413
  if (msgs.length === 0) return;
115488
116414
  const lines = msgs.map((m) => JSON.stringify(m)).join("\n") + "\n";
115489
- await fs38.appendFile(filePath, lines, "utf-8");
116415
+ await fs39.appendFile(filePath, lines, "utf-8");
115490
116416
  }
115491
116417
  async function loadSession2(filePath) {
115492
116418
  try {
115493
- const content = await fs38.readFile(filePath, "utf-8");
116419
+ const content = await fs39.readFile(filePath, "utf-8");
115494
116420
  const lines = content.split("\n").filter((l) => l.length > 0);
115495
116421
  const messages = [];
115496
116422
  for (const line of lines) {
@@ -115506,8 +116432,8 @@ async function loadSession2(filePath) {
115506
116432
  }
115507
116433
  async function inspectSession(filePath, id2) {
115508
116434
  try {
115509
- const stat = await fs38.stat(filePath);
115510
- const content = await fs38.readFile(filePath, "utf-8");
116435
+ const stat = await fs39.stat(filePath);
116436
+ const content = await fs39.readFile(filePath, "utf-8");
115511
116437
  const lines = content.split("\n").filter((l) => l.length > 0);
115512
116438
  let firstUserMessage;
115513
116439
  for (const line of lines) {
@@ -115540,7 +116466,7 @@ async function listSessions2() {
115540
116466
  await ensureSessionsDir();
115541
116467
  let entries;
115542
116468
  try {
115543
- entries = await fs38.readdir(getSessionsDir());
116469
+ entries = await fs39.readdir(getSessionsDir());
115544
116470
  } catch {
115545
116471
  return [];
115546
116472
  }
@@ -115548,7 +116474,7 @@ async function listSessions2() {
115548
116474
  for (const name of entries) {
115549
116475
  if (!name.endsWith(".jsonl")) continue;
115550
116476
  const id2 = name.replace(/\.jsonl$/, "");
115551
- const info = await inspectSession(path45.join(getSessionsDir(), name), id2);
116477
+ const info = await inspectSession(path47.join(getSessionsDir(), name), id2);
115552
116478
  if (info) infos.push(info);
115553
116479
  }
115554
116480
  infos.sort((a, b) => b.lastModified - a.lastModified);
@@ -115559,7 +116485,7 @@ async function getMostRecent() {
115559
116485
  return all[0] ?? null;
115560
116486
  }
115561
116487
  async function getSessionById(id2) {
115562
- const filePath = path45.join(getSessionsDir(), `${id2}.jsonl`);
116488
+ const filePath = path47.join(getSessionsDir(), `${id2}.jsonl`);
115563
116489
  return inspectSession(filePath, id2);
115564
116490
  }
115565
116491
 
@@ -116514,4 +117440,4 @@ react/cjs/react-jsx-runtime.development.js:
116514
117440
  * LICENSE file in the root directory of this source tree.
116515
117441
  *)
116516
117442
  */
116517
- //# sourceMappingURL=chunk-WECKKLXP.js.map
117443
+ //# sourceMappingURL=chunk-JGJ4EKFB.js.map