@defai.digital/automatosx 11.2.4 → 11.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import * as path4 from 'path';
3
- import path4__default, { dirname, join, isAbsolute, basename, resolve, extname as extname$1, relative, sep, normalize, parse as parse$1, delimiter } from 'path';
3
+ import path4__default, { dirname, join, isAbsolute, basename, resolve, extname as extname$1, sep, relative, normalize, parse as parse$1, delimiter } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
5
  import * as fs4 from 'fs/promises';
6
6
  import { mkdir, appendFile, access as access$1, readFile, stat, rm, readdir, copyFile, writeFile, rename, unlink, constants as constants$1, realpath as realpath$1 } from 'fs/promises';
@@ -393,7 +393,7 @@ var init_process_manager = __esm({
393
393
  if (child.killed || child.exitCode !== null) {
394
394
  continue;
395
395
  }
396
- killPromises.push(new Promise((resolve12) => {
396
+ killPromises.push(new Promise((resolve13) => {
397
397
  let mainTimeoutId = null;
398
398
  let fallbackTimeoutId = null;
399
399
  let resolved = false;
@@ -408,7 +408,7 @@ var init_process_manager = __esm({
408
408
  }
409
409
  if (!resolved) {
410
410
  resolved = true;
411
- resolve12();
411
+ resolve13();
412
412
  }
413
413
  };
414
414
  child.once("exit", () => {
@@ -433,8 +433,8 @@ var init_process_manager = __esm({
433
433
  try {
434
434
  await Promise.race([
435
435
  Promise.all(killPromises),
436
- new Promise((resolve12) => {
437
- finalTimeoutId = setTimeout(resolve12, timeout);
436
+ new Promise((resolve13) => {
437
+ finalTimeoutId = setTimeout(resolve13, timeout);
438
438
  })
439
439
  ]);
440
440
  } finally {
@@ -2582,7 +2582,8 @@ var init_base_provider = __esm({
2582
2582
  try {
2583
2583
  const cliCommand2 = this.getCLICommand();
2584
2584
  const cliArgs = await this.getCLIArgs();
2585
- const argsString = cliArgs.length > 0 ? cliArgs.join(" ") + " " : "";
2585
+ const escapedArgs = cliArgs.map((arg) => this.escapeShellArg(arg));
2586
+ const argsString = escapedArgs.length > 0 ? escapedArgs.join(" ") + " " : "";
2586
2587
  const escapedPrompt = this.escapeShellArg(prompt);
2587
2588
  const fullCommand = `${cliCommand2} ${argsString}${escapedPrompt}`;
2588
2589
  const commandLength = fullCommand.length;
@@ -2625,7 +2626,7 @@ var init_base_provider = __esm({
2625
2626
  * @returns Promise resolving to stdout and stderr
2626
2627
  */
2627
2628
  async executeWithSpawn(command, cliCommand2) {
2628
- return new Promise((resolve12, reject) => {
2629
+ return new Promise((resolve13, reject) => {
2629
2630
  const child = spawn(command, [], {
2630
2631
  shell: true,
2631
2632
  // Auto-detects: cmd.exe on Windows, /bin/sh on Unix
@@ -2724,11 +2725,16 @@ var init_base_provider = __esm({
2724
2725
  if (stderr) {
2725
2726
  logger.debug(`${cliCommand2} CLI stderr output`, { stderr: stderr.trim() });
2726
2727
  }
2727
- if (code === 0 || code === null) {
2728
+ if ((code === 0 || code === null) && !signal) {
2728
2729
  if (progressParser) {
2729
2730
  progressParser.succeed(`${cliCommand2} completed successfully`);
2730
2731
  }
2731
- resolve12({ stdout, stderr });
2732
+ resolve13({ stdout, stderr });
2733
+ } else if (signal) {
2734
+ if (progressParser) {
2735
+ progressParser.fail(`${cliCommand2} killed by signal ${signal}`);
2736
+ }
2737
+ reject(new Error(`${cliCommand2} CLI killed by signal ${signal}. stderr: ${stderr || "none"}`));
2732
2738
  } else {
2733
2739
  if (progressParser) {
2734
2740
  progressParser.fail(`${cliCommand2} failed with code ${code}`);
@@ -2778,7 +2784,7 @@ var init_base_provider = __esm({
2778
2784
  * @returns Promise resolving to stdout and stderr
2779
2785
  */
2780
2786
  async executeWithStdin(cliCommand2, cliArgs, prompt) {
2781
- return new Promise((resolve12, reject) => {
2787
+ return new Promise((resolve13, reject) => {
2782
2788
  const commandArgs = cliArgs ? cliArgs.split(" ").filter(Boolean) : [];
2783
2789
  logger.debug(`Executing ${cliCommand2} CLI with stdin`, {
2784
2790
  command: cliCommand2,
@@ -2891,7 +2897,7 @@ var init_base_provider = __esm({
2891
2897
  if (progressParser) {
2892
2898
  progressParser.succeed(`${cliCommand2} completed successfully`);
2893
2899
  }
2894
- resolve12({ stdout, stderr });
2900
+ resolve13({ stdout, stderr });
2895
2901
  } else {
2896
2902
  if (progressParser) {
2897
2903
  progressParser.fail(`${cliCommand2} failed with code ${code}`);
@@ -3014,6 +3020,10 @@ ${fullPrompt}
3014
3020
  errors: responseValidation.error.issues,
3015
3021
  response
3016
3022
  });
3023
+ throw new ProviderError(
3024
+ `Provider returned invalid response structure: ${responseValidation.error.issues.map((i) => i.message).join(", ")}`,
3025
+ "E1305" /* PROVIDER_EXEC_ERROR */
3026
+ );
3017
3027
  }
3018
3028
  return response;
3019
3029
  } catch (error) {
@@ -3643,7 +3653,7 @@ var init_cli_wrapper = __esm({
3643
3653
  * Spawn codex process
3644
3654
  */
3645
3655
  async spawnProcess(args, prompt, timeout) {
3646
- return new Promise((resolve12, reject) => {
3656
+ return new Promise((resolve13, reject) => {
3647
3657
  let stdout = "";
3648
3658
  let stderr = "";
3649
3659
  let hasTimedOut = false;
@@ -3700,7 +3710,7 @@ var init_cli_wrapper = __esm({
3700
3710
  return;
3701
3711
  }
3702
3712
  if (code === 0) {
3703
- resolve12({ stdout, stderr, exitCode: code });
3713
+ resolve13({ stdout, stderr, exitCode: code });
3704
3714
  } else {
3705
3715
  reject(
3706
3716
  new CodexError(
@@ -3733,7 +3743,7 @@ var init_cli_wrapper = __esm({
3733
3743
  * Spawn codex process with streaming support
3734
3744
  */
3735
3745
  async spawnProcessWithStreaming(args, prompt, timeout, renderer) {
3736
- return new Promise((resolve12, reject) => {
3746
+ return new Promise((resolve13, reject) => {
3737
3747
  let stdout = "";
3738
3748
  let stderr = "";
3739
3749
  let hasTimedOut = false;
@@ -3803,7 +3813,7 @@ var init_cli_wrapper = __esm({
3803
3813
  if (renderer) {
3804
3814
  renderer.succeed("Execution complete");
3805
3815
  }
3806
- resolve12({ stdout, stderr, exitCode: code });
3816
+ resolve13({ stdout, stderr, exitCode: code });
3807
3817
  } else {
3808
3818
  if (renderer) {
3809
3819
  renderer.fail(`Process exited with code ${code}`);
@@ -4291,16 +4301,16 @@ var init_command_builder = __esm({
4291
4301
  const args = [];
4292
4302
  args.push("-p", this.escape(prompt));
4293
4303
  if (options.provider) {
4294
- args.push("--provider", options.provider);
4304
+ args.push("--provider", this.escape(options.provider));
4295
4305
  }
4296
4306
  if (options.model) {
4297
- args.push("--model", options.model);
4307
+ args.push("--model", this.escape(options.model));
4298
4308
  }
4299
4309
  if (options.apiKey) {
4300
- args.push("--api-key", options.apiKey);
4310
+ args.push("--api-key", this.escape(options.apiKey));
4301
4311
  }
4302
4312
  if (options.baseUrl) {
4303
- args.push("--base-url", options.baseUrl);
4313
+ args.push("--base-url", this.escape(options.baseUrl));
4304
4314
  }
4305
4315
  if (options.directory) {
4306
4316
  args.push("--directory", this.escape(options.directory));
@@ -4318,7 +4328,7 @@ var init_command_builder = __esm({
4318
4328
  args.push("--selection", this.escape(options.selection));
4319
4329
  }
4320
4330
  if (options.lineRange) {
4321
- args.push("--line-range", options.lineRange);
4331
+ args.push("--line-range", this.escape(options.lineRange));
4322
4332
  }
4323
4333
  if (options.gitDiff) {
4324
4334
  args.push("--git-diff");
@@ -9279,7 +9289,7 @@ var PRECOMPILED_CONFIG = {
9279
9289
  "enableFreeTierPrioritization": true,
9280
9290
  "enableWorkloadAwareRouting": true
9281
9291
  },
9282
- "version": "11.2.4"
9292
+ "version": "11.2.6"
9283
9293
  };
9284
9294
 
9285
9295
  // src/core/config-schemas.ts
@@ -10902,7 +10912,7 @@ var configCommand = {
10902
10912
  } else if (process.env.AUTOMATOSX_CONFIG_PATH) {
10903
10913
  configPath = process.env.AUTOMATOSX_CONFIG_PATH;
10904
10914
  } else {
10905
- const projectConfig = resolve(process.cwd(), "automatosx.config.json");
10915
+ const projectConfig = resolve(process.cwd(), "ax.config.json");
10906
10916
  const hiddenConfig = resolve(process.cwd(), ".automatosx", "config.json");
10907
10917
  const fs7 = await import('fs');
10908
10918
  if (fs7.existsSync(projectConfig)) {
@@ -11165,9 +11175,9 @@ var PromptHelper = class {
11165
11175
  */
11166
11176
  async question(query) {
11167
11177
  const rl = this.ensureInterface();
11168
- return new Promise((resolve12) => {
11178
+ return new Promise((resolve13) => {
11169
11179
  rl.question(query, (answer) => {
11170
- resolve12(answer.trim());
11180
+ resolve13(answer.trim());
11171
11181
  });
11172
11182
  });
11173
11183
  }
@@ -12128,7 +12138,7 @@ var __filename2 = fileURLToPath(import.meta.url);
12128
12138
  var __dirname3 = dirname(__filename2);
12129
12139
  function getPackageRoot() {
12130
12140
  const currentDir = __dirname3;
12131
- if (currentDir.includes("/dist")) {
12141
+ if (currentDir.includes(`${sep}dist`) || currentDir.includes("/dist")) {
12132
12142
  return join(currentDir, "..");
12133
12143
  } else {
12134
12144
  return join(currentDir, "../..");
@@ -13362,18 +13372,30 @@ var setupCommand = {
13362
13372
  } else if (axCliConfigured === "manual_required") {
13363
13373
  console.log(chalk5.yellow(" \u26A0 ax-cli detected - manual MCP configuration required"));
13364
13374
  console.log(chalk5.gray(" Run: ax-cli mcp add automatosx --transport stdio --command ax --args mcp server"));
13375
+ } else if (axCliConfigured === "error") {
13376
+ console.log(chalk5.yellow(" \u26A0 ax-cli MCP configuration failed"));
13377
+ console.log(chalk5.gray(" CLI integration still works via subprocess"));
13365
13378
  } else {
13366
13379
  console.log(chalk5.green(" \u2713 ax-cli MCP integration configured"));
13367
13380
  }
13381
+ let geminiMcpStatus = "skipped";
13368
13382
  if (providers["gemini-cli"]) {
13369
13383
  console.log(chalk5.cyan("\u{1F50C} Setting up Gemini CLI integration..."));
13370
13384
  const geminiDir = join(projectDir, ".gemini");
13371
13385
  const geminiDirExistedBefore = await checkExists2(geminiDir);
13372
- await setupGeminiIntegration(projectDir, packageRoot);
13386
+ geminiMcpStatus = await setupGeminiIntegration(projectDir, packageRoot);
13373
13387
  if (!geminiDirExistedBefore) {
13374
13388
  createdResources.push(geminiDir);
13375
13389
  }
13376
- console.log(chalk5.green(" \u2713 Gemini CLI integration configured"));
13390
+ if (geminiMcpStatus === "configured") {
13391
+ console.log(chalk5.green(" \u2713 Gemini CLI MCP integration configured"));
13392
+ } else if (geminiMcpStatus === "skipped") {
13393
+ console.log(chalk5.yellow(" \u26A0 Gemini CLI MCP skipped (MCP server not found)"));
13394
+ console.log(chalk5.gray(" CLI integration still works via subprocess"));
13395
+ } else {
13396
+ console.log(chalk5.yellow(" \u26A0 Gemini CLI MCP configuration failed"));
13397
+ console.log(chalk5.gray(" CLI integration still works via subprocess"));
13398
+ }
13377
13399
  }
13378
13400
  console.log(chalk5.cyan("\u{1F4C2} Creating workspace directories..."));
13379
13401
  await createWorkspaceDirectories(projectDir);
@@ -13382,17 +13404,11 @@ var setupCommand = {
13382
13404
  const isGitRepo = await checkExists2(gitDir);
13383
13405
  if (!isGitRepo) {
13384
13406
  console.log(chalk5.cyan("\u{1F527} Initializing git repository..."));
13385
- await initializeGitRepository(projectDir);
13386
- console.log(chalk5.green(" \u2713 Git repository initialized"));
13387
- }
13388
- console.log(chalk5.cyan("\u{1F50C} Setting up Codex CLI MCP integration..."));
13389
- const codexDir = join(projectDir, ".codex");
13390
- const codexDirExistedBefore = await checkExists2(codexDir);
13391
- await setupCodexIntegration(projectDir, packageRoot);
13392
- if (!codexDirExistedBefore) {
13393
- createdResources.push(codexDir);
13407
+ const gitInitSuccess = await initializeGitRepository(projectDir);
13408
+ if (gitInitSuccess) {
13409
+ console.log(chalk5.green(" \u2713 Git repository initialized"));
13410
+ }
13394
13411
  }
13395
- console.log(chalk5.green(" \u2713 Codex CLI MCP integration configured"));
13396
13412
  console.log(chalk5.cyan("\u{1F4DD} Updating .gitignore..."));
13397
13413
  await updateGitignore(projectDir);
13398
13414
  console.log(chalk5.green(" \u2713 .gitignore updated"));
@@ -13889,10 +13905,10 @@ async function initializeGitRepository(projectDir) {
13889
13905
  const isGitRepo = await checkExists2(gitDir);
13890
13906
  if (isGitRepo) {
13891
13907
  logger.info("Git repository already exists, skipping initialization");
13892
- return;
13908
+ return true;
13893
13909
  }
13894
13910
  const { spawn: spawn9 } = await import('child_process');
13895
- await new Promise((resolve12, reject) => {
13911
+ await new Promise((resolve13, reject) => {
13896
13912
  const child = spawn9("git", ["init"], {
13897
13913
  cwd: projectDir,
13898
13914
  stdio: "pipe",
@@ -13908,7 +13924,7 @@ async function initializeGitRepository(projectDir) {
13908
13924
  reject(new Error(`git init failed with code ${code}: ${stderr}`));
13909
13925
  } else {
13910
13926
  logger.info("Git repository set up successfully");
13911
- resolve12();
13927
+ resolve13();
13912
13928
  }
13913
13929
  });
13914
13930
  child.on("error", (error) => {
@@ -13927,6 +13943,7 @@ async function initializeGitRepository(projectDir) {
13927
13943
  return;
13928
13944
  }
13929
13945
  });
13946
+ return true;
13930
13947
  } catch (error) {
13931
13948
  const errorMessage = error.message;
13932
13949
  if (errorMessage.includes("ENOENT") || errorMessage.includes("spawn git")) {
@@ -13942,6 +13959,7 @@ async function initializeGitRepository(projectDir) {
13942
13959
  error: errorMessage
13943
13960
  });
13944
13961
  }
13962
+ return false;
13945
13963
  }
13946
13964
  }
13947
13965
  async function updateGitignore(projectDir) {
@@ -14124,24 +14142,25 @@ async function initializeSpecKit(projectDir) {
14124
14142
  async function setupGeminiIntegration(projectDir, packageRoot) {
14125
14143
  const geminiDir = join(projectDir, ".gemini");
14126
14144
  await mkdir(geminiDir, { recursive: true });
14127
- await setupGeminiMCPConfig(projectDir, packageRoot);
14145
+ const mcpStatus = await setupGeminiMCPConfig(projectDir, packageRoot);
14146
+ return mcpStatus;
14128
14147
  }
14129
14148
  async function setupGeminiMCPConfig(projectDir, packageRoot) {
14130
14149
  const mcpServersPath = join(projectDir, ".gemini", "mcp-servers.json");
14131
14150
  try {
14132
- const globalMcpPath = join(packageRoot, "dist", "mcp", "index.js");
14133
14151
  const localMcpPath = join(projectDir, "node_modules", "@defai.digital", "automatosx", "dist", "mcp", "index.js");
14152
+ const globalMcpPath = join(packageRoot, "dist", "mcp", "index.js");
14134
14153
  let mcpServerPath;
14135
- if (await checkExists2(globalMcpPath)) {
14136
- mcpServerPath = globalMcpPath;
14137
- } else if (await checkExists2(localMcpPath)) {
14154
+ if (await checkExists2(localMcpPath)) {
14138
14155
  mcpServerPath = localMcpPath;
14156
+ } else if (await checkExists2(globalMcpPath)) {
14157
+ mcpServerPath = globalMcpPath;
14139
14158
  } else {
14140
14159
  logger.warn("AutomatosX MCP server not found, skipping Gemini CLI MCP configuration", {
14141
- globalPath: globalMcpPath,
14142
- localPath: localMcpPath
14160
+ localPath: localMcpPath,
14161
+ globalPath: globalMcpPath
14143
14162
  });
14144
- return;
14163
+ return "skipped";
14145
14164
  }
14146
14165
  let mcpConfig = {};
14147
14166
  if (await checkExists2(mcpServersPath)) {
@@ -14173,32 +14192,15 @@ async function setupGeminiMCPConfig(projectDir, packageRoot) {
14173
14192
  path: mcpServersPath,
14174
14193
  mcpServerPath
14175
14194
  });
14195
+ return "configured";
14176
14196
  } catch (error) {
14177
14197
  logger.warn("Failed to setup Gemini CLI MCP configuration", {
14178
14198
  error: error.message,
14179
14199
  path: mcpServersPath
14180
14200
  });
14201
+ return "failed";
14181
14202
  }
14182
14203
  }
14183
- async function setupCodexIntegration(projectDir, packageRoot) {
14184
- const codexDir = join(projectDir, ".codex");
14185
- await mkdir(codexDir, { recursive: true });
14186
- await setupCodexMCPConfig(projectDir);
14187
- }
14188
- async function setupCodexMCPConfig(_projectDir, _packageRoot) {
14189
- const mcpServersPath = join(_projectDir, ".codex", "mcp-servers.json");
14190
- if (await checkExists2(mcpServersPath)) {
14191
- try {
14192
- const { unlink: unlink7 } = await import('fs/promises');
14193
- await unlink7(mcpServersPath);
14194
- logger.info("Removed .codex/mcp-servers.json - using CLI mode instead of MCP", {
14195
- path: mcpServersPath
14196
- });
14197
- } catch {
14198
- }
14199
- }
14200
- logger.debug("Codex integration configured for CLI mode (MCP disabled)");
14201
- }
14202
14204
  async function createWorkspaceDirectories(projectDir) {
14203
14205
  const workspaceDirs = [
14204
14206
  join(projectDir, "automatosx"),
@@ -16068,7 +16070,7 @@ var configureCommand = {
16068
16070
  }
16069
16071
  console.log(chalk5.bold.cyan("\n\u2728 AutomatosX Setup Wizard\n"));
16070
16072
  console.log(chalk5.dim("This wizard will help you configure the OpenAI integration mode.\n"));
16071
- const configPath = resolve(process.cwd(), "automatosx.config.json");
16073
+ const configPath = resolve(process.cwd(), "ax.config.json");
16072
16074
  const config = await loadConfig(configPath);
16073
16075
  if (!config.providers.openai) {
16074
16076
  console.log(chalk5.red("\n\u274C OpenAI provider not found in configuration\n"));
@@ -18237,23 +18239,29 @@ var Router = class {
18237
18239
  const isCircuitOpen = this.circuitBreaker.isOpen(provider.name);
18238
18240
  healthMultipliers.set(provider.name, isCircuitOpen ? 0.5 : 1);
18239
18241
  }
18240
- const scores = await getProviderMetricsTracker().getAllScores(
18241
- providerNames,
18242
- strategyManager.getWeights(),
18243
- healthMultipliers
18244
- );
18245
- if (scores.length > 0) {
18246
- const scoreMap = new Map(scores.map((s) => [s.provider, s.totalScore]));
18247
- const originalOrder = providersToTry.map((p) => p.name);
18248
- providersToTry = [...providersToTry].sort((a, b) => {
18249
- const scoreA = scoreMap.get(a.name) ?? 0;
18250
- const scoreB = scoreMap.get(b.name) ?? 0;
18251
- return scoreB - scoreA;
18252
- });
18253
- logger.debug("Provider order after multi-factor routing", {
18254
- original: originalOrder,
18255
- reordered: providersToTry.map((p) => p.name),
18256
- scores: Object.fromEntries(scoreMap)
18242
+ try {
18243
+ const scores = await getProviderMetricsTracker().getAllScores(
18244
+ providerNames,
18245
+ strategyManager.getWeights(),
18246
+ healthMultipliers
18247
+ );
18248
+ if (scores.length > 0) {
18249
+ const scoreMap = new Map(scores.map((s) => [s.provider, s.totalScore]));
18250
+ const originalOrder = providersToTry.map((p) => p.name);
18251
+ providersToTry = [...providersToTry].sort((a, b) => {
18252
+ const scoreA = scoreMap.get(a.name) ?? 0;
18253
+ const scoreB = scoreMap.get(b.name) ?? 0;
18254
+ return scoreB - scoreA;
18255
+ });
18256
+ logger.debug("Provider order after multi-factor routing", {
18257
+ original: originalOrder,
18258
+ reordered: providersToTry.map((p) => p.name),
18259
+ scores: Object.fromEntries(scoreMap)
18260
+ });
18261
+ }
18262
+ } catch (scoringError) {
18263
+ logger.warn("Multi-factor scoring failed, using priority order", {
18264
+ error: scoringError.message
18257
18265
  });
18258
18266
  }
18259
18267
  }
@@ -20132,8 +20140,11 @@ var MemoryManager = class _MemoryManager {
20132
20140
  }
20133
20141
  const tempPath = `${this.config.dbPath}.restore.tmp`;
20134
20142
  const srcDb = new Database2(srcPath, { readonly: true });
20135
- await srcDb.backup(tempPath);
20136
- srcDb.close();
20143
+ try {
20144
+ await srcDb.backup(tempPath);
20145
+ } finally {
20146
+ srcDb.close();
20147
+ }
20137
20148
  try {
20138
20149
  const tempDb = new Database2(tempPath, { readonly: true });
20139
20150
  tempDb.prepare("SELECT COUNT(*) FROM memory_entries").get();
@@ -22725,7 +22736,7 @@ var __filename4 = fileURLToPath(import.meta.url);
22725
22736
  var __dirname5 = dirname(__filename4);
22726
22737
  function getPackageRoot3() {
22727
22738
  const currentDir = __dirname5;
22728
- if (currentDir.includes("/dist")) {
22739
+ if (currentDir.includes(`${sep}dist`) || currentDir.includes("/dist")) {
22729
22740
  return join(currentDir, "..");
22730
22741
  } else {
22731
22742
  return join(currentDir, "../..");
@@ -22856,6 +22867,7 @@ init_path_resolver();
22856
22867
  // src/core/conversation-context-store.ts
22857
22868
  init_esm_shims();
22858
22869
  init_logger();
22870
+ var VALID_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
22859
22871
  var ConversationContextStore = class {
22860
22872
  storePath;
22861
22873
  maxEntries;
@@ -22865,6 +22877,33 @@ var ConversationContextStore = class {
22865
22877
  this.maxEntries = options.maxEntries ?? 100;
22866
22878
  this.ttlMs = options.ttlMs ?? 24 * 60 * 60 * 1e3;
22867
22879
  }
22880
+ /**
22881
+ * Validate and sanitize context ID to prevent path traversal attacks
22882
+ *
22883
+ * SECURITY: This is critical to prevent path traversal vulnerabilities.
22884
+ * A malicious ID like "../../.ssh/id_rsa" could read/write/delete files
22885
+ * outside the context store directory.
22886
+ *
22887
+ * @param id - Context ID to validate
22888
+ * @returns Sanitized file path within storePath
22889
+ * @throws Error if ID is invalid or path escapes storePath
22890
+ */
22891
+ validateAndResolvePath(id) {
22892
+ if (!VALID_ID_PATTERN.test(id)) {
22893
+ throw new Error(
22894
+ `Invalid context ID: "${id}". IDs must be 1-64 characters, alphanumeric with underscores/hyphens only.`
22895
+ );
22896
+ }
22897
+ const filePath = join(this.storePath, `${id}.json`);
22898
+ const resolvedPath = resolve(filePath);
22899
+ const resolvedStorePath = resolve(this.storePath);
22900
+ const relativePath = relative(resolvedStorePath, resolvedPath);
22901
+ if (relativePath.startsWith("..") || relativePath.includes("/..") || relativePath.includes("\\..")) {
22902
+ logger.error("[ContextStore] Path traversal attempt blocked", { id, resolvedPath });
22903
+ throw new Error(`Security violation: context ID "${id}" would escape store directory`);
22904
+ }
22905
+ return resolvedPath;
22906
+ }
22868
22907
  /**
22869
22908
  * Initialize store (create directory if needed)
22870
22909
  */
@@ -22882,7 +22921,7 @@ var ConversationContextStore = class {
22882
22921
  */
22883
22922
  async save(context) {
22884
22923
  await this.initialize();
22885
- const filePath = join(this.storePath, `${context.id}.json`);
22924
+ const filePath = this.validateAndResolvePath(context.id);
22886
22925
  const data = JSON.stringify(context, null, 2);
22887
22926
  try {
22888
22927
  await writeFile(filePath, data, "utf-8");
@@ -22901,7 +22940,7 @@ var ConversationContextStore = class {
22901
22940
  * Get conversation context by ID
22902
22941
  */
22903
22942
  async get(id) {
22904
- const filePath = join(this.storePath, `${id}.json`);
22943
+ const filePath = this.validateAndResolvePath(id);
22905
22944
  try {
22906
22945
  const data = await readFile(filePath, "utf-8");
22907
22946
  const context = JSON.parse(data);
@@ -22955,7 +22994,7 @@ var ConversationContextStore = class {
22955
22994
  * Delete context entry
22956
22995
  */
22957
22996
  async delete(id) {
22958
- const filePath = join(this.storePath, `${id}.json`);
22997
+ const filePath = this.validateAndResolvePath(id);
22959
22998
  try {
22960
22999
  await unlink(filePath);
22961
23000
  logger.info("[ContextStore] Context deleted", { id });
@@ -25339,7 +25378,7 @@ ${context.task}`;
25339
25378
  * @param signal - Optional AbortSignal to cancel the sleep
25340
25379
  */
25341
25380
  sleep(ms, signal) {
25342
- return new Promise((resolve12, reject) => {
25381
+ return new Promise((resolve13, reject) => {
25343
25382
  if (signal?.aborted) {
25344
25383
  reject(new Error("Sleep cancelled"));
25345
25384
  return;
@@ -25349,7 +25388,7 @@ ${context.task}`;
25349
25388
  if (abortHandler && signal) {
25350
25389
  signal.removeEventListener("abort", abortHandler);
25351
25390
  }
25352
- resolve12();
25391
+ resolve13();
25353
25392
  }, ms);
25354
25393
  if (signal) {
25355
25394
  abortHandler = () => {
@@ -26767,10 +26806,10 @@ var McpClient = class extends EventEmitter {
26767
26806
  return;
26768
26807
  }
26769
26808
  if (this.state.status === "connecting") {
26770
- return new Promise((resolve12, reject) => {
26809
+ return new Promise((resolve13, reject) => {
26771
26810
  const onConnected = () => {
26772
26811
  this.off("error", onError);
26773
- resolve12();
26812
+ resolve13();
26774
26813
  };
26775
26814
  const onError = (err) => {
26776
26815
  this.off("connected", onConnected);
@@ -26937,14 +26976,14 @@ var McpClient = class extends EventEmitter {
26937
26976
  method,
26938
26977
  params
26939
26978
  };
26940
- return new Promise((resolve12, reject) => {
26979
+ return new Promise((resolve13, reject) => {
26941
26980
  const timeoutMs = timeout ?? this.config.timeout;
26942
26981
  const timeoutHandle = setTimeout(() => {
26943
26982
  this.pendingRequests.delete(id);
26944
26983
  reject(new Error(`Request timed out after ${timeoutMs}ms: ${method}`));
26945
26984
  }, timeoutMs);
26946
26985
  this.pendingRequests.set(id, {
26947
- resolve: resolve12,
26986
+ resolve: resolve13,
26948
26987
  reject,
26949
26988
  timeout: timeoutHandle
26950
26989
  });
@@ -27402,15 +27441,15 @@ var McpClientPool = class extends EventEmitter {
27402
27441
  }
27403
27442
  }
27404
27443
  async waitForConnection(provider, pool) {
27405
- return new Promise((resolve12, reject) => {
27444
+ return new Promise((resolve13, reject) => {
27406
27445
  const timeout = setTimeout(() => {
27407
- const index = pool.waitQueue.findIndex((w) => w.resolve === resolve12);
27446
+ const index = pool.waitQueue.findIndex((w) => w.resolve === resolve13);
27408
27447
  if (index !== -1) {
27409
27448
  pool.waitQueue.splice(index, 1);
27410
27449
  }
27411
27450
  reject(new ConnectionTimeoutError(provider, this.config.acquireTimeoutMs));
27412
27451
  }, this.config.acquireTimeoutMs);
27413
- pool.waitQueue.push({ resolve: resolve12, reject, timeout });
27452
+ pool.waitQueue.push({ resolve: resolve13, reject, timeout });
27414
27453
  logger.debug("[MCP Pool] Waiting for connection", {
27415
27454
  provider,
27416
27455
  queuePosition: pool.waitQueue.length
@@ -28887,6 +28926,8 @@ var McpServer = class _McpServer {
28887
28926
  initializationPromise = null;
28888
28927
  initializationMutex = new Mutex();
28889
28928
  // BUG FIX (v9.0.1): Prevent concurrent initialization
28929
+ stdinMutex = new Mutex();
28930
+ // BUG FIX: Prevent race conditions in stdin message processing
28890
28931
  version;
28891
28932
  ajv;
28892
28933
  compiledValidators = /* @__PURE__ */ new Map();
@@ -29262,7 +29303,15 @@ var McpServer = class _McpServer {
29262
29303
  * v10.5.0: Capture clientInfo for Smart Routing
29263
29304
  */
29264
29305
  async handleInitialize(request, id) {
29265
- const clientInfo = request.params.clientInfo;
29306
+ const clientInfo = request.params?.clientInfo;
29307
+ if (!clientInfo || typeof clientInfo.name !== "string" || typeof clientInfo.version !== "string") {
29308
+ logger.warn("[MCP Server] Invalid initialize request: missing or invalid clientInfo", {
29309
+ hasParams: !!request.params,
29310
+ hasClientInfo: !!clientInfo,
29311
+ clientInfo
29312
+ });
29313
+ return this.createErrorResponse(id, -32600 /* InvalidRequest */, "Invalid initialize request: clientInfo with name and version is required");
29314
+ }
29266
29315
  logger.info("[MCP Server] Initialize request received (fast handshake mode)", { clientInfo });
29267
29316
  this.session = {
29268
29317
  clientInfo: {
@@ -29388,67 +29437,77 @@ ${json}`;
29388
29437
  logger.info("[MCP Server] Starting stdio JSON-RPC server...");
29389
29438
  let buffer = "";
29390
29439
  let contentLength = null;
29391
- process.stdin.on("data", async (chunk) => {
29392
- buffer += chunk.toString("utf-8");
29393
- if (buffer.length > STDIO_MAX_BUFFER_SIZE) {
29394
- logger.error("[MCP Server] Buffer size exceeded maximum", {
29395
- bufferSize: buffer.length,
29396
- maxSize: STDIO_MAX_BUFFER_SIZE
29397
- });
29398
- buffer = "";
29399
- contentLength = null;
29400
- return;
29401
- }
29402
- let iterations = 0;
29403
- while (iterations < STDIO_MAX_ITERATIONS) {
29404
- iterations++;
29405
- if (contentLength === null) {
29406
- const delimiter2 = buffer.includes("\r\n\r\n") ? "\r\n\r\n" : buffer.includes("\n\n") ? "\n\n" : null;
29407
- if (!delimiter2) break;
29408
- const headerEndIndex = buffer.indexOf(delimiter2);
29409
- const headerBlock = buffer.slice(0, headerEndIndex);
29410
- for (const line of headerBlock.split(delimiter2 === "\r\n\r\n" ? "\r\n" : "\n")) {
29411
- const [key, value] = line.split(":", 2).map((s) => s.trim());
29412
- if (key && key.toLowerCase() === "content-length" && value) {
29413
- contentLength = parseInt(value, 10);
29414
- if (isNaN(contentLength) || contentLength <= 0 || contentLength > STDIO_MAX_MESSAGE_SIZE) {
29415
- logger.error("[MCP Server] Invalid Content-Length", { contentLength });
29416
- buffer = buffer.slice(headerEndIndex + delimiter2.length);
29417
- contentLength = null;
29418
- continue;
29440
+ process.stdin.on("data", (chunk) => {
29441
+ void this.stdinMutex.runExclusive(async () => {
29442
+ buffer += chunk.toString("utf-8");
29443
+ if (buffer.length > STDIO_MAX_BUFFER_SIZE) {
29444
+ logger.error("[MCP Server] Buffer size exceeded maximum", {
29445
+ bufferSize: buffer.length,
29446
+ maxSize: STDIO_MAX_BUFFER_SIZE
29447
+ });
29448
+ buffer = "";
29449
+ contentLength = null;
29450
+ return;
29451
+ }
29452
+ let iterations = 0;
29453
+ while (iterations < STDIO_MAX_ITERATIONS) {
29454
+ iterations++;
29455
+ if (contentLength === null) {
29456
+ const delimiter2 = buffer.includes("\r\n\r\n") ? "\r\n\r\n" : buffer.includes("\n\n") ? "\n\n" : null;
29457
+ if (!delimiter2) break;
29458
+ const headerEndIndex = buffer.indexOf(delimiter2);
29459
+ const headerBlock = buffer.slice(0, headerEndIndex);
29460
+ for (const line of headerBlock.split(delimiter2 === "\r\n\r\n" ? "\r\n" : "\n")) {
29461
+ const [key, value] = line.split(":", 2).map((s) => s.trim());
29462
+ if (key && key.toLowerCase() === "content-length" && value) {
29463
+ contentLength = parseInt(value, 10);
29464
+ if (isNaN(contentLength) || contentLength <= 0 || contentLength > STDIO_MAX_MESSAGE_SIZE) {
29465
+ logger.error("[MCP Server] Invalid Content-Length", { contentLength });
29466
+ this.writeResponse({
29467
+ jsonrpc: "2.0",
29468
+ id: null,
29469
+ error: {
29470
+ code: -32600 /* InvalidRequest */,
29471
+ message: `Invalid Content-Length: ${contentLength}`
29472
+ }
29473
+ });
29474
+ buffer = buffer.slice(headerEndIndex + delimiter2.length);
29475
+ contentLength = null;
29476
+ continue;
29477
+ }
29419
29478
  }
29420
29479
  }
29421
- }
29422
- if (contentLength === null) {
29423
- logger.error("[MCP Server] No Content-Length header found");
29480
+ if (contentLength === null) {
29481
+ logger.error("[MCP Server] No Content-Length header found");
29482
+ buffer = buffer.slice(headerEndIndex + delimiter2.length);
29483
+ continue;
29484
+ }
29424
29485
  buffer = buffer.slice(headerEndIndex + delimiter2.length);
29425
- continue;
29426
29486
  }
29427
- buffer = buffer.slice(headerEndIndex + delimiter2.length);
29428
- }
29429
- if (Buffer.byteLength(buffer, "utf-8") < contentLength) break;
29430
- const messageBuffer = Buffer.from(buffer, "utf-8");
29431
- const jsonMessage = messageBuffer.slice(0, contentLength).toString("utf-8");
29432
- buffer = messageBuffer.slice(contentLength).toString("utf-8");
29433
- contentLength = null;
29434
- try {
29435
- const request = JSON.parse(jsonMessage);
29436
- logger.debug("[MCP Server] Request received", { method: request.method, id: request.id });
29437
- const response = await this.handleRequest(request);
29438
- if (request.id !== void 0 && request.id !== null) {
29439
- this.writeResponse(response);
29487
+ if (Buffer.byteLength(buffer, "utf-8") < contentLength) break;
29488
+ const messageBuffer = Buffer.from(buffer, "utf-8");
29489
+ const jsonMessage = messageBuffer.slice(0, contentLength).toString("utf-8");
29490
+ buffer = messageBuffer.slice(contentLength).toString("utf-8");
29491
+ contentLength = null;
29492
+ try {
29493
+ const request = JSON.parse(jsonMessage);
29494
+ logger.debug("[MCP Server] Request received", { method: request.method, id: request.id });
29495
+ const response = await this.handleRequest(request);
29496
+ if (request.id !== void 0 && request.id !== null) {
29497
+ this.writeResponse(response);
29498
+ }
29499
+ } catch (error) {
29500
+ logger.error("[MCP Server] Failed to parse or handle request", { jsonMessage, error });
29501
+ this.writeResponse({ jsonrpc: "2.0", id: null, error: { code: -32700 /* ParseError */, message: "Parse error: Invalid JSON" } });
29440
29502
  }
29441
- } catch (error) {
29442
- logger.error("[MCP Server] Failed to parse or handle request", { jsonMessage, error });
29443
- this.writeResponse({ jsonrpc: "2.0", id: null, error: { code: -32700 /* ParseError */, message: "Parse error: Invalid JSON" } });
29444
29503
  }
29445
- }
29446
- if (iterations >= STDIO_MAX_ITERATIONS) {
29447
- logger.warn("[MCP Server] Maximum iterations reached in message processing", {
29448
- iterations,
29449
- bufferSize: buffer.length
29450
- });
29451
- }
29504
+ if (iterations >= STDIO_MAX_ITERATIONS) {
29505
+ logger.warn("[MCP Server] Maximum iterations reached in message processing", {
29506
+ iterations,
29507
+ bufferSize: buffer.length
29508
+ });
29509
+ }
29510
+ });
29452
29511
  });
29453
29512
  const shutdown = (reason) => {
29454
29513
  logger.info(`[MCP Server] ${reason}`);
@@ -30339,7 +30398,7 @@ var UnifiedMCPManager = class {
30339
30398
  };
30340
30399
  this.setupProcessHandlers(config.name, childProcess, serverProcess);
30341
30400
  this.servers.set(config.name, serverProcess);
30342
- await new Promise((resolve12) => setTimeout(resolve12, 100));
30401
+ await new Promise((resolve13) => setTimeout(resolve13, 100));
30343
30402
  if (childProcess.killed || childProcess.exitCode !== null) {
30344
30403
  throw new Error(
30345
30404
  `Server process exited immediately with code ${childProcess.exitCode}`
@@ -30362,6 +30421,14 @@ var UnifiedMCPManager = class {
30362
30421
  name: config.name,
30363
30422
  error: error.message
30364
30423
  });
30424
+ const serverProcess = this.servers.get(config.name);
30425
+ if (serverProcess?.process && !serverProcess.process.killed) {
30426
+ try {
30427
+ serverProcess.process.kill("SIGTERM");
30428
+ } catch {
30429
+ }
30430
+ }
30431
+ this.servers.delete(config.name);
30365
30432
  throw error;
30366
30433
  }
30367
30434
  }
@@ -30442,7 +30509,7 @@ var UnifiedMCPManager = class {
30442
30509
  async restartServer(serverName) {
30443
30510
  logger.info("UnifiedMCPManager: Restarting server", { name: serverName });
30444
30511
  await this.stopServer(serverName);
30445
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
30512
+ await new Promise((resolve13) => setTimeout(resolve13, 1e3));
30446
30513
  const serverConfig = this.config.servers.find((s) => s.name === serverName);
30447
30514
  if (!serverConfig) {
30448
30515
  throw new Error(`Server configuration not found: ${serverName}`);
@@ -30689,31 +30756,34 @@ var UnifiedMCPManager = class {
30689
30756
  this.pendingRestarts.set(serverName, restartTimer);
30690
30757
  }
30691
30758
  });
30692
- if (this.config.logging?.logServerOutput) {
30693
- if (process2.stdout) {
30694
- process2.stdout.on("data", (data) => {
30759
+ const shouldLog = this.config.logging?.logServerOutput;
30760
+ if (process2.stdout) {
30761
+ process2.stdout.on("data", (data) => {
30762
+ if (shouldLog) {
30695
30763
  logger.debug(`MCP[${serverName}] stdout:`, {
30696
30764
  data: data.toString().trim()
30697
30765
  });
30698
- });
30699
- }
30700
- if (process2.stderr) {
30701
- process2.stderr.on("data", (data) => {
30766
+ }
30767
+ });
30768
+ }
30769
+ if (process2.stderr) {
30770
+ process2.stderr.on("data", (data) => {
30771
+ if (shouldLog) {
30702
30772
  logger.debug(`MCP[${serverName}] stderr:`, {
30703
30773
  data: data.toString().trim()
30704
30774
  });
30705
- });
30706
- }
30775
+ }
30776
+ });
30707
30777
  }
30708
30778
  }
30709
30779
  /**
30710
30780
  * Wait for process to exit
30711
30781
  */
30712
30782
  async waitForExit(process2, timeoutMs) {
30713
- return new Promise((resolve12, reject) => {
30783
+ return new Promise((resolve13, reject) => {
30714
30784
  const exitListener = () => {
30715
30785
  clearTimeout(timeout);
30716
- resolve12();
30786
+ resolve13();
30717
30787
  };
30718
30788
  const timeout = setTimeout(() => {
30719
30789
  process2.removeListener("exit", exitListener);
@@ -31768,8 +31838,8 @@ var deleteCommand = {
31768
31838
  input: process.stdin,
31769
31839
  output: process.stdout
31770
31840
  });
31771
- const answer = await new Promise((resolve12) => {
31772
- rl.question(chalk5.yellow("\nAre you sure you want to delete this entry? (y/N): "), resolve12);
31841
+ const answer = await new Promise((resolve13) => {
31842
+ rl.question(chalk5.yellow("\nAre you sure you want to delete this entry? (y/N): "), resolve13);
31773
31843
  });
31774
31844
  rl.close();
31775
31845
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
@@ -32729,7 +32799,7 @@ ${this.config.locale === "zh" ? "\u8ACB\u9078\u64C7" : "Select"}${defaultDisplay
32729
32799
  async promptWithTimeout(prompt, parser, defaultValue) {
32730
32800
  const rl = this.getReadline();
32731
32801
  const template = this.getTemplate();
32732
- return new Promise((resolve12) => {
32802
+ return new Promise((resolve13) => {
32733
32803
  let resolved = false;
32734
32804
  let timeoutHandle;
32735
32805
  let warningHandle;
@@ -32743,7 +32813,7 @@ ${this.config.locale === "zh" ? "\u8ACB\u9078\u64C7" : "Select"}${defaultDisplay
32743
32813
  ${template.timedOut}`);
32744
32814
  rl.close();
32745
32815
  this.rl = null;
32746
- resolve12({
32816
+ resolve13({
32747
32817
  value: defaultValue,
32748
32818
  timedOut: true
32749
32819
  });
@@ -32767,7 +32837,7 @@ ${template.timeoutWarning(30)}`);
32767
32837
  clearTimeout(warningHandle);
32768
32838
  }
32769
32839
  const value = parser(answer);
32770
- resolve12({
32840
+ resolve13({
32771
32841
  value,
32772
32842
  timedOut: false
32773
32843
  });
@@ -33849,9 +33919,9 @@ ${action.modifications}`;
33849
33919
  )
33850
33920
  );
33851
33921
  console.log(chalk5.gray(` Waiting ${delay}ms before retry...`));
33852
- await new Promise((resolve12) => setTimeout(resolve12, delay));
33922
+ await new Promise((resolve13) => setTimeout(resolve13, delay));
33853
33923
  } else {
33854
- await new Promise((resolve12) => setTimeout(resolve12, delay));
33924
+ await new Promise((resolve13) => setTimeout(resolve13, delay));
33855
33925
  }
33856
33926
  }
33857
33927
  const executionOptions = {
@@ -36988,7 +37058,7 @@ Result: ${result.stages.map((s) => s.output).join("\n\n")}`;
36988
37058
  if (argv.save) {
36989
37059
  try {
36990
37060
  const savePath = argv.save;
36991
- const saveDir = join(savePath, "..");
37061
+ const saveDir = dirname(savePath);
36992
37062
  await mkdir(saveDir, { recursive: true });
36993
37063
  const outputData = formatForSave(result, argv.format || "text", {
36994
37064
  agent: resolvedAgentName,
@@ -37036,7 +37106,7 @@ Response: ${result.response.content}`;
37036
37106
  if (router) {
37037
37107
  router.destroy();
37038
37108
  }
37039
- await new Promise((resolve12) => setImmediate(resolve12));
37109
+ await new Promise((resolve13) => setImmediate(resolve13));
37040
37110
  if (!verbosity.isQuiet()) {
37041
37111
  const executionTime = ((Date.now() - executionStartTime) / 1e3).toFixed(1);
37042
37112
  if (verbosity.isNormal()) {
@@ -37103,7 +37173,7 @@ Response: ${result.response.content}`;
37103
37173
  logger.debug("Context cleanup error", { error: errMsg });
37104
37174
  });
37105
37175
  }
37106
- await new Promise((resolve12) => setImmediate(resolve12));
37176
+ await new Promise((resolve13) => setImmediate(resolve13));
37107
37177
  try {
37108
37178
  const { processManager: processManager2 } = await Promise.resolve().then(() => (init_process_manager(), process_manager_exports));
37109
37179
  await processManager2.shutdown(3e3);
@@ -38002,10 +38072,10 @@ async function getCurrentVersion() {
38002
38072
  return result.dependencies["@defai.digital/automatosx"]?.version || "unknown";
38003
38073
  } catch (error) {
38004
38074
  const { readFile: readFile24 } = await import('fs/promises');
38005
- const { dirname: dirname16, join: join48 } = await import('path');
38075
+ const { dirname: dirname17, join: join48 } = await import('path');
38006
38076
  const { fileURLToPath: fileURLToPath8 } = await import('url');
38007
38077
  const __filename7 = fileURLToPath8(import.meta.url);
38008
- const __dirname8 = dirname16(__filename7);
38078
+ const __dirname8 = dirname17(__filename7);
38009
38079
  const pkgPath = join48(__dirname8, "../../../package.json");
38010
38080
  const content = await readFile24(pkgPath, "utf-8");
38011
38081
  const pkg = JSON.parse(content);
@@ -38160,16 +38230,22 @@ var cleanupCommand = {
38160
38230
  },
38161
38231
  handler: async (argv) => {
38162
38232
  try {
38233
+ const olderThan = argv.olderThan ?? 7;
38234
+ if (isNaN(olderThan) || olderThan < 0) {
38235
+ console.error(chalk5.red.bold("\n\u2717 Invalid --older-than value\n"));
38236
+ console.error(chalk5.red("Value must be a non-negative number (days)"));
38237
+ process.exit(1);
38238
+ }
38163
38239
  const { detectProjectRoot: detectProjectRoot2 } = await Promise.resolve().then(() => (init_path_resolver(), path_resolver_exports));
38164
38240
  const projectDir = await detectProjectRoot2(process.cwd());
38165
38241
  const workspaceManager = new WorkspaceManager(projectDir);
38166
38242
  if (!argv.confirm) {
38167
38243
  console.log(chalk5.yellow(`
38168
- \u26A0 This will remove temporary files older than ${argv.olderThan} days`));
38244
+ \u26A0 This will remove temporary files older than ${olderThan} days`));
38169
38245
  console.log(chalk5.gray("Run with --confirm to proceed\n"));
38170
38246
  process.exit(0);
38171
38247
  }
38172
- const removed = await workspaceManager.cleanupTmp(argv.olderThan);
38248
+ const removed = await workspaceManager.cleanupTmp(olderThan);
38173
38249
  console.log(chalk5.green.bold(`
38174
38250
  \u2713 Cleanup complete
38175
38251
  `));
@@ -39444,7 +39520,7 @@ var resumeCommand = {
39444
39520
  if (router) {
39445
39521
  router.destroy();
39446
39522
  }
39447
- await new Promise((resolve12) => setImmediate(resolve12));
39523
+ await new Promise((resolve13) => setImmediate(resolve13));
39448
39524
  console.log(chalk5.green.bold("\u2705 Complete\n"));
39449
39525
  process.exit(0);
39450
39526
  } catch (error) {
@@ -39464,7 +39540,7 @@ var resumeCommand = {
39464
39540
  if (router) {
39465
39541
  router.destroy();
39466
39542
  }
39467
- await new Promise((resolve12) => setImmediate(resolve12));
39543
+ await new Promise((resolve13) => setImmediate(resolve13));
39468
39544
  } catch (cleanupError) {
39469
39545
  const errMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
39470
39546
  logger.debug("Cleanup error ignored", { error: errMsg });
@@ -41755,7 +41831,7 @@ var doctorCommand = {
41755
41831
  }
41756
41832
  }
41757
41833
  async function checkCLIVersion() {
41758
- return new Promise((resolve12) => {
41834
+ return new Promise((resolve13) => {
41759
41835
  const child = spawn("gemini", ["--version"], {
41760
41836
  stdio: ["ignore", "pipe", "pipe"]
41761
41837
  });
@@ -41769,14 +41845,14 @@ var doctorCommand = {
41769
41845
  });
41770
41846
  child.on("close", (code) => {
41771
41847
  if (code === 0 && stdout.trim()) {
41772
- resolve12({
41848
+ resolve13({
41773
41849
  name: "CLI Version",
41774
41850
  status: "pass",
41775
41851
  message: "Gemini CLI version detected",
41776
41852
  details: stdout.trim()
41777
41853
  });
41778
41854
  } else {
41779
- resolve12({
41855
+ resolve13({
41780
41856
  name: "CLI Version",
41781
41857
  status: "warn",
41782
41858
  message: "Could not detect version",
@@ -41786,7 +41862,7 @@ var doctorCommand = {
41786
41862
  });
41787
41863
  setTimeout(() => {
41788
41864
  child.kill();
41789
- resolve12({
41865
+ resolve13({
41790
41866
  name: "CLI Version",
41791
41867
  status: "fail",
41792
41868
  message: "Version check timed out"
@@ -43283,22 +43359,30 @@ var DagGenerator = class {
43283
43359
  }
43284
43360
  /**
43285
43361
  * Calculate maximum depth of DAG (longest path)
43362
+ * BUG FIX: Added cycle detection with visiting set to prevent infinite recursion
43286
43363
  */
43287
43364
  calculateMaxDepth(dag) {
43288
43365
  const depths = /* @__PURE__ */ new Map();
43366
+ const visiting = /* @__PURE__ */ new Set();
43289
43367
  const calculateDepth = (nodeId) => {
43290
43368
  if (depths.has(nodeId)) {
43291
43369
  return depths.get(nodeId);
43292
43370
  }
43371
+ if (visiting.has(nodeId)) {
43372
+ return 0;
43373
+ }
43374
+ visiting.add(nodeId);
43293
43375
  const node = dag.nodes.find((n) => n.id === nodeId);
43294
43376
  if (!node || !node.dependencies || node.dependencies.length === 0) {
43295
43377
  depths.set(nodeId, 1);
43378
+ visiting.delete(nodeId);
43296
43379
  return 1;
43297
43380
  }
43298
43381
  const depthValues = node.dependencies.map((dep) => calculateDepth(dep));
43299
43382
  const maxDepDep = depthValues.length > 0 ? Math.max(...depthValues) : 0;
43300
43383
  const depth = maxDepDep + 1;
43301
43384
  depths.set(nodeId, depth);
43385
+ visiting.delete(nodeId);
43302
43386
  return depth;
43303
43387
  };
43304
43388
  let maxDepth = 0;
@@ -44297,11 +44381,23 @@ var genCommand = {
44297
44381
  process.exit(1);
44298
44382
  }
44299
44383
  specFile = resolve(process.cwd(), specFile);
44300
- const dangerousPaths = ["/etc", "/sys", "/proc", "/dev", "/root", "/boot"];
44301
- const isDangerousPath = dangerousPaths.some(
44384
+ const dangerousUnixPaths = ["/etc", "/sys", "/proc", "/dev", "/root", "/boot"];
44385
+ const isDangerousUnixPath = dangerousUnixPaths.some(
44302
44386
  (dangerous) => specFile.startsWith(dangerous + "/") || specFile === dangerous
44303
44387
  );
44304
- if (isDangerousPath) {
44388
+ const specFileLower = specFile.toLowerCase();
44389
+ const dangerousWindowsPaths = [
44390
+ "c:\\windows",
44391
+ "c:\\program files",
44392
+ "c:\\program files (x86)",
44393
+ "c:\\programdata",
44394
+ "c:\\users\\public",
44395
+ "c:\\system32"
44396
+ ];
44397
+ const isDangerousWindowsPath = dangerousWindowsPaths.some(
44398
+ (dangerous) => specFileLower.startsWith(dangerous + "\\") || specFileLower === dangerous
44399
+ );
44400
+ if (isDangerousUnixPath || isDangerousWindowsPath) {
44305
44401
  console.error(chalk5.red(`\u2717 Error: Access to system directory '${specFile}' is not allowed`));
44306
44402
  console.error(chalk5.gray("Spec files should be in your project directory"));
44307
44403
  process.exit(1);
@@ -46458,7 +46554,7 @@ async function findProcesses(processName, verbose) {
46458
46554
  }
46459
46555
  async function killProcess(pid, verbose) {
46460
46556
  try {
46461
- await new Promise((resolve12, reject) => {
46557
+ await new Promise((resolve13, reject) => {
46462
46558
  const proc = spawn("kill", ["-TERM", String(pid)], {
46463
46559
  stdio: "pipe",
46464
46560
  shell: false
@@ -46466,23 +46562,23 @@ async function killProcess(pid, verbose) {
46466
46562
  });
46467
46563
  proc.on("close", (code) => {
46468
46564
  if (code === 0) {
46469
- resolve12();
46565
+ resolve13();
46470
46566
  } else {
46471
46567
  reject(new Error(`kill -TERM failed with code ${code}`));
46472
46568
  }
46473
46569
  });
46474
46570
  proc.on("error", reject);
46475
46571
  });
46476
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
46572
+ await new Promise((resolve13) => setTimeout(resolve13, 1e3));
46477
46573
  try {
46478
- await new Promise((resolve12, reject) => {
46574
+ await new Promise((resolve13, reject) => {
46479
46575
  const proc = spawn("ps", ["-p", String(pid)], {
46480
46576
  stdio: "pipe",
46481
46577
  shell: false
46482
46578
  });
46483
46579
  proc.on("close", (code) => {
46484
46580
  if (code === 0) {
46485
- resolve12();
46581
+ resolve13();
46486
46582
  } else {
46487
46583
  reject(new Error("Process not running"));
46488
46584
  }
@@ -46492,14 +46588,14 @@ async function killProcess(pid, verbose) {
46492
46588
  if (verbose) {
46493
46589
  logger.debug(`Process ${pid} didn't respond to SIGTERM, using SIGKILL`);
46494
46590
  }
46495
- await new Promise((resolve12, reject) => {
46591
+ await new Promise((resolve13, reject) => {
46496
46592
  const proc = spawn("kill", ["-KILL", String(pid)], {
46497
46593
  stdio: "pipe",
46498
46594
  shell: false
46499
46595
  });
46500
46596
  proc.on("close", (code) => {
46501
46597
  if (code === 0) {
46502
- resolve12();
46598
+ resolve13();
46503
46599
  } else {
46504
46600
  reject(new Error(`kill -KILL failed with code ${code}`));
46505
46601
  }
@@ -48077,7 +48173,7 @@ async function handleKill(argv) {
48077
48173
  `);
48078
48174
  console.log(chalk5.yellow("This will immediately disable the feature for ALL users."));
48079
48175
  console.log(chalk5.gray("Press Ctrl+C to cancel, or wait 5 seconds to confirm...\n"));
48080
- await new Promise((resolve12) => setTimeout(resolve12, 5e3));
48176
+ await new Promise((resolve13) => setTimeout(resolve13, 5e3));
48081
48177
  try {
48082
48178
  await flagManager.killSwitch(flagName, reason);
48083
48179
  console.log(chalk5.red("\u2713 Kill switch activated"));