snow-ai 0.4.31 → 0.4.32

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.
Files changed (5) hide show
  1. package/LICENSE +121 -0
  2. package/README.md +308 -0
  3. package/bundle/cli.mjs +372 -267
  4. package/package.json +1 -1
  5. package/readme.md +0 -145
package/bundle/cli.mjs CHANGED
@@ -50964,7 +50964,7 @@ function useGlobalExit(onNotification) {
50964
50964
  if (key.ctrl && input2 === "c") {
50965
50965
  const now = Date.now();
50966
50966
  if (now - lastCtrlCTime < ctrlCTimeout) {
50967
- process.exit(0);
50967
+ process.emit("SIGINT");
50968
50968
  } else {
50969
50969
  setLastCtrlCTime(now);
50970
50970
  if (onNotification) {
@@ -51342,6 +51342,105 @@ var init_ThemeContext = __esm({
51342
51342
  }
51343
51343
  });
51344
51344
 
51345
+ // dist/utils/core/processManager.js
51346
+ var processManager_exports = {};
51347
+ __export(processManager_exports, {
51348
+ gracefulExit: () => gracefulExit,
51349
+ processManager: () => processManager
51350
+ });
51351
+ import { exec as exec2 } from "child_process";
51352
+ function gracefulExit() {
51353
+ process.emit("SIGINT");
51354
+ }
51355
+ var ProcessManager, processManager;
51356
+ var init_processManager = __esm({
51357
+ "dist/utils/core/processManager.js"() {
51358
+ "use strict";
51359
+ ProcessManager = class {
51360
+ constructor() {
51361
+ Object.defineProperty(this, "processes", {
51362
+ enumerable: true,
51363
+ configurable: true,
51364
+ writable: true,
51365
+ value: /* @__PURE__ */ new Set()
51366
+ });
51367
+ Object.defineProperty(this, "isShuttingDown", {
51368
+ enumerable: true,
51369
+ configurable: true,
51370
+ writable: true,
51371
+ value: false
51372
+ });
51373
+ Object.defineProperty(this, "isWindows", {
51374
+ enumerable: true,
51375
+ configurable: true,
51376
+ writable: true,
51377
+ value: process.platform === "win32"
51378
+ });
51379
+ }
51380
+ /**
51381
+ * Register a child process for tracking
51382
+ */
51383
+ register(process19) {
51384
+ if (this.isShuttingDown) {
51385
+ this.killProcess(process19);
51386
+ return;
51387
+ }
51388
+ this.processes.add(process19);
51389
+ const cleanup = () => {
51390
+ this.processes.delete(process19);
51391
+ };
51392
+ process19.once("exit", cleanup);
51393
+ process19.once("error", cleanup);
51394
+ }
51395
+ /**
51396
+ * Kill a specific process gracefully
51397
+ * On Windows, uses taskkill with /T flag to terminate process tree
51398
+ */
51399
+ killProcess(process19) {
51400
+ const pid = process19.pid;
51401
+ if (!pid || process19.killed) {
51402
+ return;
51403
+ }
51404
+ if (this.isWindows) {
51405
+ exec2(`taskkill /PID ${pid} /T /F 2>NUL`, { windowsHide: true }, () => {
51406
+ });
51407
+ } else {
51408
+ try {
51409
+ process19.kill("SIGTERM");
51410
+ setTimeout(() => {
51411
+ try {
51412
+ if (!process19.killed) {
51413
+ process19.kill("SIGKILL");
51414
+ }
51415
+ } catch {
51416
+ }
51417
+ }, 1e3);
51418
+ } catch {
51419
+ }
51420
+ }
51421
+ }
51422
+ /**
51423
+ * Kill all tracked processes
51424
+ * On Windows, kills process trees to ensure no orphaned children
51425
+ */
51426
+ killAll() {
51427
+ this.isShuttingDown = true;
51428
+ for (const process19 of this.processes) {
51429
+ this.killProcess(process19);
51430
+ }
51431
+ this.processes.clear();
51432
+ }
51433
+ /**
51434
+ * Get count of active processes
51435
+ */
51436
+ getActiveCount() {
51437
+ return this.processes.size;
51438
+ }
51439
+ };
51440
+ processManager = new ProcessManager();
51441
+ }
51442
+ });
51443
+
51345
51444
  // node_modules/react-is/cjs/react-is.production.min.js
51346
51445
  var require_react_is_production_min = __commonJS({
51347
51446
  "node_modules/react-is/cjs/react-is.production.min.js"(exports2) {
@@ -182219,9 +182318,9 @@ var require_prettier = __commonJS({
182219
182318
  });
182220
182319
  var require_fails = __commonJS2({
182221
182320
  "node_modules/core-js/internals/fails.js"(exports22, module22) {
182222
- module22.exports = function(exec5) {
182321
+ module22.exports = function(exec6) {
182223
182322
  try {
182224
- return !!exec5();
182323
+ return !!exec6();
182225
182324
  } catch (error) {
182226
182325
  return true;
182227
182326
  }
@@ -183346,7 +183445,7 @@ var require_prettier = __commonJS({
183346
183445
  var empty = [];
183347
183446
  var construct = getBuiltIn("Reflect", "construct");
183348
183447
  var constructorRegExp = /^\s*(?:class|function)\b/;
183349
- var exec5 = uncurryThis(constructorRegExp.exec);
183448
+ var exec6 = uncurryThis(constructorRegExp.exec);
183350
183449
  var INCORRECT_TO_STRING = !constructorRegExp.exec(noop5);
183351
183450
  var isConstructorModern = function isConstructor(argument) {
183352
183451
  if (!isCallable(argument))
@@ -183368,7 +183467,7 @@ var require_prettier = __commonJS({
183368
183467
  return false;
183369
183468
  }
183370
183469
  try {
183371
- return INCORRECT_TO_STRING || !!exec5(constructorRegExp, inspectSource(argument));
183470
+ return INCORRECT_TO_STRING || !!exec6(constructorRegExp, inspectSource(argument));
183372
183471
  } catch (error) {
183373
183472
  return true;
183374
183473
  }
@@ -183875,13 +183974,13 @@ var require_prettier = __commonJS({
183875
183974
  editLength++;
183876
183975
  }
183877
183976
  if (callback) {
183878
- (function exec5() {
183977
+ (function exec6() {
183879
183978
  setTimeout(function() {
183880
183979
  if (editLength > maxEditLength) {
183881
183980
  return callback();
183882
183981
  }
183883
183982
  if (!execEditLength()) {
183884
- exec5();
183983
+ exec6();
183885
183984
  }
183886
183985
  }, 0);
183887
183986
  })();
@@ -198085,7 +198184,7 @@ ${fromBody}`;
198085
198184
  let processingKey;
198086
198185
  let processingTimer;
198087
198186
  let processingDeferred;
198088
- const cleanup2 = () => __awaiter22(this, void 0, void 0, function* () {
198187
+ const cleanup = () => __awaiter22(this, void 0, void 0, function* () {
198089
198188
  if (processingKey !== void 0) {
198090
198189
  return;
198091
198190
  }
@@ -198137,10 +198236,10 @@ ${fromBody}`;
198137
198236
  if (processingKey && processingKey === key) {
198138
198237
  reset();
198139
198238
  }
198140
- cleanup2();
198239
+ cleanup();
198141
198240
  return result2;
198142
198241
  };
198143
- cleanup2();
198242
+ cleanup();
198144
198243
  return map3;
198145
198244
  }
198146
198245
  exports22.default = mapAgeCleaner2;
@@ -220635,7 +220734,7 @@ var init_vscodeConnection = __esm({
220635
220734
  let isResolved = false;
220636
220735
  const timeout2 = setTimeout(() => {
220637
220736
  if (!isResolved) {
220638
- cleanup2();
220737
+ cleanup();
220639
220738
  resolve10([]);
220640
220739
  }
220641
220740
  }, 2e3);
@@ -220644,14 +220743,14 @@ var init_vscodeConnection = __esm({
220644
220743
  const data = JSON.parse(message.toString());
220645
220744
  if (data.type === "diagnostics" && data.requestId === requestId) {
220646
220745
  if (!isResolved) {
220647
- cleanup2();
220746
+ cleanup();
220648
220747
  resolve10(data.diagnostics || []);
220649
220748
  }
220650
220749
  }
220651
220750
  } catch (error) {
220652
220751
  }
220653
220752
  };
220654
- const cleanup2 = () => {
220753
+ const cleanup = () => {
220655
220754
  isResolved = true;
220656
220755
  clearTimeout(timeout2);
220657
220756
  if (this.client) {
@@ -220666,7 +220765,7 @@ var init_vscodeConnection = __esm({
220666
220765
  filePath
220667
220766
  }));
220668
220767
  } catch (error) {
220669
- cleanup2();
220768
+ cleanup();
220670
220769
  resolve10([]);
220671
220770
  }
220672
220771
  });
@@ -231594,7 +231693,7 @@ var require_stream_readable = __commonJS({
231594
231693
  if (readable === src) {
231595
231694
  if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
231596
231695
  unpipeInfo.hasUnpiped = true;
231597
- cleanup2();
231696
+ cleanup();
231598
231697
  }
231599
231698
  }
231600
231699
  }
@@ -231605,7 +231704,7 @@ var require_stream_readable = __commonJS({
231605
231704
  var ondrain = pipeOnDrain(src);
231606
231705
  dest.on("drain", ondrain);
231607
231706
  var cleanedUp = false;
231608
- function cleanup2() {
231707
+ function cleanup() {
231609
231708
  debug6("cleanup");
231610
231709
  dest.removeListener("close", onclose);
231611
231710
  dest.removeListener("finish", onfinish);
@@ -287530,9 +287629,9 @@ var init_pdf = __esm({
287530
287629
  1103: (
287531
287630
  /***/
287532
287631
  ((module2) => {
287533
- module2.exports = function(exec5) {
287632
+ module2.exports = function(exec6) {
287534
287633
  try {
287535
- return { error: false, value: exec5() };
287634
+ return { error: false, value: exec6() };
287536
287635
  } catch (error) {
287537
287636
  return { error: true, value: error };
287538
287637
  }
@@ -287896,7 +287995,7 @@ var init_pdf = __esm({
287896
287995
  var parseInt2 = globalThis2.parseInt;
287897
287996
  var min2 = Math.min;
287898
287997
  var NOT_HEX = /[^\da-f]/i;
287899
- var exec5 = uncurryThis(NOT_HEX.exec);
287998
+ var exec6 = uncurryThis(NOT_HEX.exec);
287900
287999
  var stringSlice = uncurryThis("".slice);
287901
288000
  module2.exports = function(string, into) {
287902
288001
  var stringLength = string.length;
@@ -287907,7 +288006,7 @@ var init_pdf = __esm({
287907
288006
  var written = 0;
287908
288007
  while (written < maxLength) {
287909
288008
  var hexits = stringSlice(string, read2, read2 += 2);
287910
- if (exec5(NOT_HEX, hexits)) throw new SyntaxError2("String should only contain hex characters");
288009
+ if (exec6(NOT_HEX, hexits)) throw new SyntaxError2("String should only contain hex characters");
287911
288010
  bytes[written++] = parseInt2(hexits, 16);
287912
288011
  }
287913
288012
  return { bytes, read: read2 };
@@ -290657,7 +290756,7 @@ var init_pdf = __esm({
290657
290756
  var fromCharCode = String.fromCharCode;
290658
290757
  var at = uncurryThis("".charAt);
290659
290758
  var slice2 = uncurryThis("".slice);
290660
- var exec5 = uncurryThis(/./.exec);
290759
+ var exec6 = uncurryThis(/./.exec);
290661
290760
  var codePoints = {
290662
290761
  '\\"': '"',
290663
290762
  "\\\\": "\\",
@@ -290683,7 +290782,7 @@ var init_pdf = __esm({
290683
290782
  } else if (twoChars === "\\u") {
290684
290783
  i += 2;
290685
290784
  var fourHexDigits = slice2(source2, i, i + 4);
290686
- if (!exec5(IS_4_HEX_DIGITS, fourHexDigits)) throw new $SyntaxError("Bad Unicode escape at: " + i);
290785
+ if (!exec6(IS_4_HEX_DIGITS, fourHexDigits)) throw new $SyntaxError("Bad Unicode escape at: " + i);
290687
290786
  value += fromCharCode($parseInt(fourHexDigits, 16));
290688
290787
  i += 4;
290689
290788
  } else throw new $SyntaxError('Unknown escape sequence: "' + twoChars + '"');
@@ -290692,7 +290791,7 @@ var init_pdf = __esm({
290692
290791
  i++;
290693
290792
  break;
290694
290793
  } else {
290695
- if (exec5(IS_C0_CONTROL_CODE, chr)) throw new $SyntaxError("Bad control character in string literal at: " + i);
290794
+ if (exec6(IS_C0_CONTROL_CODE, chr)) throw new $SyntaxError("Bad control character in string literal at: " + i);
290696
290795
  value += chr;
290697
290796
  i++;
290698
290797
  }
@@ -290779,7 +290878,7 @@ var init_pdf = __esm({
290779
290878
  var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
290780
290879
  var at = uncurryThis("".charAt);
290781
290880
  var slice2 = uncurryThis("".slice);
290782
- var exec5 = uncurryThis(/./.exec);
290881
+ var exec6 = uncurryThis(/./.exec);
290783
290882
  var push2 = uncurryThis([].push);
290784
290883
  var IS_DIGIT = /^\d$/;
290785
290884
  var IS_NON_ZERO_DIGIT = /^[1-9]$/;
@@ -290850,7 +290949,7 @@ var init_pdf = __esm({
290850
290949
  var i = this.skip(IS_WHITESPACE, this.index);
290851
290950
  var fork = this.fork(i);
290852
290951
  var chr = at(source2, i);
290853
- if (exec5(IS_NUMBER_START, chr)) return fork.number();
290952
+ if (exec6(IS_NUMBER_START, chr)) return fork.number();
290854
290953
  switch (chr) {
290855
290954
  case "{":
290856
290955
  return fork.object();
@@ -290939,7 +291038,7 @@ var init_pdf = __esm({
290939
291038
  var i = startIndex;
290940
291039
  if (at(source2, i) === "-") i++;
290941
291040
  if (at(source2, i) === "0") i++;
290942
- else if (exec5(IS_NON_ZERO_DIGIT, at(source2, i))) i = this.skip(IS_DIGIT, i + 1);
291041
+ else if (exec6(IS_NON_ZERO_DIGIT, at(source2, i))) i = this.skip(IS_DIGIT, i + 1);
290943
291042
  else throw new SyntaxError2("Failed to parse number at: " + i);
290944
291043
  if (at(source2, i) === ".") i = this.skip(IS_DIGIT, i + 1);
290945
291044
  if (at(source2, i) === "e" || at(source2, i) === "E") {
@@ -290960,7 +291059,7 @@ var init_pdf = __esm({
290960
291059
  },
290961
291060
  skip: function(regex2, i) {
290962
291061
  var source2 = this.source;
290963
- for (; i < source2.length; i++) if (!exec5(regex2, at(source2, i))) break;
291062
+ for (; i < source2.length; i++) if (!exec6(regex2, at(source2, i))) break;
290964
291063
  return i;
290965
291064
  },
290966
291065
  until: function(array, i) {
@@ -291221,9 +291320,9 @@ var init_pdf = __esm({
291221
291320
  9039: (
291222
291321
  /***/
291223
291322
  ((module2) => {
291224
- module2.exports = function(exec5) {
291323
+ module2.exports = function(exec6) {
291225
291324
  try {
291226
- return !!exec5();
291325
+ return !!exec6();
291227
291326
  } catch (error) {
291228
291327
  return true;
291229
291328
  }
@@ -320077,82 +320176,6 @@ var init_security_utils = __esm({
320077
320176
  }
320078
320177
  });
320079
320178
 
320080
- // dist/utils/core/processManager.js
320081
- var processManager_exports = {};
320082
- __export(processManager_exports, {
320083
- processManager: () => processManager
320084
- });
320085
- var ProcessManager, processManager;
320086
- var init_processManager = __esm({
320087
- "dist/utils/core/processManager.js"() {
320088
- "use strict";
320089
- ProcessManager = class {
320090
- constructor() {
320091
- Object.defineProperty(this, "processes", {
320092
- enumerable: true,
320093
- configurable: true,
320094
- writable: true,
320095
- value: /* @__PURE__ */ new Set()
320096
- });
320097
- Object.defineProperty(this, "isShuttingDown", {
320098
- enumerable: true,
320099
- configurable: true,
320100
- writable: true,
320101
- value: false
320102
- });
320103
- }
320104
- /**
320105
- * Register a child process for tracking
320106
- */
320107
- register(process19) {
320108
- if (this.isShuttingDown) {
320109
- this.killProcess(process19);
320110
- return;
320111
- }
320112
- this.processes.add(process19);
320113
- const cleanup2 = () => {
320114
- this.processes.delete(process19);
320115
- };
320116
- process19.once("exit", cleanup2);
320117
- process19.once("error", cleanup2);
320118
- }
320119
- /**
320120
- * Kill a specific process gracefully
320121
- */
320122
- killProcess(process19) {
320123
- try {
320124
- if (process19.pid && !process19.killed) {
320125
- process19.kill("SIGTERM");
320126
- setTimeout(() => {
320127
- if (process19.pid && !process19.killed) {
320128
- process19.kill("SIGKILL");
320129
- }
320130
- }, 1e3);
320131
- }
320132
- } catch (error) {
320133
- }
320134
- }
320135
- /**
320136
- * Kill all tracked processes
320137
- */
320138
- killAll() {
320139
- this.isShuttingDown = true;
320140
- for (const process19 of this.processes) {
320141
- this.killProcess(process19);
320142
- }
320143
- this.processes.clear();
320144
- }
320145
- /**
320146
- * Get count of active processes
320147
- */
320148
- getActiveCount() {
320149
- return this.processes.size;
320150
- }
320151
- };
320152
- processManager = new ProcessManager();
320153
- }
320154
- });
320155
-
320156
320179
  // dist/mcp/bash.js
320157
320180
  var bash_exports = {};
320158
320181
  __export(bash_exports, {
@@ -320160,7 +320183,7 @@ __export(bash_exports, {
320160
320183
  mcpTools: () => mcpTools2,
320161
320184
  terminalService: () => terminalService
320162
320185
  });
320163
- import { exec as exec2 } from "child_process";
320186
+ import { exec as exec3 } from "child_process";
320164
320187
  var TerminalCommandService, terminalService, mcpTools2;
320165
320188
  var init_bash = __esm({
320166
320189
  "dist/mcp/bash.js"() {
@@ -320197,7 +320220,7 @@ var init_bash = __esm({
320197
320220
  if (isDangerousCommand(command)) {
320198
320221
  throw new Error(`Dangerous command detected and blocked: ${command.slice(0, 50)}`);
320199
320222
  }
320200
- const childProcess2 = exec2(command, {
320223
+ const childProcess2 = exec3(command, {
320201
320224
  cwd: this.workingDirectory,
320202
320225
  timeout: timeout2,
320203
320226
  maxBuffer: this.maxOutputLength,
@@ -364329,18 +364352,18 @@ var require_parse_proxy_response = __commonJS({
364329
364352
  else
364330
364353
  socket.once("readable", read2);
364331
364354
  }
364332
- function cleanup2() {
364355
+ function cleanup() {
364333
364356
  socket.removeListener("end", onend);
364334
364357
  socket.removeListener("error", onerror);
364335
364358
  socket.removeListener("readable", read2);
364336
364359
  }
364337
364360
  function onend() {
364338
- cleanup2();
364361
+ cleanup();
364339
364362
  debug6("onend");
364340
364363
  reject2(new Error("Proxy connection ended before receiving CONNECT response"));
364341
364364
  }
364342
364365
  function onerror(err) {
364343
- cleanup2();
364366
+ cleanup();
364344
364367
  debug6("onerror %o", err);
364345
364368
  reject2(err);
364346
364369
  }
@@ -364384,7 +364407,7 @@ var require_parse_proxy_response = __commonJS({
364384
364407
  }
364385
364408
  }
364386
364409
  debug6("got proxy server response: %o %o", firstLine, headers);
364387
- cleanup2();
364410
+ cleanup();
364388
364411
  resolve10({
364389
364412
  connect: {
364390
364413
  statusCode,
@@ -368485,7 +368508,7 @@ var require_dist6 = __commonJS({
368485
368508
  // than necessary since socks will always override the host and port
368486
368509
  socket_options: this.socketOptions ?? void 0
368487
368510
  };
368488
- const cleanup2 = (tlsSocket) => {
368511
+ const cleanup = (tlsSocket) => {
368489
368512
  req.destroy();
368490
368513
  socket.destroy();
368491
368514
  if (tlsSocket)
@@ -368496,7 +368519,7 @@ var require_dist6 = __commonJS({
368496
368519
  debug6("Successfully created socks proxy connection");
368497
368520
  if (timeout2 !== null) {
368498
368521
  socket.setTimeout(timeout2);
368499
- socket.on("timeout", () => cleanup2());
368522
+ socket.on("timeout", () => cleanup());
368500
368523
  }
368501
368524
  if (opts.secureEndpoint) {
368502
368525
  debug6("Upgrading socket connection to TLS");
@@ -368506,7 +368529,7 @@ var require_dist6 = __commonJS({
368506
368529
  });
368507
368530
  tlsSocket.once("error", (error) => {
368508
368531
  debug6("Socket TLS error", error.message);
368509
- cleanup2(tlsSocket);
368532
+ cleanup(tlsSocket);
368510
368533
  });
368511
368534
  return tlsSocket;
368512
368535
  }
@@ -391298,7 +391321,7 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
391298
391321
  }
391299
391322
  #recordStream(stream) {
391300
391323
  const rl = readline.createInterface(stream);
391301
- const cleanup2 = () => {
391324
+ const cleanup = () => {
391302
391325
  rl.off("line", onLine);
391303
391326
  rl.off("close", onClose);
391304
391327
  try {
@@ -391318,7 +391341,7 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
391318
391341
  this.#lineEmitter.emit("line", line);
391319
391342
  };
391320
391343
  const onClose = () => {
391321
- cleanup2();
391344
+ cleanup();
391322
391345
  };
391323
391346
  rl.on("line", onLine);
391324
391347
  rl.on("close", onClose);
@@ -391334,7 +391357,7 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
391334
391357
  waitForLineOutput(regex2, timeout2 = 0) {
391335
391358
  return new Promise((resolve10, reject2) => {
391336
391359
  const onClose = (errorOrCode) => {
391337
- cleanup2();
391360
+ cleanup();
391338
391361
  reject2(new Error([
391339
391362
  `Failed to launch the browser process: ${errorOrCode instanceof Error ? ` ${errorOrCode.message}` : ` Code: ${errorOrCode}`}`,
391340
391363
  "",
@@ -391349,14 +391372,14 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
391349
391372
  this.#browserProcess.on("error", onClose);
391350
391373
  const timeoutId = timeout2 > 0 ? setTimeout(onTimeout, timeout2) : void 0;
391351
391374
  this.#lineEmitter.on("line", onLine);
391352
- const cleanup2 = () => {
391375
+ const cleanup = () => {
391353
391376
  clearTimeout(timeoutId);
391354
391377
  this.#lineEmitter.off("line", onLine);
391355
391378
  this.#browserProcess.off("exit", onClose);
391356
391379
  this.#browserProcess.off("error", onClose);
391357
391380
  };
391358
391381
  function onTimeout() {
391359
- cleanup2();
391382
+ cleanup();
391360
391383
  reject2(new TimeoutError2(`Timed out after ${timeout2} ms while waiting for the WS endpoint URL to appear in stdout!`));
391361
391384
  }
391362
391385
  for (const line of this.#logs) {
@@ -391367,7 +391390,7 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
391367
391390
  if (!match2) {
391368
391391
  return;
391369
391392
  }
391370
- cleanup2();
391393
+ cleanup();
391371
391394
  resolve10(match2[1]);
391372
391395
  }
391373
391396
  });
@@ -393289,20 +393312,41 @@ var init_systemPrompt = __esm({
393289
393312
 
393290
393313
  PLACEHOLDER_FOR_WORKFLOW_SECTION
393291
393314
 
393292
- ### TODO Management - USE ACTIVELY
393315
+ ### TODO Management - AUTOMATICALLY AVAILABLE
393293
393316
 
393294
- **STRONGLY RECOMMENDED: Create TODO for ALL multi-step tasks (3+ steps)** - Prevents missing steps, ensures systematic execution
393317
+ **TODO lists are automatically created for each session** - No need to manually create TODO lists
393318
+
393319
+ **Available TODO tools:**
393320
+ - **todo-get**: Get current session's TODO list
393321
+ - **todo-add**: Add one or multiple new tasks to existing TODO list (supports batch adding)
393322
+ - **todo-update**: Update task status or content
393323
+ - **todo-delete**: Remove tasks from TODO list
393295
393324
 
393296
393325
  **When to use:** Multi-file changes, features, refactoring, bug fixes touching 2+ files
393297
393326
  **Skip only:** Single-file trivial edits (1-2 lines)
393298
393327
 
393328
+ **RECOMMENDED WORKFLOW - Plan Before Execute:**
393329
+ - **Before starting programming tasks**: Use todo-add to create a task list first (supports batch adding multiple tasks at once)
393330
+ - **While executing**: Update task status with todo-update as you complete each step
393331
+ - **Benefits**: Clear task structure, trackable progress, prevents missing requirements
393332
+
393299
393333
  **CRITICAL - PARALLEL CALLS ONLY:** ALWAYS call TODO tools WITH action tools in same function call block
393300
- - CORRECT: todo-create + filesystem-read | todo-update + filesystem-edit
393334
+ - CORRECT: todo-get + filesystem-read | todo-update + filesystem-edit | todo-add + filesystem-read
393301
393335
  - FORBIDDEN: NEVER call TODO tools alone then wait for result
393302
393336
 
393303
- **Lifecycle:** New task \u2192 todo-create + initial action | Major change \u2192 delete + recreate | Minor \u2192 todo-add/update
393337
+ **Lifecycle:** Receive task \u2192 Add TODO items (todo-add) \u2192 Execute & update progress (todo-update) \u2192 Clean up completed items (todo-delete)
393304
393338
 
393305
- **Best practice:** Start every non-trivial task with todo-create in parallel with first action
393339
+ **todo-add supports both single and batch adding:**
393340
+ - Single task: Pass a string for 'content' parameter
393341
+ - Multiple tasks: Pass an array of strings for 'content' to add multiple tasks at once
393342
+ - Example single: todo-add(content="Task 1")
393343
+ - Example batch: todo-add(content=["Task 1", "Task 2", "Task 3"])
393344
+ - This avoids redundant tool calls when adding multiple tasks
393345
+
393346
+ **Best practice:**
393347
+ - Always check current TODO status with todo-get before making changes
393348
+ - **Keep TODO clean**: Proactively delete obsolete, redundant, or overly detailed completed subtasks to maintain clarity and focus on current work
393349
+ - Use batch adding when you have multiple tasks to add at once to reduce tool call overhead
393306
393350
 
393307
393351
  ## Available Tools
393308
393352
 
@@ -393545,14 +393589,14 @@ async function delay(ms, abortSignal) {
393545
393589
  return;
393546
393590
  }
393547
393591
  const timer2 = setTimeout(() => {
393548
- cleanup2();
393592
+ cleanup();
393549
393593
  resolve10();
393550
393594
  }, ms);
393551
393595
  const abortHandler = () => {
393552
- cleanup2();
393596
+ cleanup();
393553
393597
  reject2(new Error("Aborted"));
393554
393598
  };
393555
- const cleanup2 = () => {
393599
+ const cleanup = () => {
393556
393600
  clearTimeout(timer2);
393557
393601
  abortSignal == null ? void 0 : abortSignal.removeEventListener("abort", abortHandler);
393558
393602
  };
@@ -400060,13 +400104,20 @@ var init_todo = __esm({
400060
400104
  async addTodoItem(sessionId, content, parentId) {
400061
400105
  const todoList = await this.getTodoList(sessionId);
400062
400106
  const now = (/* @__PURE__ */ new Date()).toISOString();
400107
+ let validatedParentId;
400108
+ if (parentId && parentId.trim() !== "" && todoList) {
400109
+ const parentExists = todoList.todos.some((todo) => todo.id === parentId);
400110
+ if (parentExists) {
400111
+ validatedParentId = parentId;
400112
+ }
400113
+ }
400063
400114
  const newTodo = {
400064
400115
  id: `todo-${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
400065
400116
  content,
400066
400117
  status: "pending",
400067
400118
  createdAt: now,
400068
400119
  updatedAt: now,
400069
- parentId
400120
+ parentId: validatedParentId
400070
400121
  };
400071
400122
  const todos = todoList ? [...todoList.todos, newTodo] : [newTodo];
400072
400123
  return this.saveTodoList(sessionId, todos, todoList);
@@ -400082,6 +400133,12 @@ var init_todo = __esm({
400082
400133
  const filteredTodos = todoList.todos.filter((t) => t.id !== todoId && t.parentId !== todoId);
400083
400134
  return this.saveTodoList(sessionId, filteredTodos, todoList);
400084
400135
  }
400136
+ /**
400137
+ * 创建空 TODO 列表(会话自动创建时使用)
400138
+ */
400139
+ async createEmptyTodo(sessionId) {
400140
+ return this.saveTodoList(sessionId, [], null);
400141
+ }
400085
400142
  /**
400086
400143
  * 删除整个会话的 TODO 列表
400087
400144
  */
@@ -400116,67 +400173,6 @@ var init_todo = __esm({
400116
400173
  */
400117
400174
  getTools() {
400118
400175
  return [
400119
- {
400120
- name: "todo-create",
400121
- description: ` RECOMMENDED: Create TODO list for structured task execution. Use this for ALL multi-step tasks!
400122
-
400123
- MANDATORY RULE - PARALLEL CALLS ONLY:
400124
- NEVER call todo-create alone! MUST call with other tools in the SAME function call block.
400125
- ALWAYS: todo-create + filesystem-read (or other action tool) in parallel
400126
- FORBIDDEN: Call todo-create, wait for result, then call other tools
400127
-
400128
- ## DEFAULT USAGE - Use TODO by default for:
400129
- ANY multi-file changes (always create TODO first)
400130
- ANY feature implementation (plan with TODO)
400131
- ANY refactoring work (track with TODO)
400132
- Bug fixes involving 2+ files (use TODO)
400133
- Tasks with 3+ distinct steps (create TODO)
400134
- SKIP ONLY: Single-file trivial edits (1-2 lines)
400135
-
400136
- ## WHY CREATE TODO:
400137
- - Ensures all requirements are addressed
400138
- - Prevents missing critical steps
400139
- - Provides clear progress tracking
400140
- - Improves code quality through systematic approach
400141
- - Builds user confidence with visible structure
400142
-
400143
- ## WHEN TO CALL:
400144
- 1. **NEW TASK**: Create TODO immediately when starting work (with parallel action)
400145
- 2. **NEW REQUIREMENT**: Delete old todos, create fresh list (with parallel action)
400146
- 3. **BEST PRACTICE**: Call todo-create + filesystem-read in parallel
400147
-
400148
- ## CREATION GUIDELINES:
400149
- - Break work into 3-7 clear, actionable tasks
400150
- - Order by logical dependencies
400151
- - Be specific (e.g., "Modify validateInput in form.ts" not "fix validation")
400152
- - Include verification step if critical
400153
- - Creates root tasks only - use todo-add to create subtasks
400154
-
400155
- ## LIFECYCLE:
400156
- This REPLACES the entire TODO list. For adding tasks to existing list, use "todo-add" instead.
400157
-
400158
- ## REMEMBER: MUST call with other tools - never alone!`,
400159
- inputSchema: {
400160
- type: "object",
400161
- properties: {
400162
- todos: {
400163
- type: "array",
400164
- items: {
400165
- type: "object",
400166
- properties: {
400167
- content: {
400168
- type: "string",
400169
- description: 'TODO item description - must be specific, actionable, and technically precise (e.g., "Modify handleSubmit function in ChatInput.tsx to validate user input before processing" NOT "fix input validation")'
400170
- }
400171
- },
400172
- required: ["content"]
400173
- },
400174
- description: "Complete list of TODO items. Each item must represent a discrete, verifiable unit of work. For programming tasks, typical structure: analyze code \u2192 implement changes \u2192 test functionality \u2192 verify build \u2192 commit (if requested)."
400175
- }
400176
- },
400177
- required: ["todos"]
400178
- }
400179
- },
400180
400176
  {
400181
400177
  name: "todo-get",
400182
400178
  description: `Get current TODO list with task IDs, status, and hierarchy.
@@ -400232,7 +400228,7 @@ Example: todo-update(task1, completed) + filesystem-edit(task2) \u2192 Update wh
400232
400228
  },
400233
400229
  {
400234
400230
  name: "todo-add",
400235
- description: `Add new task to existing TODO list when requirements expand.
400231
+ description: `Add one or multiple new tasks to existing TODO list when requirements expand.
400236
400232
 
400237
400233
  MANDATORY RULE - PARALLEL CALLS ONLY:
400238
400234
  NEVER call todo-add alone! MUST call with other tools in the SAME function call block.
@@ -400244,17 +400240,31 @@ USE WHEN:
400244
400240
  - You discover additional necessary steps
400245
400241
  - Breaking down a complex task into subtasks
400246
400242
 
400247
- DO NOT use for initial planning - use todo-create instead.`,
400243
+ SUPPORTS BOTH:
400244
+ - Single task: Pass a string for 'content'
400245
+ - Multiple tasks: Pass an array of strings for 'content' to batch add tasks efficiently
400246
+
400247
+ TODO will be automatically created for each session.`,
400248
400248
  inputSchema: {
400249
400249
  type: "object",
400250
400250
  properties: {
400251
400251
  content: {
400252
- type: "string",
400253
- description: "TODO item description - must be specific, actionable, and technically precise"
400252
+ oneOf: [
400253
+ {
400254
+ type: "string",
400255
+ description: "Single TODO item description"
400256
+ },
400257
+ {
400258
+ type: "array",
400259
+ items: { type: "string" },
400260
+ description: "Multiple TODO item descriptions for batch adding"
400261
+ }
400262
+ ],
400263
+ description: "TODO item description(s) - must be specific, actionable, and technically precise. Can be a single string or an array of strings."
400254
400264
  },
400255
400265
  parentId: {
400256
400266
  type: "string",
400257
- description: "Parent TODO ID to create a subtask (optional). Get valid IDs from todo-get."
400267
+ description: "Parent TODO ID to create a subtask (optional). Get valid IDs from todo-get. When adding multiple tasks, all will be added under the same parent."
400258
400268
  }
400259
400269
  },
400260
400270
  required: ["content"]
@@ -400269,7 +400279,10 @@ DO NOT use for initial planning - use todo-create instead.`,
400269
400279
  ALWAYS: todo-delete + filesystem-edit/todo-get/etc in parallel
400270
400280
  FORBIDDEN: Call todo-delete alone
400271
400281
 
400272
- NOTE: Deleting a parent task will cascade delete all its children automatically.`,
400282
+ NOTE: Deleting a parent task will cascade delete all its children automatically.
400283
+
400284
+ BEST PRACTICE - MAINTAIN CLEAN TODO:
400285
+ Proactively delete obsolete, redundant, or overly detailed completed subtasks to keep the TODO list clear and focused on current work status.`,
400273
400286
  inputSchema: {
400274
400287
  type: "object",
400275
400288
  properties: {
@@ -400301,36 +400314,16 @@ NOTE: Deleting a parent task will cascade delete all its children automatically.
400301
400314
  }
400302
400315
  try {
400303
400316
  switch (toolName) {
400304
- case "create": {
400305
- const { todos } = args2;
400306
- const todoItems = todos.map((t) => {
400307
- const now = (/* @__PURE__ */ new Date()).toISOString();
400308
- return {
400309
- id: `todo-${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
400310
- content: t.content,
400311
- status: "pending",
400312
- createdAt: now,
400313
- updatedAt: now
400314
- };
400315
- });
400316
- const existingList = await this.getTodoList(sessionId);
400317
- const result2 = await this.saveTodoList(sessionId, todoItems, existingList);
400318
- return {
400319
- content: [
400320
- {
400321
- type: "text",
400322
- text: JSON.stringify(result2, null, 2)
400323
- }
400324
- ]
400325
- };
400326
- }
400327
400317
  case "get": {
400328
- const result2 = await this.getTodoList(sessionId);
400318
+ let result2 = await this.getTodoList(sessionId);
400319
+ if (!result2) {
400320
+ result2 = await this.createEmptyTodo(sessionId);
400321
+ }
400329
400322
  return {
400330
400323
  content: [
400331
400324
  {
400332
400325
  type: "text",
400333
- text: result2 ? JSON.stringify(result2, null, 2) : "No TODO list found"
400326
+ text: JSON.stringify(result2, null, 2)
400334
400327
  }
400335
400328
  ]
400336
400329
  };
@@ -400354,15 +400347,30 @@ NOTE: Deleting a parent task will cascade delete all its children automatically.
400354
400347
  }
400355
400348
  case "add": {
400356
400349
  const { content, parentId } = args2;
400357
- const result2 = await this.addTodoItem(sessionId, content, parentId);
400358
- return {
400359
- content: [
400360
- {
400361
- type: "text",
400362
- text: JSON.stringify(result2, null, 2)
400363
- }
400364
- ]
400365
- };
400350
+ if (Array.isArray(content)) {
400351
+ let currentList = await this.getTodoList(sessionId);
400352
+ for (const item of content) {
400353
+ currentList = await this.addTodoItem(sessionId, item, parentId);
400354
+ }
400355
+ return {
400356
+ content: [
400357
+ {
400358
+ type: "text",
400359
+ text: JSON.stringify(currentList, null, 2)
400360
+ }
400361
+ ]
400362
+ };
400363
+ } else {
400364
+ const result2 = await this.addTodoItem(sessionId, content, parentId);
400365
+ return {
400366
+ content: [
400367
+ {
400368
+ type: "text",
400369
+ text: JSON.stringify(result2, null, 2)
400370
+ }
400371
+ ]
400372
+ };
400373
+ }
400366
400374
  }
400367
400375
  case "delete": {
400368
400376
  const { todoId } = args2;
@@ -401717,7 +401725,7 @@ __export(unifiedHooksExecutor_exports, {
401717
401725
  UnifiedHooksExecutor: () => UnifiedHooksExecutor,
401718
401726
  unifiedHooksExecutor: () => unifiedHooksExecutor
401719
401727
  });
401720
- import { exec as exec3 } from "child_process";
401728
+ import { exec as exec4 } from "child_process";
401721
401729
  var UnifiedHooksExecutor, unifiedHooksExecutor;
401722
401730
  var init_unifiedHooksExecutor = __esm({
401723
401731
  "dist/utils/execution/unifiedHooksExecutor.js"() {
@@ -401952,7 +401960,7 @@ var init_unifiedHooksExecutor = __esm({
401952
401960
  const timeout2 = action.timeout || this.defaultTimeout;
401953
401961
  const stdinData = context2 ? JSON.stringify(context2) : "";
401954
401962
  try {
401955
- const childProcess2 = exec3(command, {
401963
+ const childProcess2 = exec4(command, {
401956
401964
  cwd: process.cwd(),
401957
401965
  timeout: timeout2,
401958
401966
  maxBuffer: this.maxOutputLength,
@@ -402345,8 +402353,23 @@ var init_sessionManager = __esm({
402345
402353
  if (!isTemporary) {
402346
402354
  await this.saveSession(session);
402347
402355
  }
402356
+ await this.createEmptyTodoForSession(sessionId);
402348
402357
  return session;
402349
402358
  }
402359
+ /**
402360
+ * 为会话创建空TODO列表
402361
+ */
402362
+ async createEmptyTodoForSession(sessionId) {
402363
+ try {
402364
+ const todoService2 = getTodoService();
402365
+ await todoService2.createEmptyTodo(sessionId);
402366
+ } catch (error) {
402367
+ logger.warn("Failed to create empty TODO for session:", {
402368
+ sessionId,
402369
+ error: error instanceof Error ? error.message : String(error)
402370
+ });
402371
+ }
402372
+ }
402350
402373
  async saveSession(session) {
402351
402374
  if (session.isTemporary) {
402352
402375
  return;
@@ -405259,13 +405282,7 @@ function SubAgentConfigScreen({ onBack, onSave, inlineMode = false, agentId }) {
405259
405282
  },
405260
405283
  {
405261
405284
  name: t.subAgentConfig.todoTools,
405262
- tools: [
405263
- "todo-create",
405264
- "todo-get",
405265
- "todo-update",
405266
- "todo-add",
405267
- "todo-delete"
405268
- ]
405285
+ tools: ["todo-get", "todo-update", "todo-add", "todo-delete"]
405269
405286
  },
405270
405287
  {
405271
405288
  name: t.subAgentConfig.webSearchTools,
@@ -408170,13 +408187,13 @@ var init_base2 = __esm({
408170
408187
  editLength++;
408171
408188
  };
408172
408189
  if (callback) {
408173
- (function exec5() {
408190
+ (function exec6() {
408174
408191
  setTimeout(function() {
408175
408192
  if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
408176
408193
  return callback(void 0);
408177
408194
  }
408178
408195
  if (!execEditLength()) {
408179
- exec5();
408196
+ exec6();
408180
408197
  }
408181
408198
  }, 0);
408182
408199
  })();
@@ -474187,12 +474204,50 @@ function parseAndRenderTable(content) {
474187
474204
  cellContent += part;
474188
474205
  }
474189
474206
  }
474207
+ const terminalWidth = process.stdout.columns || 80;
474208
+ const numColumns = headers.length;
474209
+ const bordersWidth = numColumns + 1;
474210
+ const paddingWidth = numColumns * 2;
474211
+ const availableWidth = terminalWidth - bordersWidth - paddingWidth;
474212
+ const columnWidths = [];
474213
+ if (availableWidth > 0 && numColumns > 0) {
474214
+ const contentLengths = headers.map((header, colIndex) => {
474215
+ const getDisplayWidth = (str) => {
474216
+ let width = 0;
474217
+ for (const char of str) {
474218
+ width += char.charCodeAt(0) > 255 ? 2 : 1;
474219
+ }
474220
+ return width;
474221
+ };
474222
+ let maxLen = getDisplayWidth(header);
474223
+ rows.forEach((row) => {
474224
+ const cellContent2 = row[colIndex] || "";
474225
+ maxLen = Math.max(maxLen, getDisplayWidth(cellContent2));
474226
+ });
474227
+ return maxLen;
474228
+ });
474229
+ const totalContentWidth = contentLengths.reduce((sum, len) => sum + len, 0);
474230
+ if (totalContentWidth > 0) {
474231
+ contentLengths.forEach((len, index) => {
474232
+ const proportion = len / totalContentWidth;
474233
+ let colWidth = Math.floor(availableWidth * proportion);
474234
+ colWidth = Math.max(8, colWidth);
474235
+ columnWidths[index] = colWidth;
474236
+ });
474237
+ } else {
474238
+ const equalWidth = Math.floor(availableWidth / numColumns);
474239
+ headers.forEach(() => columnWidths.push(Math.max(8, equalWidth)));
474240
+ }
474241
+ }
474190
474242
  const table2 = new import_cli_table3.default({
474191
474243
  head: headers,
474244
+ colWidths: columnWidths.length > 0 ? columnWidths : void 0,
474192
474245
  style: {
474193
474246
  head: ["cyan"],
474194
474247
  border: ["gray"]
474195
- }
474248
+ },
474249
+ wordWrap: true,
474250
+ wrapOnWordBoundary: false
474196
474251
  });
474197
474252
  rows.forEach((row) => table2.push(row));
474198
474253
  return "\n" + table2.toString() + "\n";
@@ -475695,7 +475750,7 @@ ${combinedOutput}`;
475695
475750
  return result2;
475696
475751
  }
475697
475752
  function getToolResourceType(toolName) {
475698
- if (toolName === "todo-create" || toolName === "todo-update" || toolName === "todo-add" || toolName === "todo-delete") {
475753
+ if (toolName === "todo-update" || toolName === "todo-add" || toolName === "todo-delete") {
475699
475754
  return "todo-state";
475700
475755
  }
475701
475756
  if (toolName === "terminal-execute") {
@@ -476223,7 +476278,7 @@ var init_contextCompressor = __esm({
476223
476278
  });
476224
476279
 
476225
476280
  // dist/utils/ui/fileDialog.js
476226
- import { exec as exec4 } from "child_process";
476281
+ import { exec as exec5 } from "child_process";
476227
476282
  import { promisify } from "util";
476228
476283
  import * as path37 from "path";
476229
476284
  import * as os18 from "os";
@@ -476282,7 +476337,7 @@ var execAsync;
476282
476337
  var init_fileDialog = __esm({
476283
476338
  "dist/utils/ui/fileDialog.js"() {
476284
476339
  "use strict";
476285
- execAsync = promisify(exec4);
476340
+ execAsync = promisify(exec5);
476286
476341
  }
476287
476342
  });
476288
476343
 
@@ -477223,6 +477278,20 @@ async function handleConversationWithTools(options) {
477223
477278
  streaming: false
477224
477279
  });
477225
477280
  }
477281
+ for (const toolCall of [
477282
+ ...autoApprovedTools,
477283
+ ...nonSensitiveTools
477284
+ ]) {
477285
+ const rejectionMessage = {
477286
+ role: "tool",
477287
+ tool_call_id: toolCall.id,
477288
+ content: rejectMessage
477289
+ };
477290
+ conversationMessages.push(rejectionMessage);
477291
+ saveMessage(rejectionMessage).catch((error) => {
477292
+ console.error("Failed to save auto-approved tool rejection message:", error);
477293
+ });
477294
+ }
477226
477295
  if (rejectedToolUIMessages.length > 0) {
477227
477296
  setMessages((prev) => [...prev, ...rejectedToolUIMessages]);
477228
477297
  }
@@ -477280,6 +477349,17 @@ async function handleConversationWithTools(options) {
477280
477349
  streaming: false
477281
477350
  });
477282
477351
  }
477352
+ for (const toolCall of autoApprovedTools) {
477353
+ const rejectionMessage = {
477354
+ role: "tool",
477355
+ tool_call_id: toolCall.id,
477356
+ content: rejectMessage
477357
+ };
477358
+ conversationMessages.push(rejectionMessage);
477359
+ saveMessage(rejectionMessage).catch((error) => {
477360
+ console.error("Failed to save auto-approved tool rejection message:", error);
477361
+ });
477362
+ }
477283
477363
  if (rejectedToolUIMessages.length > 0) {
477284
477364
  setMessages((prev) => [...prev, ...rejectedToolUIMessages]);
477285
477365
  }
@@ -486007,16 +486087,19 @@ import { writeFileSync as writeFileSync10, readFileSync as readFileSync15, exist
486007
486087
  import { join as join21 } from "path";
486008
486088
  import { homedir as homedir13, platform as platform4 } from "os";
486009
486089
  function checkCommandExists(command) {
486010
- try {
486011
- execSync5(`command -v ${command}`, {
486012
- stdio: "ignore",
486013
- shell: "/bin/zsh",
486014
- env: process.env
486015
- });
486016
- return true;
486017
- } catch {
486018
- return false;
486090
+ const shells = ["/bin/sh", "/bin/bash", "/bin/zsh"];
486091
+ for (const shell of shells) {
486092
+ try {
486093
+ execSync5(`command -v ${command}`, {
486094
+ stdio: "ignore",
486095
+ shell,
486096
+ env: process.env
486097
+ });
486098
+ return true;
486099
+ } catch {
486100
+ }
486019
486101
  }
486102
+ return false;
486020
486103
  }
486021
486104
  function getSystemEditor() {
486022
486105
  if (platform4() === "win32") {
@@ -486047,7 +486130,7 @@ function MCPConfigScreen({ onBack }) {
486047
486130
  console.error(" Ubuntu/Debian: sudo apt-get install nano");
486048
486131
  console.error(" CentOS/RHEL: sudo yum install nano");
486049
486132
  console.error(" macOS: nano is usually pre-installed");
486050
- process.exit(1);
486133
+ gracefulExit();
486051
486134
  return;
486052
486135
  }
486053
486136
  exit();
@@ -486069,11 +486152,11 @@ function MCPConfigScreen({ onBack }) {
486069
486152
  console.error("Invalid JSON format");
486070
486153
  }
486071
486154
  }
486072
- process.exit(0);
486155
+ gracefulExit();
486073
486156
  });
486074
486157
  child.on("error", (error) => {
486075
486158
  console.error("Failed to open editor:", error.message);
486076
- process.exit(1);
486159
+ gracefulExit();
486077
486160
  });
486078
486161
  };
486079
486162
  openEditor();
@@ -486087,6 +486170,7 @@ var init_MCPConfigScreen = __esm({
486087
486170
  import_react115 = __toESM(require_react(), 1);
486088
486171
  await init_build2();
486089
486172
  init_apiConfig();
486173
+ init_processManager();
486090
486174
  CONFIG_DIR7 = join21(homedir13(), ".snow");
486091
486175
  MCP_CONFIG_FILE2 = join21(CONFIG_DIR7, "mcp-config.json");
486092
486176
  }
@@ -486118,7 +486202,7 @@ function ShowTaskListWrapper() {
486118
486202
  return import_react116.default.createElement(
486119
486203
  import_react116.Suspense,
486120
486204
  { fallback: loadingFallback },
486121
- import_react116.default.createElement(TaskManagerScreen2, { onBack: () => process.exit(0), onResumeTask: () => {
486205
+ import_react116.default.createElement(TaskManagerScreen2, { onBack: () => gracefulExit(), onResumeTask: () => {
486122
486206
  setCurrentView("chat");
486123
486207
  setChatScreenKey((prev) => prev + 1);
486124
486208
  } })
@@ -486165,7 +486249,7 @@ function AppContent({ version: version2, skipWelcome, autoResume, enableYolo })
486165
486249
  setShouldAutoResume(value === "resume-last");
486166
486250
  setCurrentView(value === "resume-last" ? "chat" : value);
486167
486251
  } else if (value === "exit") {
486168
- process.exit(0);
486252
+ gracefulExit();
486169
486253
  }
486170
486254
  };
486171
486255
  const renderView = () => {
@@ -486248,7 +486332,7 @@ function App2({ version: version2, skipWelcome, autoResume, headlessPrompt, show
486248
486332
  import_react116.default.createElement(
486249
486333
  import_react116.Suspense,
486250
486334
  { fallback: loadingFallback },
486251
- import_react116.default.createElement(HeadlessModeScreen2, { prompt: headlessPrompt, onComplete: () => process.exit(0) })
486335
+ import_react116.default.createElement(HeadlessModeScreen2, { prompt: headlessPrompt, onComplete: () => gracefulExit() })
486252
486336
  )
486253
486337
  )
486254
486338
  );
@@ -486286,6 +486370,7 @@ var init_app = __esm({
486286
486370
  init_useTerminalSize();
486287
486371
  init_i18n();
486288
486372
  init_ThemeContext();
486373
+ init_processManager();
486289
486374
  WelcomeScreen2 = import_react116.default.lazy(() => init_WelcomeScreen().then(() => WelcomeScreen_exports));
486290
486375
  ChatScreen2 = import_react116.default.lazy(() => init_ChatScreen().then(() => ChatScreen_exports));
486291
486376
  HeadlessModeScreen2 = import_react116.default.lazy(() => init_HeadlessModeScreen().then(() => HeadlessModeScreen_exports));
@@ -487617,24 +487702,44 @@ var Startup = ({ version: version2, skipWelcome, autoResume, headlessPrompt, sho
487617
487702
  process.stdout.write("\x1B[?2004l");
487618
487703
  process.stdout.write("\x1B[2K\r");
487619
487704
  process.stdout.write("\x1B[?25h");
487620
- var cleanup = async () => {
487705
+ var isCleaningUp = false;
487706
+ var cleanupSync = () => {
487707
+ process.stdout.write("\x1B[?2004l");
487708
+ const deps = global.__deps;
487709
+ if (deps) {
487710
+ deps.processManager.killAll();
487711
+ deps.resourceMonitor.stopMonitoring();
487712
+ deps.vscodeConnection.stop();
487713
+ }
487714
+ };
487715
+ var cleanupAsync = async () => {
487621
487716
  var _a21;
487717
+ if (isCleaningUp)
487718
+ return;
487719
+ isCleaningUp = true;
487622
487720
  process.stdout.write("\x1B[?2004l");
487623
487721
  const deps = global.__deps;
487624
487722
  if (deps) {
487625
- await ((_a21 = deps.closeAllMCPConnections) == null ? void 0 : _a21.call(deps));
487723
+ try {
487724
+ await Promise.race([
487725
+ (_a21 = deps.closeAllMCPConnections) == null ? void 0 : _a21.call(deps),
487726
+ new Promise((resolve10) => setTimeout(resolve10, 2e3))
487727
+ // 2s timeout
487728
+ ]);
487729
+ } catch {
487730
+ }
487626
487731
  deps.processManager.killAll();
487627
487732
  deps.resourceMonitor.stopMonitoring();
487628
487733
  deps.vscodeConnection.stop();
487629
487734
  }
487630
487735
  };
487631
- process.on("exit", cleanup);
487632
- process.on("SIGINT", () => {
487633
- cleanup();
487736
+ process.on("exit", cleanupSync);
487737
+ process.on("SIGINT", async () => {
487738
+ await cleanupAsync();
487634
487739
  process.exit(0);
487635
487740
  });
487636
- process.on("SIGTERM", () => {
487637
- cleanup();
487741
+ process.on("SIGTERM", async () => {
487742
+ await cleanupAsync();
487638
487743
  process.exit(0);
487639
487744
  });
487640
487745
  render_default(import_react117.default.createElement(Startup, { version: VERSION2, skipWelcome: Boolean(cli.flags.c || cli.flags.yolo || cli.flags.cYolo), autoResume: Boolean(cli.flags.c || cli.flags.cYolo), headlessPrompt: cli.flags.ask, showTaskList: cli.flags.taskList, isDevMode: cli.flags.dev, enableYolo: Boolean(cli.flags.yolo || cli.flags.cYolo) }), {